Skip to main content

MCP Architecture

Summary

🧭 What this page covers

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.

RoleResponsibilityTypical runtimeExample in practice
HostOwns 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.
ClientManages 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.
ServerExposes 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 host decides policy

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.

The client owns protocol state

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.

Transport choice changes operational behaviour

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

🚦
Control belongs in the host
Approval and routing cannot be delegated blindly to the model

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.

🔐
Remote servers need real service design
Once MCP moves off local stdio, it becomes distributed systems work

Authentication, connection management, retries, network partitions, and rate limiting all become relevant the moment a server is shared across machines or teams.

🧭
Lifecycle clarity simplifies debugging
Most MCP failures happen at initialisation, discovery, or shutdown edges

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

TransportBest forAdvantagesTrade-offs
stdioLocal process integrationSimple, fast, no network stackLocal-only lifecycle, process management required
HTTP + streamingShared or remote serversEasier hosting, central auth, multi-client accessNetwork latency, distributed failure modes
SSE / long-lived streamsIncremental updates and notificationsReal-time server-to-client flowConnection handling complexity

Connection lifecycle

Operational guidance

  1. Prefer stdio when the server is local to the host process boundary.
  2. Prefer remote hosting only when capabilities need to be shared broadly.
  3. Add timeouts and cancellation to every invocation.
  4. Log initialize, discovery, invocation, and shutdown separately.
  5. Keep tool contracts stable; breaking changes ripple across hosts.

Realistic Example

Scenario

An IDE extension connects to two local MCP servers over stdio:

  • repo-server for code search and file resources
  • build-server for 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:

  1. build-server tool: get_recent_failures
  2. repo-server resource: ci/pipeline.yaml
  3. repo-server tool: 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

PitfallWhat goes wrongPrevention
Putting approval logic in prompts onlyModel bypasses expected policy pathEnforce approval in host code before invocation
Starting with remote transport too earlyUnnecessary auth and networking overheadBegin with stdio unless sharing is required
No timeout or cancellationHung tool calls block the whole agent loopSet invocation timeouts and cancellation tokens
Not logging initialization separatelyDiscovery bugs look like tool bugsTrace lifecycle stages independently

References and Next Steps