Model Context Protocol, plainly explained — how it works, what it isn't, and how it bears on connecting your own chat product to somebody else's.
Before MCP, connecting a model to a database, a calendar, or a CRM meant writing a bespoke integration for that exact pairing. An organisation with 6 agents and 10 tools faced up to 60 one-off integrations — each with its own auth pattern, its own way of describing what it does, its own failure modes.
MCP is a specification: a shared grammar for how an AI application asks what's available, and how it asks for something to be done. Three roles do the work.
Your chatbot, IDE, or agent runtime. It's what the person actually talks to, and it holds the conversation.
Lives inside the host, keeps one dedicated 1:1 link open to a server, and speaks MCP on the host's behalf.
A small program that exposes a specific set of tools, data, or templates — e.g. "our booking system" or "internal wiki search."
Messages between them are plain JSON-RPC 2.0, carried over stdio for a server running on your machine, or over HTTP for a remote one. Nothing exotic — the value is entirely in everyone agreeing to describe things the same way.
A server can expose three kinds of thing, and who decides to use each one differs:
Model-controlled. The LLM itself decides, mid-reasoning, to call one — the way it already decides to call any function.
{
"name": "get_portfolio_valuation",
"description": "Return the current valuation of a client's portfolio.",
"inputSchema": {
"type": "object",
"properties": {
"client_id": { "type": "string" },
"as_of_date": { "type": "string", "format": "date" }
},
"required": ["client_id"]
}
}
Application-controlled. The host decides what to attach as background context — a file, a record, a page — before the model ever reasons about it. Think of it as read-only material handed to the model, not something the model requests mid-thought.
User-controlled. Reusable, parameterised instruction templates a person explicitly invokes — a slash command, a saved workflow — rather than something the model reaches for on its own.
This is the part that enables an agent to "talk to tools" — a fixed sequence, the same regardless of which tool sits behind it.
On connecting, the client asks the server what it offers. The server replies with a list of tools, each with a name, a plain-language description, and a JSON Schema for its inputs — this is the part the model actually reads.
Those tool descriptions get folded into the model's context alongside the conversation. Mid-reasoning, the model decides a particular tool fits the current step, and emits a structured call with arguments — ordinary function-calling, just against a standardised list.
The client packages that as a tools/call request and sends it to the server over the open connection.
The server runs the underlying code — a database query, an API call, a file read — outside the model entirely, and returns a structured result or an error.
The result is inserted back into the conversation as if the model had just been handed a document. The model reads it and continues reasoning — possibly straight into another tool call.
MCP connects one agent to its own tools and data — vertical, like roots drawing from soil the tree already owns. Getting two independent agents, run by two different systems, to collaborate as peers is a different problem, with its own emerging standard: A2A (Agent2Agent Protocol), originally published by Google and now developed as an open, multi-vendor project under the Linux Foundation.
| MCP | A2A | |
|---|---|---|
| Direction | Agent → its tools and data | Agent → another, independent agent |
| Unit exchanged | A tool call and its structured result | A task, delegated and tracked to completion |
| What's visible | Full tool schema — the caller sees exactly what a tool does | An "agent card" advertising capabilities only — internals stay opaque |
| Typical shape | Synchronous, within one turn of reasoning | Can be long-running and asynchronous |
In practice the two nest: Agent B might use A2A to accept a task from Agent A, then quietly use its own MCP connections to actually carry it out. Neither replaces the other.
The "harness" is the scaffolding code that runs around the model: the loop that decides what goes into context, calls the model, interprets what comes back, executes tool calls, and repeats. MCP standardises the last mile of that loop — how the harness reaches outward. It doesn't decide when to loop, what to remember, or when to stop.
Neither is strictly "more correct" — they answer different questions. A plain API call answers "how do I invoke this one function." MCP answers "how does my agent discover and reason about a changing set of capabilities, uniformly, alongside everything else it already talks to."
Whichever you pick, the protocol choice is the smaller decision. These matter more once real user data starts crossing an org boundary: