Claude Media
MCPのCompletion仕様 — 引数オートコンプリートAPIの仕組み

MCPのCompletion仕様 — 引数オートコンプリートAPIの仕組み

MCPのCompletion仕様はprompts/get・resources/readの引数をIDEのように補完させる機能。プロトコルの中身と、Claude Codeでの引数入力が実際にはどう扱われているかを整理する。

MCPのCompletionとは何か

MCPのCompletionは、Promptsの引数やResource Templateの変数を埋めるときに、サーバーが候補を返す仕組みです。仕様は「IDEのコード補完に似たインタラクティブな体験を支えるよう設計されている」と説明しています。ユーザーが引数を入力している途中で、ドロップダウンやポップアップに候補を出し、絞り込みながら選ばせる用途を想定しています。

プロトコル自体は、どのUIで見せるかを規定しません。ドロップダウンにするか、インラインの薄い候補表示にするかはクライアント実装の裁量です。サーバーがcompletions能力を宣言していれば、クライアントはcompletion/completeリクエストで候補を取りに行けます。

宣言は、初期化時に返す能力の中に空のオブジェクトを置くだけです。仕様は、補完に対応するサーバーにこの宣言を必須(MUST)としています。

{
  "capabilities": {
    "completions": {}
  }
}
くらべる

補完の呼び出し先は2種類

Promptの引数

ref/prompt

nameにPromptの名前を指定し、そのPromptの引数値を補完します。

リソースのURI

ref/resource

uriにURIまたはURIテンプレート(file:///{path}など)を指定し、URI中の変数部分を補完します。

どちらも応答の形式は共通で、values / total / hasMoreの3フィールドを返します。対象がPromptの引数かリソースのURIかが違うだけなので、クライアント側の処理は同じロジックで書けます。

補完リクエストの中身と応答の読み方

最小のやり取りは次のとおりです。argument.valueに入力途中の文字列(この例ではpy)を渡します。

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "completion/complete",
  "params": {
    "ref": { "type": "ref/prompt", "name": "code_review" },
    "argument": { "name": "language", "value": "py" }
  }
}
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "complete",
    "completion": {
      "values": ["python", "pytorch", "pyside"],
      "total": 10,
      "hasMore": true
    }
  }
}

valuesは候補の配列で、関連度順に並べて返す前提です。1回の応答に入る候補は最大100件までと、仕様が上限を決めています。totalは一致件数の総数、hasMoreはvaluesに入りきらなかった残りがあるかの真偽値です。上の例ならtotal: 10に対してvaluesが3件なので、「他に7件」と出せます。

仕様が任意としているのはtotalです。サーバーがtotalを省いてvaluesとhasMoreだけを返しても仕様どおりなので、クライアントは件数が分からなくても表示が崩れないUIにしておく必要があります。件数不明のまま、hasMoreだけで続きの有無を示す形です。

複数引数をまたぐ補完 — contextの役割

1つのPromptに複数の引数があると、後の引数の候補は前の引数の値に依存することがあります。言語にpythonを選んだあとなら、フレームワークの候補はflask / fastapi / djangoに絞りたい、といった場合です。仕様はこの依存をcontext.argumentsで渡します。

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "completion/complete",
  "params": {
    "ref": { "type": "ref/prompt", "name": "code_review" },
    "argument": { "name": "framework", "value": "fla" },
    "context": { "arguments": { "language": "python" } }
  }
}

この例の応答はvalues: ["flask"]、total: 1、hasMore: falseの1件です。クライアント側の動きは次の流れになります。

手順

引数を1つ確定するたびの流れ

  1. 1

    入力途中の値だけを送る

    最初の引数はcontextなしで、argumentに入力途中の文字列を入れて送ります。

  2. 2

    確定した値を積み上げる

    引数が1つ確定したら、その名前と値をcontext.argumentsに加えます。

  3. 3

    次の引数の補完を投げる

    積み上げたcontext.argumentsと、次の引数の入力途中の値を付けて、再びcompletion/completeを送ります。

仕様はどう変わってきたか

Completion仕様はバージョンごとに小さな追加が入っています。MCPサーバーを実装するとき、相手のクライアントがどの版に対応しているかで返すべき形が変わるので、差分を押さえておく価値があります。

あゆみ

Completion仕様の変遷

  1. 2025-03-26版ref/promptとref/resourceで補完

    completions能力、completion/complete、values / total / hasMoreの3フィールド、候補最大100件が入っています。contextはまだありません。

  2. 2025-06-18版context.argumentsを追加

    確定済みの引数を渡すcontext.argumentsが加わり、複数引数のPromptやURIテンプレートで後続の候補を絞れるようになりました。

  3. 2025-11-25版説明文の整理

    仕様の導入文が「Promptの引数とリソースURI」から「Promptの引数とResource Templateの変数」の書き方に変わりました。プロトコルのメッセージ形式は2025-06-18版と同じです。

  4. 2026-07-28版resultTypeと_metaが加わる

    応答に"resultType": "complete"が入り、ref/resourceのuriは「URIまたはURIテンプレート」と明記されました。仕様の冒頭には、リクエストに_meta(プロトコルバージョン・クライアント情報・クライアント能力)を必ず含めるという注記が付いています。

    データ型の定義では、リクエストのrefの型名がResourceReferenceからResourceTemplateReferenceに変わっています。JSONの形(typeとuri)は同じなので、メッセージ自体は変わりません。型名で実装を分けている言語のSDKでは、仕様の版を上げるときに名前の差を意識することになります。

上のJSON例は_metaを省いています。コピーして試すときは、_metaを足してください。

エラーを4つに切り分ける

仕様がサーバーに求める標準エラー(SHOULD)は4種類です。実装では「どの状況を、どう扱うか」の表で押さえると迷いません。

エラーコード発生条件クライアント側の扱いの例
-32601(Method not found)発生条件サーバーがcompletions能力に対応していないクライアント側の扱いの例そのサーバーへの補完リクエストを止める
-32602(Invalid params)発生条件指定したPrompt名が存在しないクライアント側の扱いの例Prompt名の指定ミスとして修正を促す
-32602(Invalid params)発生条件必須引数が欠けているクライアント側の扱いの例引数の入力漏れとして扱う
-32603(Internal error)発生条件サーバー内部の失敗クライアント側の扱いの例補完候補を出さずに入力は続けさせる

同じ-32602が2つの状況に割り当てられている点が、実装で見落としやすいところです。エラーコードだけでは「名前が違う」のか「必須引数が足りない」のかを区別できないので、必要ならエラーメッセージ側で区別します。仕様は-32601に「能力が未対応」という注記だけを付けており、他の3つはJSON-RPCの標準コードをそのまま使っています。

入力のたびに往復する設計と、実装側の注意

メッセージフローは単純です。ユーザーが引数を入力し始めるとクライアントがcompletion/completeを送り、入力を続けるたびに更新した文字列で再び送ります。この往復が打鍵のたびに起きるので、仕様はクライアントに「連続する補完リクエストのデバウンス」を求めています。デバウンスの間隔の数値は仕様が指定しておらず、短すぎればリクエスト数が減らず、長すぎれば候補の表示が遅れます。サーバーのレート制限とあわせて、実装者が調整する部分です。

仕様がサーバーとクライアントに挙げる推奨事項は次のとおりです。

サーバー側(SHOULD)クライアント側(SHOULD)
関連度順に候補を並べるクライアント側(SHOULD)連続する入力のリクエストを間引く(デバウンス)
可能ならあいまい一致(fuzzy matching)に対応するクライアント側(SHOULD)補完結果を適宜キャッシュする
補完リクエストにレート制限をかけるクライアント側(SHOULD)結果が欠けていたり部分的だったりしても正しく扱う
すべての入力を検証するクライアント側(SHOULD)—

セキュリティ面は、より強い必須(MUST)です。仕様は、補完の入力すべての検証、レート制限、機密性の高い候補へのアクセス制御、補完を通じた情報漏えいの防止を求めています。最後の項目は見落としやすく、候補の一覧そのものが、他ユーザーのデータや内部識別子など、本来見えてはいけない情報の通り道になり得ます。

ファイルパスのような値を補完する

ref/resourceを使うと、URIテンプレート(file:///{path})の変数部分も補完できます。ファイルパスの一部を入力した時点で、実在するパスの候補を返す使い方です。

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "completion/complete",
  "params": {
    "ref": { "type": "ref/resource", "uri": "file:///{path}" },
    "argument": { "name": "path", "value": "projects/myapp/src" }
  }
}

refはnameではなく、URIテンプレートそのものをuriに入れます。応答はref/promptのときと同じvalues / total / hasMoreです。候補が頻繁に変わるファイルシステムや、一覧を丸ごと持つのが現実的でないデータでは、問い合わせのたびに最新の候補を作れるこの方式が向いています。

Claude Codeは補完APIを使っているか

Claude CodeでMCPのPromptsを実行するには、/mcp__servername__promptnameの形で呼びます。/を入力すると、MCPのPromptは/servername:promptname (MCP)の形で一覧に並びます。mcp__形式では、サーバー名のうち英数字・_・-以外の文字が_に置き換わり、Prompt名はサーバーが宣言したままの名前が使われます。引数は、コマンドの後ろに空白区切りで渡します。公式ドキュメントは「Claude Codeは引数を空白で分割し、1つの引数が1トークンになる」と説明し、例として/mcp__jira__create_issue login-bug highを挙げています。Claude CodeのMCPドキュメントにはcompletion/completeへの言及がなく、入力途中でサーバーへ候補を問い合わせる動作は書かれていません。

オートコンプリートが書かれているのはリソースの参照です。プロンプトで@を入力すると、接続中のすべてのMCPサーバーのリソースがファイルと並んで候補に出ます。リソースのパスはあいまい検索の対象です。選んだリソースは、@server:protocol://resource/pathの形で参照され、Compare @postgres:schema://users with @docs:file://database/user-modelのように1つのプロンプトに複数並べられます。ただし、この候補がどの仕組みで出るかは同ドキュメントに書かれていません。サーバー側で補完を実装した場合に、この@の候補へ現れるかどうかも、同ドキュメントには載っていません。

ファイルを扱うサーバーをリソースとして公開する場合は、Filesystem MCPサーバーの使い方のように、公開するディレクトリを絞る設計と合わせて考えます。

まとめ

補完を作る価値は、使うクライアントがcompletion/completeを呼ぶかで決まります。Claude Code向けなら、まずPromptのdescriptionと引数設計で足りるかを見ます。サーバー自体の作り方はMCPサーバー自作ガイド、動作確認はMCP Inspectorで行えます。

この記事を共有:XはてブLinkedIn
MCP をもっと見る →