AI エージェントにとっての MCP と API:API カタログはディレクトリであり、選択を決めるのは間に誰が入るか
API カタログは MCP サーバーと競合しません。MCP サーバーを掲載できる側です。そこを押さえると、MCP か OpenAPI で記述した HTTP API かの選択は、ホストアプリケーションがモデルのためにサービスを組み込むかどうか、そして誰かがすでにそのサービスを組み込むと決めているかどうかにかかってきます。
目次
このサイトには /.well-known/api-catalog に API カタログがあります。10 月 8 日以降、その先頭に載っているのはサイトの MCP サーバーです。
この 1 項目で、「MCP vs API」の比較記事の多くが出発点にしている問いは成り立たなくなります。API カタログと MCP サーバーは同じ問題への 2 つの答えではありません。カタログはディレクトリで、MCP サーバーはディレクトリが指し示せるものの 1 つです。指し示す先同士を比べると、本当の選択は残ります。ただ、その選択はたいてい間違った変数で語られている、というのが筆者の見立てです。プロトコルよりも重要なのは、ホストアプリケーションがモデルのためにサービスを組み込むかどうか、そして誰かがすでにそのサービスを組み込むと決めているかどうかです。この 2 つは結局、同じ条件を両側から見たものです。
RFC 9727 の API カタログがすること、しないこと
2025 年 6 月の Proposed Standard である RFC 9727 は、Linkset を返す Well-Known URI を定義しています。配信形式は application/linkset+json です。各エントリにはアンカー(エンドポイント)と、それに付くリレーションがあります。service-desc は機械可読な記述、典型的には OpenAPI ファイルを指します。service-doc は人間向けのドキュメントを指します。目的として掲げられているのは、提供者の公開 API エンドポイントの自動発見です。
できるのはそこまでです。RFC は、クライアントがどう認証するかも、どう呼び出すかも定めていません。「ここに何があるか」に答え、「どう使うか」はリンクの先に任せます。
形式そのものは RFC 9264 から来ていて、間違えやすい点が 1 つあります。リレーションタイプがメンバー名になり、その値は href を持つターゲットの配列になる、という点です。このサイトの 2 つのエントリをその形にし、RFC 9727 の 2 つのリレーションだけに絞るとこうなります。
{
"linkset": [
{
"anchor": "https://max.nardit.com/mcp",
"service-desc": [{ "href": "https://max.nardit.com/.well-known/mcp/server-card.json" }],
"service-doc": [{ "href": "https://max.nardit.com/api-docs/mcp.md" }]
},
{
"anchor": "https://max.nardit.com/api/md",
"service-desc": [{ "href": "https://max.nardit.com/api-docs/openapi.json" }],
"service-doc": [{ "href": "https://max.nardit.com/api-docs/markdown-for-agents.md" }]
}
]
}実際に公開したのはこの形ではありません。4 月に書いたカタログも、10 月 18 日に配信されているカタログも、各リンクを links 配列に入れ、rel フィールドを持つオブジェクトにしています。rel は RFC 9264 が定義していないメンバーです。RFC に従うパーサーには、知っているリレーションを持たないアンカーしか見えません。ファイルは正しい JSON で、Content-Type も合っていて、人間が読めばすぐに意味がわかります。だからこそ、何も警告してくれませんでした。ディレクトリはこの仕組みの中でいちばん安く書ける部分で、どうやら音もなく間違えやすい部分でもあるようです。
2 つ目のアンカーは、OpenAPI 3.1 の記述を持つ HTTP API です。1 つ目は MCP サーバーで、その service-desc は以前の提案の形をしたサーバーカードです。後継の SEP-2127 はすでに Final になっていて、カードの置き場所として別の場所を推奨しています。カタログは、アンカーの裏にどのプロトコルがあるかを気にしません。だから、MCP の代わりに API カタログで「足りるか」という問いは、ディレクトリとその掲載項目の 1 つを比べていることになります。
OpenAPI と MCP:それぞれが呼び出し側に渡すもの
2 つのエントリは、同じデータを 2 種類の包装で包んだものでもありません。OpenAPI ファイルが記述するのは 1 つの操作で、パスを渡すとページが Markdown で返ってきます。MCP サーバーが公開するのは読み取り専用の 3 つのツールで、連絡先、プロダクト一覧、記事タイトルと要約の検索(正規 URL を返します)です。
OpenAPI の記述は、呼び出す側が読むための資料です。スクリプトや Fetch ツールを持つエージェントがそれを読み、HTTP リクエストを自分で組み立て、返ってきたものをパースします。エージェントのランタイムはその Fetch にも独自のルールを適用しますが、それは HTTP 全般に対するルールです。サービス側はランタイムと何も取り決めておらず、事前に誰かが設定する必要もありません。ブラウジング中にカタログを見つけたエージェントは、GET リクエストを送れるだけで Markdown API を使えます。
MCP が呼び出し側に渡すのは別のもの、つまりホストです。2026-07-28 版の仕様は 3 つの役割を挙げています。ホスト(LLM アプリケーション)、クライアント(ホスト内のコネクタ)、サーバーです。サーバーはホストと話し、何をモデルに届けるかはホストが決めます。ホストはツール名、説明、スキーマを型付きのリストで受け取り、モデルに提示します。一度に全部提示するのが今も一般的で、以前に書いたトークンのコストはそこから生じます。ホストが遅延させる場合は、必要になった時点で提示します。そしてホストは人間をループに入れることになっています。仕様のツール安全原則は短いものです。
Tools represent arbitrary code execution and must be treated with
appropriate caution.
...
Hosts must obtain explicit user consent before invoking any tool仕様のツールのページは、アノテーションについて厳しいルールを追加しています。信頼できるサーバーから来たものでない限り、クライアントはアノテーションを信頼できないものとして扱わなければなりません。隣のフィールドである説明文については、同じくらい明確なことは何も書かれていません。説明文も外部の書き手と同じ扱いを受けるべきだ、と筆者は以前に論じました。
つまり、どちらの経路もエージェントのランタイムを通ります。違いは、サービスがそこに組み込まれているかどうかです。OpenAPI なら、サービスはエージェントが読む文書です。MCP なら、ホストが受け入れ、モデルに提示し、独自の同意ポリシーで管理するツール群です。
MCP 2026-07-28 でサーバーは安くなった。コストはホスト側に残る
2025 年の各リビジョンでは、すべての接続が initialize ハンドシェイクで始まり、接続単位のセッションを確立していました。HTTP のセッション ID は 2025 年 11 月のリビジョンですでに任意になっていましたが、ハンドシェイクは必須のままでした。現行の仕様はこれをなくしています。ベースプロトコルには「stateless, self-contained requests」とリクエスト単位の Capability ネゴシエーションが挙げられ、Streamable HTTP トランスポートでは、各メッセージが単一エンドポイントへの HTTP POST になり、JSON オブジェクトか、そのリクエストに限定されたストリームで応答されます。
このサイトのサーバーは、サーバーレス関数上の 1 つのルートハンドラーです。POST に応答し、GET には 405 を返し、セッションを持たず、データが公開されているので認証も要りません。仕様の後方互換性のセクションが説明しているとおり、古い initialize ハンドシェイクにも今も応答します。サーバーを書くことは、もう高くつく部分ではありません。
安くならなかったものはホスト側にあります。誰かがサーバーを見つけて許可しなければなりません。クライアントの設定に手で書くか、レジストリを通すかです。多くのホストは今もすべての定義を最初にコンテキストへ読み込み、遅延させるかどうかを決めるのはサービス側ではなくホストです。概要の原則はホストが同意を得なければならないとしていますが、ツールのページはそれを、人間がループにいて呼び出しを拒否できるようにすべき(SHOULD)、と弱め、やり取りの形はホストに任せています。実際には、初回使用時の確認、ツールごとの許可リスト、毎回の確認のいずれかです。すでに承認済みのリスクの低い参照なら、確認を繰り返してもあまり意味はありません。それでも無価値ではありません。このサイトの検索ツールは自由入力のクエリを受け取り、クエリはユーザーのセッションにある私的な情報を、ユーザーが一度も確かめたことのないサーバーへ運び得るからです。
「MCP はエージェント向け、REST はコード向け」のどこが間違っているか
よくある一言の区分では、MCP は AI エージェントのためのインターフェースで、REST API はプログラムのためのインターフェースだとされます。どちらの半分も外れています。
Web Fetch ツールを持つエージェントは REST クライアントです。OpenAPI ファイルを読むこともできますし、単に Accept: text/markdown でページを要求することもでき、公開コンテンツならそれが最短の経路です。設定は要らず、サービス側のツール一覧をコンテキストに抱える必要もありません。呼び出し側が検索やリンクから流れてくるエージェントなら、MCP サーバーは、MCP を話すホストがそれを見つけて接続を許可されるまで使えないものです。カタログはサーバーを指し示せますし、サーバーカードはそれを記述できます。しかし、どちらも何かを接続するわけではありません。
ここで、先週筆者が書いた一文と意見が分かれます。MCP エンドポイントをページ内の WebMCP ツールと比べたとき、筆者はそれを今日エージェントが到達できる経路だと書きました。WebMCP と比べるならそれは正しいです。しかし、クライアントをまったく必要としない Markdown API と比べれば、MCP は 1 番目ではなく 2 番目の経路です。
MCP が主に相手にするのは、エージェントよりもホスト、そしてホストを通じて、そのホストを運用しサービスを接続すると決めた人たちです。その決定こそ MCP がもたらすものです。いったん決まれば、モデルが先にサービスを見つける必要なく、ツールはそのクライアントで使える状態になり、型付きでホストに管理されます。対象は「エージェント」より狭く、そのぶん関与が深い人たちです。
ですから、筆者が使う区分はエージェント対コードではありません。見知らぬ相手対インストール済みの統合です。見知らぬ相手には、読めて発見できるエンドポイントが必要です。インストール済みの統合なら間にホストを挟んでも困らず、保持すべき認証情報や、確認する価値のある操作が出てきた時点で、ホストが実際の価値を生みます。
開いたタブの WebMCP:3 つ目の扉、このサイトにいちばん必要ないもの
3 つ目の呼び出し側があります。ブラウザーのタブを操作するエージェントで、ページはすでに動いているセッションに向けてツールを登録できます。上でリンクした記事は、WebMCP の登録が今どう動くかを説明しています。ページ内のスクリプトが、現行のドラフトではもう定義されていないオブジェクトをまだ探している点もそこに書きました。そのため、現行のブラウザーではこの扉からは何も公開されません。ここで言いたいことはもっと狭いものです。WebMCP が合うのは、役に立つ状態がタブの中にあるときです。カート、途中まで入力したフォーム、ログイン後の画面などです。誰にでも同じ答えを返す公開サイトには、そうした状態がありません。
MCP サーバーは必要か:最初に答えるべき問い
プロトコルを選ぶ前に、1 つの問いに答えてください。誰がすでにあなたのサービスを使うと決めているか、です。
正直な答えが「まだ誰も」で、呼び出し側が Web を取得する途中でサービスを見つけるエージェントなら、まず素朴な経路を作ってください。コンテンツを HTTP で読めるようにし、操作が 2 つ以上あるなら OpenAPI で記述し、クローラーが何があるかを把握できるよう API カタログに載せます。そうすれば、普通の HTTP アクセスを持つエージェントは、サービス側のスキーマを事前に読み込まずに使えます。取得したものはやはりコンテキストを消費しますが、それは取得したときだけです。
すでに使っているクライアントの中で、意図的にサービスを接続する人やチームがいるなら、MCP は元が取れ始めます。ホストが得意とするものに近いほど、その価値は大きくなります。ホストがユーザーの代わりに保持する認証情報、同意の確認が本来の役目を果たす書き込み操作、作業の中で頻繁に使われるのでコンテキストに置いておく価値のあるツールなどです。
そして両方を作るなら、両方をカタログに載せ、自分の目ではなく RFC 9264 に従うパーサーで確認してください。カタログは呼び出し側に何も求めない唯一の部分です。そしてこのサイトのカタログは、筆者が確かめるまでの 6 か月間、厳密なパーサーには何も伝えていませんでした。
01 / ディスカッション
コメント欄はありません。議論は X で行っています。
02 / ほかの記事
claude -p での Claude Code フォークサブエージェント:2.1.302 がヘッドレス実行で変えたこと
提供されることと使われることは別です。ヘッドレス実行のモデルはフォークを一度も選ばないかもしれず、公式ドキュメントはまだ古いデフォルトを説明しています。パイプラインがどのサブエージェントを使ったかの確認方法、バックグラウンドのフォークがパーサーに2つの回答を渡す理由、そして無効にする価値がある場面を解説します。
Claude Code のステータスラインと ccusage:ネイティブのレート制限と、別の時刻に終わる 5 時間ブロック
2 つのツールが同じ問いに別の根拠で答えます。サーバーはリセット時刻を報告し、ログパーサーはそれを推定します。数時間ずれたらサーバーを信じ、パーサーは履歴用に残してください。サブスクリプションでは、ドル金額は為替レートのようなものです。
Claude Code Review が GA に:周囲のレビュー層と、Team プランなしで真似できる層
Claude Code チームのプロセスを支えているものの大半は GitHub の設定と文章化されたルールで、どのプランでも動きます。真似できないのは、ルールをどこから読むかです。マネージドサービスはプルリクエストが触れられないブランチからルールを読みます。ローカルのレビューはディスク上にあるものを読み、レビュー対象の変更が書き換えたばかりのルールファイルも例外ではありません。