An MCP server is a program that offers capabilities: tools a model can call, resources an app can load, prompts a user can pick. An MCP client is the small component inside an AI app that holds the line to one of those servers. The app itself, whether that's Claude, Cursor, VS Code or ChatGPT, is the host. When people say "Claude is an MCP client", they mean the host. The host creates one client for every server you add.
That covers the definitions. The interesting part is what happens once the server stops running on your laptop. A remote server serves many clients, from many apps and many people, so who authenticates whom, where the client actually runs, and who keeps state all change. The current spec revision, 2026-07-28, changed how clients and servers talk, and most explainers you'll find still describe the 2025 version. We checked everything below against the 2026-07-28 spec on October 8, 2026.
Host, client, server: the three roles
The spec calls MCP a "client-host-server architecture where each host can run multiple client instances." In practice:
| Host | Client | Server | |
|---|---|---|---|
| What it is | The AI app you use | A connector object the host creates, one per server | A program that exposes tools, resources and prompts |
| Examples | Claude Desktop, Claude Code, claude.ai, Cursor, VS Code, ChatGPT | Rarely visible. It's the thing behind each entry in your server list | A filesystem server on your machine, GitHub's or Sentry's hosted server, DialMCP |
| Sees the conversation? | Yes, all of it | Only what the host hands it | No. Only the requests it receives |
| Talks to the model? | Yes | No | No |
| Decides | Which servers connect, what the user approves, which context reaches the model | How to speak MCP to its one server | What it offers and whether a request is allowed |
The spec's job list for the host includes creating and managing clients, enforcing security policies and consent, handling the user's authorization decisions, and pulling context together across clients. The client attaches the protocol version and its capabilities to every request, routes messages, and keeps one server walled off from the others. The server exposes its primitives and "can be local processes or remote services."
One design rule explains most of the split. Per the spec, "Servers should not be able to read the whole conversation, nor 'see into' other servers." The full history stays with the host, and the host controls anything that crosses between servers. A server sees the arguments of the tool call it was sent and nothing more. That's a privacy feature, and it's also why a server can't "just look at" what another server returned.
One client per server, many clients per host
The relationship is strictly 1:1 at the client level: "Each client is created by the host and communicates with exactly one server." Configure four servers in VS Code and VS Code runs four client objects. The MCP docs use exactly that example, with VS Code creating a client for the Sentry server and another client for each server after it.
The 1:1 rule is about client instances, not server programs. The official architecture diagram shows two clients in the same host both talking to one remote server. Turn that around and you get the first way remote changes things. A local stdio server "typically serve[s] a single MCP client." A remote server over Streamable HTTP "will typically serve many MCP clients." Those clients belong to different hosts, run in different places, and act for different people.
A note on the word "connection". The learn docs still say each client "maintains a dedicated connection". Since 2026-07-28 there is no protocol session behind that word. Over HTTP every request is its own POST, so "one client object per server" is more accurate than "one persistent session per server".
What each side offers
Servers offer three primitives, and each has a different owner. This is the most useful distinction in MCP once you start building:
| Server primitive | Controlled by | What that means |
|---|---|---|
| Tools | The model | Functions the LLM decides to call, such as search_issues or place_call |
| Resources | The application | Data the host attaches as context: files, records, schemas |
| Prompts | The user | Templates the user picks, often shown as slash commands |
Servers also implement some utilities: argument completion, pagination, response caching hints, and server/discover, a new call that reports which protocol versions and capabilities the server supports. Our tools, prompts and resources guide goes deeper on the three primitives.
Clients can offer features to servers too, and here the 2026 revision made the biggest cut. The spec overview now lists one active client feature: elicitation, where a server asks the user for input. It has two modes. Form mode collects structured answers. URL mode sends the user to a web page, and the spec requires it for anything sensitive: "Servers MUST NOT use form mode elicitation to request sensitive information such as passwords, API keys, access tokens, or payment credentials."
The other two client features you'll see in older articles are deprecated as of 2026-07-28, not removed:
- Sampling, where a server borrows the host's model for a completion. The migration advice is to "integrate directly with LLM provider APIs."
- Roots, where the client tells a server which folders it may work in. The advice is to pass paths through tool parameters, resource URIs or server config instead. The spec also notes roots were never enforced: they "are informational guidance rather than an access-control mechanism."
The deprecation registry gives both an earliest removal of the "first revision released on or after 2027-07-28." Hosts that support them keep working for now. New servers shouldn't depend on them.
How they talk in 2026: the client always speaks first
MCP messages are JSON-RPC 2.0. What changed in 2026-07-28 is who may say what, and when. Four changes matter for the client/server split.
No handshake. The initialize / notifications/initialized exchange is gone. Every request carries its own protocol version and the client's capabilities in _meta. The spec puts it plainly: "There is no negotiation handshake. Every request carries its protocol version, and the server accepts or rejects each request independently." A server that doesn't support the version returns an UnsupportedProtocolVersionError (code -32022) listing the versions it does support, and the client retries. A request now looks like this:
{
"jsonrpc": "2.0",
"id": 7,
"method": "tools/call",
"params": {
"name": "search_issues",
"arguments": { "query": "login bug" },
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": { "elicitation": {} }
}
}
}
A client that wants to know a server's capabilities up front can call server/discover first. Servers must implement it. Calling it is optional.
Servers never start a request. "Servers MUST NOT initiate JSON-RPC requests, and clients do not send JSON-RPC responses." Every exchange begins with the client. So how does a server ask the user a question in the middle of a tool call? With a pattern called Multi Round-Trip Requests. The server finishes the call early with an InputRequiredResult describing what it needs, plus an opaque requestState. The client gets the answer, then retries the original call with a new request ID, the answers, and that state attached. Only tools/call, prompts/get and resources/read can do this. The spec calls the switch "a breaking change."
No sessions. The Mcp-Session-Id header is gone. If a server needs state across calls, it hands the model an explicit ID and expects it back as an ordinary tool argument. The spec's example is a shopping cart: create_basket() returns a basket_id that later calls pass in.
Old and new don't automatically mix. The compatibility matrix is blunt. A modern-only client talking to a 2025-era server fails. A 2025-era client talking to a modern-only server also fails, because "Legacy clients have no fall-forward mechanism." Implementations that speak both eras (the spec calls them dual-era) work with either side. Python SDK 2.x clients probe with server/discover by default and fall back. TypeScript SDK v2 clients stay on the 2025 protocol unless you opt in.
If you're reading a 2025 tutorial, mentally translate: the handshake, the session ID, and the server sending sampling/createMessage whenever it likes are all legacy (2025-11-25 and earlier). The versioned 2026-07-28 architecture page is the one to read. Our Streamable HTTP guide covers the transport side of the same revision.
Why remote changes the model
With a local server, the client/server line barely matters day to day. With a remote server it becomes the line that security, identity and operations hang on.
Local: the client owns the server
Over stdio, "the client launches the MCP server as a subprocess." The server lives and dies with the client, serves exactly that one client, and talks over stdin and stdout. Credentials come from the environment. The spec says stdio implementations "SHOULD NOT follow" the authorization spec and should "retrieve credentials from the environment" instead. The trust boundary is your machine. If you've set this up in Claude Desktop, that's what each entry in claude_desktop_config.json is: a command the host runs to spawn a server for one of its clients.
Remote: the server is on its own
Over Streamable HTTP the server "operates as an independent process that can handle multiple client connections." Three things follow.
Identity becomes explicit. The server can't assume who is on the other end, so the authorization spec comes into play. It's optional, but HTTP servers should follow it. In OAuth terms the roles map cleanly: "A protected MCP server acts as an OAuth 2.1 resource server," and "An MCP client acts as an OAuth 2.1 client." The server publishes Protected Resource Metadata (RFC 9728) so the client can find the authorization server. The client must name the server it wants a token for using a resource indicator (RFC 8707). Every HTTP request carries the token, and the server must check the token was issued for it specifically. When client and server have no prior relationship, 2026-07-28 recommends Client ID Metadata Documents and deprecates Dynamic Client Registration, keeping it for backward compatibility. Our MCP authorization guide walks the full flow.
The client might not be on your machine. This one surprises people. Claude's custom connectors "connect to your MCP server from Anthropic's cloud, not from your local device," so the client for that server runs in Anthropic's infrastructure. That's why a connector can't reach localhost. ChatGPT's docs likewise describe connecting to remote MCP servers, not launching local ones. Desktop and terminal hosts such as Claude Code, Cursor and VS Code run their clients on your machine, so they can usually reach a server on your network. "Where does the client run?" is often the real answer to "why can't it connect?"
State has to travel with the request. A busy remote server runs as many instances behind a load balancer. The 2025 session model meant routing each session back to the instance that held it. The 2026 model is built so it doesn't matter: per the spec, the server handling a retried request "does not need any information beyond what is directly present in the retry request." Long-running work can use the tasks extension, where the server returns a durable handle and the client polls it.
Where the roles blur
"Client" and "server" describe roles, not products, and one program can hold both.
- Bridges. mcp-remote, a community package, is a stdio server from Claude Desktop's point of view and a Streamable HTTP client from the remote server's point of view. It exists for hosts, or config paths like Desktop's config file, that can only launch local commands.
- Gateways and proxies. A gateway is a server to your host and a client to every server behind it. Our MCP gateway explainer covers when that layer earns its keep.
- Servers that call APIs. A remote server is a resource server to MCP clients and is often an OAuth client to some upstream API at the same time. The spec draws a hard line here: the server "MUST NOT pass through the token it received from the MCP client." Upstream calls use separate credentials.
The security checklist flips too
| Local (stdio) | Remote (Streamable HTTP) | |
|---|---|---|
| Who starts the server | The client, as a subprocess | The operator, ahead of time |
| Clients per server | One | Many, across hosts and users |
| Credentials | Environment variables | OAuth 2.1 bearer token on every request, when the server requires auth |
| Main risks | Running an untrusted command on your machine | Token misuse, confused-deputy proxies, SSRF during OAuth discovery |
| Spec guidance | Hosts that offer one-click install must show the exact command, untruncated, and get explicit approval. Local HTTP servers should bind to 127.0.0.1 only | Validate Origin and token audience, no token passthrough, per-client consent for proxies, never treat a state handle as proof of identity |
That last point catches people. The spec says servers "MUST NOT treat possession of a state handle as authentication." A basket_id or call_id is a pointer, not a password, so check it against the signed-in user every time. Our remote vs local MCP servers guide compares the two deployment models more broadly.
One phone call, three roles
Here is a real remote server end to end. DialMCP lets an agent place phone calls from the user's own verified number. Say you add it to Claude as a custom connector.
- Host: Claude. It decides whether a call tool is appropriate, shows you the tool request, and keeps the conversation.
- Client: the connector Claude creates for
https://mcp.dialmcp.com/mcp, running in Anthropic's cloud. - Server: DialMCP's endpoint. Its first answer to an unauthenticated request, as we saw when we checked on October 8, 2026, is a
401with aWWW-Authenticateheader pointing at/.well-known/oauth-protected-resource/mcp. That document names the authorization server. Its metadata offers a registration endpoint and PKCE with S256. The client registers, sends you through sign-in and phone verification, and comes back with a token issued for that one resource.
From there the client lists the four tools and the model calls place_call. The call can run for many minutes, so the tool returns a call ID right away, and the model polls get_call for the transcript and outcome. That call ID is a state handle in the 2026 sense, checked against the signed-in user rather than trusted on sight.
To be straight about where it sits: DialMCP was built in July 2026 on a 1.x SDK and still speaks the 2025 protocol, up to 2025-06-18, with sessions. Clients connect using the legacy handshake, and dual-era clients such as Claude Code fall back to it. That's typical of production servers in October 2026, and the matrix above is why dual-era clients matter right now.
Should you build a client or a server?
Usually a server. Ask which side of the line your code lives on:
- You have a capability or data (an API, a database, a device, a phone line) and want any AI app to use it: build a server. Remote if other people will use it, stdio if it only makes sense on the user's machine. Start with how to build an MCP server or the Python walkthrough.
- You're building the AI app (an agent, a chat product, an IDE feature) and want it to use other people's servers: you're building a host, and you'll create clients inside it.
- Both is common for gateways and agent platforms.
The official SDKs cover both sides. The SDK page lists ten languages and says all of them support "Creating MCP servers" and "Building MCP clients". TypeScript v2 makes the split literal with separate @modelcontextprotocol/server and @modelcontextprotocol/client packages. The Python SDK 2.x renamed FastMCP to MCPServer, so older snippets need a small update.
Common mix-ups
- "Cursor is an MCP client." Cursor is a host that creates clients. The shorthand is everywhere, including in the MCP docs, and it's harmless until you're debugging one specific server connection.
- "Remote" means "somebody else's". It means the server runs as its own HTTP process. You can run a remote-style server on your laptop. Connectors that run in a vendor cloud just can't reach it.
- "The client and server keep a session." Not in 2026-07-28. State goes into explicit handles.
- "Sampling and roots are core client features." Both are deprecated as of 2026-07-28, and elicitation is the active one.
- "The latest spec is 2025-06-18" (or 2025-11-25). The current revision is 2026-07-28.
- "Put the remote URL in claude_desktop_config.json." That file launches local commands. Use Customize → Connectors or a bridge.
Further reading
- Remote vs local MCP servers
- DialMCP client setup: Claude, Codex, Cursor, VS Code
- DialMCP OAuth and phone verification
- MCP spec 2026-07-28: architecture
- MCP docs: understanding MCP clients
- MCP spec 2026-07-28: changelog
- MCP spec: Multi Round-Trip Requests
- MCP spec: authorization
- MCP spec: deprecated features
See the roles in action. DialMCP is a remote MCP server that lets Claude, Codex, Cursor or VS Code place real phone calls from your own verified number and hand back a transcript and a structured outcome. Add https://mcp.dialmcp.com/mcp as a connector and sign in. US and Canada, free during launch.
FAQ
What is the difference between an MCP client and an MCP server?
A server exposes capabilities: tools the model can call, resources the app can load, and prompts the user can pick. A client is the component inside an AI app that talks to exactly one server on the app's behalf. The app itself, such as Claude or Cursor, is the host, and it creates one client per server you add.
Is Claude an MCP client or an MCP host?
Strictly, Claude is a host. Claude Desktop, Claude Code and claude.ai create an MCP client for each server you connect. Calling the app an MCP client is common shorthand and is fine until you are debugging one specific server connection.
What is an MCP host?
The host is the AI application the user interacts with. It creates and manages the clients, enforces consent and security policy, handles authorization decisions, and decides what context reaches the model. It is the only party that sees the whole conversation.
Can one MCP server serve many clients?
Yes, if it is remote. A stdio server is launched by one client and serves only that client. A server reached over Streamable HTTP typically serves many clients, from different hosts and different users, which is why it needs authorization and stateless request handling.
Do MCP clients and servers still do an initialize handshake?
Not in the 2026-07-28 revision. Every request carries its protocol version and client capabilities in _meta, servers accept or reject each request independently, and session IDs are gone. Servers and clients built for 2025 still use initialize, so dual-era implementations support both.