Sari la conținut
26/30Capitolul 26 din 30

MCP explicat pe specificație: ce este, de fapt, un server

O linie de JSON într-un subprocess și revin treisprezece definiții de instrumente, citite prin revizia 2026-07-28.

Pe această pagină

Instalează un server MCP publicat, trimite-i o linie de JSON și citește ce se întoarce.

terminalBASH
npm i @modelcontextprotocol/server-everything@2026.8.31
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \
  | npx @modelcontextprotocol/server-everything stdio
TEXT
{"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}

Treisprezece definiții de instrumente, pe o singură linie, de la un proces care a citit o linie din intrarea sa standard. Tocmai ai vorbit Model Context Protocol, fără SDK, fără bibliotecă de client și fără framework. Asta este tot: un transport, un format de mesaj și un set mic de metode numite.

Capitolul 18 a definit un instrument ca două lucruri — un JSON Schema pe care îl vede modelul și un endpoint în codul tău pe care modelul nu îl vede niciodată. Capitolul 23 a construit un harness care ține un catalog cu ele. Niciunul nu a răspuns la întrebarea care decide dacă ceva din toate acestea este reutilizabil: cine scrie schema și cum ajunge ea de la cel care a scris-o în prompt? MCP este un răspuns la această întrebare și merită citit în original, fiindcă aproape tot ce s-a scris despre el descrie o revizie care nu mai există.

Trei lucruri din comanda pe care tocmai ai rulat-o sunt greșite, iar fiecare este o secțiune din acest capitol. Nu a purtat nicio versiune de protocol, deci un server conform ar fi refuzat-o. A primit totuși un răspuns, dintr-un motiv pe care specificația îl numește pericol, nu funcționalitate. Și a cerut una dintre cele trei primitive fără să descopere vreodată că celelalte două există.

Problema pe care o rezolvă și analogia pe care o face chiar specificația

Link către secțiunea: Problema pe care o rezolvă și analogia pe care o face chiar specificația

Înainte de wire, aritmetica. Ai NN aplicații AI și MM lucruri la care ar trebui să poată ajunge — un calendar, un sistem de tichete, o bază de date din depozit, un instrument de design. Fără un contract comun, cineva scrie N×MN \times M integrări, iar fiecare dintre ele este o schemă plus un endpoint plus o poveste de autentificare plus o povară de mentenanță. Cu unul, furnizorul instrumentului scrie un server, furnizorul aplicației scrie un client, iar totalul este N+MN + M.

Nu este o observație nouă, iar specificația spune a cui idee a fost:

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

Ia comparația literal, nu ca pe un compliment. Înainte de acel protocol, suportul pentru un limbaj într-un editor însemna câte un plugin pentru fiecare editor; după aceea, o echipă de limbaj livra un singur server și fiecare editor îl primea. Măsura succesului nu era eleganța, ci faptul că numărul integrărilor nu mai creștea prin înmulțire. Același lucru urmează și aici: valoarea este în numărul de implementări, nu în design. Un protocol pe care îl vorbesc două produse este un format de date cu ceremonie în plus.

Mesajele MCP sunt JSON-RPC 2.0. O cerere este un obiect cu jsonrpc, un id, un method și params opțional; un răspuns poartă același id și fie result, fie error; o notificare este o cerere fără id și nu primește răspuns. Specificația adaugă trei constrângeri peste asta: id trebuie să fie un șir sau un număr și nu trebuie să fie null, nu trebuie să intre în coliziune cu o altă cerere încă în curs, iar fiecare rezultat trebuie să poarte un câmp resultType.2

Pe transportul stdio — cel folosit de comanda de mai sus — regula de framing este o linie per mesaj:

Messages are delimited by newlines, and MUST NOT contain embedded newlines. […] The server MUST NOT write anything to its stdout that is not a valid MCP message.3

Ultima clauză este cel mai frecvent mod în care se strică un server făcut acasă, și se strică în tăcere: un console.log rătăcit, o bară de progres, un avertisment de deprecate de la o dependență, iar parserul de linii al clientului lovește ceva ce nu este JSON. Portița de scăpare este în aceeași secțiune — serverul poate scrie orice vrea în stderr, iar clientul nu ar trebui să trateze asta ca pe o eroare. Serverul de referință de mai sus afișează Starting default (STDIO) server... la fiecare pornire, pe stderr, de aceea pipe-ul a funcționat în continuare.

Celălalt transport standard este Streamable HTTP: fiecare mesaj este un POST către un singur endpoint, iar răspunsul este fie un obiect JSON, fie un stream de Server-Sent Events limitat la cerere — formatul wire pe care Capitolul 14 l-a parsat de mână. Semantica este identică pe ambele, fiindcă un transport este un binding: definește framing și livrare, nu sens.4

Comanda de mai sus a trimis tools/list și nimic altceva. În revizia curentă, acea cerere este malformată, iar un server conform trebuie să o respingă.

Din 2026-07-28, MCP este un protocol stateless, iar specificația o spune fără ezitare:

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

Așadar, fiecare cerere poartă propria versiune de protocol și propriile capabilități ale clientului, într-un obiect rezervat _meta din interiorul params. Două dintre aceste câmpuri sunt obligatorii în fiecare cerere; o cerere căreia îi lipsește oricare dintre ele este malformată, iar serverul trebuie să răspundă cu -32602:2

Cheie _metaobligatoriuce este
io.modelcontextprotocol/protocolVersiondarevizia pe care o vorbește această cerere, de ex. "2026-07-28"
io.modelcontextprotocol/clientCapabilitiesdace poate face clientul pentru server în această cerere
io.modelcontextprotocol/clientInfonu (dar ar trebui)numele și versiunea clientului, doar pentru afișare și loguri
io.modelcontextprotocol/logLevelnunivelul minim de log pe care serverul ar trebui să îl emită pentru această cerere

Scris complet, un tools/list corect este acesta — și este ultima dată când acest capitol arată metadatele integral, fiindcă de aici înainte sunt pe fiecare cerere:

one line, split for the pageTEXT
{"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"}}}}

Obiectul de capabilități este negocierea. Nu mai există un pas separat de negociere: clientul declară ce poate face în fiecare cerere, serverul declară ce poate face în rezultat, iar niciuna dintre părți nu poate folosi o funcționalitate pe care cealaltă nu a revendicat-o. Un server care are nevoie de o capabilitate pe care clientul nu a declarat-o trebuie să răspundă cu -32021 și să numească în data.requiredCapabilities capabilitatea lipsă. Un server care nu vorbește versiunea cerută trebuie să răspundă cu -32022 și să listeze versiunile pe care le vorbește.2

Clienții care vor răspunsul de la început îl pot cere: server/discover este un RPC obligatoriu care returnează versiunile acceptate, capabilitățile, identitatea și un bloc opțional de instructions într-un singur round trip.5 Apelarea lui este opțională. Implementarea lui nu este.

Comanda a funcționat. În revizia curentă nu ar fi trebuit, iar motivul pentru care a funcționat merită o măsurătoare, nu un paragraf, fiindcă este starea întregului ecosistem într-o singură linie.

Sondează serverul de referință așa cum îi spune specificația unui client modern să sondeze:

terminalBASH
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
TEXT
{"jsonrpc":"2.0","id":1,"error":{"code":-32601,"message":"Method not found"}}

Aceasta este a treia ramură a regulii de compatibilitate: un DiscoverResult înseamnă modern, o eroare modernă recunoscută înseamnă modern-dar-versiune-greșită, iar orice altceva — inclusiv -32601 — înseamnă legacy, revino la handshake-ul initialize.3 Așa că fă asta, cerând revizia curentă:

TEXT
→ {"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":"…"}}

Clientul a cerut 2026-07-28, iar serverul a răspuns 2025-11-25. Pe 7 septembrie 2026, serverul oficial de referință — pachetul npm @modelcontextprotocol/server-everything, versiunea 2026.8.31, publicat pe 31 august 2026 — nu implementează revizia curentă. Nici TypeScript SDK pe care este construit nu o implementează, după date: release-ul 1.30.0 a ieșit pe 27 iulie 2026, cu o zi înaintea reviziei.

Citește consecința, nu bârfa. Aproape tot ce s-a scris despre MCP descrie un protocol cu handshake initialize, o sesiune, o cerere roots/list pe care serverul o trimite clientului și un transport HTTP+SSE. Toate patru au dispărut sau dispar. Când citești orice despre MCP, inclusiv pagina aceasta, primul lucru pe care trebuie să îl cauți este un număr de revizie.

Iar motivul pentru care prima comandă a funcționat este enunțat în specificație ca pericol, nu ca funcționalitate:

some legacy servers do not validate that a request arrives after initialize and would process an era-ambiguous method (such as tools/call) under legacy semantics. Probing yields a deterministic failure instead.3

Măsurat: trimiterea tools/list către acel server, fără niciun handshake, returnează catalogul complet. O metodă care ar fi trebuit refuzată a fost servită, exact de aceea specificația spune să sondezi mai întâi cu server/discover chiar și când accepți doar versiuni moderne.

Trei roluri și propoziția de citat din tot documentul

Link către secțiunea: Trei roluri și propoziția de citat din tot documentul

MCP are trei părți, iar distincția dintre primele două este cea pe care oamenii o comprimă:

Host. Aplicația: produsul de chat, editorul, agent. Deține conversația, modelul, acreditările și consimțământul utilizatorului. Creează clienți și impune limita de securitate dintre ei.

Client. Un conector din interiorul hostului. Fiecare client vorbește cu exact un server — o relație strictă 1:1 — și atașează versiunea de protocol și capabilitățile la fiecare cerere pe care o rutează.

Server. Un proces sau un serviciu care expune resurse, instrumente și prompts. Poate fi local sau remote, operează independent, iar întreaga lui treabă este un domeniu concentrat.6

Regula „exact un server” nu este contabilitate. Ea face principiul de design de mai jos implementabil, iar aceasta este propoziția de luat din specificație dacă iei una singură:

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

Asta răstoarnă modelul mental cu care ajung majoritatea oamenilor. Un server de vreme pe care îl conectezi la asistentul tău nu vede ce ai întrebat. Vede un tools/call cu argumentele alese de model și nimic altceva — nu turele anterioare, nu system prompt, nu rezultatele pe care serverul de calendar le-a returnat cu o clipă înainte. Dacă două servere trebuie să coopereze, hostul duce o valoare de la unul la altul, deliberat, fiindcă modelul a cerut-o. De aceea izolarea este proprietatea de securitate pe care se sprijină Capitolul 30: un server compromis are o rază de explozie mică, definită, iar lărgirea ei cere cooperarea hostului.

Al treilea lucru: trei primitive, ordonate după cine deține controlul

Link către secțiunea: Al treilea lucru: trei primitive, ordonate după cine deține controlul

Prima comandă a cerut serverului instrumente și a primit treisprezece. Pune-i celelalte două întrebări și răspunde și la ele: resources/list returnează șapte, prompts/list returnează patru. Niciuna nu a apărut, fiindcă nu a întrebat nimic. Asta ne duce la coloana vertebrală pedagogică a MCP, aflată în specificație ca tabel pe care aproape nimeni nu îl citează:

PrimitiveControlDescriptionExample
PromptsControlat de utilizatorȘabloane interactive invocate prin alegerea utilizatoruluiComenzi slash, opțiuni de meniu
ResourcesControlat de aplicațieDate contextuale atașate și gestionate de clientConținut de fișier, istoric git
ToolsControlat de modelFuncții expuse către LLM pentru a acționaCereri API POST, scriere de fișiere

Nu „trei moduri de a expune o capabilitate”. Trei răspunsuri la cine decide că se întâmplă asta. Modelul decide să apeleze un instrument. Aplicația decide să atașeze o resursă. Persoana decide să ruleze un prompt. Dacă greșești asta, funcționalitatea tot merge, dar merge în momentul greșit și din motivul greșit.

Cel mai clar mod de a simți diferența este un calendar. Iată un server care expune același calendar de trei ori, o dată ca fiecare primitivă, în o sută de linii de Node simplu, fără dependențe:

calendar.mjs — the parts that matterJS
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" });
}

Rulează-l și întreabă-l în toate cele trei moduri. Output real, un mesaj per linie pe wire, împachetat aici pentru pagină, cu cererea _meta și blocul de identitate al serverului omise:

TEXT
→ 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}

Trei metode, trei forme, un calendar. Acum ideea:

Este adresată printr-un URI, este inertă, iar aplicația decide dacă o atașează conversației. Nimic din protocol nu lasă modelul să o ia singur. Rezultatul poartă ttlMs și cacheScope, noi în această revizie, astfel încât clientul să poată cache-ui săptămâna pentru un minut în loc să facă polling.

Are o schemă, are efecte secundare, iar modelul decide când să îl apeleze. Rezultatul poartă isError, câmpul pentru care a pledat Capitolul 18: un eșec de validare se întoarce ca rezultat de instrument pe care modelul îl poate citi și corecta, nu ca eroare de protocol.

Este un șablon numit, cu argumente, pe care persoana îl invocă — comanda slash din meniu. Returnează mesaje, nu un răspuns. Este o cale prin care autorul unui server livrează formularea care funcționează cu propriile instrumente, exact cunoașterea pe care autorul serverului o are, iar utilizatorul nu.

Aproape toată lumea le transformă pe toate trei în instrumente. Rezultatul este un catalog în care o citire pe care aplicația ar fi trebuit să o atașeze tăcut concurează pentru attention cu o scriere care are nevoie de aprobare, iar singurul lucru pentru care o persoană voia un buton este îngropat într-o schemă. Nu costă nimic să îl faci corect, iar decizia se ia înainte să scrii o linie.

Instrumentul de calendar are un argument obligatoriu, title, și unul opțional, startsAt. Cere-i să creeze un eveniment fără dată și se întoarce ceva interesant:

TEXT
→ 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=="}

Serverul nu a trimis o cerere. A răspuns celei primite, cu resultType: "input_required" și o descriere a ceea ce încă îi trebuie. Clientul colectează răspunsul de la persoană, apoi retrimite apelul inițial — cu un id nou, purtând inputResponses și întorcând în ecou requestState opac:

TEXT
→ 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}

Acesta este Multi Round-Trip Requests, introdus în revizia curentă, și a înlocuit designul mai vechi în care serverele trimiteau cereri JSON-RPC înapoi către clienți. Specificația de transport enunță acum regula direct: „servers do not initiate JSON-RPC requests and clients do not send JSON-RPC responses”.4 Există o singură direcție a inițiativei, iar ea aparține hostului.

Două funcționalități de partea clientului se sprijină pe acest mecanism, iar una dintre ele are un nume care îți va pune piedică.

Elicitation este serverul care cere ceva persoanei: un formular cu un JSON Schema deliberat restrâns — obiecte plate, proprietăți primitive, fără imbricare — astfel încât orice client să îl poată reda fără un motor de layout. Poartă o regulă dură: serverele nu trebuie să folosească modul formular pentru a cere „passwords, API keys, access tokens, or payment credentials” și trebuie să folosească modul URL pentru acestea, care trimite utilizatorul la o pagină pe care clientul nu o citește niciodată.7

Sampling este serverul care cere o generație de la modelul hostului, astfel încât un server să poată fi inteligent fără să dețină o cheie API. Și iată avertismentul de vocabular, fiindcă acest cuvânt înseamnă deja altceva în acest curs: acesta nu este sampling din Capitolul 17. Nimic de aici nu este despre temperatură, top-p sau forma unei distribuții de probabilitate. Este un apel de model imbricat care călătorește înapoi printr-un protocol.

Există un al doilea motiv să nu te grăbești să îl folosești: începând cu această revizie, sampling este deprecated, alături de roots și logging, sub SEP-2577, cu o migrare sugerată fără menajamente — „integrate directly with LLM provider APIs instead of Sampling”.8 Ideea nu a eșuat tehnic; nu și-a justificat suprafața, iar un protocol care poate elimina lucruri este mai sănătos decât unul care nu poate.

Strică-l intenționat: conexiunile nu sunt sesiuni

Link către secțiunea: Strică-l intenționat: conexiunile nu sunt sesiuni

Statelessness pare un detaliu de wire-format până îl testezi. Ia schimbul de trei mesaje de mai sus și rulează fiecare mesaj într-un proces separat — un node calendar.mjs proaspăt, fără memorie partajată, fără nimic dus mai departe:

TEXT
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)

Procesul B, care nu a văzut niciodată întrebarea, a finalizat un apel multi-round-trip început de procesul A. Acesta este scopul requestState: continuarea călătorește în mesaj, deci nimic nu depinde de faptul că procesul este același.

Procesul C este eșecul. Evenimentul a fost creat și nu este acolo — fiindcă serverul de jucărie păstrează EVENTS într-un array la nivel de modul, iar un array la nivel de modul este stare de conexiune. Nota specificației numește greșeala precis:

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

Remediul prescris nu este o sesiune. Este un handle explicit: un instrument de creare returnează un identificator opac, iar fiecare apel ulterior îl primește ca argument obișnuit. Protocolul nu are niciun concept pentru el — „from the wire's perspective a handle is an ordinary string in a tool result and an ordinary argument to subsequent tool calls”.9 Asta pune modelul să îl transporte și pune serverul să valideze că acest apelant are voie să îl folosească la fiecare apel, fiindcă un handle este un nume, nu o permisiune.

Fiecare instrument pe care îl expune un server este o schemă care intră în prompt la fiecare cerere, iar Capitolul 24 a măsurat ce face asta unei context window. MCP adaugă un al doilea element de cost ușor de ratat, așa că merită numărate ambele pe serverul de referință de mai sus.

o200k_base tokensTEXT
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

Două observații. Prima este aritmetică: conectează cinci servere de această dimensiune și aproximativ opt mii de tokens din context window sunt ocupați la fiecare tură, pentru totdeauna, indiferent dacă modelul folosește vreunul dintre ele — acesta este mecanismul din spatele reducerii de la 150.000 la 2.000 citate în Capitolul 24 și motivul pentru care există descoperirea just-in-time a instrumentelor.

A doua este o notă de securitate deghizată în contabilitate. instructions este text în limbaj natural, scris de autorul serverului, care ajunge în prompt al hostului, iar descrierile instrumentelor de lângă el sunt la fel. Specificația spune ce trebuie făcut cu asta în propriile principii de securitate: adnotările și descrierile instrumentelor „should be considered untrusted, unless obtained from a trusted server”, iar hosturile „must obtain explicit user consent before invoking any tool”.1 Conectarea unui server MCP nu este adăugarea unei dependențe. Este acordarea către un străin a 1.619 tokens din system prompt și a dreptului de a fi apelat. Capitolul 30 este ce se întâmplă când acel străin este ostil.

Secțiune datată: revizia 2026-07-28 și ce strică

Link către secțiunea: Secțiune datată: revizia 2026-07-28 și ce strică

Totul din această secțiune este adevărat pentru revizia de protocol 2026-07-28, cea curentă, citită pe 7 septembrie 2026. Reviziile sunt datate YYYY-MM-DD, iar data este ultima dată când a fost făcută o schimbare incompatibilă înapoi.10 Documentul normativ este un fișier TypeScript, schema/2026-07-28/schema.ts; JSON Schema de lângă el este generat din acesta, de aceea specificația este citită aici în TypeScript și de aceea a preda MCP din orice altceva înseamnă a preda o traducere.

Ce s-a schimbatEraEste acumStrică
Handshake-ulinitialize + notifications/initialized, o dată per conexiuneeliminat; fiecare cerere poartă versiunea și capabilitățile _metafiecare client scris înainte de această revizie
Sesiunileheader Mcp-Session-Id, stare legată de conexiuneeliminate; starea călătorește în handle-uri explicite create de serverendpointuri de listare care variau per conexiune
Discoverydedus din rezultatul initializeserver/discover, pe care serverele trebuie să îl implementezenimic, dar acum este obligatoriu de implementat
Apeluri server-către-clientserverul trimitea roots/list, sampling/createMessage, elicitation/createInputRequiredResult și un retry al clientuluifiecare server care împingea o cerere către un client
Forma rezultatuluiorice obiectresultType obligatoriu: "complete" sau "input_required"nimic: un câmp absent trebuie citit ca "complete"
Subscriptionsstream HTTP GET, resources/subscribeun stream subscriptions/listen cu tipuri opt-inendpointul GET a dispărut
Reluarea streamuluireplay Last-Event-ID pe Streamable HTTPeliminat; un stream rupt pierde cererea, retrimite cu un id nouclienți care se bazau pe redelivery
Rootso funcționalitate de client pe care serverele o puteau ceredeprecated (SEP-2577); transmite căi ca argumente de instrument sau URI-uri de resursenimic încă — fereastră de douăsprezece luni
Sampling și loggingfuncționalități de clientdeprecated (SEP-2577)nimic încă — fereastră de douăsprezece luni
Transport HTTP+SSEdeprecated din 2025-03-26Deprecated sub politica de lifecycle (SEP-2596)migrează la Streamable HTTP
Înregistrarea clientuluiOAuth 2.0 Dynamic Client Registration, RFC 7591deprecated în favoarea Client ID Metadata Documentspăstrat pentru servere de autorizare fără ele
Coduri de eroare-32002 pentru resursă negăsită-32602; -32020-32099 rezervate pentru specificațiecoduri noi -32020, -32021, -32022

Schimbarea de guvernanță de sub acel tabel contează mai mult decât orice rând individual. Această revizie a adoptat o politică de feature lifecycle și deprecate: funcționalitățile sunt Active, Deprecated sau Removed, o funcționalitate deprecated își documentează calea de migrare și rămâne în specificație cel puțin douăsprezece luni înainte să devină eligibilă pentru eliminare, iar un registru listează tot ce se află în prezent în starea Deprecated.8 Înainte de acea politică, „deprecated” într-un protocol AI însemna orice spunea ultimul articol de blog. Acum înseamnă o dată.

Afișează detaliile

Extensiile, partea despre care nu a scris încă nimeni.

Dincolo de nucleu, MCP definește extensii opționale — „always opt-in and require explicit support from both client and server”, declarate printr-un câmp extensions în capabilitățile clientului și serverului.1 Trei merită cunoscute pe nume:

  • Tasks (io.modelcontextprotocol/tasks), mutate din protocolul de bază într-o extensie oficială în această revizie: execuție asincronă a operațiunilor de durată, cu polling prin tasks/get, input în timpul rulării prin tasks/update și handle-uri durabile. Este răspunsul la un instrument care durează douăzeci de minute, lucru pe care Capitolul 23 l-a tratat cu un eveniment de progres și un semnal care ajunge la instrument.
  • Skills over MCP, un grup de lucru care face agent skills — subiectul Capitolului 28 — descoperibile și consumabile prin protocol.
  • MCP Apps, UI interactiv redat inline în conversație: grafice, formulare, playere video.

Și observă ce înseamnă acum „negociat”: nu există initialization la care să negociezi, deci o extensie este declarată per cerere, ca orice altceva.

Unde se află MCP față de tot ce se confundă cu el

Link către secțiunea: Unde se află MCP față de tot ce se confundă cu el

Acesta este vocabularul întregului bloc, într-un singur loc.

Ce esteCine vorbește cu cineCând este răspunsul
Un API simpluO interfață pentru un programcodul tău ↔ un serviciuTu scrii apelantul. Tu controlezi schema, auth și tratarea erorilor, iar nu există o problemă de discovery de rezolvat.
MCPUn protocol pentru expunerea instrumentelor, datelor și șabloanelor către o aplicație AIhost ↔ server, câte un client pentru fiecareAltcineva a scris capabilitatea și multe hosturi ar trebui să o poată folosi fără o integrare bespoke.
RAGO tehnică pentru găsirea textului și introducerea lui în promptcodul tău ↔ indexul tăuModelul trebuie să știe ceva. Capitolul 19. MCP este o cale de a livra un retriever; nu este un retriever.
Agent skillsUn folder cu un SKILL.md pe care modelul îl citeștemodel ↔ un documentCunoașterea este procedurală — cum facem noi asta — și este proză, nu funcție. Capitolul 28.
A2AUn protocol prin care agent colaborează ca egaliagent ↔ agentCealaltă parte raționează, planifică și păstrează stare pe parcursul unei sarcini lungi, în loc să răspundă la un apel.
ACPA fost un protocol separat de comunicare între agentNu mai este o comparație activă. Vezi mai jos.

Două dintre acestea merită câte o propoziție, fiindcă acolo apare de fapt confuzia.

MCP față de A2A nu este o rivalitate, iar ambele specificații o spun. Documentația A2A trasează linia după ce este la celălalt capăt: MCP „defines how an AI agent interacts with and utilizes individual tools and resources, such as a database or an API”, unde un instrument îndeplinește „specific, often stateless, functions”; A2A se ocupă de agent, „more autonomous systems” care „reason, plan, use multiple tools, maintain state over longer interactions, and engage in complex, often multi-turn dialogues”. Propriul rezumat este propoziția de ținut minte: „A2A is about agents partnering on tasks, while MCP is more about agents using capabilities.”11 Cele două se imbrică — o aplicație folosește A2A pentru a ajunge la alți agent, iar fiecare agent folosește MCP pentru a ajunge la propriile instrumente. Capitolul 25 a trasat acea linie în interiorul unui singur proces, între a întreba un sub-agent și a-i preda conversația; A2A o trasează între organizații.

MCP față de ACP este o comparație cu o premisă expirată, exact de aceea merită răspunsă. Agent Communication Protocol a fost un standard deschis separat pentru mesagerie agent-to-agent. Propria documentație se deschide acum cu anunțul: „ACP is now part of A2A under the Linux Foundation!”12 Răspunsul onest la „MCP sau ACP?” în septembrie 2026 este că întrebarea are cu o opțiune mai puțin decât sugerează paginile care se poziționează pentru ea.

Iar comparația pe care oamenii o cer cel mai des, mcp vs api, are răspunsul cel mai puțin interesant: MCP este un API. Ce adaugă nu este putere, ci convenții — un set fix de nume de metode, un apel de discovery, o ierarhie de control peste primitive și un model de izolare. Renunți la libertatea de a-ți proiecta propria interfață și primești fiecare host care vorbește protocolul, adică schimbul pe care l-a oferit dintotdeauna orice protocol.

Acum poți citi specificația fără translator, poți deosebi o resursă de un instrument și de un prompt după cine deține controlul, poți scrie o cerere de mână când o bibliotecă de client te minte și poți data orice articol MCP pe care îl citești după care dintre funcționalitățile deprecated încă le predă ca fiind curente.

Ce nu ai făcut încă este să livrezi unul. Capitolul 27 scrie același server de două ori — TypeScript și Python, side by side, fiindcă MCP este singurul teritoriu cu adevărat bilingv din acest curs, iar cifrele o spun în ambele direcții. Acoperă corect cele două transporturi live, inspectorul, packagingul și jumătatea de protocol pe care acest capitol a lăsat-o deliberat deoparte: authorization. Fiindcă în clipa în care serverul tău este remote, nu un subprocess pe propriul laptop, clientul unui străin va prezenta un token, iar regula specificației despre ce ai voie să faci cu el este neobișnuit de strictă.

Ceea ce ridică întrebarea la care capitolul următor trebuie să răspundă, și nu este una prietenoasă: dacă un token ajunge la serverul tău și a fost emis pentru audience-ul altcuiva, ce anume te oprește să îl forwardezi?


Fiecare citat, nume de metodă, cod de eroare și regulă din acest capitol a fost citit din specificația Model Context Protocol, revizia 2026-07-28, pe 7 septembrie 2026. Fiecare urmă a fost produsă local pe Node 22: serverul de calendar de jucărie are 101 linii fără dependențe, iar serverul de referință este pachetul npm publicat, numit mai jos. Nu a fost apelat niciun API plătit pentru a scrie acest capitol — nimic de aici nu are nevoie de un model, iar acesta este chiar sensul.

Măsurătorile: @modelcontextprotocol/server-everything@2026.8.31, publicat pe 31 august 2026, construit pe @modelcontextprotocol/sdk@1.30.0, publicat pe 27 iulie 2026 — cu o zi înaintea reviziei pe care o descrie acest capitol. Răspunde la server/discover cu -32601, negociază 2025-11-25 când i se cere 2026-07-28 și servește tools/list fără niciun handshake. Catalogul său are 13 instrumente în 7.663 bytes; numărătorile de token sunt o200k_base prin tiktoken, peste name, description și inputSchema ale fiecărei definiții, adică ce redă un provider în prompt, nu cât cântărește frame-ul JSON-RPC.

Anthropic, Code execution with MCP: building more efficient agents, 4 noiembrie 2025, este sursa cifrei 150.000-la-2.000, citată și folosită în Capitolul 24 și doar referită aici.

  1. Specification, modelcontextprotocol.io/specification/latest (redirecționând către /2026-07-28), citit pe 7 septembrie 2026. Sursa comparației cu Language Server Protocol; a afirmației că specificația este „based on the TypeScript schema in schema.ts”; a rezumatului protocolului de bază („Stateless, self-contained requests”, „Per-request capability negotiation”); a listei de extensii (Tasks, Skills over MCP, MCP Apps) și a afirmației că extensiile „are always opt-in and require explicit support from both client and server”; și a principiilor Security and Trust & Safety, inclusiv „Hosts must obtain explicit user consent before invoking any tool” și tratarea adnotărilor de instrumente ca neîncrezute. 2 3

  2. Base Protocol, modelcontextprotocol.io/specification/2026-07-28/basic. Sursa constrângerilor JSON-RPC (id non-null, fără reutilizare de id, resultType obligatoriu); a secțiunii Statelessness și a notei ei că un proces stdio deschis nu este o sesiune; a tabelului de chei rezervate _meta și a statutului obligatoriu/opțional al fiecărui câmp per cerere; a regulii -32602 pentru un câmp obligatoriu lipsă; a regulii MissingRequiredClientCapability (-32021); și a politicii de alocare a codurilor de eroare. 2 3 4 5

  3. stdio transport, modelcontextprotocol.io/specification/2026-07-28/basic/transports/stdio. Sursa regulilor de framing delimitate prin newline, a cerinței de puritate stdout, a permisiunii stderr și a sondei de compatibilitate înapoi cu trei rezultate — inclusiv avertismentul că unele servere legacy procesează metode ambigue de epocă fără handshake, lucru pe care măsurătoarea din acest capitol îl reproduce. 2 3

  4. Transports overview, modelcontextprotocol.io/specification/2026-07-28/basic/transports. Sursa formulării „a transport is a binding” și a afirmației că serverele nu inițiază cereri JSON-RPC și clienții nu trimit răspunsuri JSON-RPC. 2

  5. Discovery, modelcontextprotocol.io/specification/2026-07-28/server/discover. Sursa statutului obligatoriu al server/discover, a formei DiscoverResult și a câmpului instructions descris ca „optional natural-language guidance for LLMs on how to use this server effectively”.

  6. Architecture, modelcontextprotocol.io/specification/2026-07-28/architecture. Sursa definițiilor host/client/server, a regulii 1:1 client-către-server, a celor patru principii de design, dintre care principiul izolării este citat aici fără al cincilea bullet, „Host process enforces security boundaries”, și a secțiunii despre capability-negotiation. 2

  7. Elicitation, .../client/elicitation, și Sampling, .../client/sampling. Sursa celor două moduri de elicitation și a schemei lor restrânse; a interdicției de a solicita acreditări prin modul formular; a definiției sampling, a cerinței human-in-the-loop și a avertismentului de deprecate atașat lui.

  8. Key Changes, modelcontextprotocol.io/specification/2026-07-28/changelog, și Feature lifecycle and deprecation policy, .../community/feature-lifecycle. Sursa fiecărui rând din tabelul schimbărilor: eliminarea sesiunilor și a headerului Mcp-Session-Id (SEP-2567); statelessness și eliminarea initialize (SEP-2575); server/discover (SEP-2575); subscriptions/listen (SEP-2575); Multi Round-Trip Requests și resultType (SEP-2322); eliminarea capacității de reluare a streamurilor (SEP-2575); deprecate pentru Roots, Sampling și Logging (SEP-2577); reclasificarea HTTP+SSE (SEP-2596); deprecate pentru Dynamic Client Registration în favoarea Client ID Metadata Documents; renumerotarea codurilor de eroare; și fereastra de deprecate de douăsprezece luni. 2

  9. Tools, modelcontextprotocol.io/specification/2026-07-28/server/tools, și Server Features, .../server. Sursa tabelului ierarhiei de control reprodus mai sus; a formelor tools/list și tools/call; a distincției isError între erori de protocol și erori de execuție ale instrumentului; a regulilor de numire a instrumentelor și a notei de namespace care recomandă „prefixing tool names with a server identifier”; și a ghidajului non-normativ „Stateful Tools” despre handle-uri explicite.

  10. Versioning, modelcontextprotocol.io/specification/versioning. Sursa schemei YYYY-MM-DD, a stărilor de revizie Draft/Current/Final, a confirmării că 2026-07-28 este curentă și a regulilor de negociere per cerere. Tabelul de niveluri SDK de la modelcontextprotocol.io/docs/sdk listează TypeScript, Python, C#, Go și Rust la Tier 1, Java și Ruby la Tier 2, iar Swift, PHP și Kotlin la Tier 3.

  11. A2A Protocol, versiunea 1.0.0, a2a-protocol.org — specificația și pagina A2A and MCP: Relationship and Distinction, citite pe 7 septembrie 2026. Sursa distincției instrumente-față-de-agent, a afirmației că cele două protocoale „address distinct but highly complementary needs” și a formulării partnering/using.

  12. Agent Communication Protocol, agentcommunicationprotocol.dev, citit pe 7 septembrie 2026: „ACP is now part of A2A under the Linux Foundation!”, un banner adăugat deasupra unei specificații care este încă servită complet — arhitectură, agent manifest, agent discovery, structură de mesaje, agent stateful, run lifecycle și lista de endpointuri REST încă răspund toate 200. Specificația nu a dispărut; proiectul da.

Gata să lași LIA să aleagă?

Construiește cu toate modelele AI într-un singur loc — începe gratuit azi.