MCP Architecture
Summary
MCP Overview defined what MCP is. This page shows the runtime architecture: host, client, server, transports, and the lifecycle of a connection.
MCP is a host-client-server protocol. The host owns the user interaction and model loop. The client manages a connection to a server. The server advertises and fulfils capabilities. This separation is what makes the same MCP server usable from multiple hosts.
| Role | Responsibility | Typical runtime | Example in practice |
|---|---|---|---|
| Host | Owns UX, orchestration, policy checks, and model loop decisions. | Desktop app, web app, IDE, agent runtime. | A support copilot decides whether a create_ticket tool requires user confirmation before execution. |
| Client | Manages protocol session lifecycle: initialization, discovery, request/response, and shutdown. | In-process library inside the host. | The host uses an MCP client package to discover server tools at startup and apply per-tool timeouts. |
| Server | Exposes tools/resources/prompts and executes requested capabilities behind governed boundaries. | Local process or remote service. | A single MCP server exposes CRM lookup, policy resources, and triage prompts reused by multiple host apps. |
The model does not talk directly to the server. The host decides which servers are connected, which capabilities are visible, when calls are allowed, and what approval steps exist for sensitive actions.
Initialisation, capability listing, requests, notifications, and shutdown all pass through the MCP client. The client layer is where retries, timeouts, and transport handling usually live.
stdio is ideal for local process integration. HTTP and streaming transports work better for remote shared services. The transport is not an implementation detail; it affects latency, authentication, hosting, and observability.
Why This Matters
The host remains the policy owner. It can hide destructive tools, inject user identity, require approval before write actions, or disable certain servers entirely for a given session.
stdio, it becomes distributed systems workAuthentication, connection management, retries, network partitions, and rate limiting all become relevant the moment a server is shared across machines or teams.
When teams understand the lifecycle, they can distinguish protocol failures from tool failures: the server may be reachable but not initialised, initialised but not exposing the expected tool, or healthy but timing out during a specific invocation.
Core Concepts
Host, client, server topology
Transport options
| Transport | Best for | Advantages | Trade-offs |
|---|---|---|---|
stdio | Local process integration | Simple, fast, no network stack | Local-only lifecycle, process management required |
| HTTP + streaming | Shared or remote servers | Easier hosting, central auth, multi-client access | Network latency, distributed failure modes |
| SSE / long-lived streams | Incremental updates and notifications | Real-time server-to-client flow | Connection handling complexity |
Connection lifecycle
Operational guidance
- Prefer
stdiowhen the server is local to the host process boundary. - Prefer remote hosting only when capabilities need to be shared broadly.
- Add timeouts and cancellation to every invocation.
- Log
initialize, discovery, invocation, and shutdown separately. - Keep tool contracts stable; breaking changes ripple across hosts.
Realistic Example
Scenario
An IDE extension connects to two local MCP servers over stdio:
repo-serverfor code search and file resourcesbuild-serverfor test execution and build logs
At startup, the host launches both server processes, initialises sessions, lists capabilities, and exposes only safe read-oriented tools until the user explicitly approves write operations.
When the user asks, "Why did yesterday's build fail?", the host routes the model toward:
build-servertool:get_recent_failuresrepo-serverresource:ci/pipeline.yamlrepo-servertool:search_code("NullReferenceException")
The host coordinates all of that; the model never opens raw sockets or direct process pipes itself.
Senior Tech vs Dev Conversation
Senior Tech: Should we start with a remote MCP server so every app can share it?
Dev: Only if you already need cross-host reuse. A remote shared server sounds attractive, but it adds auth, tenancy, throughput limits, and transport troubleshooting immediately. If one app needs the capability today, start with a local stdio server and promote it to a remote service when the reuse pressure is real.
Senior Tech: Where do retries belong?
Dev: In the host or client layer, not inside the model prompt. The model should not be instructed to "retry three times" as a reliability mechanism. Transport retries, idempotency checks, and timeout handling belong in executable code around the MCP client.
Common Pitfalls
| Pitfall | What goes wrong | Prevention |
|---|---|---|
| Putting approval logic in prompts only | Model bypasses expected policy path | Enforce approval in host code before invocation |
| Starting with remote transport too early | Unnecessary auth and networking overhead | Begin with stdio unless sharing is required |
| No timeout or cancellation | Hung tool calls block the whole agent loop | Set invocation timeouts and cancellation tokens |
| Not logging initialization separately | Discovery bugs look like tool bugs | Trace lifecycle stages independently |
References and Next Steps
- Next: MCP Tools, Resources, and Prompts →
- Previous: MCP Overview →
- Specification: modelcontextprotocol.io/specification