MCP in Plain English: AI's USB-C Moment
One protocol between models and tools. What it replaces and why every vendor adopted it.
The Model Context Protocol (MCP) is a shared language that lets an AI app ask an outside program what it can do, and then ask it to do it. Think of the USB-C port on a laptop. Any charger, screen or drive that follows the standard fits the same port, so nobody needs a drawer of adapters. MCP plays that part between AI apps and the tools and data they use. It names three roles: hosts (the AI apps), clients (the connectors inside a host) and servers (the programs that offer tools and data).
Anthropic released MCP as an open standard in November 2024. About a year later ChatGPT, Gemini, Microsoft Copilot, Cursor and Visual Studio Code had adopted it, and in December 2025 Anthropic donated MCP to the Agentic AI Foundation, a fund under the Linux Foundation that Anthropic, Block and OpenAI co-founded. The reason for the rush is simple. A company that wraps its product in one MCP server reaches every app that speaks MCP, instead of writing a separate plugin for each one. That is the USB-C moment for AI tooling: write one connector and it works everywhere.
Why did AI tools need a standard protocol?
Before MCP, connecting an LLM to a real-world tool meant writing custom glue for each platform. You described the tool one way for ChatGPT's function calling API (application programming interface), another way for Claude's tool use, and wrapped it again for LangChain or a custom agent. Each integration was a one-off that tied you to a vendor.
This fragmentation created real pain. Engineers had to maintain several implementations of the same tool, each with its own schema, error handling and authentication flow. Switching model providers meant rewriting every tool connector. The lack of a shared interface also made it hard to combine tools from different sources or to reuse them across projects.
MCP solves this by defining one protocol between an AI app and the programs that provide its capabilities. It is not a framework or an orchestration layer. It is the message format and the rules that let any host talk to any server. Before USB-C, every device had its own port and cable. After USB-C, one cable works for phones, laptops, monitors and peripherals. MCP does the same for AI tools: one protocol, many hosts, many servers.
This is more than a convenience. It changes the economics of building AI assistants. Instead of betting on a single model vendor, you can build a personal assistant that connects to files, calendar, music and smart home tools through MCP servers, then swap the underlying LLM without touching the tool layer. That is the promise, and the rest of this article shows how it works under the hood.
- 3 platforms × 3 tools = 9 custom integrations
- Every tool needs its own schema, auth and error handling per platform
- Locked to one model vendor, hard to switch
- 1 MCP server per tool, any MCP host can use it
- One protocol, one way to describe every tool
- Swap the model or the app without rewriting tools
How does MCP structure communication between models and tools?
MCP separates the world into three roles, which the spec's architecture page describes. The host is the AI application that runs the model and manages the conversation. The client is a connector inside the host that talks to exactly one server. The server is a program that offers a catalogue of tools, resources or prompts.
Imagine you are building a personal assistant. The host is your assistant app: it embeds an LLM and shows a chat window. To give it access to your local files, you add a filesystem MCP server. To check your calendar, you add a calendar MCP server. For music, a music server, and for the lights, a smart home server. Each server runs on its own, either on your computer or somewhere on the internet.
The host does not speak MCP to these servers itself. For each server, it creates one MCP client, and that client handles every protocol message for its server. The host asks the client to list tools, call a tool or read a resource, and the client turns those requests into the right messages and hands back the results. This keeps the host's own logic clean and separate from the details of how bytes travel.
MCP defines two standard transports, which are the ways messages travel between a client and a server. stdio is for servers on your own computer: the host starts the server as a program, and the two talk through that program's standard input and output, the same text channels a terminal uses. Streamable HTTP is for servers on the internet: each message is an HTTP POST to one web address, and the reply comes back as a single answer or as a short stream of updates followed by the answer. An older remote transport called HTTP+SSE is deprecated, so you will only meet it in old servers and tutorials.
The messages themselves use JSON-RPC, a simple format for sending a named request with arguments and getting a reply, written as JSON (JavaScript Object Notation) text. Each request has a method name, its parameters and an ID that ties the reply to the request. Here is a client asking the filesystem server to read a file:
The _meta part is the newest piece of the design. Under the current revision of the specification, dated 2026-07-28 and the latest as of October 2026, MCP is stateless: there is no opening handshake, and every request says for itself which protocol version it speaks and what the client supports. Every server must answer server/discover, which a client may send first to learn the server's versions and capabilities in one go. After that the client asks for the catalogue with tools/list, resources/list and prompts/list, and runs a tool with tools/call.
There is no goodbye message either. A conversation with a stdio server ends when the client closes the server's input and the program exits, as the spec's stdio transport page describes, and a remote server simply stops receiving requests.
What changed in the 2026-07-28 revision?
You will meet two versions of this story, so here is the difference in one place, from the spec's changelog:
- Revisions from 2024-11-05 to 2025-11-25 opened every connection with a handshake: the client sent
initializewith its version and capabilities, the server answered with its own, and the client confirmed with aninitializednotification. That handshake is gone. Each request now carries its version and the client's capabilities in_meta, andserver/discoverreplaces the server's half of the handshake. - Sessions are gone too. A remote server no longer hands out a session ID, so any server instance can answer any request.
- A server can no longer send requests to the client in the middle of a call. When it needs something, such as an answer from the user, it returns a result that says input is required, and the client retries the original request with the answer attached.
- Change notifications, such as "my tool list changed", now flow only to clients that open a
subscriptions/listenstream. - Roots, Sampling and Logging are deprecated, as is Dynamic Client Registration for sign in. HTTP+SSE has been deprecated since 2025-03-26. Long running tasks moved out of the core into an optional extension.
Older code still speaks the handshake version. Version 1 of the official TypeScript SDK, for example, implements the spec only up to 2025-11-25, and the spec's versioning page explains how new and old programs detect each other and fall back. So when a tutorial shows initialize, it is not wrong, only older.
Here is a concrete flow from our personal assistant. The user types, "Summarize my notes from today." The host has already started the filesystem MCP server over stdio, fetched its tool list and handed the tool definitions, including read_text_file, to the LLM. The LLM emits a tool call for read_text_file with the path of today's notes file. The host sends that as a tools/call request through the filesystem client. The server reads the file and returns its text. The host adds that text to the conversation, and the LLM writes the summary.
This clean split between the host's logic and the server's code is what makes MCP composable. You can swap the filesystem server for a cloud storage server without changing the assistant's code, and the same server works with Claude, Visual Studio Code, Cursor or an agent you build yourself. The protocol boundary is the contract.
What are tools, resources, and prompts in MCP?
MCP defines three building blocks, called primitives, that a server can offer. Tools are functions the server runs. Resources are data that can be read. Prompts are reusable templates with blanks to fill in. Each has its own way to list and use it, and the spec's server features overview sorts them by who is in charge: tools are model-controlled, resources are application-controlled, and prompts are user-controlled.
A tool is how an LLM does something in the outside world. It takes structured arguments and returns content. Servers list their tools with tools/list, and each entry has a name, a description and a JSON Schema for its inputs. The host turns these entries into tool definitions the LLM can call. When the model calls one, the host sends a tools/call request with the tool's name and the model's arguments, and the server runs the function and returns the result. The model decides when to call a tool, which is why the spec asks hosts to let you approve tool calls.
In our assistant, the calendar MCP server might offer a tool called create_event with arguments like summary, start_time and end_time. The music server might offer play_track with a track_id. The assistant's LLM calls these like any other function, and the host handles the protocol.
A resource is a piece of data that can be read. It is not an action. It is a document, a file, a database record or the output of a query, and each resource has an address called a URI, such as file:///notes/today.md. Servers list resources with resources/list and can also offer resource templates, URI patterns with a variable part. Clients read one with resources/read, and the server returns its text or binary content. The app, not the model, decides which resources to read and attach to the conversation.
The calendar server might offer a resource at the URI calendar://today that returns today's events. When the user asks, "What does my day look like?", the assistant can read that resource and give it to the LLM as context. The model does not call a tool for this. It just receives the data.
A prompt is a named template with arguments that a server provides. Servers list prompts with prompts/list, and clients fetch a filled-in prompt with prompts/get by supplying the argument values. Prompts are user-controlled: the person chooses to run one, often from a slash command menu, rather than the model triggering it.
Our assistant could use a prompt from the smart home server called goodnight_routine, a template that asks the model to turn off the lights, lock the doors and set the thermostat. The user picks it from a slash command menu, the host fetches the filled-in prompt, and the LLM carries out the steps with the right tools. Prompts let the people who know a domain package good workflows inside the server.
These three primitives keep concerns separate. Tools handle actions. Resources handle data for context. Prompts handle reusable workflows the user starts. One server can offer any mix of them, and each host decides which to show.
Clients can offer features to servers too. The one that stays current is elicitation: a server asks the user a question in the middle of a task, such as "which calendar should I use?", and the client shows it to the user. Sampling, which let a server borrow the host's model, and roots, which told a server which folders the user cares about, are deprecated in the 2026-07-28 revision. You will still meet both in older servers, and roots in particular are a hint about where to look, not a lock: the spec says plainly that the protocol does not force a server to stay inside them.
How does MCP handle authentication and remote servers?
The two transports handle credentials differently, and the spec's authorization section says so directly. Authorization is optional in MCP: a server may require none. A local stdio server should not use the sign in flow at all. It takes its credentials from its environment, usually environment variables in the host's config file, and it runs with your user account's permissions. That is simple and fast, and it is also why you should only run local servers you trust.
A remote server that does protect its tools uses a sign in flow based on OAuth 2.1, the standard behind most "Sign in with" buttons. The MCP server acts as an OAuth resource server, the thing that holds what you want, and the MCP client acts as an OAuth client. In plain steps:
- The client sends a request with no token, and the server answers with HTTP 401 (unauthorized). The
WWW-Authenticateheader on that answer, or a standard address on the server, tells the client where the server's metadata lives. - The client reads that metadata, which names the authorization server that issues tokens for this MCP server.
- You sign in there and approve what the app may do. The token issued is bound to this one MCP server, so another server cannot replay it.
- The client retries the request with the token attached, and sends it on every request after that.
Under the hood this uses a few standards the spec lists: protected resource metadata (RFC 9728), resource indicators (RFC 8707) that bind a token to one server, and PKCE, which protects the sign in step. The 2026-07-28 revision also deprecates Dynamic Client Registration in favour of Client ID Metadata Documents, a simpler way for an app to identify itself.
In practice, connecting your assistant to GitHub's official MCP server looks like this: you either sign in with OAuth or paste a personal access token, depending on the server and the app. The server then calls the GitHub API on your behalf, within the permissions you granted. Other services run remote MCP servers the same way; Stripe's, for example, lets you sign in with OAuth or use an agent API key limited to what the client needs.
Hosts mix these transports freely. OpenAI's Agents SDK (software development kit), for example, can let OpenAI's Responses API call a publicly reachable MCP server for the model, connect to Streamable HTTP servers you run locally or remotely, or launch a local stdio server. In every case the tool semantics stay the same: list with tools/list, run with tools/call. The transport and the sign in are the client's job.
This layered design is what makes MCP a real protocol. The meaning of tools, resources and prompts does not depend on how the bytes move. You can start with a local server over stdio during development and later run the same tools behind an OAuth-protected HTTP endpoint. On the server you swap the transport and add sign in, which Build Your First MCP Server shows; the assistant's own tool-calling code stays as it was.
Quick Reference
| Property | Value |
|---|---|
| Roles | host (the AI app), one client per server, servers |
| Wire format | JSON-RPC 2.0 |
| Current revision | 2026-07-28 (stateless, no initialize handshake), as of October 2026 |
| Request flow | optional server/discover, then tools/list, resources/list, prompts/list, then tools/call |
| Transports | stdio (local) and Streamable HTTP (remote); HTTP+SSE deprecated |
| Server primitives | tools (model-controlled), resources (application-controlled), prompts (user-controlled) |
| Client features | elicitation; roots and sampling deprecated in 2026-07-28 |
| Authorization | optional; for HTTP servers that use it, based on OAuth 2.1; stdio servers read credentials from their environment |
| Specification | MCP specification 2026-07-28 |
| Official SDKs | TypeScript, Python, C#, Go, Rust, Ruby, Java, Swift, PHP and Kotlin, as of October 2026 (SDK list) |
| Example servers | Filesystem, GitHub |
| Host integrations | Claude, ChatGPT, Gemini, Visual Studio Code, Cursor, OpenAI Agents SDK, LangChain |
Frequently Asked Questions
Q: Do I need to use Anthropic's Claude to use MCP? No. MCP is an open protocol, now hosted by the Agentic AI Foundation under the Linux Foundation. Any application can implement the host side, and ChatGPT, Gemini, Visual Studio Code, Cursor, LangChain and many others already support it. You can build your own host with the official SDKs.
Q: Is MCP only for remote servers, or can I run it locally? Both. The stdio transport runs servers on your computer as child programs of the host. Streamable HTTP connects to remote servers. One host can mix local and remote servers in the same conversation.
Q: How does MCP handle authentication for third-party services? Authorization is optional. A remote server that protects its tools uses a flow based on OAuth 2.1: the client finds the right authorization server from the server's metadata, you sign in and approve, and every request then carries a token issued for that one server. A local stdio server reads its credentials, such as an API key, from its environment instead.
Q: What is the difference between a tool and a resource?
A tool is a function the model can choose to call, like creating a calendar event. A resource is data the app can read and attach to the conversation, like today's schedule at calendar://today. Tools are model-controlled; resources are application-controlled.
Q: Can one MCP server expose multiple types of primitives?
Yes. One server can provide tools, resources and prompts, and the host discovers each type separately. A calendar server might offer a create_event tool, a calendar://today resource and a summarize_day prompt.
Q: A tutorial I found starts with an initialize request. Is it out of date?
It follows a revision before 2026-07-28, which many servers, hosts and SDKs still use. The ideas carry over unchanged; only the opening differs. Under the current revision there is no handshake, each request carries its version in _meta, and a client can call server/discover instead.
Test yourself
You are extending the personal assistant with a weather MCP server that provides a get_forecast tool. The server is local, communicates over stdio and speaks the 2026-07-28 revision. Describe the full flow from host startup to the assistant answering a question about the weather in Berlin, and say what would differ with an older server.
Answer: The host creates an MCP client for the weather server and starts the server as a child program. There is no handshake. The client may send server/discover first to learn the server's versions and capabilities, and every request it sends carries the protocol version and the client's capabilities in _meta. The client calls tools/list and finds get_forecast with its input schema, say location and units. The host turns that into a tool definition for the LLM. When the user asks about Berlin, the LLM emits a call to get_forecast with {"location": "Berlin", "units": "metric"}, and the host sends it as tools/call. The server calls a weather API and returns the result as text. The host adds it to the conversation, and the LLM answers in words. When the assistant shuts down, the client closes the server's input and the program exits. An older server would expect an initialize request and an initialized notification before anything else.
Next: Using MCP Servers: Plug Tools Into Your Assistant. It shows how to find servers, add them to Claude Desktop, Claude Code and VS Code, and check that they work.
If you want this kind of breakdown every week, how real systems actually work under the hood, subscribe to Internals Decoded at internalsdecoded.com.
Sources
- Introducing the Model Context Protocol
- Donating the Model Context Protocol and establishing the Agentic AI Foundation
- MCP specification 2026-07-28
- MCP specification 2026-07-28: Key changes
- MCP specification: Architecture
- MCP specification: Versioning and compatibility
- MCP specification: Transports
- MCP specification: stdio
- MCP specification: Discovery
- MCP specification: Server features
- MCP specification: Authorization
- MCP SDKs
- OpenAI Agents SDK: Model Context Protocol
- LangChain: Model Context Protocol
- GitHub MCP Server
- Stripe: Model Context Protocol
- Filesystem MCP Server