MCP Servers Explained: What Model Context Protocol Actually Does

April 13, 2026 · 14 min read · mcp, llm-tools, claude, anthropic, protocol
MCP Servers Explained: What Model Context Protocol Actually Does

If you have heard “MCP” thrown around in the last year without getting a clear answer on what it is, here is the explainer that stays grounded in what it actually does, not what the marketing decks claim.

I run an MCP server in production. It exposes my task manager to every LLM client I use, daily, as a systemd service on a Debian VPS. That constant use is where this explainer comes from. No conference slides, no speculation about where the protocol is heading in five years. Just what MCP is, what it replaces, and when you should bother writing one.

The short version: MCP is a standard way for an LLM client to talk to a tool or data source. If you understand the language server protocol for code editors, you already understand the shape of it. If you do not, keep reading.

What MCP actually is (in one paragraph)

MCP stands for Model Context Protocol. It is an open protocol, originally published by Anthropic in late 2024 and since adopted by OpenAI, Google, and most major LLM tooling vendors, that lets any LLM client talk to any external tool or data source using a standard JSON-RPC 2.0 message format. Think of it as the language server protocol, but for LLMs and tools instead of editors and compilers. One side runs a server that exposes capabilities. The other side runs a client that discovers and calls those capabilities. The wire format is stable, documented, and the same regardless of which LLM sits behind the client.

That is the whole idea. Everything else is implementation detail.

Why MCP exists: the pre-protocol pain

Before MCP, every LLM client had its own way of wiring up tools. OpenAI had function calling with its own JSON schema conventions. Claude had tool use with a slightly different schema. Cursor had its own plugin model. Claude Desktop had yet another. If you wanted to expose a Postgres query tool to three different LLM clients, you wrote three different adapters.

Worse, tools lived inside apps. Your Claude Desktop integration could not be reused in Claude Code. Your Cursor plugin could not be reused in Zed. Every integration was trapped in the app that built it, and anyone who wanted the same capability somewhere else had to rebuild it from scratch.

The pain was not that function calling did not work. Function calling works fine. The pain was that there was no way to share a tool across clients. Every capability was a reimplementation. A thousand teams were writing the same GitHub adapter, the same Slack adapter, the same filesystem adapter, for slightly different LLM surfaces.

MCP fixes that by moving the integration out of the app and into a separate process that any client can speak to.

The architecture

MCP has four moving parts.

Client: the LLM surface. Claude Desktop, Claude Code, Cursor, Zed, Continue.dev, or any custom app built on the MCP SDK. The client is the thing the user talks to.

Server: a separate process that exposes tools, resources, and prompts. Servers are independent of the client. You can write one in TypeScript, Python, Go, Rust, or anything else that can speak JSON-RPC.

Transport: how the client and server talk. Two main options. stdio means the client runs the server as a subprocess and communicates over stdin/stdout, which is the default for local tools. SSE or streamable HTTP means the server is a network service at a URL, which is how you expose tools over the network or to hosted clients.

Protocol: JSON-RPC 2.0 with a defined set of message types. Initialize handshake, capability discovery, tool calls, resource reads, prompt invocations, notifications. It is boring, which is the point. Boring protocols are easy to implement and easy to debug.

The separation matters. The client does not know or care what language your server is written in. The server does not know which LLM is sitting behind the client. Everything in the middle is the protocol.

What an MCP server exposes

A server can expose three kinds of things.

Tools are callable functions with typed schemas. This is the most common thing you will build and the main reason people write MCP servers. A tool has a name, a description, a JSON schema for its inputs, and a handler that returns a result. The LLM reads the description, decides when to call it, and sends arguments that match the schema. Tools are the pattern you already know from function calling, just exposed over a protocol instead of baked into an SDK.

Resources are URI-addressable data. A file path, a database record, the result of a query, a config blob. The client can list available resources and read them. Resources are how you give the LLM access to data without turning every read into a tool call.

Prompts are predefined prompt templates the user can invoke by name. Less common than tools and resources, but useful when you want to ship reusable prompt scaffolds with a server.

Most MCP servers in production today are tool-heavy, resource-medium, prompt-light. Start with tools, add resources when you need them, add prompts rarely.

The call flow, step by step

Here is what happens from startup to tool call.

  1. The client reads its config file and sees a list of configured MCP servers.
  2. The client starts each server (subprocess for stdio, HTTP connection for SSE).
  3. The server sends an initialize response announcing its protocol version and capabilities.
  4. The client calls tools/list, resources/list, and prompts/list to discover what the server exposes.
  5. The user types a message. The LLM receives the tool descriptions as part of its context.
  6. The LLM decides to call a tool. It emits a structured tool call in its output.
  7. The client routes that call to the right server via tools/call.
  8. The server executes the tool and returns the result.
  9. The client passes the result back to the LLM as part of the conversation.
  10. The LLM continues generating, possibly calling more tools, until it produces a final response.

That is the entire loop. Discovery once, many calls.

What MCP does not do

A lot of confusion comes from people assuming MCP is more than it is. It is not.

MCP is not an agent framework. It does not manage conversation state, planning, or multi-step execution. That is the client’s job, or your job if you are writing the agent.

MCP is not a chat UI. There is no UI in the protocol at all. The UI lives in whichever client you use.

MCP does not call LLMs. Servers do not talk to Anthropic, OpenAI, or anyone else. The client is the thing with an API key. The server just exposes tools.

MCP does not replace function calling. It standardizes function calling at the protocol layer so the same tool works across clients. The underlying mechanism inside each LLM is still tool use, structured outputs, or whatever that vendor calls it. MCP sits above that, not below. For a deeper look at how tool calls work inside the Claude API itself, see Claude API tool use.

Real MCP servers people run today

A short sample from the ecosystem, with the kinds of things they expose.

Filesystem MCP (official Anthropic) exposes file read, write, and directory listing as tools. Probably the first server most people install. Useful for letting Claude Desktop work on files without pasting them into chat.

Git MCP exposes git commands, diff reading, and log queries.

GitHub MCP exposes issues, pull requests, repo search, and code browsing via the GitHub API.

Postgres MCP exposes a SQL query tool and optionally schema introspection, so any MCP client can read or write a database.

Slack MCP exposes send-message, read-channel, and search tools.

Playwright MCP exposes browser automation. Navigate, click, fill forms, read the DOM.

TickTick MCP is my own. It exposes task management tools for my personal task manager. Add a task, search semantically, postpone, check completion stats. It runs as a systemd service on my VPS and is connected to every LLM client I use. I built it because my task manager is the most frequently accessed system I have, and making it available to every LLM I use was the single biggest workflow win I have had in two years.

There are hundreds more. Community servers for Notion, Linear, Jira, Google Drive, Calendar, Spotify, HomeAssistant, Kubernetes, AWS, and on and on. The pattern is always the same: pick a system you care about, wrap its API or CLI in a set of tools, serve it over MCP.

When to write one of your own

Write an MCP server when the answer to any of these is yes.

You want the same capability in more than one LLM client. If you use Claude Desktop for general thinking, Claude Code for engineering, and an internal chatbot for team support, writing one MCP server gives you that capability in all three. That is the single strongest case.

You want to ship capability to customers who use LLMs. If your product is a data source or an API and your users want to query it from their own LLM clients, publishing an MCP server lets them wire you in without you writing integrations for each surface.

You want to decouple tool evolution from app release cycles. An MCP server can ship independently of the clients it serves. You can add a tool, push the server, and every connected client picks it up on restart without any client-side change.

You want a reusable internal tool catalog. Larger teams end up with dozens of internal systems they want LLMs to touch. A shared set of MCP servers means one team does not keep reinventing the wheel. It also centralizes audit, logging, and auth.

For a practical walkthrough of writing your first server, see build an MCP server in TypeScript.

When not to bother

The honest counter-cases.

Single app, single client, one tool. If you are building one feature in one product for one LLM, a direct tool definition inside that app is faster to ship and simpler to debug. MCP adds a process boundary you do not need. The MCP vs custom API integration guide walks through this tradeoff in detail.

Tight latency budgets. A local tool call inside your app runs in microseconds. An MCP call adds at minimum a few milliseconds of IPC overhead and, for remote SSE servers, a network round trip. For human-in-the-loop LLM workflows this is invisible. For very high-throughput pipelines it matters.

Very simple integrations. One API call, one place it is needed, no reuse expected. Just call the API directly.

Agents that need tight coupling with their tools. Some agent frameworks manage tool definitions, retry logic, and state together. Pulling tools behind a protocol boundary can make that coupling awkward. For agent-building patterns that use tools tightly bound to the loop, see Claude Code SDK agents and AI agents build vs buy.

The client side of the ecosystem is larger than most people realize.

Claude Desktop configures servers via claude_desktop_config.json in the app support directory. The original reference client and still the most common entry point.

Claude Code (Anthropic’s CLI) configures servers in ~/.claude.json under the mcpServers key. This is where most developers hit MCP first.

Cursor IDE added MCP support in 2025 and uses a similar config file.

Zed editor supports MCP natively for its AI features.

Continue.dev ships MCP support in its VS Code and JetBrains extensions.

Custom clients via the MCP SDK. If you are building a chat app or an agent, the SDK gives you client-side primitives to discover and call servers.

The config format has mostly standardized. An mcpServers block with command, args, and env for stdio servers, or a url for remote servers, works across nearly every client today.

The ecosystem in 2026

Hundreds of community servers on GitHub. Official Anthropic servers for filesystem, git, fetch, memory, and a few others. A growing registry of third-party servers covering every system you can name.

Adoption has spread past Anthropic. OpenAI’s clients now speak MCP. Google added MCP support to the Gemini app and API SDK. Framework integrations in LangChain, LlamaIndex, and the major agent libraries treat MCP as a first-class tool source. The protocol won, faster than I expected.

What this means practically: if you write one good MCP server today, it will work with every LLM client you care about, and probably with several you have not heard of yet. That was not true in 2023. It is true now.

Security implications you should know

MCP is powerful, which means MCP is dangerous if you are not careful.

Servers run with full user privileges when they use stdio. A malicious server you installed has the same access to your files, environment variables, and processes that you do. Treat installing an MCP server the way you would treat installing a browser extension or a CLI tool from a random repo. Read the source if you care about what it is doing.

Tool descriptions are prompts. The LLM reads the description text to decide when to call the tool. A malicious server can write a description that instructs the LLM to do something harmful, or to hide its behavior from the user, or to exfiltrate data. Prompt injection through tool descriptions is a real attack surface, not a hypothetical one.

Remote MCP servers need auth. If you are running a server over HTTP, put OAuth2, a bearer token, or a signed request scheme in front of it. Do not rely on obscurity. Public MCP endpoints without auth are a gift to anyone who finds them.

Always review third-party servers before installing. Same caution as browser extensions, same caution as random npm packages. Official and well-maintained servers from known publishers are usually fine. A random server from a six-month-old GitHub account is not.

Beginner gotchas

Things that bite people when they first start.

Stdio transport runs the server as a subprocess of the client. That means the server inherits the client’s working directory and a subset of its environment. Relative paths in your server config will resolve against wherever the client was launched from, which is rarely what you want. Use absolute paths.

SSE transport needs a reachable URL. If you are hosting a remote server, TLS, CORS, and sometimes proxy configuration will all bite you at least once. Test with curl against the initialize endpoint before you plug it into a client.

The LLM decides when to call tools based on the description. Vague descriptions lead to tool misuse. Write descriptions that explicitly state when the tool should be used and when it should not. “Use this to add a task to the user’s TickTick inbox. Do not use it for calendar events.” is better than “Adds a task.”

Server crashes look like tools disappeared. If a stdio server crashes mid-session, the tools it exposed simply stop appearing in the LLM’s context, often without any visible error in the client UI. When an MCP tool stops working, check the server logs first. Most clients write them to a predictable location.

Schema mismatches are silent. If your tool’s input schema does not match what the LLM produces, the call fails and the LLM retries with slightly different arguments, sometimes in an infinite loop until the context fills. Validate schemas carefully and return clear error messages.

Getting started in 5 minutes

The fastest path to actually touching an MCP server.

Install an official server. Run npx @modelcontextprotocol/server-filesystem /some/dir from your terminal to confirm it starts.

Add it to Claude Desktop. Edit claude_desktop_config.json and add an entry under mcpServers:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/projects"]
    }
  }
}

Restart Claude Desktop. Ask it to list files in the directory. You should see a tool call happen, and the result come back.

That is the whole onboarding. From there you can install other community servers, combine several in one config, or start building your own. The build an MCP server in TypeScript walkthrough covers the next step.

The future is boring, which is good

MCP is becoming the default protocol for LLM-to-tool communication. In two years, asking “how does an LLM call my API” will have the same boring answer as “how does a web client talk to your backend”. Through a standard protocol. Through an MCP server. You stop thinking about it and just use it.

That is the quiet win. The interesting stuff moves up the stack, into agents and products and workflows, while the plumbing fades into background infrastructure. Protocols that work are protocols you stop noticing.

MCP is getting there.

Download the AI Automation Checklist (PDF)