Your coding agent reads the repository, checks the build and files issues in your tracker. A typical diagram of that setup shows one box labeled "MCP" between the model and the tools. Then a security reviewer asks which process can read your home directory, which token reaches the tracker and who approved the call that created an issue. The box has no answer.
The Model Context Protocol (MCP) has a precise architecture, and its 2026-07-28 revision changed part of it. This post covers participants, protocol layers, transports, features, one tool call, remote authorization and trust boundaries, with a diagram you can copy.
Hosts, clients and servers
Before MCP, every AI application needed its own adapter for every tool: five applications and twenty tools meant up to 100 integrations. With MCP, 25 implementations (one client per application, one server per tool) cover every pairing.
| Participant | What it is | What it holds |
|---|---|---|
| Host | The AI application: an IDE, a chat app, an agent runtime | The conversation, model calls, user consent, credentials |
| Client | A connector the host creates for one server | One connection and the capabilities it declares |
| Server | A program that exposes tools, resources and prompts | Access to the system it wraps |
A host creates one client per server, and each client talks to exactly one server. The model never calls a server itself: it asks for a tool call, and the host decides whether to run it and which client sends it. Servers stay isolated: they should not see the whole conversation or each other.
Two layers, and what 2026-07-28 changed
The data layer is JSON-RPC 2.0: requests (with an id that is never null), results, errors and one-way notifications. The transport layer moves those messages and handles framing, cancellation and authorization.
The 2026-07-28 specification, released on 28 July 2026, made MCP stateless. Earlier revisions opened each connection with an initialize handshake that fixed the version and capabilities, and HTTP servers could pin a session with Mcp-Session-Id. Now every request carries its protocol version and client capabilities in _meta, so it can land on any server instance behind a plain round-robin load balancer.
| 2025-11-25 and earlier | 2026-07-28 | |
|---|---|---|
| Version and capabilities | initialize once per connection |
_meta on every request; optional server/discover |
| State across calls | Mcp-Session-Id header |
Explicit handles passed as tool arguments |
| Server needs client input | Server sends its own request | InputRequiredResult, then the client retries |
| Change notifications | HTTP GET stream | subscriptions/listen stream |
| Broken stream | Resume with Last-Event-ID |
Re-send with a new id |
Servers built on older SDKs still expect the handshake, so dual-era clients probe first and fall back to initialize. A client that speaks only 2026-07-28 cannot use a legacy-only server. The changelog lists every breaking change.
Transports: stdio and Streamable HTTP
| stdio | Streamable HTTP | |
|---|---|---|
| Server runs as | A child process the client launches | An independent service with one endpoint, such as /mcp |
| Messages | One JSON-RPC message per line on stdin and stdout | One POST per message; the reply is JSON or a request-scoped SSE stream |
| Credentials | From the environment | Usually an OAuth 2.1 bearer token on every request |
| Cancel a request | notifications/cancelled |
Close the response stream |
| Headers for proxies | None | MCP-Protocol-Version, Mcp-Method, Mcp-Name |
Streamable HTTP replaced the HTTP+SSE transport (a GET stream plus a separate POST endpoint) in 2025-03-26; HTTP+SSE is now formally deprecated. Gateways can route and rate limit on Mcp-Method and Mcp-Name without parsing bodies, and servers reject requests whose headers disagree with the body. HTTP servers must validate the Origin header against DNS rebinding, and local ones should bind to 127.0.0.1.
Server and client features
| Feature | Offered by | Who drives it | Methods | Status |
|---|---|---|---|---|
| Tools | Server | The model | tools/list, tools/call |
Active |
| Resources | Server | The application | resources/list, resources/read |
Active |
| Prompts | Server | The user | prompts/list, prompts/get |
Active |
| Elicitation | Client | Server asks the user | elicitation/create |
Active |
| Sampling | Client | Server asks the host's model | sampling/createMessage |
Deprecated |
| Roots | Client | Server asks for folders | roots/list |
Deprecated |
Elicitation's form mode must never ask for passwords, API keys or tokens; URL mode sends the user to a page outside the client instead. Sampling, roots and server logging were deprecated in 2026-07-28 and can be removed no earlier than the first revision released on or after 28 July 2027.
One tool call, step by step
The model files an issue through a remote server:
- Optionally, the client calls
server/discoverfor versions and capabilities. - The client calls
tools/list. The host merges the lists from all servers, prefixing names that collide, and gives them to the model. - The model asks for
create_issue. The host shows the call, and the user approves it. - The client sends
tools/call, shown below. - If the server needs a confirmation, it returns
input_requiredwith an elicitation request. The client asks the user and retries with the answer and the server's opaquerequestState. - The result arrives as
complete. A tool failure setsisError: true, so the model can correct itself. - On a
subscriptions/listenstream,notifications/tools/list_changedtells the client to list tools again.
POST /mcp HTTP/1.1
Host: mcp.tracker.example
Authorization: Bearer eyJhbGciOi...
Content-Type: application/json
Accept: application/json, text/event-stream
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: create_issue
{"jsonrpc": "2.0", "id": 7, "method": "tools/call",
"params": {"name": "create_issue",
"arguments": {"title": "Login fails on Safari"},
"_meta": {"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {"name": "my-ide", "version": "1.4.0"},
"io.modelcontextprotocol/clientCapabilities": {"elicitation": {}}}}}
{"jsonrpc": "2.0", "id": 7, "result": {"resultType": "complete",
"content": [{"type": "text", "text": "Created issue #482"}], "isError": false}}
Remote servers and authorization
A remote MCP server is an OAuth resource server; its tokens come from an authorization server run by the same vendor or by a separate identity provider. On a first connection:
- The client calls without a token and gets
401, usually with aWWW-Authenticateheader pointing to the server's protected resource metadata (RFC 9728). - That document, or
/.well-known/oauth-protected-resourceas a fallback, names the authorization server, whose metadata the client reads; it stops if PKCE is not advertised. - The client uses a pre-registered client ID, a Client ID Metadata Document (an HTTPS URL as the client ID) or Dynamic Client Registration, which 2026-07-28 deprecates.
- The client runs the authorization code flow with PKCE (
S256) and aresourceparameter naming the MCP server (RFC 8707). The user signs in and consents in the browser, and the client checks theissin the response (RFC 9207). - Every request carries
Authorization: Bearer. A403withinsufficient_scopetriggers step-up authorization.
The server accepts only tokens issued for itself and never passes them through: calls to an upstream API use a separate token. The OAuth 2.0 flow diagram explains PKCE, and the authorization spec has the full rules, built on the OAuth 2.1 draft.
Where the trust boundaries are
| Boundary | Risk | Control |
|---|---|---|
| Model and tool text | Injected instructions in descriptions or results; definitions changed after approval | Treat as untrusted data, show calls to the user, re-approve changed definitions |
| Machine and stdio servers | A server reads files, environment variables or SSH keys and sends them out | Vet packages; sandbox third-party servers with one read-only mount and no network; one narrow token per server |
| Network edge | Stolen or over-scoped tokens | Audience-bound, short-lived tokens; minimal scopes with step-up |
| Between servers | One server steers how the agent uses another's tools | Few servers, distinct tool names, host mediation |
The stdio transport is not a sandbox: the MCP local server security guide says a stdio server runs with the client's privileges, and isolation is up to the host and whoever runs the machine. A state handle minted by a stateless server is not a credential either; bind it to the authenticated user. The threat modeling data flow diagram shows how to walk such boundaries with STRIDE.
The MCP architecture diagram
Diagram contents
- Developer machine: one OS user, one trust domain
- Host application (IDE or chat app)
- Remote service (vendor cloud)
- Developer
- Agent loop + LLM
- MCP client 1
- MCP client 2
- MCP client 3
- Filesystem server
- Git server
- Issue tracker MCP server
- Issues API
- Authorization server
- prompts, approvals
- read_file
- git_log
- create_issue
- stdin / stdout
- POST /mcp + Bearer token
- OAuth 2.1: browser sign-in, code + PKCE + resource
- own token
How to read it:
- The green frame is one trust domain: the host, its three clients and both stdio servers run as the developer's OS user.
- One client per server. Clients 1 and 2 use stdin and stdout; client 3 uses Streamable HTTP.
- Gray edges from the model are tool calls the host routes; servers never reach the model directly.
- Blue crosses the network with a bearer token. Dashed violet is the OAuth flow, which runs only when the client has no valid token.
- Teal is the remote server calling its API with its own token: no passthrough.
- The Markdown block sums up revision 2026-07-28.
Drawing MCP architecture diagrams clearly
- One client per server. A single "MCP" box hides what each server can see.
- Label edges with transport and payload: stdin and stdout, a POST with a bearer token, an OAuth flow, example tool names.
- Draw trust boundaries as frames: the machine, the host, each vendor. Mark sandboxed servers.
- Give the authorization server and upstream APIs their own nodes, so token sources and the no-passthrough rule are visible.
- State the protocol revision. A 2026-07-28 diagram has no handshake or session IDs.
- Leave out SDK internals, full tool lists and the model provider's infrastructure.
The AI agent architecture diagram covers the agent loop around these calls.
Build it in Archboard
- Sign in with Google or GitHub and create a diagram.
- Add a Frame from the Core pack for the developer machine and, inside it, a Container Boundary from the C4 Model pack for the host.
- In the boundary, add a Model from the ML pack and three Component nodes from the C4 Model pack for the clients, with technology stdio, stdio and Streamable HTTP.
- Add two Container nodes from the C4 Model pack for the local servers, connected with "stdin / stdout" edges, and a Person from the same pack connected to the model.
- Outside the frame, add a System Boundary from the C4 Model pack holding a Container for the remote server, an External System for its API and an Identity Provider from the Security pack, then draw the bearer-token, dashed OAuth and "own token" edges.
- Add a Markdown block from the Core pack with the protocol facts, and Core Text notes for the boundaries.
No free tool reads MCP client config files, so draw the servers yourself or paste a Mermaid flowchart, such as the one in the MCP specification, into the Mermaid to editable diagram tool.
At the time of writing (November 2026), Archboard is itself a remote MCP server at https://getarchboard.app/mcp: Streamable HTTP, OAuth 2.1 from its own authorization server with PKCE (S256) and that URL as the resource indicator, and client registration by Client ID Metadata Document or dynamic client registration. The MCP server documentation lists its tools, and the AI agents page shows how to connect your app.
The example uses 14 diagram nodes, within the Free plan.
FAQ
What is the difference between an MCP host, client and server? The host is the AI application, such as an IDE. It creates one client per server, and each client holds a dedicated connection to one server, which exposes tools, resources and prompts.
Is MCP stateless now?
Yes, since revision 2026-07-28: no initialize handshake, no session ID, and every request carries its own version and capabilities. Servers on older revisions still use the handshake.
What transports does MCP support? Two standard ones: stdio for local servers and Streamable HTTP for remote ones. HTTP+SSE is deprecated, and custom transports must keep the JSON-RPC message format.
Do local MCP servers need OAuth? No. The specification says stdio servers should take credentials from the environment. Give each one a narrowly scoped token and sandbox third-party servers.
What is token passthrough in MCP? An MCP server accepting a token that was not issued for it, or forwarding the client's token to another API. The specification forbids it; upstream calls need the server's own token.