MCP за специфікацією: що насправді є сервером
Один рядок JSON у subprocess — і 13 визначень інструментів у відповідь за редакцією 2026-07-28 без handshake.
На цій сторінці
Встановіть опублікований MCP сервер, надішліть йому один рядок JSON і прочитайте, що повернеться.
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}Тринадцять визначень інструментів, в одному рядку, від процесу, який прочитав один рядок зі свого стандартного вводу. Ви щойно говорили Model Context Protocol — без SDK, без клієнтської бібліотеки й без фреймворку. Ось і все: transport, формат повідомлень і невеликий набір іменованих методів.
Розділ 18 визначив інструмент як дві речі — JSON Schema, яку бачить модель, і endpoint у вашому коді, якого модель ніколи не бачить. Розділ 23 побудував harness, який тримає їхній каталог. Жоден із них не відповів на питання, від якого залежить, чи можна все це повторно використовувати: хто пише схему, і як вона потрапляє від автора у ваш prompt? MCP — одна з відповідей на це питання, і її варто читати в оригіналі, бо майже все, що про неї написано, описує редакцію, якої вже не існує.
У команді, яку ви щойно запустили, неправильними були три речі, і кожна з них — окремий розділ цього розділу. У ній не було версії протоколу, тож conformant сервер мав би її відхилити. Вона все одно отримала відповідь — із причини, яку специфікація називає небезпекою, а не feature. І вона попросила один із трьох примітивів, так і не дізнавшись, що існують ще два.
Проблема, яку він розвʼязує, і аналогія, яку наводить сама специфікація
Посилання на розділ: Проблема, яку він розвʼязує, і аналогія, яку наводить сама специфікаціяПеред wire — арифметика. У вас є AI застосунків і речей, до яких вони мають мати доступ: календар, трекер тікетів, база даних складу, інструмент дизайну. Без спільного контракту хтось пише інтеграцій, і кожна з них — це схема плюс endpoint плюс історія автентифікації плюс тягар підтримки. З контрактом постачальник інструмента пише сервер, постачальник застосунку пише клієнт, і загалом виходить .
Це не нове спостереження, і специфікація каже, чия це була ідея:
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
Сприймайте це порівняння буквально, а не як комплімент. До цього протоколу підтримка мови в редакторі означала plugin для кожного редактора; після нього команда мови випускала один сервер, і кожен редактор його отримував. Мірою успіху була не елегантність, а те, що кількість інтеграцій перестала множитися. Те саме випливає і тут: цінність — у кількості реалізацій, а не в дизайні. Протокол, яким говорять два продукти, — це формат даних із додатковою церемонією.
Що насправді йде по wire
Посилання на розділ: Що насправді йде по wireПовідомлення MCP — це JSON-RPC 2.0. Запит — це обʼєкт із jsonrpc, id, method та необовʼязковим params; відповідь несе той самий id і або result, або error; notification — це запит без id, і відповіді на нього немає. Специфікація додає зверху три обмеження: id має бути рядком або числом і не може бути null, він не має збігатися з іншим запитом, який ще виконується, і кожен result має містити поле resultType.2
На stdio transport — тому, який використала команда вище, — правило framing таке: один рядок на повідомлення:
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
Останній пункт — найпоширеніший спосіб, яким саморобний сервер ламається, і ламається тихо: випадковий console.log, індикатор прогресу, deprecation warning від залежності — і line parser клієнта натрапляє на щось, що не є JSON. Запасний вихід є в тому самому розділі: сервер може писати що завгодно в stderr, а клієнт не повинен вважати це помилкою. Reference server вище друкує Starting default (STDIO) server... при кожному запуску, у stderr, тому pipe усе одно спрацював.
Інший стандартний transport — Streamable HTTP: кожне повідомлення є POST до одного endpoint, а відповідь — або JSON-обʼєкт, або привʼязаний до запиту stream Server-Sent Events — wire format, який Розділ 14 розбирав вручну. Семантика в обох випадках однакова, бо transport — це binding: він визначає framing і доставку, а не значення.4
Перше, що було неправильним: версії не було
Посилання на розділ: Перше, що було неправильним: версії не булоКоманда вище надіслала tools/list і нічого більше. За поточною редакцією цей запит malformed, і conformant сервер має його відхилити.
Від 2026-07-28 MCP є stateless протоколом, і специфікація формулює це без застережень:
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
Тому кожен запит несе власну версію протоколу і власні client capabilities у зарезервованому обʼєкті _meta всередині params. Два з цих полів обовʼязкові в кожному окремому запиті; запит без будь-якого з них є malformed, і сервер мусить відповісти -32602:2
ключ _meta | обовʼязковий | що це |
|---|---|---|
io.modelcontextprotocol/protocolVersion | так | редакція, якою говорить цей запит, наприклад "2026-07-28" |
io.modelcontextprotocol/clientCapabilities | так | що клієнт може робити для сервера в цьому запиті |
io.modelcontextprotocol/clientInfo | ні (але should) | назва й версія клієнта, лише для відображення і логів |
io.modelcontextprotocol/logLevel | ні | мінімальний рівень логування, який сервер має emit для цього запиту |
У повному вигляді правильний tools/list такий — і це востаннє в цьому розділі metadata показано повністю, бо далі вона є в кожному запиті:
{"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"}}}}Обʼєкт capabilities і є negotiation. Окремого кроку negotiation більше немає: клієнт оголошує, що він може робити, у кожному запиті, сервер оголошує, що може робити, у result, і жодна сторона не може використати feature, яку інша не заявила. Сервер, якому потрібна capability, не заявлена клієнтом, мусить відповісти -32021 і назвати відсутню capability в data.requiredCapabilities. Сервер, який не говорить запитаною версією, мусить відповісти -32022 і перелічити версії, якими він говорить.2
Клієнти, які хочуть отримати відповідь наперед, можуть її попросити: server/discover — mandatory RPC, що за один round trip повертає підтримувані версії, capabilities, identity і необовʼязковий блок instructions.5 Викликати його необовʼязково. Реалізувати — обовʼязково.
Друге, що було неправильним: сервер був legacy
Посилання на розділ: Друге, що було неправильним: сервер був legacyКоманда спрацювала. За поточною редакцією вона не мала спрацювати, і причина варта не абзацу, а вимірювання, бо це стан усієї екосистеми в одному рядку.
Перевірте reference server так, як специфікація каже перевіряти modern клієнту:
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"}}Це третя гілка правила сумісності: DiscoverResult означає modern, розпізнана modern помилка означає modern-but-wrong-version, а будь-що інше — включно з -32601 — означає legacy, fallback до handshake initialize.3 Тож зробіть це, попросивши поточну редакцію:
→ {"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":"…"}}Клієнт попросив 2026-07-28, а сервер відповів 2025-11-25. 7 вересня 2026 року офіційний reference server — npm package @modelcontextprotocol/server-everything, версія 2026.8.31, опублікований 31 серпня 2026 року — не реалізує поточну редакцію. Так само, за датами, не реалізує її і TypeScript SDK, на якому він побудований: release 1.30.0 вийшов 27 липня 2026 року, за день до редакції.
Читайте наслідок, а не плітку. Майже все, що написано про MCP, описує протокол із handshake initialize, session, запитом roots/list, який сервер надсилає клієнту, і HTTP+SSE transport. Усі чотири речі вже зникли або зникають. Коли ви читаєте щось про MCP, включно з цією сторінкою, перше, що слід шукати, — номер редакції.
А причина, з якої найперша команда спрацювала, у специфікації названа hazard, а не feature:
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
Виміряно: надсилання tools/list цьому серверу без жодного handshake повертає повний каталог. Метод, який мав бути відхилений, був оброблений — саме тому специфікація каже спершу probe через server/discover, навіть якщо ви підтримуєте лише modern версії.
Три ролі й речення, яке варто цитувати з усього документа
Посилання на розділ: Три ролі й речення, яке варто цитувати з усього документаУ MCP є три сторони, і різницю між першими двома люди найчастіше стирають:
Host. Застосунок: chat-продукт, редактор, agent. Він володіє розмовою, моделлю, credentials і згодою користувача. Він створює клієнтів і забезпечує security boundary між ними.
Client. Connector всередині host. Кожен client говорить рівно з одним сервером — суворе відношення 1:1 — і додає версію протоколу та capabilities до кожного запиту, який routing.
Server. Процес або сервіс, який exposes resources, tools і prompts. Він може бути local або remote, працює незалежно, і вся його робота — одна сфокусована область.6
Правило «рівно один сервер» — не бухгалтерія. Саме воно робить наведений нижче 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, з яким приходить більшість людей. Weather server, який ви підключаєте до свого assistant, не бачить, що ви запитали. Він бачить tools/call з аргументами, які вибрала модель, і нічого більше — ні попередніх turns, ні вашого system prompt, ні result, який calendar server повернув хвилину тому. Якщо двом серверам треба співпрацювати, host переносить значення від одного до іншого — навмисно, бо модель попросила. Ось чому isolation — це security property, на яку спирається Розділ 30: compromised сервер має малий, визначений blast radius, а його розширення вимагає співпраці host.
Третє: три примітиви, відсортовані за тим, хто керує
Посилання на розділ: Третє: три примітиви, відсортовані за тим, хто керуєПерша команда попросила в того сервера tools і отримала тринадцять. Поставте йому два інші питання, і він відповість також: resources/list повертає сім, prompts/list повертає чотири. Жодні з них не зʼявилися, бо ніхто не попросив. І це приводить нас до педагогічного хребта MCP — таблиці в специфікації, яку майже ніхто не цитує:
| Primitive | Control | Description | Example |
|---|---|---|---|
| Prompts | User-controlled | Інтерактивні templates, invoked за вибором користувача | Slash commands, параметри меню |
| Resources | Application-controlled | Контекстні дані, attached і керовані клієнтом | Вміст файлів, git history |
| Tools | Model-controlled | Функції, exposed для LLM, щоб виконувати дії | API POST requests, запис файлів |
Не «три способи expose capability». А три відповіді на питання хто вирішує, що це станеться. Модель вирішує call tool. Застосунок вирішує attach resource. Людина вирішує run prompt. Помиліться тут — і feature все ще працюватиме, але в неправильний момент і з неправильної причини.
Найпростіше відчути це на календарі. Ось сервер, який exposes той самий календар тричі, по одному разу як кожен primitive, у сотні рядків простого Node без dependencies:
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" });
}Запустіть його і запитайте всіма трьома способами. Справжній output, одне повідомлення на рядок на wire, тут перенесено для сторінки; request _meta і 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}Три методи, три форми, один календар. Тепер суть:
Читання тижня — це resource
Посилання на розділ: Читання тижня — це resourceВін адресується URI, він inert, і застосунок вирішує, чи attached його до розмови. Ніщо в протоколі не дозволяє моделі дотягнутися до нього самостійно. Result несе ttlMs і cacheScope, нові в цій редакції, щоб клієнт міг cache тиждень на хвилину замість polling.
Створення події — це tool
Посилання на розділ: Створення події — це toolВін має schema, має side effects, і модель вирішує, коли його call. Його result несе isError — поле, за яке виступав Розділ 18: validation failure повертається як tool result, який модель може прочитати й виправити, а не як protocol error.
«Підготуй мій тиждень» — це prompt
Посилання на розділ: «Підготуй мій тиждень» — це promptЦе іменований template з аргументами, який людина invokes — slash command у меню. Він повертає messages, а не відповідь. Це спосіб для автора сервера доставити формулювання, яке працює з його власними tools, тобто саме те знання, яке має автор сервера і якого не має користувач.
Майже всі роблять усі три речі tools. У результаті виходить каталог, де read, який застосунок мав би мовчки attach, конкурує за attention моделі з write, який потребує approval, а єдина річ, для якої людина хотіла кнопку, похована в schema. Правильно зробити це нічого не коштує, і це вирішується до того, як ви напишете рядок.
Сервер не може call you
Посилання на розділ: Сервер не може call youCalendar tool має один обовʼязковий argument, title, і необовʼязковий startsAt. Попросіть його створити подію без дати, і повернеться цікава річ:
→ 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=="}Сервер не надіслав request. Він відповів на той, який отримав, із resultType: "input_required" і описом того, що йому ще потрібно. Клієнт збирає відповідь від людини, а потім повторно надсилає original call — з новим id, несучи inputResponses і echoing 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}Це Multi Round-Trip Requests, introduced у поточній редакції, і воно замінило старіший design, де сервери надсилали JSON-RPC requests назад клієнтам. Специфікація transport тепер формулює правило прямо: «servers do not initiate JSON-RPC requests and clients do not send JSON-RPC responses».4 Є один напрям initiative, і він належить host.
Дві client-side features їдуть на цьому механізмі, і одна з них має назву, яка вас підловить.
Elicitation — це коли сервер просить людину про щось: форму з навмисно обмеженою JSON Schema — flat objects, primitive properties, без nesting — щоб будь-який клієнт міг її render без layout engine. Вона несе жорстке правило: сервери must not використовувати form mode, щоб запитувати «passwords, API keys, access tokens, or payment credentials», і must використовувати URL mode для таких речей, що відправляє користувача на сторінку, яку клієнт ніколи не читає.7
Sampling — це коли сервер просить модель host зробити generation, щоб сервер міг бути intelligent без власного API key. І ось попередження щодо словника, бо це слово вже означає щось інше в цьому курсі: це не sampling із Розділу 17. Тут нічого не про temperature, top-p чи форму probability distribution. Це вкладений model call, який рухається назад через протокол.
Є й друга причина не хапатися за нього: станом на цю редакцію sampling deprecated, разом із roots і logging, у межах SEP-2577, із прямою suggested migration — «integrate directly with LLM provider APIs instead of Sampling».8 Ідея не провалилася технічно; вона не змогла виправдати свою surface area, а протокол, який може видаляти речі, здоровіший за той, який не може.
Зламайте це навмисно: connections — не sessions
Посилання на розділ: Зламайте це навмисно: connections — не sessionsStatelessness звучить як деталь wire format, доки ви її не протестуєте. Візьміть наведений вище обмін із трьох повідомлень і запустіть кожне повідомлення в окремому процесі — свіжий 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, який ніколи не бачив питання, completed multi-round-trip call, який почав process A. У цьому й сенс requestState: continuation подорожує в повідомленні, тож ніщо не залежить від того, чи це той самий процес.
Process C — це failure. Подію було створено, а її там немає — бо 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. Протокол узагалі не має про нього поняття — «from the wire's perspective a handle is an ordinary string in a tool result and an ordinary argument to subsequent tool calls».9 Це ставить модель відповідальною за його перенесення, а сервер — за перевірку, що цей caller має право ним користуватися в кожному окремому call, бо handle — це імʼя, а не permission.
Скільки сервер коштує, перш ніж щось зробить
Посилання на розділ: Скільки сервер коштує, перш ніж щось зробитьКожен tool, який exposes сервер, — це schema, що йде у ваш prompt у кожному запиті, і Розділ 24 виміряв, що це робить із window. MCP додає другу 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Два спостереження. Перше — арифметичне: підключіть пʼять серверів такого розміру, і приблизно вісім тисяч tokens вашого window будуть зайняті на кожному turn, назавжди, незалежно від того, чи модель використає хоч один із них. Саме цей механізм стоїть за скороченням 150 000 до 2 000, яке цитував Розділ 24, і саме тому існує just-in-time tool discovery.
Друге — security note в костюмі бухгалтерії. instructions — це natural-language text, written by the server author, that lands in the host's prompt, і tool descriptions поруч із ним — те саме. Специфікація каже, що з цим робити, у власних security principles: tool annotations and descriptions «should be considered untrusted, unless obtained from a trusted server», а hosts «must obtain explicit user consent before invoking any tool».1 Підключити MCP сервер — не те саме, що додати dependency. Це дати незнайомцю 1 619 tokens вашого system prompt і право бути called. Розділ 30 — про те, що стається, коли цей незнайомець hostile.
Датований розділ: редакція 2026-07-28 і що вона ламає
Посилання на розділ: Датований розділ: редакція 2026-07-28 і що вона ламаєУсе в цьому розділі істинне для редакції протоколу 2026-07-28, поточної на 7 вересня 2026 року. Редакції датуються YYYY-MM-DD, і дата — це останній раз, коли було зроблено backwards-incompatible change.10 Нормативний документ — TypeScript file, schema/2026-07-28/schema.ts; JSON Schema поруч із ним generated із нього, тому специфікацію тут читають у TypeScript, і тому навчати MCP з будь-чого іншого означає навчати перекладу.
| Що змінилося | Було | Тепер | Ламає |
|---|---|---|---|
| Handshake | initialize + notifications/initialized, once per connection | removed; кожен request carries _meta version і capabilities | кожен client, написаний до цієї редакції |
| Sessions | header Mcp-Session-Id, connection-scoped state | removed; state travels in explicit, server-minted handles | list endpoints, які varied per connection |
| Discovery | inferred from result initialize | server/discover, який servers must implement | нічого, але тепер це mandatory to implement |
| Server-to-client calls | server sent roots/list, sampling/createMessage, elicitation/create | InputRequiredResult і client retry | кожен server, який pushed request at a client |
| Result shape | будь-який object | required resultType: "complete" або "input_required" | нічого: absent field must be read as "complete" |
| Subscriptions | HTTP GET stream, resources/subscribe | one subscriptions/listen stream with opt-in types | GET endpoint зник |
| Stream resumption | replay Last-Event-ID on Streamable HTTP | removed; broken stream loses the request, re-issue with a new id | clients, які relied on redelivery |
| Roots | client feature, яку servers could ask for | deprecated (SEP-2577); pass paths as tool arguments or resource URIs | поки нічого — twelve-month window |
| Sampling and logging | client features | deprecated (SEP-2577) | поки нічого — twelve-month window |
| HTTP+SSE transport | deprecated since 2025-03-26 | Deprecated under the lifecycle policy (SEP-2596) | migrate to Streamable HTTP |
| Client registration | OAuth 2.0 Dynamic Client Registration, RFC 7591 | deprecated in favour of Client ID Metadata Documents | kept for authorization servers without them |
| Error codes | -32002 for resource not found | -32602; -32020–-32099 reserved for the spec | new codes -32020, -32021, -32022 |
Governance change під цією таблицею важливіша за будь-який окремий рядок. Ця редакція adopted feature lifecycle and deprecation policy: features бувають Active, Deprecated або Removed; deprecated feature documents migration path і залишається в специфікації щонайменше twelve months, перш ніж стає eligible for removal; і є registry, що перелічує все, що зараз у стані Deprecated.8 До цієї політики «deprecated» в AI протоколі означало те, що сказав останній blog post. Тепер це означає дату.
Показати подробиці
Extensions — частина, про яку ще майже ніхто не писав.
Поза core MCP визначає optional extensions — «always opt-in and require explicit support from both client and server», declared через поле extensions у capabilities клієнта і сервера.1 Три варто знати за назвою:
- Tasks (
io.modelcontextprotocol/tasks), moved out of the core protocol into an official extension in this revision: asynchronous execution of long-running operations, with polling throughtasks/get, mid-flight input throughtasks/update, and durable handles. Це відповідь на tool, який триває двадцять хвилин, що Розділ 23 обробляв через progress event і signal, який доходить до tool. - Skills over MCP, working group, що робить agent skills — тему Розділу 28 — discoverable and consumable через протокол.
- MCP Apps, інтерактивний UI, rendered inline in the conversation: charts, forms, video players.
І зверніть увагу, що тепер означає «negotiated»: initialization, у якому можна було б negotiate, немає, тож extension declared per request, як і все інше.
Де MCP стоїть відносно всього, з чим його плутають
Посилання на розділ: Де MCP стоїть відносно всього, з чим його плутаютьОсь словник усього блоку в одному місці.
| Що це | Хто з ким говорить | Коли це відповідь | |
|---|---|---|---|
| Звичайний API | Interface для програми | ваш код ↔ сервіс | Ви пишете caller. Ви control schema, auth і error handling, і немає discovery problem, яку треба розвʼязувати. |
| MCP | Протокол для exposing tools, data і templates to an AI application | host ↔ server, one client each | Хтось інший написав capability, і many hosts should be able to use it without a bespoke integration. |
| RAG | Техніка для пошуку тексту і розміщення його в prompt | ваш код ↔ ваш index | Моделі треба знати щось. Розділ 19. MCP — спосіб доставити retriever; він не є retriever. |
| Agent skills | Папка з SKILL.md, яку модель reads | model ↔ document | Knowledge is procedural — how we do this — і це prose, not a function. Розділ 28. |
| A2A | Протокол, за яким agents collaborate as peers | agent ↔ agent | Інша сторона reasons, plans and holds state across a long task, rather than answering a call. |
| ACP | Був окремим agent-communication protocol | — | Це вже не live comparison. Див. нижче. |
Два з них заслуговують на речення кожен, бо саме там і живе плутанина.
MCP проти A2A — не rivalry, і обидві специфікації так кажуть. Документація A2A проводить межу за тим, що на іншому кінці: MCP «defines how an AI agent interacts with and utilizes individual tools and resources, such as a database or an API», де 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 Вони вкладаються один в одного: application використовує A2A, щоб дістатися інших agents, а кожен agent використовує MCP, щоб дістатися власних tools. Розділ 25 провів цю межу всередині одного process — між тим, щоб asking a sub-agent, і тим, щоб handing it the conversation; A2A проводить її між organizations.
MCP проти ACP — це comparison зі stale premise, і саме тому на нього варто відповісти. Agent Communication Protocol був окремим open standard for agent-to-agent messaging. Його власна документація тепер починається з notice: «ACP is now part of A2A under the Linux Foundation!»12 Чесна відповідь на «MCP or ACP?» у вересні 2026 року така: у питання на одну опцію менше, ніж припускають сторінки, що ранжуються за ним.
А comparison, про який питають найчастіше, mcp vs api, має найменш цікаву відповідь: MCP — це API. Те, що він додає, — не power, а conventions: fixed set of method names, discovery call, control hierarchy over the primitives і isolation model. Ви відмовляєтеся від свободи designed your own interface і отримуєте every host that speaks the protocol — trade, який завжди пропонував кожен protocol.
Куди це веде далі
Посилання на розділ: Куди це веде даліТепер ви можете читати специфікацію без перекладача, відрізняти resource від tool від prompt за тим, хто ним керує, набрати request вручну, коли client library вам бреше, і датувати будь-яку статтю про MCP за тим, які deprecated features вона все ще подає як current.
Чого ви ще не зробили — так це не ship one. Розділ 27 пише той самий сервер двічі — TypeScript і Python поруч, бо MCP є єдиною genuinely bilingual територією в цьому курсі, і numbers say so в обидва боки. Він нормально покриває два live transports, inspector, packaging і половину протоколу, яку цей розділ навмисно залишив осторонь: authorization. Бо щойно ваш сервер стає remote, а не subprocess на вашому власному laptop, клієнт незнайомця принесе token, і правило специфікації про те, що ви можете з ним робити, незвично суворе.
Це піднімає питання, на яке має відповісти наступний розділ, і воно не дружнє: якщо token приходить на ваш server і був issued для чиєїсь іншої audience, що саме заважає вам forwarded його?
Джерела й метод
Посилання на розділ: Джерела й методКожну цитату, назву методу, error code і rule у цьому розділі прочитано зі специфікації Model Context Protocol, редакція 2026-07-28, 7 вересня 2026 року. Кожен trace produced локально на Node 22: toy calendar server має 101 рядок без dependencies, а reference server — це опублікований npm package, названий нижче. Для написання цього розділу не викликали жодного paid API — нічому тут не потрібна модель, і саме це є суттю.
Вимірювання: @modelcontextprotocol/server-everything@2026.8.31, published 31 August 2026, built on @modelcontextprotocol/sdk@1.30.0, published 27 July 2026 — one day before the revision this chapter describes. It answers server/discover with -32601, negotiates 2025-11-25 when asked for 2026-07-28, and serves tools/list with no handshake at all. Its catalogue is 13 tools in 7,663 bytes; token counts are o200k_base via tiktoken, over the name, description and inputSchema of each definition, which is what a provider renders into your prompt and not what the JSON-RPC frame weighs.
Anthropic, Code execution with MCP: building more efficient agents, 4 November 2025, is the source of the 150,000-to-2,000 figure, quoted and used in Chapter 24 and only referenced here.
Примітки
Посилання на розділ: Примітки-
Specification,
modelcontextprotocol.io/specification/latest(redirecting to/2026-07-28), прочитано 7 вересня 2026 року. Джерело порівняння з Language Server Protocol; твердження, що специфікація «based on the TypeScript schema inschema.ts»; summary base protocol («Stateless, self-contained requests», «Per-request capability negotiation»); списку extensions (Tasks, Skills over MCP, MCP Apps) і твердження, що extensions «are always opt-in and require explicit support from both client and server»; а також 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, no id reuse, requiredresultType); розділу Statelessness і його note, що open stdio process is not a session; таблиці reserved-key_metaі required/optional status кожного per-request field; правила-32602для missing required field; правилаMissingRequiredClientCapability(-32021); і error-code allocation policy. ↩ ↩2 ↩3 ↩4 ↩5 -
stdio transport,
modelcontextprotocol.io/specification/2026-07-28/basic/transports/stdio. Джерело newline-delimited framing rules, вимоги puritystdout, allowancestderrі three-outcome backward-compatibility probe — including warning that some legacy servers process era-ambiguous methods without a handshake, which the measurement in this chapter reproduces. ↩ ↩2 ↩3 -
Transports overview,
modelcontextprotocol.io/specification/2026-07-28/basic/transports. Джерело framing «a transport is a binding» і твердження, що servers do not initiate JSON-RPC requests and clients do not send JSON-RPC responses. ↩ ↩2 -
Discovery,
modelcontextprotocol.io/specification/2026-07-28/server/discover. Джерело mandatory statusserver/discover, shapeDiscoverResultі fieldinstructions, described as «optional natural-language guidance for LLMs on how to use this server effectively». ↩ -
Architecture,
modelcontextprotocol.io/specification/2026-07-28/architecture. Джерело definitions host/client/server, правила 1:1 client-to-server, чотирьох design principles, із яких isolation principle тут quoted без пʼятого bullet, «Host process enforces security boundaries», і розділу capability-negotiation. ↩ ↩2 -
Elicitation,
.../client/elicitation, and Sampling,.../client/sampling. Джерело двох elicitation modes і їх restricted schema; prohibition on requesting credentials through form mode; sampling definition, its human-in-the-loop requirement, and deprecation warning attached to it. ↩ -
Key Changes,
modelcontextprotocol.io/specification/2026-07-28/changelog, and Feature lifecycle and deprecation policy,.../community/feature-lifecycle. Джерело кожного рядка change table: removal of sessions and headerMcp-Session-Id(SEP-2567); statelessness and removal ofinitialize(SEP-2575);server/discover(SEP-2575);subscriptions/listen(SEP-2575); Multi Round-Trip Requests andresultType(SEP-2322); removal of stream resumability (SEP-2575); deprecation of Roots, Sampling and Logging (SEP-2577); reclassification of HTTP+SSE (SEP-2596); deprecation of Dynamic Client Registration in favour of Client ID Metadata Documents; error-code renumbering; and twelve-month deprecation window. ↩ ↩2 -
Tools,
modelcontextprotocol.io/specification/2026-07-28/server/tools, and Server Features,.../server. Джерело control-hierarchy table, reproduced above; shapestools/listandtools/call; distinctionisErrorbetween protocol errors and tool execution errors; tool-name rules і namespace note, що recommends «prefixing tool names with a server identifier»; and non-normative «Stateful Tools» guidance on explicit handles. ↩ -
Versioning,
modelcontextprotocol.io/specification/versioning. Джерело schemeYYYY-MM-DD, revision states Draft/Current/Final, confirmation that 2026-07-28 is current, and per-request negotiation rules. SDK tier table atmodelcontextprotocol.io/docs/sdklists TypeScript, Python, C#, Go and Rust at Tier 1, Java and Ruby at Tier 2, and Swift, PHP and Kotlin at Tier 3. ↩ -
A2A Protocol, version 1.0.0,
a2a-protocol.org— specification and page A2A and MCP: Relationship and Distinction, прочитано 7 вересня 2026 року. Джерело tools-against-agents distinction, statement that the two protocols «address distinct but highly complementary needs», and partnering/using formulation. ↩ -
Agent Communication Protocol,
agentcommunicationprotocol.dev, прочитано 7 вересня 2026 року: «ACP is now part of A2A under the Linux Foundation!», banner added above a specification that is still served whole — architecture, agent manifest, agent discovery, message structure, stateful agents, run lifecycle and the REST endpoint list all still answer 200. Специфікація не зникла; project зник. ↩