MCP
This block explains how a tool built by another team reaches your agent through the Model Context Protocol (MCP), what the current version of the protocol looks like, and what it leaves for you to secure.
The same two forms for every department
The colleague on the phone keeps asking for things other departments own: parcel status from Shipping, stock counts from the Warehouse. Each department has its own procedure, so you keep a folder of instructions for each.
Then all the departments agree on two forms. One asks "what can you do?" and the other says "please do this." Each department fills in its own answers to the first form, and you read them out to your colleague.
Northwind has three agents that need the same three services. Without a shared format, every pair needs its own adapter.
MCP is that pair of forms, written as JSON-RPC 2.0 messages. The service's API stays where it is. Here an MCP server is an adapter in front of it, and any application that speaks MCP can use it without code written for that server.
Who does what
- The host is your application. It holds the conversation and talks to the model.
- A client is a connector inside the host. It keeps one connection to one server, so a host with four servers holds four client objects, all from the same code.
- A server is a program that offers capabilities. It can run on the same machine or remotely.
The model is not a party to the protocol and opens no connection. Here is one parcel lookup:
- Your app sends
tools/list, and the Shipping server replies with its definitions. - Your app copies them into the
toolsfield of the model request. MCP calls the schemainputSchemaand Anthropic's API calls itinput_schema, so your app converts it. - The model replies with a
tool_useblock fortrack_parcel. - Your app runs its own checks and sends
tools/call. - The server does the work and returns a result. Your app wraps it in a
tool_result, and the loop from the earlier blocks continues.
Names need care in step 2. A tool name is unique only inside one server, so two servers can each offer search, and the specification says clients should disambiguate, for example with a server prefix. The prefix should be a label your host assigns, because the specification warns that a server's own name is not guaranteed unique. MCP also allows a dot in a name, which Anthropic's API does not. Northwind's host therefore exposes shipping__track_parcel, with any dot replaced by an underscore, and removes the prefix before it calls the server.
Step 4 on the wire, in the current revision:
{
"jsonrpc": "2.0",
"id": 7,
"method": "tools/call",
"params": {
"name": "track_parcel",
"arguments": {
"order_id": "4417"
},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}And the reply:
{
"jsonrpc": "2.0",
"id": 7,
"result": {
"resultType": "complete",
"content": [
{
"type": "text",
"text": "4417: out for delivery"
}
],
"isError": false
}
}Servers can offer more than tools. Tools are functions for the model to run, resources are data for the user or the model, and prompts are message templates for the user. In the other direction, a client can offer elicitation, which lets a server ask the user for information.
Messages travel over one of two standard transports. With stdio, the client launches the server as a subprocess and they exchange lines on its standard streams. With Streamable HTTP, each message is a POST to one endpoint. The older HTTP+SSE transport is deprecated.
Which version you are reading about
As of 2026-11-10 the current revision is 2026-07-28, and it changed the base of the protocol. Articles and SDK examples written earlier describe the handshake on the left.
| | |
|---|---|---|
Version and client capabilities | Agreed once in | Sent in |
Learning a server's capabilities | The | |
State across calls | Optional | No protocol session; the server issues an ID, called a handle, that is passed as a tool argument |
Server needs user input | The server sends a request to the client | The result has |
Roots, Sampling, Logging | Active | Deprecated, still working for at least twelve months |
Deprecated does not mean removed, but new implementations should not adopt these features. In place of Roots, the specification suggests tool parameters, resource URIs or server configuration. Elicitation stays active, and the earliest removal of Roots, Sampling and Logging is the first revision released on or after 2027-07-28.
The two eras do not mix by default. A client that speaks only the new revision fails against a server that knows only the handshake, and a handshake-only client fails against a new-only server. An implementation that needs both supports both, and the specification calls that dual-era.
What MCP leaves to you
The specification says plainly that MCP cannot enforce its security principles at the protocol level. That work belongs to your host and to the service.
- Tool descriptions are text from the server, and they go to the model. The next block is about this.
- A server is someone else's code. A stdio server is a local program, and stdio alone does not limit what it can read or send.
- Long tool lists use up the context window. Anthropic's example of five servers and 58 tools takes about 55,000 tokens before the conversation starts.
The rule from the refund block still holds. customer_id stays out of arguments. MCP's authorization is optional. When a Streamable HTTP server uses it, the token travels with every request, and the server takes the identity from it.
MCP pays off when several agents share a service or when the service comes from another team. One agent with two functions you own does not need it.
Conclusion
- An MCP server is an adapter in front of a service:
tools/listto discover,tools/callto run, with your app between the model and the server. - Check the revision. In
2026-07-28there is no handshake, and every request carries its version and client capabilities. - The protocol does not make a server safe. Your host and the service have to do that.