Model Context Protocol · specification 2025-11-25

An AI application can only use what it can reach. MCP is how it reaches.

The Model Context Protocol is an open standard for connecting AI applications to external systems. One integration, written once, works in every client that speaks it. Below is a real interaction — the handshake, the discovery, the tool call, the result — with nothing hidden. Press play, or step through it yourself.

An interactive diagram of one MCP connection. From left to right: you, the AI application that hosts an MCP client, the transport, the MCP server, and the external system the server talks to. Messages travel along the connections between them. Every step is also written out in full in the sequence list and transcript below the diagram.

Use the controls after the diagram to play, pause, step and scrub the sequence. Focus any node or connection to read what it is responsible for.

Left and right arrow keys move one message at a time. Home and End jump to the start and end.

Step 1 of 13

The sequence

Lifecycle Discovery Interaction

    Request

    initialize — the client proposes

    The message on the wire for the current step

    Why it matters

    Read the whole sequence as text Every step, every message, no animation required

    The short version

    What MCP is, and what it is not

    Six things that make the rest of this site make sense. If you only read one panel, read the one about the three primitives — almost every confusion about MCP is a confusion between tools, resources and prompts.

    It is a protocol, not a product

    MCP standardises one thing: how an AI application asks an external system what it can do, and then does it. It says nothing about which model you use, how you prompt it, or how you manage context. That narrowness is the point — it is why the same server works in Claude Code, VS Code, Cursor and a script you wrote yourself.

    Think of it the way the docs do: a standard port, not a standard appliance.

    Host, client, server

    The host is the application you use. Inside it, one client is created per connection, and each client maintains a dedicated, stateful link to one server. Four servers means four clients in the same application, each negotiated independently.

    “Server” describes a role, not a location. A local filesystem server launched as a child process and a vendor’s HTTP endpoint on the other side of the world are both servers.

    Two transports, one message format

    stdio: the client spawns the server as a child process and speaks JSON-RPC over its standard input and output. No port, no network, nothing to firewall.

    Streamable HTTP: HTTP POST for client-to-server messages, with optional Server-Sent Events for streaming, plus standard HTTP authentication. MCP recommends OAuth for obtaining tokens. An older SSE-only transport still exists at many /sse endpoints and is being deprecated.

    The messages are identical either way. That is what lets a server move from your laptop to a vendor’s infrastructure without changing its data layer.

    Three primitives, three different owners

    This is the distinction worth internalising. All three are things a server can offer, but they differ in who decides when they are used.

    Primitive What it is Who controls it Protocol methods
    Tools Executable functions with a JSON Schema for their input. They act: write a file, open a pull request, run a query. The model decides when to call one. tools/list, tools/call
    Resources Read-only context addressed by URI, with a MIME type. A file, a schema, a record. Templates such as weather://forecast/{city} make whole families addressable. The application decides what to attach. resources/list, resources/read, resources/subscribe
    Prompts Reusable, parameterised instruction templates — usually the server author showing you how to use their own tools well. You invoke one explicitly. prompts/list, prompts/get

    Clients can expose primitives too. Sampling lets a server ask the host to run a model completion, so a server author needs no model key of their own. Elicitation lets a server ask you a question mid-operation. Logging sends diagnostics back to the client.

    It is stateful, and it negotiates

    Every connection opens with an initialize exchange in which both sides declare a protocol version and the capabilities they support. If no mutually compatible version exists, the connection should be terminated rather than guessed at.

    Discovery happens at runtime, not build time. A server that declares listChanged: true can send notifications/tools/list_changed later, and the client re-lists — so an agent’s capabilities can change mid-conversation without a restart.

    “Official” means three different things

    The directory labels every listing with one of three tiers, because they carry genuinely different risk. Reference servers live in modelcontextprotocol/servers and are explicitly educational examples rather than production products. Vendor-maintained servers are built by the company whose product they wrap — usually the safest default. Community servers are everything else, and are sometimes the only option, sometimes better than the official one, and always worth reading before you hand over a credential.

    A large star count is a popularity signal, not a security review — and where a repository is a whole platform rather than the server itself, this site says so next to the number.

    Everything a tool returns is data, not instruction

    An issue body, a web page, a calendar invite, a support ticket: these arrive in the model’s context looking exactly like legitimate content. If any of them contains “ignore previous instructions and …”, a naive agent may comply. This is prompt injection, and it is the central security problem of connecting agents to real systems.

    The mitigations are boring and effective: least-privilege credentials, read-only modes, narrow toolsets, approval for writes, and never pairing broad read access to private data with an unrestricted outbound channel.

    Read the trust and permissions guide

    The directory

    Servers worth your credentials

    167 listings across 17 categories, each checked against its own repository or its vendor’s documentation. Star counts and last-commit dates come from the GitHub API. Where something is archived, beta, or riskier than it looks, the listing says so.

    Researched
    24–25 July 2026
    Spec revision
    2025-11-25
    Cross-checked against
    Vendor docs, repository READMEs, the GitHub API and the official MCP Registry

    Practicalities

    Getting one running, and not regretting it

    Four things nobody tells you until you have already pasted a token into a config file.

    Adding a server to a real client

    Almost every client uses the same idea with a different key name. Below is the identical server — the reference filesystem server, scoped to one directory — written for each of the four most common clients, so you can see exactly what differs.

    • Restart matters. Most desktop clients read their config at launch. If a new server does not appear, restart before debugging anything else.
    • Paths must be absolute in stdio configs. npx and uvx need to be on the PATH that the client process sees, which is not always the one your shell sees.
    • Windows wraps npx: use "command": "cmd" with "args": ["/c", "npx", …]. Leave uvx entries alone.
    • Check it with the Inspector. npx @modelcontextprotocol/inspector connects directly to a server and lists its real tools, resources and prompts. It is the fastest way to find out whether the problem is the server or the client.

    Transports and authentication, in practice

    Choose stdio when…

    • The thing you want to reach is on this machine: files, a git repo, a local database, a running editor.
    • You want no listening socket and no network trust decisions at all.
    • You are happy for the credential to live in a config file on disk — and you know which file that is.

    Choose remote (Streamable HTTP) when…

    • The vendor runs it. There is no package to keep current and no token to rotate yourself.
    • You want OAuth rather than a long-lived key, so revocation is a real option.
    • Several people or several machines need the same connection.

    The four credential shapes you will actually meet

    No credential
    Public data or a purely local capability. Still not risk-free: a server that fetches arbitrary URLs is a request-forgery and injection surface even with no key.
    OAuth
    A browser consent flow; the token is short-lived and scoped, and you can revoke it. Read the consent screen — it tells you the blast radius. MCP recommends OAuth for remote servers.
    API key or token
    Usually an environment variable. Prefer keys that can be scoped or restricted (Stripe restricted keys, GitHub fine-grained tokens, per-base Airtable tokens). Watch for servers that want the key in a URL: it will end up in logs and shell history.
    If a server takes a key with no scoping at all, that is a design fact about the vendor, not the server.
    Existing local credentials
    A kubeconfig, an AWS profile, a database URI, a signed-in CLI. Convenient and dangerous in the same breath: the server inherits exactly what you can do. Use a scoped context or a read-only role.

    Trust, permissions and prompt injection

    The uncomfortable part. Connecting an agent to external systems creates a genuinely new risk surface, and most of it comes down to one sentence: tool output is untrusted input. The following is not paranoia, it is the ordinary cost of doing this well.

    1. Assume every string a server returns is hostile

      Issue bodies, PR comments, scraped pages, emails, calendar invites, support tickets, wiki pages and file contents are all written by someone who is not you. Hidden instructions in any of them can steer a model. Servers cannot fix this for you; hosts can only mitigate it.

    2. Never combine broad private read access with an unrestricted outbound channel

      Mail read plus mail send. Database read plus HTTP POST. Repository read plus a public gist tool. That pairing is the classic exfiltration shape, and it does not require anyone to attack you deliberately — a confused model is enough.

    3. Start read-only, every time

      A surprising number of good servers ship an explicit read-only or restricted mode: GitHub’s GITHUB_READ_ONLY, Postgres MCP Pro’s --access-mode=restricted, MongoDB’s --readOnly, ClickHouse’s write flag being off by default, Square’s DISALLOW_WRITES, SonarQube’s SONARQUBE_READ_ONLY. Use them, then remove the training wheels deliberately.

    4. Narrow the tool list, not just the permissions

      Every extra tool is context-window cost, a chance for the model to pick the wrong one, and one more thing an injected instruction could reach for. Toolsets, enabled-tool lists and per-tool disabling are the most underused features in this ecosystem.

    5. Understand what you consented to

      The MCP security guidance describes the confused deputy problem in detail: a server that proxies a third-party API with a static client ID, allows dynamic client registration, and does not implement per-client consent can have an authorization code redirected to an attacker who is riding your existing consent cookie. If you build a proxying server, read that document properly.

    6. Prefer local execution for sensitive code and data

      Scanning, indexing and analysis servers usually offer both a local and a hosted path. The local one keeps your source and your data on your machine.

    7. Know which tools are irreversible

      drop-database. pay_order. place_stock_order. publish_entry. DeleteDatabaseTool. Filled trades, sent emails and published pages do not have an undo. Require approval, or do not expose them at all.

    8. Bind HTTP-mode servers to localhost and set allowed origins

      Several servers can run in HTTP mode locally. An unauthenticated local HTTP endpoint is a DNS-rebinding target: any web page you visit can try to talk to it. That is why servers such as Terraform’s and Vault’s ship MCP_ALLOWED_ORIGINS, and why HashiCorp say to always set it.

    Glossary

    Every term on this site, defined once.

    Yours, kept locally

    My stack

    Shortlist servers as you browse and they collect here, saved in this browser only — no account, no sync, nothing sent anywhere. Then take the merged configuration for your client in one block.

    Side by side

    Esc

    Up and down arrows to move, Enter to open, Escape to close.