MCP explicado fronte á especificación: que é realmente un servidor
Unha liña de JSON a un subprocesso e volven trece definicións de ferramentas, lida contra a revisión 2026-07-28.
Nesta páxina
Instala un servidor MCP publicado, envíalle unha liña de JSON e le o que devolve.
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}Trece definicións de ferramentas, nunha soa liña, desde un proceso que leu unha liña da súa entrada estándar. Acabas de falar o Model Context Protocol, sen SDK, sen biblioteca cliente e sen framework. Iso é todo: un transporte, un formato de mensaxe e un pequeno conxunto de métodos con nome.
O capítulo 18 definiu unha ferramenta como dúas cousas: un JSON Schema que o modelo ve e un endpoint no teu código que o modelo nunca ve. O capítulo 23 construíu un harness que mantén un catálogo delas. Ningún dos dous respondeu á pregunta que decide se algo disto é reutilizable: quen escribe o schema, e como chega desde quen o escribiu ata o teu prompt? MCP é unha resposta a esa pregunta, e paga a pena lelo no orixinal, porque case todo o que se escribiu sobre el describe unha revisión que xa non existe.
Tres cousas sobre o comando que acabas de executar están mal, e cada unha delas é unha sección deste capítulo. Non levaba versión de protocolo, así que un servidor conforme teríao rexeitado. Obtivo unha resposta igualmente, por unha razón que a especificación chama perigo en vez de funcionalidade. E pediu unha das tres primitivas sen descubrir nunca que as outras dúas existen.
O problema que resolve, e a analoxía que fai a propia especificación
Ligazón á sección: O problema que resolve, e a analoxía que fai a propia especificaciónAntes do fío, a aritmética. Tes aplicacións de IA e cousas ás que deberían poder chegar: un calendario, un xestor de tickets, unha base de datos de almacén, unha ferramenta de deseño. Sen un contrato compartido, alguén escribe integracións, e cada unha delas é un schema máis un endpoint máis unha historia de autenticación máis unha carga de mantemento. Con un, o provedor da ferramenta escribe un servidor, o provedor da aplicación escribe un cliente, e o total é .
Non é unha observación nova, e a especificación di de quen foi a idea:
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
Toma esa comparación literalmente, non como un eloxio. Antes dese protocolo, dar soporte a unha linguaxe nun editor significaba un plugin por editor; despois, un equipo de linguaxe distribuía un servidor e todos os editores o obtiñan. A medida do éxito non era a elegancia, era que a conta de integracións deixaba de multiplicarse. Aquí pasa o mesmo: o valor está no número de implementacións, non no deseño. Un protocolo que falan dous produtos é un formato de datos con cerimonia extra.
Que hai realmente no fío
Ligazón á sección: Que hai realmente no fíoAs mensaxes MCP son JSON-RPC 2.0. Unha petición é un obxecto con jsonrpc, un id, un method e params opcional; unha resposta leva o mesmo id e ou ben result ou ben error; unha notificación é unha petición sen id e non recibe resposta. A especificación engade tres restricións por riba: o id debe ser unha cadea ou un número e non debe ser null, non debe colidir con outra petición aínda en curso, e cada resultado debe levar un campo resultType.2
No transporte stdio —o que usou o comando anterior— a regra de framing é unha liña por mensaxe:
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
Esa última cláusula é a forma máis común na que rompe un servidor feito na casa, e rompe en silencio: un console.log perdido, unha barra de progreso, un aviso de deprecación dunha dependencia, e o parser de liñas do cliente bate con algo que non é JSON. A vía de escape está na mesma sección: o servidor pode escribir o que queira en stderr, e o cliente non debería tratalo como un erro. O servidor de referencia anterior imprime Starting default (STDIO) server... en cada arranque, en stderr, por iso a tubaxe seguiu funcionando.
O outro transporte estándar é Streamable HTTP: cada mensaxe é un POST a un único endpoint, e a resposta é ou ben un obxecto JSON ou ben un fluxo de Server-Sent Events limitado á petición: o formato de fío que o capítulo 14 parseou á man. A semántica é idéntica nos dous, porque un transporte é un binding: define framing e entrega, non significado.4
A primeira cousa que estaba mal: non había versión
Ligazón á sección: A primeira cousa que estaba mal: non había versiónO comando anterior enviou tools/list e nada máis. Segundo a revisión actual, esa petición está mal formada, e un servidor conforme debe rexeitala.
Desde o 2026-07-28, MCP é un protocolo sen estado, e a especificación dilo sen matices:
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
Así que cada petición leva a súa propia versión de protocolo e as súas propias capacidades de cliente, nun obxecto reservado _meta dentro de params. Dous deses campos son obrigatorios en absolutamente cada petición; unha petición á que lle falte calquera deles está mal formada e o servidor debe responder -32602:2
clave _meta | obrigatoria | que é |
|---|---|---|
io.modelcontextprotocol/protocolVersion | si | a revisión que fala esta petición, p. ex. "2026-07-28" |
io.modelcontextprotocol/clientCapabilities | si | o que o cliente pode facer polo servidor nesta petición |
io.modelcontextprotocol/clientInfo | non (pero debería) | nome e versión do cliente, só para visualización e logs |
io.modelcontextprotocol/logLevel | non | o nivel mínimo de log que o servidor debería emitir para esta petición |
Escrito completo, un tools/list correcto é isto —e é a última vez que este capítulo mostra os metadatos enteiros, porque desde aquí van en cada petición:
{"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"}}}}O obxecto de capacidades é a negociación. Xa non hai un paso de negociación separado: o cliente declara o que pode facer en cada petición, o servidor declara o que pode facer no resultado, e ningún dos lados pode usar unha función que o outro non reivindicou. Un servidor que necesita unha capacidade que o cliente non declarou debe responder -32021 e nomear a capacidade que falta en data.requiredCapabilities. Un servidor que non fala a versión solicitada debe responder -32022 e listar as versións que si fala.2
Os clientes que queiran a resposta por adiantado poden pedila: server/discover é unha RPC obrigatoria que devolve versións soportadas, capacidades, identidade e un bloque opcional de instructions nunha soa ida e volta.5 Chamala é opcional. Implementala non.
A segunda cousa que estaba mal: o servidor era legacy
Ligazón á sección: A segunda cousa que estaba mal: o servidor era legacyO comando funcionou. Segundo a revisión actual non debería telo feito, e paga a pena medir a razón máis ca explicala nun parágrafo, porque é o estado de todo o ecosistema nunha liña.
Proba o servidor de referencia como a especificación lle di a un cliente moderno que probe:
echo '{"jsonrpc":"2.0","id":1,"method":"server/discover","params":{"_meta":{
"io.modelcontextprotocol/protocolVersion":"2026-07-28",
"io.modelcontextprotocol/clientCapabilities":{}}}}' \
| npx @modelcontextprotocol/server-everything stdio{"jsonrpc":"2.0","id":1,"error":{"code":-32601,"message":"Method not found"}}Esa é a terceira rama da regra de compatibilidade: un DiscoverResult significa moderno, un erro moderno recoñecido significa moderno-pero-versión-incorrecta, e calquera outra cousa —incluído -32601— significa legacy, volve ao handshake initialize.3 Así que fai iso, pedindo a revisión actual:
→ {"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":"…"}}O cliente pediu 2026-07-28 e o servidor respondeu 2025-11-25. O 7 de setembro de 2026, o servidor oficial de referencia —paquete npm @modelcontextprotocol/server-everything, versión 2026.8.31, publicado o 31 de agosto de 2026— non implementa a revisión actual. Tampouco, polas datas, o fai o SDK TypeScript sobre o que está construído: a release 1.30.0 saíu o 27 de xullo de 2026, o día anterior á revisión.
Le a consecuencia, non o cotilleo. Case todo o que se escribiu sobre MCP describe un protocolo cun handshake initialize, unha sesión, unha petición roots/list que o servidor envía ao cliente e un transporte HTTP+SSE. As catro cousas desapareceron ou están desaparecendo. Cando leas calquera cousa sobre MCP, incluída esta páxina, o primeiro que debes buscar é un número de revisión.
E a razón pola que o primeiro comando funcionou aparece na especificación como un perigo, non como unha funcionalidade:
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
Medido: enviar tools/list a ese servidor sen ningún handshake devolve o catálogo completo. Un método que debería ser rexeitado foi servido, que é exactamente por que a especificación di que probes con server/discover primeiro mesmo cando só soportas versións modernas.
Tres roles, e a frase que citar de todo o documento
Ligazón á sección: Tres roles, e a frase que citar de todo o documentoMCP ten tres partes, e a distinción entre as dúas primeiras é a que a xente adoita comprimir:
Host. A aplicación: o produto de chat, o editor, o agent. É quen posúe a conversa, o modelo, as credenciais e o consentimento do usuario. Crea clientes e aplica a fronteira de seguridade entre eles.
Cliente. Un conector dentro do host. Cada cliente fala con exactamente un servidor —unha relación estrita 1:1— e engade a versión do protocolo e as capacidades a cada petición que enruta.
Servidor. Un proceso ou un servizo que expón recursos, ferramentas e prompts. Pode ser local ou remoto, opera de maneira independente, e todo o seu traballo é unha área enfocada.6
Esa regra de "exactamente un servidor" non é burocracia. É o que fai implementable o principio de deseño de abaixo, e esta é a frase que debes levar da especificación se só levas unha:
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
Iso derruba o modelo mental co que chega a maioría da xente. Un servidor do tempo que conectas ao teu asistente non ve o que preguntaches. Ve un tools/call cos argumentos que escolleu o modelo, e nada máis: nin as quendas anteriores, nin o teu system prompt, nin os resultados que devolveu hai un intre o servidor de calendario. Se dous servidores teñen que cooperar, o host leva un valor dun ao outro, deliberadamente, porque o modelo o pediu. Por iso o illamento é a propiedade de seguridade na que se apoia o capítulo 30: un servidor comprometido ten un radio de explosión pequeno e definido, e amplialo require que o host coopere.
A terceira cousa: tres primitivas, ordenadas por quen manda
Ligazón á sección: A terceira cousa: tres primitivas, ordenadas por quen mandaO primeiro comando pediulle ferramentas a ese servidor e recibiu trece. Failles as outras dúas preguntas e tamén as responde: resources/list devolve sete, prompts/list devolve catro. Ningunha delas apareceu, porque nada preguntou. Isto lévanos á columna vertebral pedagóxica de MCP, situada na especificación como unha táboa que case ninguén cita:
| Primitiva | Control | Descrición | Exemplo |
|---|---|---|---|
| Prompts | Controlado polo usuario | Templates interactivas invocadas por elección do usuario | Comandos slash, opcións de menú |
| Recursos | Controlado pola aplicación | Datos contextuais anexados e xestionados polo cliente | Contidos de ficheiros, historial git |
| Ferramentas | Controlado polo modelo | Funcións expostas ao LLM para realizar accións | Peticións API POST, escritura de ficheiros |
Non "tres formas de expoñer unha capacidade". Tres respostas a quen decide que isto acontece. O modelo decide chamar unha ferramenta. A aplicación decide anexar un recurso. A persoa decide executar un prompt. Se o entendes mal, a funcionalidade segue funcionando, pero funciona no momento equivocado e polo motivo equivocado.
A forma máis clara de notalo é un calendario. Aquí tes un servidor que expón o mesmo calendario tres veces, unha como cada primitiva, en cen liñas de Node puro sen dependencias:
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" });
}Execútao e pregúntalle das tres maneiras. Saída real, unha mensaxe por liña no fío, envolta aquí para a páxina, coa petición _meta e o bloque de identidade do servidor omitidos:
→ 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}Tres métodos, tres formas, un calendario. Agora o punto:
Ler a semana é un recurso
Ligazón á sección: Ler a semana é un recursoEstá dirixido por unha URI, é inerte, e a aplicación decide se o anexa á conversa. Nada no protocolo deixa que o modelo vaia buscalo pola súa conta. O resultado leva ttlMs e cacheScope, novos nesta revisión, para que o cliente poida cachear a semana durante un minuto en vez de facer polling.
Crear un evento é unha ferramenta
Ligazón á sección: Crear un evento é unha ferramentaTen un schema, ten efectos secundarios, e o modelo decide cando chamala. O seu resultado leva isError, que é o campo polo que argumentaba o capítulo 18: unha validación fallida volve como resultado da ferramenta que o modelo pode ler e corrixir, non como erro de protocolo.
"Preparar a miña semana" é un prompt
Ligazón á sección: "Preparar a miña semana" é un promptÉ unha template con nome e argumentos que a persoa invoca: o comando slash no menú. Devolve mensaxes, non unha resposta. É unha maneira de que o autor dun servidor distribúa a formulación que funciona coas súas propias ferramentas, que é exactamente o coñecemento que ten o autor do servidor e non ten o usuario.
Case todo o mundo converte estas tres cousas en ferramentas. O resultado é un catálogo no que unha lectura que a aplicación debería anexar en silencio compite pola attention do modelo cunha escritura que precisa aprobación, e no que o único para o que unha persoa quería un botón queda soterrado nun schema. Non custa nada facelo ben, e decídese antes de escribir unha liña.
O servidor non pode chamarte
Ligazón á sección: O servidor non pode chamarteA ferramenta de calendario ten un argumento obrigatorio, title, e un startsAt opcional. Pídelle que cree un evento sen data, e devolve algo interesante:
→ 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=="}O servidor non enviou unha petición. Respondeu á que recibiu, con resultType: "input_required" e unha descrición do que aínda necesita. O cliente recolle a resposta da persoa, e logo reenvía a chamada orixinal, cun novo id, levando inputResponses e ecoando de volta o requestState opaco:
→ 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}Isto son Multi Round-Trip Requests, introducidas na revisión actual, e substituíron o deseño anterior no que os servidores enviaban peticións JSON-RPC de volta aos clientes. A especificación de transporte agora indica a regra sen rodeos: "servers do not initiate JSON-RPC requests and clients do not send JSON-RPC responses".4 Hai unha soa dirección de iniciativa, e pertence ao host.
Dúas funcionalidades do lado do cliente van montadas nese mecanismo, e unha delas ten un nome que che fará tropezar.
Elicitation é o servidor pedíndolle algo á persoa: un formulario cun JSON Schema deliberadamente restrinxido —obxectos planos, propiedades primitivas, sen aniñamento— para que calquera cliente poida renderizalo sen motor de layout. Leva unha regra dura: os servidores non deben usar o modo formulario para pedir "passwords, API keys, access tokens, or payment credentials", e deben usar o modo URL para iso, que envía o usuario a unha páxina que o cliente nunca le.7
Sampling é o servidor pedíndolle unha xeración ao modelo do host, para que un servidor poida ser intelixente sen gardar unha API key. E aquí vai o aviso de vocabulario, porque esta palabra xa significa outra cousa neste curso: isto non é o sampling do capítulo 17. Aquí nada vai de temperatura, top-p nin da forma dunha distribución de probabilidade. É unha chamada de modelo aniñada que viaxa cara atrás a través dun protocolo.
Hai unha segunda razón para non usalo de primeiras: nesta revisión, sampling está deprecated, xunto con roots e logging, baixo SEP-2577, cunha migración suxerida moi clara: "integrate directly with LLM provider APIs instead of Sampling".8 A idea non fallou tecnicamente; non xustificou a súa superficie, e un protocolo que pode quitar cousas é máis san ca un que non pode.
Rómpeo a propósito: as conexións non son sesións
Ligazón á sección: Rómpeo a propósito: as conexións non son sesiónsA ausencia de estado soa a detalle de formato de fío ata que a probas. Colle o intercambio de tres mensaxes de arriba e executa cada mensaxe nun proceso separado: un node calendar.mjs novo, sen memoria compartida, sen arrastrar nada:
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)O proceso B, que nunca viu a pregunta, completou unha chamada multi-round-trip que iniciou o proceso A. Ese é o propósito de requestState: a continuación viaxa na mensaxe, así que nada depende de que o proceso sexa o mesmo.
O proceso C é o fallo. O evento foi creado e non está aí, porque o servidor de xoguete garda EVENTS nun array a nivel de módulo, e un array a nivel de módulo é estado de conexión. A nota da especificación nomea o erro con precisión:
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
A corrección prescrita non é unha sesión. É un handle explícito: unha ferramenta de creación devolve un identificador opaco, e cada chamada posterior tómao como un argumento ordinario. O protocolo non ten ningún concepto del: "from the wire's perspective a handle is an ordinary string in a tool result and an ordinary argument to subsequent tool calls".9 Iso pon o modelo a cargo de transportalo, e pon o servidor a cargo de validar que este chamador ten permiso para usalo en cada chamada, porque un handle é un nome e non un permiso.
Que custa un servidor antes de facer nada
Ligazón á sección: Que custa un servidor antes de facer nadaCada ferramenta que expón un servidor é un schema que entra no teu prompt en cada petición, e o capítulo 24 mediu o que iso lle fai a unha window. MCP engade unha segunda partida fácil de pasar por alto, así que paga a pena contar as dúas no servidor de referencia de arriba.
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 tokensDúas observacións. A primeira é aritmética: conecta cinco servidores deste tamaño e aproximadamente oito mil tokens da túa window quedan ocupados en cada quenda, para sempre, use ou non o modelo algún deles; este é o mecanismo detrás da redución de 150.000 a 2.000 que citou o capítulo 24, e a razón pola que existe o descubrimento de ferramentas just-in-time.
A segunda é unha nota de seguridade disfrazada de contabilidade. instructions é texto en linguaxe natural, escrito polo autor do servidor, que aterra no prompt do host, e as descricións das ferramentas ao lado son o mesmo. A especificación di que facer con iso nos seus propios principios de seguridade: as anotacións e descricións de ferramentas "should be considered untrusted, unless obtained from a trusted server", e os hosts "must obtain explicit user consent before invoking any tool".1 Conectar un servidor MCP non é engadir unha dependencia. É concederlle a un estraño 1.619 tokens do teu system prompt e o dereito a ser chamado. O capítulo 30 é o que pasa cando ese estraño é hostil.
Sección datada: a revisión 2026-07-28, e o que rompe
Ligazón á sección: Sección datada: a revisión 2026-07-28, e o que rompeTodo nesta sección é certo para a revisión do protocolo 2026-07-28, a actual, lida o 7 de setembro de 2026. As revisións dátanse como YYYY-MM-DD e a data é a última vez que se fixo un cambio incompatible cara atrás.10 O documento normativo é un ficheiro TypeScript, schema/2026-07-28/schema.ts; o JSON Schema que hai ao lado xérase a partir del, por iso aquí a especificación se le en TypeScript e por iso ensinar MCP desde calquera outra cousa é ensinar unha tradución.
| Que cambiou | Era | É agora | Rompe |
|---|---|---|---|
| O handshake | initialize + notifications/initialized, unha vez por conexión | eliminado; cada petición leva versión e capacidades _meta | todos os clientes escritos antes desta revisión |
| Sesións | cabeceira Mcp-Session-Id, estado limitado á conexión | eliminadas; o estado viaxa en handles explícitos xerados polo servidor | endpoints de lista que variaban por conexión |
| Descubrimento | inferido do resultado initialize | server/discover, que os servidores deben implementar | nada, pero agora é obrigatorio implementalo |
| Chamadas de servidor a cliente | o servidor enviaba roots/list, sampling/createMessage, elicitation/create | InputRequiredResult e un reintento do cliente | todos os servidores que empurraban unha petición a un cliente |
| Forma do resultado | calquera obxecto | resultType obrigatorio: "complete" ou "input_required" | nada: un campo ausente debe lerse como "complete" |
| Subscricións | fluxo HTTP GET, resources/subscribe | un fluxo subscriptions/listen con tipos opt-in | o endpoint GET desaparece |
| Reanudación de fluxo | replay Last-Event-ID en Streamable HTTP | eliminado; un fluxo roto perde a petición, reemítea cun novo id | clientes que dependían da reentrega |
| Roots | unha funcionalidade de cliente que os servidores podían pedir | deprecated (SEP-2577); pasa rutas como argumentos de ferramenta ou URIs de recurso | nada aínda: xanela de doce meses |
| Sampling e logging | funcionalidades de cliente | deprecated (SEP-2577) | nada aínda: xanela de doce meses |
| Transporte HTTP+SSE | deprecated desde 2025-03-26 | Deprecated baixo a política de ciclo de vida (SEP-2596) | migra a Streamable HTTP |
| Rexistro de cliente | OAuth 2.0 Dynamic Client Registration, RFC 7591 | deprecated en favor de Client ID Metadata Documents | mantido para servidores de autorización sen eles |
| Códigos de erro | -32002 para recurso non atopado | -32602; -32020–-32099 reservados para a especificación | novos códigos -32020, -32021, -32022 |
O cambio de gobernanza baixo esa táboa importa máis ca calquera fila concreta. Esta revisión adoptou unha política de ciclo de vida de funcionalidades e deprecación: as funcionalidades son Active, Deprecated ou Removed, unha funcionalidade deprecated documenta a súa ruta de migración e queda na especificación polo menos doce meses antes de ser elixible para a eliminación, e hai un rexistro que lista todo o que está actualmente no estado Deprecated.8 Antes desa política, "deprecated" nun protocolo de IA significaba o que dixese o último blog post. Agora significa unha data.
Mostrar detalles
Extensións, que son a parte sobre a que aínda non escribiu ninguén.
Máis alá do núcleo, MCP define extensións opcionais: "always opt-in and require explicit support from both client and server", declaradas mediante un campo extensions nas capacidades do cliente e do servidor.1 Tres paga a pena coñecelas polo nome:
- Tasks (
io.modelcontextprotocol/tasks), movida fóra do protocolo núcleo a unha extensión oficial nesta revisión: execución asíncrona de operacións longas, con polling mediantetasks/get, entrada en metade do voo mediantetasks/updatee handles duradeiros. É a resposta a unha ferramenta que tarda vinte minutos, que o capítulo 23 resolveu cun evento de progreso e un sinal que chega á ferramenta. - Skills over MCP, un grupo de traballo que fai que as skills de agent —o tema do capítulo 28— sexan descubribles e consumibles a través do protocolo.
- MCP Apps, UI interactiva renderizada inline na conversa: gráficas, formularios, reprodutores de vídeo.
E observa que significa agora "negociado": non hai inicialización na que negociar, así que unha extensión declárase por petición como todo o demais.
Onde encaixa MCP fronte a todo aquilo co que se confunde
Ligazón á sección: Onde encaixa MCP fronte a todo aquilo co que se confundeEste é o vocabulario de todo o bloque nun só lugar.
| Que é | Quen fala con quen | Cando é a resposta | |
|---|---|---|---|
| Unha API simple | Unha interface para un programa | o teu código ↔ un servizo | Estás escribindo o chamador. Controlas o schema, a auth e a xestión de erros, e non hai un problema de descubrimento que resolver. |
| MCP | Un protocolo para expoñer ferramentas, datos e templates a unha aplicación de IA | host ↔ servidor, un cliente por cada un | Outra persoa escribiu a capacidade e moitos hosts deberían poder usala sen unha integración a medida. |
| RAG | Unha técnica para atopar texto e poñelo no prompt | o teu código ↔ o teu índice | O modelo necesita saber algo. Capítulo 19. MCP é unha maneira de entregar un retriever; non é un retriever. |
| Agent skills | Un cartafol cun SKILL.md que o modelo le | modelo ↔ un documento | O coñecemento é procedemental —como o facemos nós— e é prosa, non unha función. Capítulo 28. |
| A2A | Un protocolo para que agents colaboren como pares | agent ↔ agent | O outro lado razoa, planifica e mantén estado ao longo dunha tarefa longa, en vez de responder unha chamada. |
| ACP | Era un protocolo separado de comunicación entre agents | — | Xa non é unha comparación viva. Mira abaixo. |
Dous deles merecen unha frase cada un, porque aí é onde vive realmente a confusión.
MCP fronte a A2A non é unha rivalidade, e as dúas especificacións o din. A documentación de A2A traza a liña polo que hai no outro extremo: MCP "defines how an AI agent interacts with and utilizes individual tools and resources, such as a database or an API", onde unha ferramenta realiza "specific, often stateless, functions"; A2A trata con agents, "more autonomous systems" que "reason, plan, use multiple tools, maintain state over longer interactions, and engage in complex, often multi-turn dialogues". O seu propio resumo é a frase que cómpre lembrar: "A2A is about agents partnering on tasks, while MCP is more about agents using capabilities."11 Os dous aniñan: unha aplicación usa A2A para chegar a outros agents, e cada agent usa MCP para chegar ás súas propias ferramentas. O capítulo 25 trazou esa liña dentro dun proceso, entre preguntarlle a un sub-agent e pasarlle a conversa; A2A trázaa entre organizacións.
MCP fronte a ACP é unha comparación cunha premisa caducada, que é exactamente por iso que paga a pena respondela. O Agent Communication Protocol era un estándar aberto separado para mensaxería agent-to-agent. A súa propia documentación agora abre co aviso: "ACP is now part of A2A under the Linux Foundation!"12 A resposta honesta a "MCP ou ACP?" en setembro de 2026 é que a pregunta ten unha opción menos do que suxiren as páxinas que posicionan por ela.
E a comparación que máis pide a xente, mcp vs api, ten a resposta menos interesante: MCP é unha API. O que engade non é potencia, son convencións: un conxunto fixo de nomes de métodos, unha chamada de descubrimento, unha xerarquía de control sobre as primitivas e un modelo de illamento. Renuncias á liberdade de deseñar a túa propia interface e recibes todos os hosts que falan o protocolo, que é o intercambio que todo protocolo ofreceu sempre.
Onde vai isto agora
Ligazón á sección: Onde vai isto agoraAgora podes ler a especificación sen tradutor, distinguir un recurso dunha ferramenta e dun prompt por quen está a cargo del, escribir unha petición á man cando unha biblioteca cliente che mente, e poñerlle data a calquera artigo sobre MCP que leas mirando cales das funcionalidades deprecated segue ensinando como actuais.
O que aínda non fixeches é publicar un. O capítulo 27 escribe o mesmo servidor dúas veces —TypeScript e Python, lado a lado, porque MCP é o único territorio realmente bilingüe deste curso e os números din o mesmo nas dúas direccións. Cobre correctamente os dous transportes vivos, o inspector, o empaquetado e a metade do protocolo que este capítulo deixou deliberadamente a un lado: autorización. Porque no momento en que o teu servidor é remoto en vez dun subprocesso no teu propio portátil, o cliente dun estraño presentará un token, e a regra da especificación sobre o que podes facer con el é inusualmente estrita.
Isto suscita a pregunta que debe responder o seguinte capítulo, e non é amable: se un token chega ao teu servidor e foi emitido para a audience doutra persoa, que impide exactamente que o reenvíes?
Fontes e método
Ligazón á sección: Fontes e métodoCada cita, nome de método, código de erro e regra deste capítulo leuse na especificación do Model Context Protocol, revisión 2026-07-28, o 7 de setembro de 2026. Cada traza produciuse localmente en Node 22: o servidor de calendario de xoguete ten 101 liñas sen dependencias, e o servidor de referencia é o paquete npm publicado que se nomea abaixo. Non se chamou ningunha API de pago para escribir este capítulo: nada aquí necesita un modelo, que é en si mesmo o punto.
As medicións: @modelcontextprotocol/server-everything@2026.8.31, publicado o 31 de agosto de 2026, construído sobre @modelcontextprotocol/sdk@1.30.0, publicado o 27 de xullo de 2026, un día antes da revisión que describe este capítulo. Responde server/discover con -32601, negocia 2025-11-25 cando se lle pide 2026-07-28, e serve tools/list sen ningún handshake. O seu catálogo son 13 ferramentas en 7.663 bytes; as contas de tokens son o200k_base vía tiktoken, sobre o name, description e inputSchema de cada definición, que é o que un provedor renderiza no teu prompt e non o que pesa o frame JSON-RPC.
Anthropic, Code execution with MCP: building more efficient agents, 4 de novembro de 2025, é a fonte da cifra de 150.000 a 2.000, citada e usada no capítulo 24 e só referenciada aquí.
Referencias
Ligazón á sección: Referencias-
Specification,
modelcontextprotocol.io/specification/latest(redirixindo a/2026-07-28), lida o 7 de setembro de 2026. Fonte da comparación co Language Server Protocol; da afirmación de que a especificación está "based on the TypeScript schema inschema.ts"; do resumo do protocolo base ("Stateless, self-contained requests", "Per-request capability negotiation"); da lista de extensións (Tasks, Skills over MCP, MCP Apps) e da afirmación de que as extensións "are always opt-in and require explicit support from both client and server"; e dos principios de Security and Trust & Safety, incluído "Hosts must obtain explicit user consent before invoking any tool" e o tratamento das anotacións de ferramentas como non fiables. ↩ ↩2 ↩3 -
Base Protocol,
modelcontextprotocol.io/specification/2026-07-28/basic. Fonte das restricións JSON-RPC (id non null, non reutilizar id,resultTypeobrigatorio); da sección Statelessness e da súa nota de que un proceso stdio aberto non é unha sesión; da táboa de claves reservadas_metae do estado obrigatorio/opcional de cada campo por petición; da regra-32602para un campo obrigatorio ausente; da regraMissingRequiredClientCapability(-32021); e da política de asignación de códigos de erro. ↩ ↩2 ↩3 ↩4 ↩5 -
stdio transport,
modelcontextprotocol.io/specification/2026-07-28/basic/transports/stdio. Fonte das regras de framing delimitado por saltos de liña, do requisito de pureza destdout, da concesión destderre da proba de compatibilidade cara atrás con tres resultados, incluído o aviso de que algúns servidores legacy procesan métodos ambiguos de era sen handshake, que reproduce a medición deste capítulo. ↩ ↩2 ↩3 -
Transports overview,
modelcontextprotocol.io/specification/2026-07-28/basic/transports. Fonte do framing de "a transport is a binding" e da afirmación de que os servidores non inician peticións JSON-RPC e os clientes non envían respostas JSON-RPC. ↩ ↩2 -
Discovery,
modelcontextprotocol.io/specification/2026-07-28/server/discover. Fonte do carácter obrigatorio deserver/discover, da forma deDiscoverResulte do campoinstructionsdescrito como "optional natural-language guidance for LLMs on how to use this server effectively". ↩ -
Architecture,
modelcontextprotocol.io/specification/2026-07-28/architecture. Fonte das definicións de host/client/server, da regra 1:1 de cliente a servidor, dos catro principios de deseño, dos que aquí se cita o principio de illamento sen a súa quinta viñeta, "Host process enforces security boundaries", e da sección de negociación de capacidades. ↩ ↩2 -
Elicitation,
.../client/elicitation, e Sampling,.../client/sampling. Fonte dos dous modos de elicitation e do seu schema restrinxido; da prohibición de pedir credenciais mediante modo formulario; da definición de sampling, do seu requisito human-in-the-loop e do aviso de deprecación asociado. ↩ -
Key Changes,
modelcontextprotocol.io/specification/2026-07-28/changelog, e Feature lifecycle and deprecation policy,.../community/feature-lifecycle. Fonte de cada fila da táboa de cambios: eliminación de sesións e da cabeceiraMcp-Session-Id(SEP-2567); ausencia de estado e eliminación deinitialize(SEP-2575);server/discover(SEP-2575);subscriptions/listen(SEP-2575); Multi Round-Trip Requests eresultType(SEP-2322); eliminación da reanudabilidade de fluxo (SEP-2575); deprecación de Roots, Sampling e Logging (SEP-2577); reclasificación de HTTP+SSE (SEP-2596); deprecación de Dynamic Client Registration en favor de Client ID Metadata Documents; renumeración de códigos de erro; e a xanela de deprecación de doce meses. ↩ ↩2 -
Tools,
modelcontextprotocol.io/specification/2026-07-28/server/tools, e Server Features,.../server. Fonte da táboa de xerarquía de control reproducida arriba; das formastools/listetools/call; da distinciónisErrorentre erros de protocolo e erros de execución de ferramenta; das regras de nomes de ferramentas e da nota de namespace que recomenda "prefixing tool names with a server identifier"; e da guía non normativa "Stateful Tools" sobre handles explícitos. ↩ -
Versioning,
modelcontextprotocol.io/specification/versioning. Fonte do esquemaYYYY-MM-DD, dos estados de revisión Draft/Current/Final, da confirmación de que 2026-07-28 é actual e das regras de negociación por petición. A táboa de tiers de SDK enmodelcontextprotocol.io/docs/sdklista TypeScript, Python, C#, Go e Rust no Tier 1, Java e Ruby no Tier 2, e Swift, PHP e Kotlin no Tier 3. ↩ -
A2A Protocol, versión 1.0.0,
a2a-protocol.org: a especificación e a páxina A2A and MCP: Relationship and Distinction, lidas o 7 de setembro de 2026. Fonte da distinción entre ferramentas e agents, da afirmación de que os dous protocolos "address distinct but highly complementary needs", e da formulación partnering/using. ↩ -
Agent Communication Protocol,
agentcommunicationprotocol.dev, lido o 7 de setembro de 2026: "ACP is now part of A2A under the Linux Foundation!", un banner engadido por riba dunha especificación que segue servíndose enteira: arquitectura, manifesto de agent, descubrimento de agent, estrutura de mensaxe, agents con estado, ciclo de vida de run e lista de endpoints REST seguen respondendo 200. A especificación non desapareceu; desapareceu o proxecto. ↩