All posts
Fundamentals

MCP, and the problem it actually solves

Building one tool takes an afternoon. The trouble starts later, and it arrives in four stages.

Why tool building stops being fun

Most APIs were not designed for this. A search service built for language models hands back clean, compact results. Your Slack workspace, your Drive, your CRM: each has its own auth, pagination, rate limits and response shape, and none of them return anything a model can read directly. Hours go into reading documentation before you write a line, and that cost repeats per tool.

Error handling outgrows the function. The ten-line version from the last post assumed the happy path. A production version handles timeouts, backs off on rate limits, survives an outage, validates input, and returns failures the model can act on. Fifty lines is normal, and the error handling is now the bulk of the tool.

Every team builds the same thing. Marketing wants web search for a content agent. Support wants it for a FAQ bot. Research wants it for analysis. Three implementations, three sets of the same mistakes.

Reuse across teams rarely works. You would think one team builds it and the rest adopt it. In practice one team used dictionaries and another used Pydantic, one is async and the other is not, return formats differ, and adapting theirs takes longer than writing your own. So everyone writes their own, and now there are four to maintain as the upstream APIs keep changing.

None of that is exotic. It is the ordinary cost of integration work, multiplied by the number of tools an agent needs, which is usually a lot more than one.

The industry has been here before

Every one of those problems is a standardisation problem, and the pattern for fixing them is well worn. REST gave services a common way to be called. Package managers gave code a common way to be shared and versioned. Containers gave applications a common way to be deployed.

Tools for language models needed the same thing: one way to describe a tool, one way to call it, and one that works regardless of which model provider you use.

Anthropic introduced MCP in November 2024 for exactly that.

The three parts

MCP splits an agent's brain from its arms and legs across three components.

Host. Your application. It talks to the user, runs the model, and decides which tool to use and when. Claude Desktop, an AI-enabled IDE, or the agent you are building.

Client. The bridge. When the host decides it needs a tool, the client handles the conversation with a server: asking what tools exist, and forwarding execution requests. One client holds one connection to one server.

Server. Where the tools live and run. It answers two questions: what tools do you have, and please run this one with these arguments. A server can front a database, an API, or anything else.

The host reasons, the client bridges, the server holds and runs the tools.The host reasons, the client bridges, the server holds and runs the tools.

What actually gets standardised

Two interfaces, and both of them are things we hand-built in the last two posts.

Tool discovery. We wrote to_tool_definition to turn a function into a schema. Under MCP the client asks the server what it offers and gets definitions back in a standard format. The tool author writes the schema once, and any compatible client can read it.

Tool execution. We wrote a dispatch loop that mapped a tool name to a Python function and called it. Under MCP the client sends an execution request and the server runs it, returning the result in a consistent shape.

Hand-built (posts 13 and 14)Under MCP
Describing a toolYour to_tool_definition helperThe server publishes it
Finding out what existsYou maintain the listThe client asks the server
Running a toolYour dispatch dictionaryThe client sends a request
Using someone else's toolPort it into your codebasePoint a client at their server
Changing model providerYour adapter layerUnaffected either way

Servers can also expose prompt templates and data resources. Tools are the part that matters for building agents, and they are where the ecosystem's attention has gone.

How the two sides actually talk

Two transports, and the difference matters more than it first appears.

Stdio. Your client launches the server as a subprocess on the same machine and talks to it over standard input and output. No network, no latency, nothing to configure. This is the common setup for local development, and most published servers are distributed as packages you launch this way.

Streamable HTTP. The server runs somewhere else and the client reaches it over the network, with responses streamed where that helps. This is the shape you want when a server is shared across a team or has to run somewhere specific.

Tool implementations do not change between the two. You start on stdio and move to HTTP when you need the server to live somewhere other than the machine that is using it.

What it changes, and what it moves

The gain is real. Pointing a client at an existing server, instead of spending a day reading an API's documentation and writing a wrapper, is a genuine change in what an afternoon can produce. The maintenance problem moves to whoever maintains the server, which is where it belongs.

Two honest notes.

A standard interface still needs a good schema. Everything in post 13 applies to a tool published through MCP. A server offering a vaguely described tool gets called at the wrong moments, and the protocol has no opinion about that.

Launching a server is a trust decision. Read the stdio description again: your client starts the server as a subprocess on your machine, and it runs with whatever access your machine gives it. Adding a tool used to mean reading code you wrote. Adding a server means running code you did not, inside the loop that already holds your context and your credentials.

That second one is worth its own treatment, and it belongs with the rest of the security work rather than here.

What to take from this

  • MCP standardises the two things we built by hand: how a tool describes itself, and how it gets run.
  • The gain is real reuse. A published server replaces a day of reading documentation and writing a wrapper.
  • It moves the maintenance burden to the server author and introduces a trust decision in its place, because launching a server means running someone else's code next to your agent.