Information in this post reflects publicly available sources as of October 16, 2026.
You built an agent that can search your logs. It has one tool, query_logs, wired straight into your harness, and it works.
Then the requests start. The platform team wants the same tool inside their IDE assistant. Support wants it in the company chat app. And your own agent now needs to read GitHub, file Jira tickets, and query Postgres.
Each of those apps has its own plugin format. Each of those services has its own API. You can feel where this is going: every new app means rewriting every integration, and every new integration has to be written once per app. Nobody signed up to maintain that grid.
This is the problem the Model Context Protocol (MCP) was built to solve. It is a standard way for AI applications to discover and use tools and data, so an integration written once works in any app that speaks the protocol.
The integration grid
The previous post in this series showed that a model never runs tools itself. It asks, and the harness around it does the work. That leaves an open question: where do the tools come from? Before MCP, the answer was "whatever the app developer hard-coded," and every app answered it differently.
With three AI apps and four services, you need twelve separate integrations. Add a fifth service and you need three more. This is the classic N×M problem, and it is the same one that language servers solved for code editors a decade ago. The fix is also the same: put a protocol in the middle so each side implements it once.
Anthropic released MCP as an open specification in November 2024. Within a year it had been adopted by most major AI apps and IDEs, and in December 2025 it was donated to the Linux Foundation. That last step matters for adoption: the protocol is no longer one vendor's plugin format.
How it works
Hosts, clients, and servers
MCP names three roles. The host is the AI application the user works in: a chat app, an IDE, or your own agent. The server is a program that exposes capabilities, such as a logs server or a GitHub server.
Inside the host, an MCP client manages the connection to one server. A host connected to five servers runs five clients.
Servers come in two shapes. A local server runs as a child process on the user's machine and talks over stdio, which suits anything that touches local files or tools. A remote server runs as a web service and talks over Streamable HTTP, which suits SaaS products that want to offer one integration to every AI app at once.
What a server offers
A server can expose three kinds of things, and the difference between them is who decides when they get used.
- Tools are actions the model can call, like
query_logsorcreate_issue. The model decides when to use them, exactly as in the agent loop. - Resources are read-only data identified by a URI, like a file or a database schema. The host application decides when to pull them into context.
- Prompts are reusable templates the user picks explicitly, often surfaced as slash commands.
In practice, tools do most of the work. Many servers expose nothing else, and many hosts support tools far better than the other two. If you are building your first server, start with tools.
On the wire
Underneath, MCP is JSON-RPC 2.0. The host first asks each server what it offers by calling tools/list. Each tool comes back with a name, a description, and a JSON Schema for its input, which is the same shape you would hand-write for plain tool calling:
{
"name": "query_logs",
"description": "Search application logs for one service. Returns up to 50 matching lines, newest first.",
"inputSchema": {
"type": "object",
"properties": {
"service": { "type": "string" },
"level": { "type": "string", "enum": ["ERROR", "WARN", "INFO"] }
},
"required": ["service"]
}
}
The host merges the tool lists from all its servers and passes them to the model. When the model asks for query_logs, the host routes the call to whichever server owns it:
{
"jsonrpc": "2.0",
"id": 7,
"method": "tools/call",
"params": {
"name": "query_logs",
"arguments": { "service": "checkout", "level": "ERROR" },
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}
The server runs the query against the real logging system and returns content blocks, plus a resultType of "complete". The _meta block is new in the current revision of the spec and is explained below. Everything else in this exchange would look familiar to anyone who has written a JSON API.
That diagram holds the most useful mental model for MCP. It is not a new way for models to work: the model still sees tool definitions and emits tool calls, exactly as before. MCP standardizes the other half of the job: how the harness finds tools and gets them executed. It is plumbing for the host, not a capability of the model.
The 2026 revision: no more sessions
The spec is versioned by date, and the current revision, 2026-07-28, is the biggest change since launch. Earlier versions were stateful. A client opened a connection with an initialize handshake, received a session ID in the Mcp-Session-Id header, and sent that ID on every later request. The server remembered the session.
That design hurt anyone running remote servers at scale. Every request in a session had to reach the same server instance, which meant sticky load balancing, session storage, and painful failover. The new revision removes the handshake and the session header entirely. Each request now carries its protocol version and client capabilities in _meta, so any instance can serve any request.
Servers that genuinely need state across calls now use explicit handles. A tool such as start_export returns a job_id, and the model passes it to get_export_status later.
When a server needs more input partway through a request, such as a confirmation from the user, it returns a result marked input_required. The client gathers the input and retries the original request with the answers attached. The spec calls this the Multi Round-Trip Request pattern, and the retry can land on any instance.
A few older features were deprecated along the way, including Roots, Sampling, and Logging, with at least twelve months before removal. Long-running work moved into an official Tasks extension. If you maintain a server written against an older revision, read the changelog before upgrading your SDK; the "resource not found" error code also changed.
Authorization
Local stdio servers inherit whatever access the user's machine already has. Remote servers need real authorization, and MCP builds on OAuth 2.1 for it. When a user connects a remote server, the host runs a standard OAuth flow and the user approves access in their browser, just like connecting any third-party app. The current revision prefers Client ID Metadata Documents for registering the host with the authorization server, and deprecates Dynamic Client Registration.
When to use MCP, and when not to
Use MCP when an integration needs to work in more than one place. If you sell a SaaS product, one remote server makes you available in every major AI app. If you are building an agent, consuming existing servers saves you from writing a GitHub or Postgres integration yourself. And inside a company, a shared server for internal systems lets every team's tools reach them the same way.
Skip it when you have one application and a handful of tools that live in the same codebase. Plain tool calling is simpler: no extra process, no network hop, no protocol versions to track. You can always wrap those tools in a server later if a second consumer appears.
Also resist the urge to mirror an entire REST API as MCP tools, one endpoint per tool. Models do better with a small number of task-shaped tools, such as find_failing_deploys, than with forty thin wrappers they must chain correctly. The protocol makes exposing tools easy. It does not make exposing many of them a good idea.
What goes wrong
Too many tools. Connect five servers and the model may face a hundred tools on every turn. Selection accuracy drops as the list grows, and similar names across servers, such as two tools called search, invite the wrong call. Fewer, better-described tools beat a large catalog.
Untrusted servers are untrusted code. A local stdio server is a program running with your user's permissions. Installing one from an unknown source is the same decision as running any unknown script, and it deserves the same scrutiny.
Descriptions are part of the prompt. Tool descriptions go straight into the model's context. A malicious or compromised server can hide instructions there, telling the model to read a credentials file or send data to another tool. This is called tool poisoning.
A variant, sometimes called a rug pull, changes a description after the user has approved the server, so the tool that was reviewed is not the tool that runs. Hosts that pin server versions and show users what changed reduce the risk.
Tool results can carry injections too. A server that returns issue comments or web pages returns attacker-controllable text. Combine a server that reads untrusted content with one that can write or send data, and you have the classic exfiltration path. The fix lives in the host: approval prompts for sensitive actions, and narrow scopes on every connected server.
Over-broad tokens. A remote server that requests full admin scope on your issue tracker, when it only needs to read, turns any of the problems above into a bigger incident. Grant the minimum scope each server needs, and review them like any other third-party integration.
Cost, latency, and complexity
The hidden cost of MCP is tool definitions. Every tool from every connected server is sent to the model on every call. Suppose five servers expose twenty tools each, at around 250 tokens per definition. That is 25,000 tokens of definitions before the user has typed anything.
In a 20-step agent run, those definitions are resent 20 times, adding 500,000 input tokens. At an illustrative $3 per million input tokens, that is $1.50 per task spent describing tools, much of it for tools the agent never touches. Prompt caching cuts this sharply because the definitions sit in the repeated prefix, which is one reason the current spec asks servers to return tools in a deterministic order. Some hosts go further and load tool definitions on demand, searching for relevant tools rather than sending all of them.
A useful habit before connecting a new server: count the tokens its tools/list response adds. If one server costs more context than the task it helps with, disable the tools you do not need or look for a leaner server.
Latency adds up the same way. Each tool call now crosses a process or network boundary before it reaches the real system, and remote servers add an HTTP round trip. That is usually small next to model latency, but it compounds across a long agent run. The complexity cost is real too: another moving part to deploy, version, and monitor.
The current landscape
The stable spec revision is 2026-07-28, released after a ten-week release candidate period in which SDK maintainers validated the changes. The previous revision, 2025-11-25, remains widely deployed, and clients negotiate versions, so expect both in the wild for some time. Official SDKs exist for the major languages, including TypeScript, Python, C#, Java, Go, and Kotlin; check each one's support for the new revision before upgrading.
On the client side, support is now standard. The Claude apps, ChatGPT, VS Code with GitHub Copilot, Cursor, and most agent frameworks can connect to MCP servers. The OpenAI Agents SDK, Google's Agent Development Kit, and the Claude Agent SDK all consume servers natively.
Governance moved to the Agentic AI Foundation, a Linux Foundation fund that Anthropic, OpenAI, and Block co-founded in December 2025 with MCP as a founding project. An official server registry launched in preview in September 2025 to help hosts discover servers. Official extensions now carry features that do not belong in the core, including MCP Apps, which lets a server supply an interactive interface that renders in a sandbox inside the host.
One distinction worth keeping straight: MCP connects agents to tools and data. The separate A2A protocol connects agents to other agents. They solve different problems and are often used together; A2A gets its own post in this series.
Summary
MCP does not make models smarter or give them new abilities. The model still sees tool definitions and asks for tool calls, exactly as it did before. What MCP changes is everything on the other side of that request: where tools come from, how they are described, and how they get executed. It turns tool integration from per-app glue code into a shared, reusable layer.
That framing tells you where to spend your attention. The protocol handles the plumbing well, especially since the 2026 revision made remote servers stateless. The hard problems are the ones it cannot solve for you: choosing which servers to trust, keeping the tool list small and sharp, and deciding which actions need a human to approve them.
Part of the Applied AI series: AI from the builder's side.