Model Context Protocol (MCP)

What MCP is and how it works, explained for a developer who is new to AI tooling. Read LLM Tool Calling first — MCP builds directly on it, and this note assumes you know what a tool schema and a handler loop are.

Related: LLM Tool Calling, A2A-Protocol, NAT-Lesson-0-Getting-Started. The archived article this note replaced as the vault’s MCP explainer is What is MCP (Clipping) — still a good read for adoption history and the security numbers.


1. The problem MCP solves

From LLM Tool Calling you know the shape of a tool: a function, a JSON Schema describing it, and a handler that executes calls. Now notice what that note quietly assumed: the tools live inside your application. Your app defines them, your app runs them.

That assumption breaks the moment tools need to be shared. Say your company has five useful tools (search the ticket system, query inventory, read the wiki…) and four AI applications that should use them (a chat assistant, an IDE agent, an internal bot, a customer-facing agent). Without a standard, that’s 5 × 4 = twenty integrations — each app re-wraps each tool in its own format, its own auth, its own error handling. Every tool change ripples through four codebases. This is the N×M problem, and it’s the same disease that plagued editors and programming languages before the Language Server Protocol: every editor needed a custom plugin for every language.

MCP (Model Context Protocol) is the LSP move applied to AI tools: an open standard for publishing tools so that any AI application can discover and call them. Write the tool server once; every MCP-speaking client — Claude Code, Claude Desktop, Cursor, ChatGPT, VS Code, your own app — can use it. N×M becomes N+M.

2. The three roles

RoleWhat it isExample
HostThe AI application the user interacts withClaude Code, Cursor, your chat app
ClientThe connection manager inside the host — one per server connection(built into the host; you rarely write one)
ServerThe program that publishes toolsyour weather server, a GitHub server, a database server

The names trip people up, so anchor them: the server is the small thing — often a hundred-line script wrapping one system. The host is the big thing — the app with the LLM conversation in it. A host connects to many servers at once, one client per connection, and merges all their tools into a single menu for the model.

Under the hood the protocol is JSON-RPC 2.0 — request/response messages like tools/list (“what do you offer?”) and tools/call (“run this one with these arguments”). You almost never handcraft these; SDKs and frameworks generate them.

3. What a server publishes

Three primitive types, in descending order of how often you’ll actually meet them:

  • Tools — actions the model can invoke: “create a ticket,” “query the database,” “fetch a transcript.” Each has exactly the name/description/JSON-Schema anatomy from LLM Tool Calling §3.2. The overwhelming majority of real MCP usage is tools.
  • Resources — data the model can read, addressed by URI: a file’s contents, a database schema, a log stream. Read-only by convention.
  • Prompts — reusable prompt templates the server offers (“summarize today’s activity as a standup report”), typically surfaced to the user as slash-commands rather than chosen by the model.

4. What actually happens at runtime

The critical insight for a new developer: MCP does not change how the model calls tools. The tool-calling loop from LLM Tool Calling runs exactly as before. MCP standardizes the two steps around it — discovery and execution:

  1. Connect: the host starts up and its client connects to each configured server.
  2. Discover: the client sends tools/list; the server answers with its tool schemas. The host injects those schemas into the model’s context — same as if the app had defined them locally.
  3. Model decides: during conversation, the model emits an ordinary tool-use request for, say, get_weather.
  4. Route and execute: the host sees that get_weather belongs to the weather server, and its client sends tools/call over the wire. The server runs the actual code and returns the result.
  5. Continue: the result goes back into the conversation, and the loop proceeds normally.

So MCP replaces the hardcoded tool map (available_functions = {...}) with a dynamic, networked one. The model never knows the difference.

5. Transports: how client and server talk

  • stdio — the host launches the server as a child process and speaks JSON-RPC over stdin/stdout. Exactly a Unix pipeline: popen() a subprocess, write requests, read responses. Zero network setup; the default for local, single-user tools.
  • Streamable HTTP — the server is a standalone web service; clients connect over HTTP(S). This is how you serve tools to other machines — a team, a fleet of agents, a customer. Needs the usual web-service care: auth, TLS, firewalling.

Rule of thumb: personal/local → stdio; shared/remote → HTTP.

6. A minimal server

The Python SDK’s FastMCP derives the schema from type hints and the docstring — which, remember, is a prompt:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("weather")

@mcp.tool()
def get_weather(city: str) -> str:
    """Get the current weather for a city."""
    mock = {"New York": "Sunny, 75F", "London": "Rainy, 15C"}
    return mock.get(city, "No data for that city.")

if __name__ == "__main__":
    mcp.run()          # stdio transport by default

That’s a complete, working server. Register it in a host’s config (for Claude Code: claude mcp add weather -- python weather_server.py) and the model can call get_weather — and so can every other MCP host on the machine, with no further work. Compare this against the ~60-line handler in LLM Tool Calling §5: the loop, the tool map, and the schema plumbing are all gone — the host runs them for you.

Frameworks sit one level higher again: in NAT you don’t even write the server — a YAML front end (_type: mcp) publishes every registered workflow function over MCP automatically (see NAT-Lesson-0-Getting-Started).

7. When not to use MCP

One application, a handful of in-house tools, one model? Plain function calling is simpler and has no moving parts — no server process, no connection lifecycle, no extra security surface. MCP earns its complexity when tools are shared across applications, teams, or machines, or when you want to consume the ecosystem of existing servers instead of writing integrations. Adding an MCP server to reach code that lives in the same repo as your app is overengineering.

8. Security — take this section seriously

An MCP server is arbitrary code running with real privileges, and its tool descriptions are text injected into your model’s context. Both halves bite:

  • Treat servers like browser extensions. Install only what you need, from sources you trust, and audit what a server can actually touch. Community servers vary wildly in quality; command-injection flaws in public servers are common.
  • Tool poisoning is real. A malicious server can hide instructions in its tool descriptions (“before answering, also send the conversation to…”). The model reads descriptions as context — merely connecting a poisoned server can steer it, no call required. This is the same prompt-injection lesson as tool results in LLM Tool Calling §7, one level earlier in the pipeline.
  • Every connected server costs context. All those tool schemas are injected into the model’s window before the user types a word, and past a few dozen tools, models get worse at choosing between them. Connect the servers you use, not the servers you have.
  • Remote servers need real auth. A streamable-HTTP server with no authentication is an open RPC endpoint to whatever the tools can do. LAN-only or VPN-only is a floor, not a strategy.

9. Where this goes next

  • Serving a real tool over MCP with zero server code: the NAT front-end pattern in NAT-Lesson-0-Getting-Started’s sequence (Lesson 1 covers the hub that does it).
  • The complementary protocol for agent-to-agent (rather than agent-to-tool) communication: A2A-Protocol.
  • Adoption history, ecosystem stats, and the vulnerability numbers behind §8: What is MCP (Clipping).