MCPを仕様に照らして解説:サーバーとは本当は何か
subprocessへJSONを1行送ると13個のツール定義が返る。handshakeを廃止した2026-07-28改訂版に照らして読む。
このページの内容
公開済みのMCPサーバーをインストールし、JSONを1行送り、返ってくるものを読んでみます。
npm i @modelcontextprotocol/server-everything@2026.8.31
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \
| npx @modelcontextprotocol/server-everything stdio{"result":{"tools":[{"name":"echo","title":"Echo Tool","description":"Echoes
back the input string","inputSchema":{"$schema":"http://json-schema.org/draft-07/
schema#","type":"object","properties":{"message":{"type":"string","description":
"Message to echo"}},"required":["message"]},"annotations":{"readOnlyHint":true,
… … 7,663 bytes on one line …
"jsonrpc":"2.0","id":1}標準入力から1行を読んだprocessから、1行で13個のツール定義が返ってきました。SDKもclient libraryもframeworkも使わずに、あなたはもうModel Context Protocolを話したことになります。全体はこれだけです。transport、message format、そして少数の名前付きmethodです。
Chapter 18では、ツールを2つのものとして定義しました。modelが見るJSON Schemaと、modelが決して見ないあなたのコード内のendpointです。Chapter 23では、それらのcatalogueを保持するharnessを作りました。どちらも、それが再利用可能かどうかを決める問いには答えていません。誰がschemaを書き、それを書いた人からあなたのpromptへどうやって届くのか? MCPはその問いへの1つの答えです。そして原典で読む価値があります。なぜなら、MCPについて書かれているほとんどのものは、もはや存在しないrevisionを説明しているからです。
あなたが今実行したcommandには、間違っている点が3つあります。それぞれがこの章の1つのsectionです。protocol versionを含んでいなかったので、準拠したserverなら拒否していたはずです。それでも答えが返ってきたのは、仕様がfeatureではなくhazardと呼ぶ理由によります。そして、残り2つが存在することを発見しないまま、3つあるprimitiveの1つを要求しました。
それが解く問題と、仕様自身が示す比喩
セクション「それが解く問題と、仕様自身が示す比喩」へのリンクwireの前に、まず算術です。あなたには個のAI applicationがあり、それらが到達できるべきものが個あります。calendar、ticket tracker、warehouse database、design toolです。共通のcontractがなければ、誰かが個のintegrationを書き、その1つ1つがschema、endpoint、authenticationの話、maintenance burdenを抱えます。共通のcontractがあれば、tool vendorがserverを書き、application vendorがclientを書き、合計はになります。
これは新しい観察ではありません。仕様は、それが誰の発想だったかを述べています。
MCP takes some inspiration from the Language Server Protocol, which standardizes how to add support for programming languages across a whole ecosystem of development tools. In a similar way, MCP standardizes how to integrate additional context and tools into the ecosystem of AI applications.1
この比較は賛辞としてではなく、文字どおりに受け取ってください。そのprotocol以前、editorでlanguageをsupportするにはeditorごとにpluginが必要でした。その後は、language teamが1つのserverを出荷すれば、すべてのeditorがそれを得られるようになりました。成功の尺度は優雅さではなく、integration数が増殖しなくなったことでした。ここでも同じです。価値はdesignではなく、implementationの数にあります。 2つのproductしか話さないprotocolは、余分な儀式をまとったdata formatです。
実際にwire上にあるもの
セクション「実際にwire上にあるもの」へのリンクMCP messageはJSON-RPC 2.0です。requestはjsonrpc、id、method、任意のparamsを持つobjectです。responseは同じidと、resultまたはerrorのどちらかを持ちます。notificationはidのないrequestで、replyはありません。仕様はその上に3つの制約を追加します。idはstringまたはnumberでなければならず、nullであってはなりません。まだ処理中の別requestと衝突してはならず、すべてのresultはresultType fieldを持たなければなりません。2
stdio transport、つまり上のcommandが使ったtransportでは、framing ruleはmessageごとに1行です。
Messages are delimited by newlines, and MUST NOT contain embedded newlines. […] The server MUST NOT write anything to its
stdoutthat is not a valid MCP message.3
この最後の節は、自作serverが壊れる最も一般的な理由であり、しかも静かに壊れます。余計なconsole.log、progress bar、dependencyからのdeprecation warningが1つあるだけで、clientのline parserはJSONではないものにぶつかります。escape hatchは同じsectionにあります。serverはstderrへ好きなものを書いてよく、clientはそれをerrorとして扱うべきではありません。上のreference serverは起動のたびにstderr上へStarting default (STDIO) server...を出力するので、pipeはそれでも動きました。
もう1つのstandard transportはStreamable HTTPです。各messageは単一endpointへのPOSTで、replyはJSON object、またはrequestにscopeされたServer-Sent Eventsのstreamです。これはChapter 14で手作業でparseしたwire formatです。semanticsはどちらでも同一です。なぜならtransportはbindingだからです。framingとdeliveryを定義するものであって、meaningを定義するものではありません。4
最初に間違っていたこと:versionがなかった
セクション「最初に間違っていたこと:versionがなかった」へのリンク上のcommandはtools/listだけを送り、それ以外は何も送りませんでした。current revisionでは、このrequestはmalformedであり、準拠serverは拒否しなければなりません。
2026-07-28以降、MCPはstateless protocolであり、仕様は曖昧さなくそう述べています。
The Model Context Protocol (MCP) is a stateless protocol: all the information needed to process a request is contained in the request itself. A server processes each request independently; no state should be inferred from previous requests, even those on the same connection or stream.2
したがって、すべてのrequestは自分自身のprotocol versionとclient capabilitiesを、params内のreservedな_meta objectとして持ちます。これらのfieldのうち2つは、すべてのrequestで必須です。どちらかが欠けたrequestはmalformedであり、serverは-32602を返さなければなりません。2
_meta key | required | what it is |
|---|---|---|
io.modelcontextprotocol/protocolVersion | yes | このrequestが話すrevision。例:"2026-07-28" |
io.modelcontextprotocol/clientCapabilities | yes | このrequestでclientがserverのために何をできるか |
io.modelcontextprotocol/clientInfo | no (but should) | 表示とlogのためだけのclient名とversion |
io.modelcontextprotocol/logLevel | no | serverがこのrequestで出力すべきminimum log level |
正しいtools/listを書き下すとこうなります。この章でmetadataを完全に示すのはこれが最後です。ここから先、これはすべてのrequestに付くからです。
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{"_meta":{
"io.modelcontextprotocol/protocolVersion":"2026-07-28",
"io.modelcontextprotocol/clientCapabilities":{"elicitation":{"form":{}}},
"io.modelcontextprotocol/clientInfo":{"name":"bare-hands","version":"0.0.1"}}}}capability objectがnegotiationです。もはや別個のnegotiation stepはありません。clientは各requestで自分にできることをdeclareし、serverはresult内で自分にできることをdeclareします。そして、どちらの側も相手がclaimしていないfeatureを使ってはなりません。clientがdeclareしていないcapabilityをserverが必要とする場合、serverは-32021を返し、欠けているcapabilityをdata.requiredCapabilitiesで名指ししなければなりません。serverがrequested versionを話せない場合、-32022を返し、自分が話せるversionをlistしなければなりません。2
先に答えを知りたいclientは、それを尋ねられます。server/discoverはmandatory RPCであり、supported versions、capabilities、identity、そして任意のinstructions blockを1 round tripで返します。5 呼び出しはoptionalです。実装はoptionalではありません。
2つ目に間違っていたこと:serverがlegacyだった
セクション「2つ目に間違っていたこと:serverがlegacyだった」へのリンクcommandは動きました。current revisionでは動くべきではありませんでした。なぜ動いたのかは、段落で済ませるより測定する価値があります。ecosystem全体の状態が1行に表れているからです。
modern clientに対して仕様が指示するとおりに、reference serverをprobeします。
echo '{"jsonrpc":"2.0","id":1,"method":"server/discover","params":{"_meta":{
"io.modelcontextprotocol/protocolVersion":"2026-07-28",
"io.modelcontextprotocol/clientCapabilities":{}}}}' \
| npx @modelcontextprotocol/server-everything stdio{"jsonrpc":"2.0","id":1,"error":{"code":-32601,"message":"Method not found"}}これはcompatibility ruleの3番目のbranchです。DiscoverResultならmodern、recognised modern errorならmodernだがversion違い、そして-32601を含むそれ以外のすべてならlegacyで、initialize handshakeへfall backします。3 ではcurrent revisionを要求して、それを実行します。
→ {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2026-07-28",
"capabilities":{},"clientInfo":{"name":"bare-hands","version":"0.0.1"}}}
← {"result":{"protocolVersion":"2025-11-25","capabilities":{"tools":{"listChanged":true},
"prompts":{"listChanged":true},"resources":{"subscribe":true,"listChanged":true},
"logging":{},"tasks":{…},"completions":{}},"serverInfo":{"name":"mcp-servers/everything",
"title":"Everything Reference Server","version":"2.0.0"},"instructions":"…"}}clientは2026-07-28を求め、serverは2025-11-25と答えました。2026年9月7日時点で、official reference server、npm package @modelcontextprotocol/server-everything、version 2026.8.31、2026年8月31日公開は、current revisionを実装していません。日付を見る限り、それが依存するTypeScript SDKも同じです。release 1.30.0は2026年7月27日、revisionの前日に出ています。
ゴシップではなく、結果を読み取ってください。MCPについて書かれているほとんどのものは、initialize handshake、session、serverがclientへ送るroots/list request、HTTP+SSE transportを持つprotocolを説明しています。この4つはすべて、すでに消えたか、消えつつあります。MCPについて何かを読むとき、このpageを含めて、最初に探すべきものはrevision numberです。
そして最初のcommandが動いた理由は、仕様ではfeatureではなくhazardとして述べられています。
some legacy servers do not validate that a request arrives after
initializeand would process an era-ambiguous method (such astools/call) under legacy semantics. Probing yields a deterministic failure instead.3
測定結果:handshakeなしでそのserverへtools/listを送ると、catalogue全体が返ります。本来拒否されるべきmethodがserveされました。だからこそ仕様は、modern versionだけをsupportする場合であっても、まずserver/discoverでprobeせよと言っているのです。
3つのroleと、文書全体から引用すべき一文
セクション「3つのroleと、文書全体から引用すべき一文」へのリンクMCPには3つのpartyがあり、最初の2つの区別こそ、人々が潰してしまいがちなものです。
Host. applicationです。chat product、editor、agentです。conversation、model、credentials、userのconsentを所有します。clientを作成し、それらの間のsecurity boundaryを強制します。
Client. host内部のconnectorです。各clientはexactly one serverと話します。厳密な1:1 relationshipです。そして、自分がrouteするすべてのrequestへprotocol versionとcapabilitiesを付けます。
Server. resources、tools、promptsを公開するprocessまたはserviceです。localでもremoteでもよく、独立して動作し、その仕事は1つのfocused areaに限られます。6
この「exactly one server」ruleはbookkeepingではありません。下のdesign principleを実装可能にするものです。そして、仕様から一文だけ持ち帰るなら、この文です。
Servers should not be able to read the whole conversation, nor "see into" other servers. Servers receive only necessary contextual information. Full conversation history stays with the host. Each server maintains isolation. Cross-server interactions are controlled by the host.6
これは多くの人が最初に持ってくるmental modelをひっくり返します。assistantに接続したweather serverは、あなたが何を尋ねたかを見ません。それが見るのは、modelが選んだargumentsを伴うtools/callだけです。それ以外は何も見ません。前のturnも、system promptも、calendar serverがつい先ほど返したresultも見ません。2つのserverが協調する必要がある場合、hostが意図的に一方から他方へ値を運びます。modelがそれを求めたからです。だからこそisolationはChapter 30が依拠するsecurity propertyです。compromised serverのblast radiusは小さく定義されており、それを広げるにはhostの協力が必要です。
3つ目:3つのprimitiveを、誰が主導権を持つかで並べる
セクション「3つ目:3つのprimitiveを、誰が主導権を持つかで並べる」へのリンク最初のcommandはそのserverにtoolsを求め、13個を得ました。残り2つの質問も投げれば、そのserverは答えます。resources/listは7個を返し、prompts/listは4個を返します。何も尋ねなかったので、それらは現れませんでした。ここでMCPの教育的な背骨に到達します。仕様内にありながら、ほとんど誰も引用しないtableです。
| Primitive | Control | Description | Example |
|---|---|---|---|
| Prompts | User-controlled | userの選択で起動されるinteractive template | Slash commands、menu options |
| Resources | Application-controlled | clientがattachして管理するcontextual data | File contents、git history |
| Tools | Model-controlled | actionを取るためにLLMへ公開されるfunctions | API POST requests、file writing |
「capabilityを公開する3つの方法」ではありません。これが起きると誰が決めるのかへの3つの答えです。modelはtoolをcallすると決めます。applicationはresourceをattachすると決めます。人はpromptを実行すると決めます。ここを間違えてもfeatureは動きます。ただし、間違った瞬間に、間違った理由で動きます。
それを最もはっきり感じる方法はcalendarです。同じcalendarを3回、各primitiveとして1回ずつ公開するserverを示します。dependencyなし、plain Nodeで100行です。
const TOOL = {
name: "create_event",
description: "Create a calendar event. Writes to the calendar.",
inputSchema: {
type: "object",
properties: {
title: { type: "string", description: "Event title." },
startsAt: { type: "string", format: "date-time", description: "Start, ISO 8601 UTC." },
},
required: ["title"],
},
};
switch (method) {
case "resources/read":
return ok(id, { contents: [{ uri: "calendar://week",
mimeType: "application/json", text: JSON.stringify(EVENTS) }],
ttlMs: 60000, cacheScope: "private" });
case "prompts/get":
return ok(id, { description: PROMPT.description, messages: [{ role: "user",
content: { type: "text", text: `Read calendar://week and draft a plan. ` +
`Focus: ${params.arguments?.focus ?? "balance"}.` } }] });
case "tools/list":
return ok(id, { tools: [TOOL], ttlMs: 300000, cacheScope: "public" });
}実行して、3通りすべてで尋ねます。実際のoutputで、wire上では1行1messageですが、このpage用にwrapしています。requestの_metaとserverのidentity blockは省略しています。
→ resources/read {"uri":"calendar://week"}
← {"resultType":"complete","contents":[{"uri":"calendar://week",
"mimeType":"application/json","text":"[{\"id\":\"e1\",\"title\":\"Standup\",
\"startsAt\":\"2026-09-07T09:00:00Z\"},{\"id\":\"e2\",\"title\":\"Design review\",
\"startsAt\":\"2026-09-09T15:00:00Z\"}]"}],"ttlMs":60000,"cacheScope":"private"}
→ prompts/get {"name":"prepare_week","arguments":{"focus":"deep work"}}
← {"resultType":"complete","description":"Read the week and draft a plan.",
"messages":[{"role":"user","content":{"type":"text",
"text":"Read calendar://week and draft a plan. Focus: deep work."}}]}
→ tools/call {"name":"create_event","arguments":{"title":"Dentist",
"startsAt":"2026-09-10T08:30:00Z"}}
← {"resultType":"complete","content":[{"type":"text",
"text":"Created e3: Dentist at 2026-09-10T08:30:00Z"}],
"structuredContent":{"id":"e3","title":"Dentist","startsAt":"2026-09-10T08:30:00Z"},
"isError":false}3つのmethod、3つのshape、1つのcalendar。ここが要点です。
週を読むのはresource
セクション「週を読むのはresource」へのリンクURIでaddressされ、不活性であり、conversationへattachするかどうかはapplicationが決めます。protocol上、modelが自力でそれを取りに行く方法はありません。resultはこのrevisionで新しく入ったttlMsとcacheScopeを持つので、clientはpollingする代わりに1分間その週をcacheできます。
eventを作成するのはtool
セクション「eventを作成するのはtool」へのリンクschemaがあり、side effectがあり、いつcallするかはmodelが決めます。resultはisErrorを持ちます。これはChapter 18が必要だと論じたfieldです。validation failureはprotocol errorではなく、modelが読んで修正できるtool resultとして返ります。
「今週の準備をして」はprompt
セクション「「今週の準備をして」はprompt」へのリンク名前付きでargumentを取るtemplateであり、人が呼び出します。menu内のslash commandです。これはanswerではなくmessagesを返します。server authorが、自分自身のtoolsでうまく機能するphrasingを出荷する方法です。まさにそれはserver authorにはあり、userにはない知識です。
ほとんど全員が、これら3つをすべてtoolsにしてしまいます。その結果、本来applicationが静かにattachすべきreadが、approvalを必要とするwriteとmodelのattentionを奪い合うcatalogueになります。そして人がbuttonとして欲しかったものがschemaの中に埋もれます。正しくするのにcostはかかりません。そしてそれは、1行書く前に決まります。
serverはあなたをcallできない
セクション「serverはあなたをcallできない」へのリンクcalendar toolには必須argumentのtitleと、任意のstartsAtがあります。dateなしでevent作成を頼むと、興味深いものが返ってきます。
→ tools/call {"name":"create_event","arguments":{"title":"Dentist"}}
← {"resultType":"input_required",
"inputRequests":{"when":{"method":"elicitation/create","params":{"mode":"form",
"message":"When should \"Dentist\" start?",
"requestedSchema":{"type":"object",
"properties":{"startsAt":{"type":"string","format":"date-time"}},
"required":["startsAt"]}}}},
"requestState":"eyJ0aXRsZSI6IkRlbnRpc3QifQ=="}serverはrequestを送りませんでした。与えられたrequestに、resultType: "input_required"と、まだ何が必要かのdescriptionを付けて答えたのです。clientは人からanswerを集め、それから元のcallを再送します。新しいidで、inputResponsesを運び、opaqueなrequestStateをそのまま返します。
→ tools/call {"name":"create_event","arguments":{"title":"Dentist"},
"inputResponses":{"when":{"action":"accept",
"content":{"startsAt":"2026-09-10T08:30:00Z"}}},
"requestState":"eyJ0aXRsZSI6IkRlbnRpc3QifQ=="}
← {"resultType":"complete","content":[{"type":"text",
"text":"Created e3: Dentist at 2026-09-10T08:30:00Z"}],"isError":false}これはcurrent revisionで導入されたMulti Round-Trip Requestsで、serverがclientへJSON-RPC requestsを送り返す古いdesignを置き換えました。transport specificationは今、そのruleを平然と述べています。「servers do not initiate JSON-RPC requests and clients do not send JSON-RPC responses」。4 initiativeの方向は1つであり、それはhostに属します。
2つのclient-side featureがそのmechanismに乗っています。そしてそのうち1つは、あなたをつまずかせる名前を持っています。
Elicitationは、serverが人に何かを求めることです。意図的に制限されたJSON Schema、つまりflat objects、primitive properties、no nestingのformで、layout engineなしでもどんなclientでもrenderできます。hard ruleがあります。serverはform modeを使って「passwords, API keys, access tokens, or payment credentials」を求めてはならず、それらにはURL modeを使わなければなりません。URL modeはuserを、clientが決して読まないpageへ送ります。7
Samplingは、serverがhostのmodelにgenerationを求めることです。これにより、serverはAPI keyを保持せずにintelligentになれます。そして語彙上の警告です。この単語はこのcourseではすでに別の意味を持っています。これはChapter 17のsamplingではありません。 ここではtemperature、top-p、probability distributionのshapeについては何も扱っていません。protocolを逆向きに進むnested model callです。
手を伸ばすべきではない理由がもう1つあります。このrevision時点で、samplingはdeprecatedです。rootsとloggingも同様に、SEP-2577の下でdeprecatedになっており、移行案は率直です。「Samplingの代わりにLLM provider APIsと直接統合する」。8 発想がtechnicalに失敗したわけではありません。surface areaを正当化できなかったのです。そして、ものを削除できるprotocolは、削除できないprotocolより健全です。
わざと壊す:connectionsはsessionsではない
セクション「わざと壊す:connectionsはsessionsではない」へのリンクStatelessnessは、testするまではwire-formatの細部に聞こえます。上の3 message exchangeを取り、各messageを別processで実行します。freshなnode calendar.mjs、shared memoryなし、何も引き継ぎません。
process A tools/call (no date) → resultType: input_required
requestState: eyJ0aXRsZSI6IkRlbnRpc3QifQ==
process B tools/call (with the answer, same requestState)
→ resultType: complete
"Created e3: Dentist at 2026-09-10T08:30:00Z"
process C resources/read calendar://week
→ events: 2 (Standup, Design review)Process Bはquestionを一度も見ていないのに、Process Aが始めたmulti-round-trip callを完了しました。これがrequestStateの要点です。continuationはmessage内を移動するので、同じprocessであることに何も依存しません。
Process Cはfailureです。eventは作成されたのに、そこにはありません。toy serverがEVENTSをmodule-level arrayに保持しており、module-level arrayはconnection stateだからです。仕様のnoteは、その誤りを正確に名指ししています。
an open connection, such as a STDIO process, is not a conversation or session: clients may interleave unrelated requests on the same transport, and a server must not treat connection or process identity as a proxy for conversation or session continuity.2
規定された修正はsessionではありません。explicit handleです。creation toolはopaque identifierを返し、以後すべてのcallがそれを普通のargumentとして受け取ります。protocolはそれをまったく概念として持ちません。「wireから見れば、handleはtool result内のordinary stringであり、subsequent tool callsへのordinary argument」です。9 これにより、それを運ぶ責任はmodelに置かれ、serverには、すべてのcallでこのcallerがそれを使ってよいかをvalidateする責任が置かれます。handleはnameであってpermissionではないからです。
serverが何かをする前にかかるcost
セクション「serverが何かをする前にかかるcost」へのリンクserverが公開する各toolは、すべてのrequestであなたのpromptへ入るschemaです。そしてChapter 24は、それがwindowに何をするかを測定しました。MCPは見落としやすい2つ目のline itemを追加するので、上のreference serverで両方を数える価値があります。
13 tool definitions (name + description + inputSchema): 1,307 tokens
cheapest tool, get-tiny-image 52
costliest tool, gzip-file-as-resource 235
server `instructions`, returned by discovery: 312 tokens
------
one server, connected, before it is used: 1,619 tokens観察は2つです。1つ目は算術です。このsizeのserverを5つ接続すると、あなたのwindowの約8,000 tokensが、modelがそれらを使うかどうかに関係なく、毎turn、永久に確保されます。これがChapter 24で引用した150,000から2,000への削減の背後にあるmechanismであり、just-in-time tool discoveryが存在する理由です。
2つ目は、accounting costumeを着たsecurity noteです。instructionsはserver authorが書いたnatural-language textであり、hostのpromptに入ります。その横にあるtool descriptionsも同じです。仕様はsecurity principlesの中で、それにどう対処すべきかを述べています。tool annotationsとdescriptionsは「trusted serverから得たのでない限りuntrustedと見なすべき」であり、hostは「any toolをinvokeする前にexplicit user consentを得なければならない」。1 MCP serverを接続することはdependencyを追加することではありません。見知らぬ相手に、あなたのsystem promptの1,619 tokensと、callされる権利を与えることです。Chapter 30は、その見知らぬ相手がhostileだった場合に起きることです。
日付付きsection:2026-07-28 revisionと、それが壊すもの
セクション「日付付きsection:2026-07-28 revisionと、それが壊すもの」へのリンクこのsectionのすべては、protocol revision 2026-07-28、つまり2026年9月7日に読んだcurrent revisionについて真です。revisionはYYYY-MM-DDでdate付けされ、そのdateはbackwards-incompatible changeが最後に行われた時点です。10 normative documentはTypeScript fileのschema/2026-07-28/schema.tsです。隣にあるJSON Schemaはそこから生成されます。だからこの仕様はTypeScriptとして読まれますし、それ以外のものからMCPを教えることはtranslationを教えることになります。
| What changed | Was | Is now | Breaks |
|---|---|---|---|
| The handshake | initialize + notifications/initialized、connectionごとに1回 | removed。すべてのrequestが_meta versionとcapabilitiesを持つ | このrevision以前に書かれたすべてのclient |
| Sessions | Mcp-Session-Id header、connection-scoped state | removed。stateはexplicitなserver-minted handlesで移動する | connectionごとに変わっていたlist endpoints |
| Discovery | initialize resultから推論 | server/discover。serverは実装must | 何も壊さないが、実装はmandatoryになった |
| Server-to-client calls | serverがroots/list、sampling/createMessage、elicitation/createを送った | InputRequiredResultとclient retry | clientへrequestをpushしていたすべてのserver |
| Result shape | any object | required resultType: "complete"または"input_required" | 何も壊さない。field不在は"complete"として読む必要がある |
| Subscriptions | HTTP GET stream、resources/subscribe | opt-in typesを持つ1つのsubscriptions/listen stream | GET endpointは消えた |
| Stream resumption | Streamable HTTP上のLast-Event-ID replay | removed。壊れたstreamはrequestを失う。新しいidで再発行 | redeliveryに依存していたclient |
| Roots | serverが要求できるclient feature | deprecated (SEP-2577)。pathsはtool argumentsまたはresource URIsとして渡す | まだ何も壊さない — 12か月window |
| Sampling and logging | client features | deprecated (SEP-2577) | まだ何も壊さない — 12か月window |
| HTTP+SSE transport | 2025-03-26以来deprecated | lifecycle policy (SEP-2596)の下でDeprecated | Streamable HTTPへ移行 |
| Client registration | OAuth 2.0 Dynamic Client Registration、RFC 7591 | Client ID Metadata Documentsを優先してdeprecated | それらを持たないauthorization servers向けに維持 |
| Error codes | resource not foundには-32002 | -32602。-32020–-32099はspec用にreserved | new codes -32020、-32021、-32022 |
このtableの下にあるgovernance changeは、どの1行よりも重要です。このrevisionはfeature lifecycle and deprecation policyを採用しました。featuresはActive、Deprecated、Removedのいずれかで、deprecated featureはmigration pathをdocumentし、removalの対象になり得るまで少なくとも12か月は仕様に残ります。そして現在Deprecated stateにあるすべてをlistするregistryがあります。8 そのpolicy以前、AI protocolにおける「deprecated」は、最後のblog postが言ったことを意味していました。今はdateを意味します。
詳細を表示
Extensions。まだ誰も書いていない部分です。
coreの外で、MCPはoptionalなextensionsを定義します。これは「always opt-in and require explicit support from both client and server」であり、clientとserverのcapabilities内のextensions fieldでdeclareされます。1 名前で知っておく価値があるものが3つあります。
- Tasks (
io.modelcontextprotocol/tasks)。このrevisionでcore protocolからofficial extensionへ移されました。long-running operationsのasynchronous executionで、tasks/getによるpolling、tasks/updateによるmid-flight input、durable handlesを持ちます。20分かかるtoolへの答えであり、Chapter 23ではprogress eventとtoolへ届くsignalで扱ったものです。 - Skills over MCP。agent skills、つまりChapter 28の主題を、protocolを通してdiscoverableかつconsumableにするworking groupです。
- MCP Apps。conversation内にinlineでrenderされるinteractive UIです。charts、forms、video playersです。
そして、今「negotiated」が何を意味するかに注意してください。negotiationするinitializationは存在しないので、extensionも他のすべてと同じくrequestごとにdeclareされます。
MCPは、混同されがちなもの全体の中でどこに位置するか
セクション「MCPは、混同されがちなもの全体の中でどこに位置するか」へのリンクこのblock全体の語彙を1か所にまとめます。
| What it is | Who talks to whom | When it is the answer | |
|---|---|---|---|
| A plain API | programのためのinterface | あなたのcode ↔ service | callerを書いているのはあなたです。schema、auth、error handlingをあなたがcontrolし、解くべきdiscovery problemがありません。 |
| MCP | tools、data、templatesをAI applicationへ公開するprotocol | host ↔ server、各serverにclientが1つ | capabilityを書いたのは誰か別の人で、多くのhostがbespoke integrationなしでそれを使えるべき場合。 |
| RAG | textを探してpromptへ入れるtechnique | あなたのcode ↔ あなたのindex | modelが何かを知る必要がある場合。Chapter 19。MCPはretrieverを届ける方法になり得ますが、retrieverではありません。 |
| Agent skills | modelが読むSKILL.mdを持つfolder | model ↔ document | knowledgeがprocedural、つまり私たちはこれをどう行うかであり、functionではなくproseである場合。Chapter 28。 |
| A2A | agentsがpeerとしてcollaborateするprotocol | agent ↔ agent | 相手側がcallに答えるだけでなく、reasonし、planし、長いtaskの間stateを保持する場合。 |
| ACP | かつて別個のagent-communication protocolだったもの | — | もはやlive comparisonではありません。下を参照。 |
このうち2つは、それぞれ一文が必要です。実際の混乱はそこにあるからです。
MCP against A2Aはrivalryではありません。両方の仕様がそう述べています。A2A documentationは、向こう側に何があるかで線を引きます。MCPは「AI agentがdatabaseやAPIのようなindividual tools and resourcesとどうinteractし、utilizeするか」を定義し、toolは「specific, often stateless, functions」を実行します。一方、A2Aはagents、「more autonomous systems」を対象にします。それらは「reason, plan, use multiple tools, maintain state over longer interactions, and engage in complex, often multi-turn dialogues」します。覚えるべき要約は仕様自身の文です。「A2A is about agents partnering on tasks, while MCP is more about agents using capabilities。」11 2つは入れ子になります。applicationはA2Aを使って他のagentsに到達し、各agentはMCPを使って自分のtoolsに到達します。Chapter 25は、sub-agentに尋ねることとconversationを渡すことの間に、その線を1つのprocess内で引きました。A2Aはそれを組織間で引きます。
MCP against ACPは、古い前提に対する比較です。だからこそ答える価値があります。Agent Communication Protocolは、agent-to-agent messagingのための別個のopen standardでした。そのdocumentationは現在、「ACP is now part of A2A under the Linux Foundation!」というnoticeで始まります。12 2026年9月に「MCP or ACP?」と聞かれたときの正直な答えは、検索上位のpageが示すより選択肢が1つ少ない、というものです。
そして最もよく求められる比較、mcp vs apiには、いちばん面白みのない答えしかありません。MCP is an API. それが加えるのはpowerではなく、conventionsです。固定されたmethod nameの集合、discovery call、primitives上のcontrol hierarchy、isolation modelです。自分のinterfaceをdesignする自由を手放し、そのprotocolを話すすべてのhostを得ます。これは、すべてのprotocolがこれまで提示してきたtradeです。
次に進む先
セクション「次に進む先」へのリンクこれで、translatorなしに仕様を読めるようになりました。resource、tool、promptを誰が主導権を持つかで見分けられます。client libraryが嘘をついているときにrequestを手で入力できます。そして、読んでいるMCP記事が、deprecated featuresのどれをまだcurrentとして教えているかで日付を付けられます。
まだやっていないのは、1つshipすることです。Chapter 27では同じserverを2回書きます。TypeScriptとPythonを横並びで書きます。MCPはこのcourseで唯一、本当にbilingualな領域であり、数も両方向でそう示しているからです。2つのlive transports、inspector、packaging、そしてこの章が意図的に残したprotocolの半分、つまりauthorizationをきちんと扱います。なぜなら、あなたのserverが自分のlaptop上のsubprocessではなくremoteになった瞬間、見知らぬclientがtokenを提示し、そのtokenで何をしてよいかについての仕様のruleは異例に厳しいからです。
そこで次章が答えなければならない問いが立ち上がります。しかもそれはfriendlyな問いではありません。あなたのserverにtokenが到着し、それが誰か別のaudience向けに発行されたものだった場合、あなたがそれをforwardするのを正確に何が止めるのでしょうか?
Sources and method
セクション「Sources and method」へのリンクこの章のすべてのquotation、method name、error code、ruleは、Model Context Protocol specification、revision 2026-07-28を、2026年9月7日に読んだものです。すべてのtraceはNode 22上でlocalに生成しました。toy calendar serverはdependencyなしの101行で、reference serverは下に名を挙げるpublished npm packageです。この章を書くためにpaid APIは呼んでいません。ここにはmodelを必要とするものは何もありません。それ自体が要点です。
測定:@modelcontextprotocol/server-everything@2026.8.31、2026年8月31日公開。@modelcontextprotocol/sdk@1.30.0上に構築され、これは2026年7月27日公開、つまりこの章が説明するrevisionの1日前です。server/discoverに-32601で答え、2026-07-28を要求されると2025-11-25をnegotiateし、handshakeなしでtools/listをserveします。そのcatalogueは13 tools、7,663 bytesです。token countsは、各definitionのname、description、inputSchemaについて、tiktoken経由のo200k_baseです。これはproviderがあなたのpromptへrenderするものであり、JSON-RPC frameの重さではありません。
Anthropic, Code execution with MCP: building more efficient agents, 2025年11月4日が、150,000-to-2,000という数字の出典です。Chapter 24で引用・使用しており、ここでは参照するだけです。
参考文献
セクション「参考文献」へのリンク-
Specification,
modelcontextprotocol.io/specification/latest(/2026-07-28へredirect), 2026年9月7日閲読。Language Server Protocol comparisonの出典。仕様が「schema.ts内のTypeScript schemaに基づく」とするstatementの出典。base-protocol summary(「Stateless, self-contained requests」「Per-request capability negotiation」)、extension list(Tasks、Skills over MCP、MCP Apps)と、extensionsが「are always opt-in and require explicit support from both client and server」であるstatement、さらにSecurity and Trust & Safety principlesの出典。これには「Hosts must obtain explicit user consent before invoking any tool」およびtool annotationsをuntrustedとして扱うことが含まれます。 ↩ ↩2 ↩3 -
Base Protocol,
modelcontextprotocol.io/specification/2026-07-28/basic。JSON-RPC constraints(non-null id、id reuse禁止、requiredresultType)、Statelessness sectionと、open stdio processはsessionではないというnote、_metareserved-key tableとper-request fieldそれぞれのrequired/optional status、missing required fieldに対する-32602rule、MissingRequiredClientCapability(-32021) rule、error-code allocation policyの出典。 ↩ ↩2 ↩3 ↩4 ↩5 -
stdio transport,
modelcontextprotocol.io/specification/2026-07-28/basic/transports/stdio。newline-delimited framing rules、stdoutpurity requirement、stderrallowance、3 outcome backward-compatibility probeの出典。handshakeなしでera-ambiguous methodsを処理するlegacy serversがあるというwarningも含み、この章のmeasurementはそれを再現しています。 ↩ ↩2 ↩3 -
Transports overview,
modelcontextprotocol.io/specification/2026-07-28/basic/transports。「transport is a binding」というframing、およびservers do not initiate JSON-RPC requests and clients do not send JSON-RPC responsesというstatementの出典。 ↩ ↩2 -
Discovery,
modelcontextprotocol.io/specification/2026-07-28/server/discover。server/discoverのmandatory status、DiscoverResultのshape、instructionsfieldが「optional natural-language guidance for LLMs on how to use this server effectively」と説明されることの出典。 ↩ -
Architecture,
modelcontextprotocol.io/specification/2026-07-28/architecture。host/client/server definitions、1:1 client-to-server rule、4つのdesign principlesの出典。ここではisolation principleを、その5番目のbullet「Host process enforces security boundaries」なしで引用しています。またcapability-negotiation sectionの出典です。 ↩ ↩2 -
Elicitation,
.../client/elicitation、およびSampling,.../client/sampling。2つのelicitation modesとそのrestricted schema、form modeを通じたcredentials要求のprohibition、sampling definition、そのhuman-in-the-loop requirement、およびそれに付いたdeprecation warningの出典。 ↩ -
Key Changes,
modelcontextprotocol.io/specification/2026-07-28/changelog、およびFeature lifecycle and deprecation policy,.../community/feature-lifecycle。change tableのすべての行の出典。sessionsとMcp-Session-Idheaderのremoval(SEP-2567)、statelessnessとinitializeのremoval(SEP-2575)、server/discover(SEP-2575)、subscriptions/listen(SEP-2575)、Multi Round-Trip RequestsとresultType(SEP-2322)、stream resumabilityのremoval(SEP-2575)、Roots、Sampling、Loggingのdeprecation(SEP-2577)、HTTP+SSEのreclassification(SEP-2596)、Client ID Metadata Documentsを優先するDynamic Client Registrationのdeprecation、error-code renumbering、12か月deprecation windowです。 ↩ ↩2 -
Tools,
modelcontextprotocol.io/specification/2026-07-28/server/tools、およびServer Features,.../server。上に再掲したcontrol-hierarchy table、tools/listとtools/callのshapes、protocol errorsとtool execution errorsのisErrordistinction、tool-name rulesと「prefixing tool names with a server identifier」を推奨するnamespace note、そしてexplicit handlesに関するnon-normativeな「Stateful Tools」guidanceの出典。 ↩ -
Versioning,
modelcontextprotocol.io/specification/versioning。YYYY-MM-DDscheme、Draft/Current/Final revision states、2026-07-28がcurrentである確認、per-request negotiation rulesの出典。modelcontextprotocol.io/docs/sdkのSDK tier tableは、TypeScript、Python、C#、Go、RustをTier 1、JavaとRubyをTier 2、Swift、PHP、KotlinをTier 3としてlistしています。 ↩ -
A2A Protocol, version 1.0.0,
a2a-protocol.org— specificationおよびpage A2A and MCP: Relationship and Distinction, 2026年9月7日閲読。tools-against-agents distinction、2つのprotocolが「address distinct but highly complementary needs」であるstatement、partnering/using formulationの出典。 ↩ -
Agent Communication Protocol,
agentcommunicationprotocol.dev, 2026年9月7日閲読:「ACP is now part of A2A under the Linux Foundation!」。これは、architecture、agent manifest、agent discovery、message structure、stateful agents、run lifecycle、REST endpoint listまで丸ごとまだ200を返すspecificationの上に追加されたbannerです。specificationが消えたのではありません。projectが消えたのです。 ↩