Mid · Core path · 7 chapters
Architecture
Hosts, clients and servers; connection lifecycle; capability negotiation on initialize
Most MCP failures are boundary and lifecycle mistakes, so a plausible tool integration can still fail before its first useful call.
Read these first
What you will know
Build a minimal host with a client connection to a server, and annotate which process owns lifecycle, transport, and capabilities
Misplacing state or responsibility creates duplicated connections, unusable capabilities, and shutdown leaks.
Walk through a connection from initialize to first tool call
A valid exchange includes initialization, the response, the initialized notification, and only then discovery or invocation; ordering errors often look like tool failures.
Compare the capabilities advertised during initialize with the operations actually attempted, using a captured message fixture
A client must not infer support from product identity, and unsupported features need an explicit fallback rather than an assumed method.
Read a protocol trace and identify the failed stage, citing the message that proves it
Separating transport, initialization, capability discovery, and invocation failures prevents retries from masking the real fault.
Reproduce a capability mismatch and patch the client to degrade to a supported path
Servers and clients evolve independently, so unknown methods, missing features, and version skew must produce controlled behavior instead of broken sessions.
Chapters
- 1
Hosts, clients and servers
A host is the application; a client is the connection object inside it, bound to exactly one server for exactly one session; a server is the separate process it connects to. A desktop app joined to four servers therefore has four clients, not one — and consent policy, whether the user sees a dialog before a destructive call, is the host's job across all four and never the server's. This chapter fixes the counts and the labels, then annotates which process owns lifecycle, which owns the transport, and which owns the negotiated capabilities.
- 2
The initialized notification
A valid opening is three messages, not two: initialize, the server's response, and the initialized notification that carries no id and gets no reply. A client that sends tools/list straight after the response is still inside initialization, and the rejection it gets back — `-32601`, naming a tool that plainly exists — looks exactly like a broken tool. Expect the symptom to be intermittent, appearing only in the first second after connect, and resist the server-side fix that answers early.
- 3
Capability and version negotiation
What a session may do is whatever both sides declared during initialize, not whatever the product on the other end is known to support: a well-known desktop host can ship with sampling switched off for your server, and the capabilities object arrives as `{}`. The protocol version in the response is the server's counter-offer rather than an echo, and a client that keeps sending newer message shapes after receiving an older one has ignored it. Negotiation happens once, and nothing in the protocol reopens it.
- 4
Reading a protocol trace
Transport, initialization, capability negotiation and invocation fail differently, and each leaves a distinguishable message. An initialize response carrying an empty capabilities object followed by resources/read answered with -32601 is not a missing handler; it is a method that never existed in this session. Exactly one of the four stages benefits from a retry, which is why a generic retry wrapper turns a diagnosable error into an indefinite spinner — and why the habit worth building is citing the message that proves the diagnosis.
- 5
Degrading on the capability declaration
A server can declare resources without subscribe or listChanged, and a client that assumes otherwise renders a spinner that never resolves. Feature-testing by calling subscribe and catching the error is the wrong shape twice: the contract was already negotiated at initialize, and the failure that actually hurts is a subscription accepted and never notified. Branch on the capability set at connect time, paint from an unconditional first read, and show the staleness window the degraded path costs.
- 6
Closing an MCP session
A session ends as deliberately as it opens, and the protocol has no message for it: teardown is a transport act, closing a child's stdin or issuing an HTTP DELETE. In-flight requests have to be cancelled or abandoned, subscriptions drop with the transport, a local server's child process has to be reaped, and the host has to remove that server's tools from the aggregated definitions it sends the provider on the next turn. Nothing enforces any of it, which is why the failure mode is a leak with no exception rather than an error.
- 7
The state a connection carries
Reusing one long-lived client object across two servers to avoid reconnect cost is a design many hosts reach for, and re-running initialize on it is half the work. Pending request ids, active subscriptions, the workspace roots the previous server was told about, the cached tool list and the id counter all survive the swap, so a late response from the old server can be matched to a request sent to the new one. The three failures surface on three timescales, and the protocol is not the expense the design was avoiding.
External resources
- Architecture overviewmodelcontextprotocol.io
MCP hosts, clients and servers, with protocol layers, transports, initialization and capability negotiation.
- Survey of LLM Agent Communication with MCP: A Software Design Pattern Centric Reviewarxiv.org
Maps MCP's roles and session model onto familiar design patterns.
- MCP Key Concepts and Architecture · Hugging Facehuggingface.co
MCP hosts, clients, servers, transports and capability negotiation: the architecture and lifecycle essentials.
- What is the Model Context Protocol (MCP)?modelcontextprotocol.io
Explains MCP hosts, clients, servers, connection lifecycle, and initialization capability negotiation.
- How Model Context Protocol (MCP) actually worksGoogle Cloud Tech
Traces a connection from initialize through capability exchange to a call.
- MCP Tutorial: Build Your First MCP Server and Client from Scratch (Free Labs)KodeKloud
Builds both sides so the lifecycle and negotiation become tangible.
- What is MCP? Integrate AI Agents with Databases & APIsIBM Technology
Explains MCP hosts, clients, servers, initialization, and capability negotiation for connecting agents to APIs.