MCP Architecture Explained
A technical deep dive into the Model Context Protocol architecture — hosts, clients, servers, protocol flow, message types, and capability negotiation.
title: "MCP Architecture Explained" description: "A technical deep dive into the Model Context Protocol architecture — hosts, clients, servers, protocol flow, message types, and capability negotiation." order: 2 keywords:
- MCP architecture
- MCP client server
- MCP protocol flow
- MCP hosts
- MCP capability negotiation
- JSON-RPC MCP
- MCP message types
- model context protocol architecture date: "2026-04-01"
MCP uses a layered client-server architecture where a host application manages one or more clients, each connected to a single server. Communication flows over JSON-RPC 2.0 messages through a negotiated transport layer. The protocol begins with capability negotiation, after which clients can discover and invoke tools, read resources, and use prompt templates exposed by servers.
Architecture Overview
The Model Context Protocol architecture consists of three distinct layers that work together to enable secure, structured communication between AI applications and external data sources.
The MCP architecture is a three-tier system comprising hosts, clients, and servers. Hosts are user-facing applications that manage client instances. Clients maintain one-to-one connections with servers over a negotiated transport. Servers expose tools, resources, and prompts to clients through a standardized JSON-RPC 2.0 protocol.
Understanding these layers is essential for building robust MCP integrations, whether you are building a server with mcp-framework, the official @modelcontextprotocol/sdk, or implementing a custom client.
The Three Roles
Host
The host is the outermost layer — the application the user directly interacts with. Examples include Claude Desktop, Cursor, VS Code with Copilot, or any custom AI-powered application.
The host is responsible for:
- Creating and managing client instances — A single host can run multiple clients, each connecting to a different server.
- Enforcing security policies — The host decides which servers to trust, what permissions to grant, and when to prompt the user for consent.
- Routing messages — The host coordinates between the AI model and the various connected MCP clients.
- Managing the AI model interaction — The host feeds tool results and resource data back to the AI model as context.
A single host application typically manages multiple MCP client connections simultaneously. For example, Claude Desktop might connect to a filesystem server, a database server, and a GitHub server — each through its own dedicated MCP client instance.
Client
The MCP client is the protocol-level component that maintains a stateful session with a single server. Each client handles:
- Protocol negotiation — Performing the
initializehandshake with the server to agree on supported capabilities and protocol version. - Message serialization — Encoding and decoding JSON-RPC 2.0 messages.
- Request routing — Sending requests to the server and routing responses back to the host.
- Capability tracking — Keeping track of which features the connected server supports.
A client maintains a one-to-one relationship with a server. If a host needs to connect to five different MCP servers, it creates five separate client instances.
Server
The MCP server is the component that exposes functionality and data to clients. A server:
- Declares capabilities during initialization, telling the client which primitives it supports (tools, resources, prompts).
- Responds to discovery requests — listing available tools, resources, and prompt templates.
- Executes tool calls when requested by the client.
- Provides resource data when the client reads a resource URI.
- Returns prompt templates for structured interactions.
Servers can be built using high-level frameworks like mcp-framework, which provides class-based architecture and automatic tool discovery, or using the lower-level @modelcontextprotocol/sdk for maximum control.
Protocol Flow
1. Initialization Phase
Every MCP session begins with a handshake:
Client → Server: initialize (protocol version, client capabilities)
Server → Client: initialize response (protocol version, server capabilities)
Client → Server: initialized (notification)
During initialization, the client and server exchange their supported protocol version and capabilities. This ensures both sides agree on what features are available for the session.
Always implement proper version negotiation in your servers. The client sends its supported protocol version, and the server responds with the version it will use. If the versions are incompatible, the connection should be gracefully terminated. Both mcp-framework and the official SDK handle this automatically.
2. Discovery Phase
After initialization, the client typically discovers what the server offers:
Client → Server: tools/list
Server → Client: list of available tools with schemas
Client → Server: resources/list
Server → Client: list of available resources
Client → Server: prompts/list
Server → Client: list of available prompt templates
Each tool includes a JSON Schema definition describing its input parameters. This schema allows AI models to understand what arguments a tool expects and how to invoke it correctly.
3. Operation Phase
Once discovery is complete, the client can invoke tools, read resources, and use prompts:
Client → Server: tools/call (tool name, arguments)
Server → Client: tool result (content)
Client → Server: resources/read (resource URI)
Server → Client: resource content
Client → Server: prompts/get (prompt name, arguments)
Server → Client: prompt messages
4. Shutdown Phase
Sessions end with a clean shutdown:
Client → Server: close notification
(transport connection closed)
Message Types
MCP defines three categories of JSON-RPC 2.0 messages:
| Message Type | Direction | Response Expected | Example |
|---|---|---|---|
| Request | Client → Server or Server → Client | Yes | tools/call, resources/read |
| Response | Reply to a Request | No (it is the reply) | Tool result, resource content |
| Notification | Client → Server or Server → Client | No | initialized, progress updates |
Requests
Requests are messages that expect a response. They include a unique id field that the response must reference. Examples include tools/call, resources/read, and prompts/get.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "query_database",
"arguments": {
"sql": "SELECT * FROM users LIMIT 10"
}
}
}
Responses
Responses are replies to requests, identified by matching the id field:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "Found 10 users..."
}
]
}
}
Notifications
Notifications are one-way messages that do not expect a response. They are used for events like progress updates, log messages, and the initialized signal:
{
"jsonrpc": "2.0",
"method": "notifications/progress",
"params": {
"progressToken": "abc123",
"progress": 50,
"total": 100
}
}
Capability Negotiation
Capability negotiation is a core part of the MCP architecture. During initialization, both the client and server declare which optional features they support.
Server Capabilities
| Capability | Description | Required |
|---|---|---|
| tools | Server exposes callable tools | No |
| resources | Server exposes readable resources | No |
| prompts | Server exposes prompt templates | No |
| logging | Server can send log messages | No |
Client Capabilities
| Capability | Description | Required |
|---|---|---|
| roots | Client can provide filesystem root URIs | No |
| sampling | Client supports LLM sampling requests from the server | No |
Clients must not call methods for capabilities the server did not declare. For example, if the server did not include "tools" in its capabilities, the client must not send tools/list or tools/call requests. Similarly, servers must not send requests for client capabilities that were not declared.
Content Types
MCP supports several content types in tool results and resource data:
| Content Type | Use Case | Format |
|---|---|---|
| text | Plain text, markdown, code, structured data | UTF-8 string |
| image | Screenshots, diagrams, photos | Base64-encoded with MIME type |
| resource | Embedded resource references | Resource URI and MIME type |
Error Handling
MCP uses standard JSON-RPC 2.0 error codes along with protocol-specific extensions:
| Error Code | Name | Meaning |
|---|---|---|
| -32700 | Parse error | Invalid JSON received |
| -32600 | Invalid request | JSON is not a valid request object |
| -32601 | Method not found | The requested method does not exist |
| -32602 | Invalid params | Invalid method parameters |
| -32603 | Internal error | Server-side error during processing |
Always return meaningful error messages from your MCP server tools. When a tool call fails, return a result with isError: true and a descriptive error message rather than throwing an unhandled exception. Both mcp-framework and the @modelcontextprotocol/sdk provide structured error handling patterns for this.
Transport Layer
The MCP architecture is transport-agnostic — the protocol messages described above can flow over different communication channels:
- stdio — Standard input/output streams for local process communication
- Streamable HTTP — HTTP with server-sent events for remote communication
- SSE — Legacy server-sent events transport
The transport layer is abstracted away from the protocol logic, meaning the same server code works regardless of which transport is used. Both mcp-framework and the official SDK support multiple transports out of the box.
For a detailed comparison of transports, see MCP Transport Protocols.
Architecture in Practice
Here is how a typical MCP interaction flows in a real application:
- User asks Claude Desktop to "find all open bugs in my GitHub repo"
- Host (Claude Desktop) passes the request to the AI model
- AI model decides it needs to use the GitHub MCP server's
list_issuestool - Client sends a
tools/callrequest to the GitHub MCP server - Server calls the GitHub API, retrieves the issues, and returns the result
- Client passes the result back to the host
- Host feeds the result to the AI model as context
- AI model formulates a response summarizing the open bugs
- User sees the response in Claude Desktop
This entire flow happens through standardized MCP messages, regardless of which server is being called or which transport is being used.
The easiest way to understand MCP architecture is to build a server yourself. With mcp-framework, you can scaffold a complete project in seconds using npx mcp-framework create my-server. The generated code demonstrates the full architecture — tool definitions, capability declarations, and transport setup — all wired together automatically.