コンテンツにスキップ

ADR-33 — MCPサーバーパッケージング

ステータス: Accepted(2026-05-27); v0.1.10で実装

rigor mcp --transport stdioサブコマンドが、7つのツール — rigor_checkrigor_type_ofrigor_triagerigor_annotaterigor_sig_genrigor_explainrigor_coverage — を公開する純Ruby製のJSON-RPC 2.0 MCPサーバーを出荷する。HTTPトランスポートとセッションごとの環境キャッシュは保留のままである。

Rigorはすでに言語サーバー(rigor lsp、ADR-19)を同梱しており、LSPプロトコルを使ってstdio経由でエディタに解析エンジンを公開している。Model Context Protocol(MCP)向けの並列アダプタにより、AIコーディングアシスタント(Claude Code、Cursor、Clineなど)がRigorのツールを直接呼び出せるようになる——リファクタ提案前のrigor_check、ホバーツールチップの根拠となるrigor_type_of、プロジェクト全体のクリーンアップを計画するためのrigor_triage。LSPとMCPは異なる消費者(エディタ対AIエージェント)にサービスを提供し、重複しない。

MCPはJSON-RPC 2.0を改行区切りのJSON stdioストリーム上で使用する。プロトコルサーフェス(surface)はLSPよりも大幅にシンプルである: ケイパビリティネゴシエーションのラウンドトリップなし、ファイルごとのバッファテーブルなし、非同期プッシュ通知なし。MCPサーバーは本質的に関数ディスパッチャーである: tools/list → 利用可能なツールの一覧; tools/call → ツールを1つ呼び出す。

stdioを通じた長期稼働MCPサーバーを起動するrigor mcpサブコマンドを出荷する。

WD1 — Pure-Ruby実装;MCP gemへの依存なし

Section titled “WD1 — Pure-Ruby実装;MCP gemへの依存なし”

ADR-0のゼロランタイム依存スタンスが拘束力を持つ。MCP stdioトランスポートは改行区切りのJSON-RPC——直接実装するには十分シンプル。gemspecに新しいランタイム依存は追加しない。

WD2 — v1ではstdioのみ;HTTPトランスポートは先送り

Section titled “WD2 — v1ではstdioのみ;HTTPトランスポートは先送り”

rigor lsp v1と整合性が取れている。唯一のトランスポートは--transport stdio。HTTPトランスポート(リモートCIなど)は需要に先送り。後でHTTPを追加してもCLIサーフェスが変わらないよう、フラグは受け付けて検証する。

WD3 — 長期稼働プロセス、呼び出しごとのサブプロセスではない

Section titled “WD3 — 長期稼働プロセス、呼び出しごとのサブプロセスではない”

rigor mcpは一度起動して多くのtools/callリクエストを順番に処理し、Rubyのrequireキャッシュを呼び出し全体で共有する。最初の呼び出しがフルコールドブートコストを払い、以降の呼び出しはロード済みエンジンコードを再利用する。これはrigor lspをミラーする。

WD4 — CLI内部経由のインプロセスディスパッチ(StringIOキャプチャ)

Section titled “WD4 — CLI内部経由のインプロセスディスパッチ(StringIOキャプチャ)”

各ツール呼び出しは合成argvを構築し、StringIOでstdoutをキャプチャしながらCLI.new(argv, out:, err:).runを呼び出す。ツールの結果はキャプチャされた文字列である。

根拠: 既存のCLIコマンドはすでに出力を--format jsonでJSON形式にフォーマットする方法を知っている。それらを再利用することでツールはCLIと自動的に同期を保てる——rigor check --format jsonへのあらゆる改善は即座にrigor_check経由で見える。ツールレイヤーの別のJSONシリアライズが不要になる。

WD5 — 7つの読み取り専用ツール

Section titled “WD5 — 7つの読み取り専用ツール”
MCPツール基盤コマンド
rigor_checkrigor check --format json --no-stats [paths]
rigor_type_ofrigor type-of --format json FILE:LINE:COL
rigor_triagerigor triage --format json [paths]
rigor_annotaterigor annotate --no-color FILE
rigor_sig_genrigor sig-gen --print --format json [paths]
rigor_explainrigor explain --format json [rule]
rigor_coveragerigor coverage --format json paths

除外:

  • initbaselinediff — 書き込み側または副作用を持つコマンド。MCPツールは助言的であり、AIエージェントが開始するツール呼び出しでプロジェクトファイルツリーを変更することは適切ではない。
  • lsp — 別のプロトコルであり、ツールではない。

WD6 — isErrorはEXIT_USAGE(64)にマッピング、「解析が問題を見つけた」ではない

Section titled “WD6 — isErrorはEXIT_USAGE(64)にマッピング、「解析が問題を見つけた」ではない”

診断を見つけたrigor checkの実行は1で終了する——これは正常な解析出力であり、エラーではない。isError: trueはCLIがEXIT_USAGE(64)で終了したとき、つまり不正な引数またはランタイム失敗のみ設定される。AIクライアントはisError: falseのJSON診断配列を通常通り読み取れる。

WD7 — セッションレベルの--configデフォルト

Section titled “WD7 — セッションレベルの--configデフォルト”

rigor mcp --config=PATHは個々のツール呼び出しが独自のconfig引数を提供しないときに使用されるセッションレベルのデフォルト設定パスを設定する。rigor lsp --configをミラーする。

WD8 — rigor mcpサブコマンド(HANDLERS["mcp"]

Section titled “WD8 — rigor mcpサブコマンド(HANDLERS["mcp"])”

CLI::HANDLERSHANDLERS["lsp"]と並列。エントリーポイントはlib/rigor/cli/mcp_command.rb;サーバーロジックはlib/rigor/mcp/以下。

呼び出しごとのサブプロセスラッパーシェルスクリプト — すべてのtools/callでエンジンをコールドブートし、数百ミリ秒のレイテンシを追加する。却下。

LSPと並んで単一プロセスでMCPを公開する — プロトコルが異なりすぎて、1つのエントリーポイントに混在させると最小限のゲインで複雑さが増す。別々のrigor lsprigor mcpプロセスの方がクリーン。

MCP Rubygemの使用 — プロトコルはシンプルであり、ランタイム依存の追加はADR-0に違反する。却下。

  • スライス(slice)1(このADR): 7ツールすべてを持つrigor mcp --transport stdio。Pure-Ruby JSON-RPCループ + インプロセスCLIディスパッチ。MCP::Server + MCP::Loop
  • スライス2(需要駆動): HTTPトランスポート(Rackベース)。
  • スライス3(需要駆動):コール間の環境キャッシュ(ウォームなEnvironmentをコール間サーバー内に保持し、mtimeベースのチェックで無効化)。
  • ADR-19 — LSPパッケージング(同じ形状、並列チャネル)。
  • ADR-0 — ゼロランタイム依存スタンス。

© 2026 TypedDuck. Licensed under CC BY-SA 4.0.