MCP според спецификацията: какво всъщност е server
Един ред JSON към subprocess връща 13 tool дефиниции — прочит през ревизията от 2026-07-28, премахнала handshake.
На тази страница
Инсталирайте публикуван MCP server, изпратете му един ред 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}Тринадесет tool дефиниции, на един ред, от процес, който е прочел един ред от стандартния си вход. Вече говорихте Model Context Protocol — без SDK, без client library и без framework. Това е цялата идея: transport, формат за съобщения и малък набор от именувани методи.
Глава 18 дефинира tool като две неща — JSON Schema, която model вижда, и endpoint във вашия код, който model никога не вижда. Глава 23 изгради harness, който държи каталог от тях. Нито една не отговори на въпроса, който решава дали нещо от това е повторно използваемо: кой пише schema и как тя стига от автора си до вашия prompt? MCP е един отговор на този въпрос и си струва да бъде прочетен в оригинал, защото почти всичко написано за него описва ревизия, която вече не съществува.
Три неща в командата, която току-що изпълнихте, са грешни и всяко от тях е раздел в тази глава. Тя не носеше protocol version, така че съвместим server би я отказал. Въпреки това получи отговор — по причина, която спецификацията нарича риск, а не функция. И поиска един от три primitives, без изобщо да открие, че другите два съществуват.
Проблемът, който решава, и аналогията, която самата спецификация прави
Връзка към раздела: Проблемът, който решава, и аналогията, която самата спецификация правиПреди wire — аритметиката. Имате AI приложения и неща, до които те трябва да могат да достигат — календар, ticket tracker, warehouse database, design tool. Без общ договор някой пише интеграции и всяка от тях е schema плюс endpoint плюс история за authentication плюс тежест за поддръжка. С такъв договор доставчикът на tool пише server, доставчикът на application пише client, а общото става .
Това не е ново наблюдение и спецификацията казва чия е идеята:
MCP черпи известно вдъхновение от Language Server Protocol, който стандартизира как се добавя поддръжка за езици за програмиране в цяла екосистема от инструменти за разработка. По подобен начин MCP стандартизира как допълнителен context и tools се интегрират в екосистемата от AI приложения.1
Приемете това сравнение буквално, не като комплимент. Преди този protocol поддръжката на език в редактор означаваше plugin за всеки редактор; след това екипът на езика доставяше един server и всеки редактор го получаваше. Мярката за успех не беше елегантността, а това, че броят интеграции спря да се умножава. Същото следва и тук: стойността е в броя реализации, не в дизайна. Protocol, който два продукта говорят, е формат за данни с допълнителна церемония.
Какво всъщност е на wire
Връзка към раздела: Какво всъщност е на wireMCP съобщенията са JSON-RPC 2.0. Request е object с jsonrpc, id, method и незадължителни params; response носи същото id и или result, или error; notification е request без id и не получава reply. Спецификацията добавя три ограничения отгоре: id трябва да е string или number и не трябва да е null, не трябва да се сблъсква с друг request, който още е in flight, и всеки result трябва да носи поле resultType.2
При stdio transport — този, който командата по-горе използва — framing правилото е един ред на съобщение:
Съобщенията се разделят с нови редове и MUST NOT съдържат вградени нови редове. […] Server MUST NOT пише в своя
stdoutнищо, което не е валидно MCP съобщение.3
Тази последна клауза е най-честият начин домашно направен server да се счупи, и се чупи тихо: случаен console.log, progress bar, deprecation warning от dependency — и line parser на client попада на нещо, което не е JSON. Аварийният изход е в същия раздел — server може да пише каквото иска в stderr, а client не би трябвало да третира това като грешка. Reference server по-горе печата Starting default (STDIO) server... при всяко стартиране, в stderr, затова pipe все пак проработи.
Другият стандартен transport е Streamable HTTP: всяко съобщение е POST към един endpoint, а reply е или JSON object, или request-scoped stream от Server-Sent Events — wire форматът, който Глава 14 разнищи на ръка. Семантиката е идентична и при двата, защото transport е binding: дефинира framing и доставка, не смисъл.4
Първото грешно нещо: нямаше версия
Връзка към раздела: Първото грешно нещо: нямаше версияКомандата по-горе изпрати tools/list и нищо друго. Според текущата ревизия този request е malformed и съвместим server трябва да го отхвърли.
От 2026-07-28 MCP е stateless protocol и спецификацията го казва без уговорки:
Model Context Protocol (MCP) е stateless protocol: цялата информация, нужна за обработка на request, се съдържа в самия request. Server обработва всеки request независимо; не трябва да се извежда state от предишни requests, дори от такива по същата connection или stream.2
Затова всеки request носи собствена protocol version и собствени client capabilities, в запазен object _meta вътре в params. Две от тези полета са задължителни за всеки отделен request; request, в който липсва което и да е от тях, е malformed и server трябва да отговори с -32602:2
_meta key | required | какво е |
|---|---|---|
io.modelcontextprotocol/protocolVersion | yes | ревизията, която този request говори, напр. "2026-07-28" |
io.modelcontextprotocol/clientCapabilities | yes | какво client може да прави за server в този request |
io.modelcontextprotocol/clientInfo | no (but should) | име и версия на client, само за display и logs |
io.modelcontextprotocol/logLevel | no | минималното log level, което server трябва да emit за този request |
Изписан, правилният 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 стъпка: client декларира какво може да прави при всеки request, server декларира какво може да прави в result и никоя страна не може да използва feature, която другата не е заявила. Server, който се нуждае от capability, което client не е декларирал, трябва да отговори с -32021 и да посочи липсващото capability в data.requiredCapabilities. Server, който не говори поисканата version, трябва да отговори с -32022 и да изброи версиите, които говори.2
Clients, които искат отговора предварително, могат да го поискат: server/discover е задължителен RPC, който връща supported versions, capabilities, identity и незадължителен блок instructions с едно round trip.5 Да го извикате е незадължително. Да го реализирате — не.
Второто грешно нещо: server беше legacy
Връзка към раздела: Второто грешно нещо: server беше legacyКомандата проработи. Според текущата ревизия не трябваше, а причината си струва измерване, не абзац, защото е състоянието на цялата екосистема в един ред.
Пробвайте reference server по начина, по който спецификацията казва на modern client да пробва:
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 правилото: DiscoverResult означава modern, разпозната modern error означава modern-but-wrong-version, а всичко друго — включително -32601 — означава legacy, fallback към initialize handshake.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":"…"}}Client поиска 2026-07-28 и server отговори 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 описва protocol с initialize handshake, session, roots/list request, който server изпраща към client, и HTTP+SSE transport. И четирите са премахнати или си отиват. Когато четете каквото и да е за MCP, включително тази страница, първото, което трябва да търсите, е revision number.
А причината първата команда да проработи е посочена в спецификацията като риск, не като функция:
някои legacy servers не проверяват дали request пристига след
initializeи биха обработили era-ambiguous метод (катоtools/call) по legacy semantics. Probing дава deterministic failure вместо това.3
Измерено: изпращането на tools/list към този server без никакъв handshake връща целия каталог. Метод, който е трябвало да бъде отказан, беше обслужен — точно затова спецификацията казва първо да се probe-ва с server/discover, дори когато поддържате само modern versions.
Три роли и изречението, което да цитирате от целия документ
Връзка към раздела: Три роли и изречението, което да цитирате от целия документMCP има три страни, а разликата между първите две е тази, която хората обикновено сливат:
Host. Приложението: chat продуктът, редакторът, agent. То притежава разговора, model, credentials и съгласието на потребителя. Създава clients и налага security boundary между тях.
Client. Connector вътре в host. Всеки client говори с точно един server — строга 1:1 връзка — и прикачва protocol version и capabilities към всеки request, който route-ва.
Server. Процес или услуга, която exposes resources, tools и prompts. Може да е local или remote, работи независимо и цялата му задача е една фокусирана област.6
Правилото „точно един server“ не е счетоводство. То прави design principle по-долу приложим, а това е изречението, което да вземете от спецификацията, ако вземете само едно:
Servers не трябва да могат да четат целия разговор, нито да „виждат вътре“ в други servers. Servers получават само необходимата контекстуална информация. Пълната история на разговора остава при host. Всеки server поддържа isolation. Cross-server interactions се контролират от host.6
Това преобръща mental model, с който повечето хора идват. Weather server, който свързвате към вашия assistant, не вижда какво сте попитали. Той вижда tools/call с arguments, които model е избрал, и нищо повече — нито предишните turns, нито вашия system prompt, нито резултатите, които calendar server е върнал преди миг. Ако два servers трябва да си сътрудничат, host пренася стойност от единия към другия, умишлено, защото model го е поискал. Затова isolation е security property, на което Глава 30 разчита: компрометиран server има малък, дефиниран blast radius, а разширяването му изисква host да съдейства.
Третото нещо: три primitives, подредени според това кой управлява
Връзка към раздела: Третото нещо: три primitives, подредени според това кой управляваПървата команда поиска tools от този server и получи тринадесет. Попитайте го другите два въпроса и той отговаря и на тях: resources/list връща седем, prompts/list връща четири. Нито едно от тях не се появи, защото нищо не ги поиска. Това ни води до педагогическия гръбнак на MCP, стоящ в спецификацията като таблица, която почти никой не цитира:
| Primitive | Control | Description | Example |
|---|---|---|---|
| Prompts | User-controlled | Интерактивни templates, извиквани по избор на потребителя | Slash commands, menu options |
| Resources | Application-controlled | Контекстуални данни, прикачвани и управлявани от client | File contents, git history |
| Tools | Model-controlled | Functions, expose-нати към LLM за действия | API POST requests, file writing |
Не „три начина да expose-нете capability“. Три отговора на кой решава, че това се случва. Model решава да call-не tool. Application решава да attach-не resource. Човекът решава да run-не prompt. Сбъркате ли това, feature пак работи, но работи в грешния момент и по грешната причина.
Най-ясният начин да го усетите е календар. Ето server, който 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 на server са пропуснати:
→ 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, инертно е и application решава дали да го прикачи към разговора. Нищо в protocol не позволява на model да посегне към него самостоятелно. Result носи ttlMs и cacheScope, нови в тази ревизия, така че client може да cache-не седмицата за минута, вместо да polling-ва.
Създаването на event е tool
Връзка към раздела: Създаването на event е toolИма schema, има side effects и model решава кога да го call-не. Result носи isError — полето, за което Глава 18 настояваше: validation failure се връща като tool result, който model може да прочете и поправи, не като protocol error.
„Подготви седмицата ми“ е prompt
Връзка към раздела: „Подготви седмицата ми“ е promptТова е именуван template с arguments, който човекът извиква — slash command в менюто. Връща messages, не отговор. Това е начин server author да достави phrasing, който работи със собствените му tools — точно знанието, което server author има, а потребителят няма.
Почти всички правят и трите неща tools. Резултатът е каталог, в който read, който application е трябвало да прикачи тихо, се конкурира за attention на model с write, който има нужда от approval, а единственото нещо, за което човекът е искал бутон, е заровено в schema. Не струва нищо да го направите правилно и решението се взема преди да напишете ред.
Server не може да ви call-не
Връзка към раздела: Server не може да ви call-неCalendar tool има един задължителен argument, title, и един незадължителен startsAt. Помолете го да създаде 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. Той отговори на този, който му беше даден, с resultType: "input_required" и описание какво още му трябва. Client събира отговора от човека и после изпраща отново оригиналния call — с нов id, носещ inputResponses и echo-ващ 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, въведени в текущата ревизия, и замениха по-стария дизайн, при който servers изпращаха JSON-RPC requests обратно към clients. Спецификацията на transport вече казва правилото направо: „servers не инициират JSON-RPC requests и clients не изпращат JSON-RPC responses“.4 Има една посока на инициативата и тя принадлежи на host.
Две client-side features стъпват върху този механизъм и едната има име, което ще ви подведе.
Elicitation е server да поиска нещо от човека: form с умишлено ограничена JSON Schema — flat objects, primitive properties, без nesting — така че всеки client да може да я render-не без layout engine. Носи твърдо правило: servers не трябва да използват form mode, за да искат „passwords, API keys, access tokens, or payment credentials“, и трябва да използват URL mode за тях, който изпраща потребителя към страница, която client никога не чете.7
Sampling е server да поиска generation от model на host, така че server да може да е intelligent без да държи API key. И ето предупреждението за речника, защото тази дума вече означава нещо друго в този курс: това не е sampling от Глава 17. Тук няма нищо за temperature, top-p или формата на probability distribution. Това е nested model call, който пътува назад през protocol.
Има и втора причина да не посягате към него: към тази ревизия sampling е deprecated, заедно с roots и logging, по SEP-2577, с директно предложена migration — „интегрирайте се директно с LLM provider APIs вместо Sampling“.8 Идеята не се провали технически; не успя да оправдае surface area, а protocol, който може да премахва неща, е по-здрав от такъв, който не може.
Счупете го нарочно: connections не са sessions
Връзка към раздела: Счупете го нарочно: connections не са sessionsStatelessness звучи като wire-format детайл, докато не го тествате. Вземете трисъобщения exchange по-горе и пуснете всяко съобщение в отделен процес — свеж 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, който никога не е видял въпроса, завърши multi-round-trip call, който process A е започнал. Това е смисълът на requestState: continuation пътува в съобщението, така че нищо не зависи от това процесът да е същият.
Process C е failure. Event беше създаден и не е там — защото toy server държи EVENTS в module-level array, а module-level array е connection state. Бележката в спецификацията назовава грешката точно:
отворена connection, като STDIO процес, не е conversation или session: clients може да interleave-ват несвързани requests по същия transport, а server не трябва да третира connection или process identity като proxy за conversation или session continuity.2
Предписаната поправка не е session. Тя е explicit handle: creation tool връща opaque identifier, а всеки по-късен call го приема като обикновен argument. Protocol изобщо няма понятие за него — „от гледна точка на wire handle е обикновен string в tool result и обикновен argument към последващи tool calls“.9 Това поставя model да го пренася и server да валидира, че този caller има право да го използва при всеки отделен call, защото handle е име, не разрешение.
Колко струва един server, преди да направи каквото и да е
Връзка към раздела: Колко струва един server, преди да направи каквото и да еВсеки tool, който server exposes, е schema, която влиза във вашия prompt при всеки request, а Глава 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Две наблюдения. Първото е аритметика: свържете пет servers с такъв размер и приблизително осем хиляди tokens от вашия window са заети при всеки turn, завинаги, независимо дали model използва някой от тях — това е mechanism зад намалението от 150 000 до 2 000, цитирано в Глава 24, и причината да съществува just-in-time tool discovery.
Второто е security бележка, облечена като счетоводство. instructions е natural-language text, written by the server author, that lands in the host's prompt, и tool descriptions до него са същите. Спецификацията казва какво да се прави с това в собствените си security principles: tool annotations и descriptions „трябва да се считат за untrusted, освен ако не са obtained from a trusted server“, а hosts „трябва да получат explicit user consent, преди да invoke-нат който и да е tool“.1 Свързването на MCP server не е добавяне на dependency. То е да дадете на непознат 1 619 tokens от вашия system prompt и правото да бъде call-ван. Глава 30 е какво става, когато този непознат е hostile.
Датиран раздел: ревизията 2026-07-28 и какво чупи
Връзка към раздела: Датиран раздел: ревизията 2026-07-28 и какво чупиВсичко в този раздел е вярно за protocol revision 2026-07-28, текущата, прочетена на 7 септември 2026 г. Revisions са датирани YYYY-MM-DD и датата е последният път, когато е направена backwards-incompatible change.10 Normative document е TypeScript file, schema/2026-07-28/schema.ts; JSON Schema до него е generated from it, затова спецификацията тук се чете в TypeScript и затова преподаването на MCP от нещо друго е преподаване на translation.
| What changed | Was | Is now | Breaks |
|---|---|---|---|
| Handshake | initialize + notifications/initialized, веднъж на connection | премахнат; всеки request носи _meta version и capabilities | всеки client, написан преди тази ревизия |
| Sessions | Mcp-Session-Id header, connection-scoped state | премахнати; state пътува в explicit, server-minted handles | list endpoints, които варират по connection |
| Discovery | inferred от result на initialize | server/discover, който servers трябва да implement-нат | нищо, но вече е задължителен за implement |
| Server-to-client calls | server изпращаше roots/list, sampling/createMessage, elicitation/create | InputRequiredResult и client retry | всеки server, който push-ва request към client |
| Result shape | произволен object | задължително resultType: "complete" или "input_required" | нищо: липсващо поле трябва да се чете като "complete" |
| Subscriptions | HTTP GET stream, resources/subscribe | един subscriptions/listen stream с opt-in types | GET endpoint го няма |
| Stream resumption | Last-Event-ID replay при Streamable HTTP | премахнат; счупен stream губи request, re-issue с нов id | clients, които са разчитали на redelivery |
| Roots | client feature, която servers можеха да поискат | deprecated (SEP-2577); подавайте paths като tool arguments или resource URIs | още нищо — twelve-month window |
| Sampling and logging | client features | deprecated (SEP-2577) | още нищо — twelve-month window |
| HTTP+SSE transport | deprecated от 2025-03-26 | Deprecated по lifecycle policy (SEP-2596) | migrate към Streamable HTTP |
| Client registration | OAuth 2.0 Dynamic Client Registration, RFC 7591 | deprecated в полза на Client ID Metadata Documents | запазено за authorization servers без тях |
| Error codes | -32002 за resource not found | -32602; -32020–-32099 reserved за spec | нови codes -32020, -32021, -32022 |
Governance промяната под тази таблица е по-важна от който и да е ред. Тази ревизия прие feature lifecycle and deprecation policy: features са Active, Deprecated или Removed, deprecated feature документира migration path и остава в specification поне дванадесет месеца, преди да стане eligible for removal, и има registry, който изброява всичко в момента в Deprecated state.8 Преди тази policy „deprecated“ в AI protocol означаваше каквото е казал последният blog post. Сега означава дата.
Покажи подробности
Extensions — частта, за която още никой не е писал.
Отвъд core, MCP дефинира незадължителни extensions — „always opt-in and require explicit support from both client and server“, декларирани чрез поле extensions в capabilities на client и server.1 Три си струва да знаете по име:
- Tasks (
io.modelcontextprotocol/tasks), преместени от core protocol в official extension в тази ревизия: asynchronous execution of long-running operations, с polling чрезtasks/get, mid-flight input чрезtasks/updateи durable handles. Това е отговорът за tool, който отнема двадесет минути — нещо, с което Глава 23 се справи чрез progress event и signal, който достига tool. - Skills over MCP, working group, който прави agent skills — темата на Глава 28 — discoverable и consumable чрез protocol.
- MCP Apps, interactive UI, render-нат inline в разговора: charts, forms, video players.
И отбележете какво вече означава „negotiated“: няма initialization, при която да се negotiate-ва, така че extension се декларира per request, както всичко останало.
Къде стои MCP спрямо всичко, с което го бъркат
Връзка към раздела: Къде стои MCP спрямо всичко, с което го бъркатТова е речникът на целия блок на едно място.
| What it is | Who talks to whom | When it is the answer | |
|---|---|---|---|
| Plain API | Interface за program | вашият code ↔ service | Вие пишете caller. Контролирате schema, auth и error handling, а няма discovery problem за решаване. |
| MCP | Protocol за exposing tools, data и templates към AI application | host ↔ server, по един client за всеки | Някой друг е написал capability и много hosts трябва да могат да го използват без bespoke integration. |
| RAG | Technique за намиране на text и поставянето му в prompt | вашият code ↔ вашият index | Model трябва да знае нещо. Глава 19. MCP е начин да доставите retriever; не е retriever. |
| Agent skills | Folder с SKILL.md, който model чете | model ↔ document | Знанието е procedural — как ние правим това — и е prose, не function. Глава 28. |
| A2A | Protocol за agents да си сътрудничат като peers | agent ↔ agent | Другата страна reasons, plans и държи state през long task, вместо да отговаря на call. |
| ACP | Беше отделен agent-communication protocol | — | Вече не е live comparison. Вижте по-долу. |
Две от тях заслужават по едно изречение, защото там наистина живее объркването.
MCP срещу A2A не е съперничество и и двете спецификации го казват. Документацията на A2A тегли линията според това какво е от другата страна: MCP „дефинира как AI agent взаимодейства с и използва 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 начерта тази линия вътре в един процес, между това да попитате sub-agent и да му предадете разговора; A2A я чертае между организации.
MCP срещу ACP е сравнение с остаряла предпоставка — точно затова си струва да се отговори. Agent Communication Protocol беше отделен open standard за agent-to-agent messaging. Собствената му документация вече започва с известието: „ACP is now part of A2A under the Linux Foundation!“12 Честният отговор на „MCP или ACP?“ през септември 2026 г. е, че въпросът има една опция по-малко, отколкото подсказват страниците, които rank-ват за него.
А сравнението, което хората най-често искат, mcp vs api, има най-малко интересния отговор: MCP е API. Това, което добавя, не е мощ, а conventions — фиксиран набор от имена на methods, discovery call, control hierarchy над primitives и isolation model. Отказвате се от свободата да проектирате собствен interface и получавате всеки host, който говори protocol — trade-off, който всеки protocol някога е предлагал.
Накъде отива това
Връзка към раздела: Накъде отива товаВече можете да четете спецификацията без преводач, да различавате resource от tool от prompt според това кой го управлява, да напишете request на ръка, когато client library ви лъже, и да датирате всяка MCP статия, която четете, според това кои deprecated features още преподава като current.
Това, което още не сте направили, е да ship-нете един. Глава 27 пише същия server два пъти — TypeScript и Python, един до друг, защото MCP е една от наистина bilingual териториите в този курс и числата го показват и в двете посоки. Тя покрива двата live transports както трябва, inspector, packaging и половината от protocol, която тази глава умишлено остави настрана: authorization. Защото в момента, в който вашият server е remote, а не subprocess на собствения ви лаптоп, client на непознат ще представи token, а правилото на спецификацията за това какво можете да правите с него е необичайно строго.
Това повдига въпроса, на който следващата глава трябва да отговори, и той не е дружелюбен: ако token пристигне на вашия server и е издаден за audience на някой друг, какво точно ви спира да го forward-нете?
Източници и метод
Връзка към раздела: Източници и методВсеки quote, method name, error code и rule в тази глава беше прочетен от Model Context Protocol specification, revision 2026-07-28, на 7 септември 2026 г. Всеки trace беше произведен local на Node 22: toy calendar server е 101 реда без dependencies, а reference server е публикуваният npm package, посочен по-долу. Не беше извикан paid API за написването на тази глава — нищо тук не се нуждае от model, което само по себе си е смисълът.
Measurements: @modelcontextprotocol/server-everything@2026.8.31, published 31 August 2026, built on @modelcontextprotocol/sdk@1.30.0, published 27 July 2026 — един ден преди revision, която тази глава описва. 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, е източникът на числото 150 000 до 2 000, цитирано и използвано в Глава 24 и само реферирано тук.
Препратки
Връзка към раздела: Препратки-
Specification,
modelcontextprotocol.io/specification/latest(redirecting to/2026-07-28), read 7 September 2026. Източник на сравнението с Language Server Protocol; твърдението, че specification е „based on the TypeScript schema inschema.ts“; 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“; както и 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 section и бележката, че open stdio process не е session; reserved-key table_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, purity requirement заstdout, allowance заstderrи three-outcome backward-compatibility probe — включително warning, че някои legacy servers обработват era-ambiguous methods без handshake, което measurement в тази глава възпроизвежда. ↩ ↩2 ↩3 -
Transports overview,
modelcontextprotocol.io/specification/2026-07-28/basic/transports. Източник на framing-а „a transport is a binding“ и на statement, че servers не initiate-ват JSON-RPC requests и clients не send-ват JSON-RPC responses. ↩ ↩2 -
Discovery,
modelcontextprotocol.io/specification/2026-07-28/server/discover. Източник на mandatory status наserver/discover, shape наDiscoverResultи fieldinstructions, описано като „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, четирите design principles, от които isolation principle е цитиран тук без петия bullet, „Host process enforces security boundaries“, и capability-negotiation section. ↩ ↩2 -
Elicitation,
.../client/elicitation, и Sampling,.../client/sampling. Източник на двата elicitation modes и restricted schema; забраната да се искат credentials чрез form mode; 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: removal на sessions и headerMcp-Session-Id(SEP-2567); statelessness и removal наinitialize(SEP-2575);server/discover(SEP-2575);subscriptions/listen(SEP-2575); Multi Round-Trip Requests иresultType(SEP-2322); removal на stream resumability (SEP-2575); deprecation на Roots, Sampling и Logging (SEP-2577); reclassification на HTTP+SSE (SEP-2596); deprecation на Dynamic Client Registration в полза на Client ID Metadata Documents; error-code renumbering; и twelve-month deprecation window. ↩ ↩2 -
Tools,
modelcontextprotocol.io/specification/2026-07-28/server/tools, и Server Features,.../server. Източник на control-hierarchy table, възпроизведена по-горе; shapestools/listиtools/call; distinctionisErrorмежду protocol errors и tool execution errors; tool-name rules и namespace note, препоръчваща „prefixing tool names with a server identifier“; и non-normative guidance „Stateful Tools“ за explicit handles. ↩ -
Versioning,
modelcontextprotocol.io/specification/versioning. Източник на schemeYYYY-MM-DD, Draft/Current/Final revision states, confirmation, че 2026-07-28 е current, и per-request negotiation rules. SDK tier table вmodelcontextprotocol.io/docs/sdkизброява TypeScript, Python, C#, Go и Rust като Tier 1, Java и Ruby като Tier 2, и Swift, PHP и Kotlin като Tier 3. ↩ -
A2A Protocol, version 1.0.0,
a2a-protocol.org— specification и страницата A2A and MCP: Relationship and Distinction, read 7 September 2026. Източник на tools-against-agents distinction, statement, че двата protocols „address distinct but highly complementary needs“, и formulation partnering/using. ↩ -
Agent Communication Protocol,
agentcommunicationprotocol.dev, read 7 September 2026: „ACP is now part of A2A under the Linux Foundation!“, banner, добавен над specification, която още се served whole — architecture, agent manifest, agent discovery, message structure, stateful agents, run lifecycle и REST endpoint list all still answer 200. Specification не изчезна; project го направи. ↩