Claude Academy
Sign in

MCP Architecture (official docs)

Source: https://modelcontextprotocol.io/docs/learn/architecture

Scope

MCP includes:

  • MCP Specification — implementation requirements.
  • MCP SDKs — per-language implementations.
  • MCP Development Tools — including the MCP Inspector.
  • MCP Reference Server Implementations.

"MCP focuses solely on the protocol for context exchange — it does not dictate how AI applications use LLMs or manage the provided context."

Participants

  • MCP Host — AI application that coordinates one or more MCP clients (e.g., Claude Code, Claude Desktop, VS Code).
  • MCP Client — connection-holder; one per server. Lives inside the host.
  • MCP Server — program that provides context to clients.

Key nuance: a single host can have multiple connections to the same server (separate client objects). VS Code is the example.

"Local" vs "remote" is determined by transport, not server location:

  • stdio → local subprocess.
  • Streamable HTTP → remote (e.g., the official Sentry MCP server).

Layers

MCP has two layers:

  1. Data layer (inner) — JSON-RPC 2.0 protocol for client-server communication. Lifecycle, primitives, notifications.
  2. Transport layer (outer) — communication mechanism (stdio, Streamable HTTP) with auth.

Data layer details

  • Lifecycle management — connection init, capability negotiation, termination.
  • Server features: tools, resources, prompts.
  • Client features: sampling, elicitation, logging.
  • Utility: notifications, progress.

Transport layer details

  • stdio — stdin/stdout between local processes. No network overhead.
  • Streamable HTTP — HTTP POST + optional SSE for streaming. Supports OAuth, bearer tokens, API keys.

Same JSON-RPC message format across all transports.

Primitives — server-exposed

  • Tools — executable functions (model-controlled). Methods: tools/list, tools/call.
  • Resources — data sources (application-controlled). Methods: resources/list, resources/read.
  • Prompts — reusable templates (user-controlled). Methods: prompts/list, prompts/get.

Servers declare which primitives they support in capabilities during init.

Primitives — client-exposed (server can use these)

  • Sampling — server asks client to run an LLM call (sampling/createMessage). Server stays model-independent.
  • Elicitation — server asks user for more info / confirmation (elicitation/create).
  • Logging — server sends log messages to client for debugging.

Cross-cutting

  • Tasks (experimental) — durable execution wrappers for long-running ops, status tracking, deferred result retrieval.

Lifecycle (initialize → ready → operate → shutdown)

  1. Client sends initialize with protocolVersion, capabilities, clientInfo.
  2. Server responds with its capabilities, serverInfo.
  3. Client sends notifications/initialized.
  4. Operations: tools/list, tools/call, etc.
  5. Notifications flow either direction (e.g., notifications/tools/list_changed).

Example messages

Initialize:

{
  "jsonrpc": "2.0", "id": 1, "method": "initialize",
  "params": {
    "protocolVersion": "2025-06-18",
    "capabilities": {"elicitation": {}},
    "clientInfo": {"name": "example-client", "version": "1.0.0"}
  }
}

Initialize response:

{
  "jsonrpc": "2.0", "id": 1,
  "result": {
    "protocolVersion": "2025-06-18",
    "capabilities": {"tools": {"listChanged": true}, "resources": {}},
    "serverInfo": {"name": "example-server", "version": "1.0.0"}
  }
}

Tool call:

{
  "jsonrpc": "2.0", "id": 3, "method": "tools/call",
  "params": {"name": "weather_current", "arguments": {"location": "SF", "units": "imperial"}}
}

Notification (no id, no response expected):

{"jsonrpc": "2.0", "method": "notifications/tools/list_changed"}

Capability negotiation

  • Client capability "elicitation": {} — client can handle user-info requests.
  • Server capability "tools": {"listChanged": true} — supports tools AND emits change notifications.
  • Server capability "resources": {} — supports resources primitive.

Server only sends tools/list_changed if it declared listChanged: true at init.

Tool object fields

Each tool in tools/list response has:

  • name — unique identifier (e.g., calculator_arithmetic, not just calculate).
  • title — human-readable display name.
  • description — what it does + when to use it.
  • inputSchema — JSON Schema for params.

Stateless mode

MCP is stateful by default. Subset can be made stateless using Streamable HTTP. Important for horizontally-scaled deployments.

Why this matters for CCA-F

Memorize:

  • Host/client/server distinction (host has many clients).
  • Three server primitives + three client primitives.
  • Lifecycle order (init → ready notification → operate).
  • That listChanged capability is required for change notifications.
  • That sampling lets servers be model-agnostic.