Update architecture.mdx

This commit is contained in:
Justin Spahr-Summers 2024-11-21 15:07:56 +00:00
commit 61f6e3483d
No known key found for this signature in database

View file

@ -3,50 +3,61 @@ title: "Core architecture"
description: "Understand how MCP connects clients, servers, and LLMs" description: "Understand how MCP connects clients, servers, and LLMs"
--- ---
The Model Context Protocol (MCP) is built on a flexible, extensible architecture that enables seamless communication between LLM applications and external services. This document covers the core architectural components and concepts. The Model Context Protocol (MCP) is built on a flexible, extensible architecture that enables seamless communication between LLM applications and integrations. This document covers the core architectural components and concepts.
## Overview ## Overview
MCP follows a client-server architecture where: MCP follows a client-server architecture where:
- **Clients** are LLM applications (like claude.ai or IDEs) that initiate connections - **Hosts** are LLM applications (like Claude Desktop or IDEs) that initiate connections
- **Clients** maintain 1:1 connections with servers, inside the host application
- **Servers** provide context, tools, and prompts to clients - **Servers** provide context, tools, and prompts to clients
- **Hosts** are processes that run MCP clients
```mermaid ```mermaid
flowchart LR flowchart LR
subgraph "Host (e.g., claude.ai)" subgraph " Host (e.g., Claude Desktop) "
client[MCP Client] client1[MCP Client]
client2[MCP Client]
end end
subgraph "Server Process" subgraph "Server Process"
server[MCP Server] server1[MCP Server]
end
subgraph "Server Process"
server2[MCP Server]
end end
client <-->|Transport Layer| server client1 <-->|Transport Layer| server1
client2 <-->|Transport Layer| server2
``` ```
## Core components ## Core components
### Protocol layer ### Protocol layer
The protocol layer handles message framing, request/response linking, and high-level communication patterns. Key classes include: The protocol layer handles message framing, request/response linking, and high-level communication patterns.
```typescript ```typescript
class Protocol<SendRequestT, SendNotificationT, SendResultT> { class Protocol<Request, Notification, Result> {
// Handle incoming requests // Handle incoming requests
setRequestHandler<T>(schema: T, handler: (request: T) => Result): void setRequestHandler<T>(schema: T, handler: (request: T, extra: RequestHandlerExtra) => Promise<Result>): void
// Handle incoming notifications // Handle incoming notifications
setNotificationHandler<T>(schema: T, handler: (notification: T) => void): void setNotificationHandler<T>(schema: T, handler: (notification: T) => Promise<void>): void
// Send requests and await responses // Send requests and await responses
request<T>(request: Request, schema: T): Promise<T> request<T>(request: Request, schema: T, options?: RequestOptions): Promise<T>
// Send one-way notifications // Send one-way notifications
notification(notification: Notification): Promise<void> notification(notification: Notification): Promise<void>
} }
``` ```
Key classes include:
* `Protocol`
* `Client`
* `Server`
### Transport layer ### Transport layer
The transport layer handles the actual communication between clients and servers. MCP supports multiple transport mechanisms: The transport layer handles the actual communication between clients and servers. MCP supports multiple transport mechanisms:
@ -54,66 +65,48 @@ The transport layer handles the actual communication between clients and servers
1. **Stdio transport** 1. **Stdio transport**
- Uses standard input/output for communication - Uses standard input/output for communication
- Ideal for local processes - Ideal for local processes
```typescript
class StdioTransport implements Transport {
constructor(stdin: Readable, stdout: Writable)
send(message: JSONRPCMessage): Promise<void>
}
```
2. **WebSocket transport** 2. **SSE transport**
- Enables real-time bidirectional communication
- Supports remote connections
```typescript
class WebSocketTransport implements Transport {
constructor(url: URL)
send(message: JSONRPCMessage): Promise<void>
}
```
3. **SSE transport**
- Uses Server-Sent Events for server-to-client messages - Uses Server-Sent Events for server-to-client messages
- HTTP POST for client-to-server messages - HTTP POST for client-to-server messages
```typescript
class SSETransport implements Transport { All transports use [JSON-RPC](https://www.jsonrpc.org/) 2.0 to exchange messages. See the [specification](https://spec.modelcontextprotocol.io) for more information.
constructor(url: URL)
send(message: JSONRPCMessage): Promise<void>
}
```
### Message types ### Message types
MCP uses JSON-RPC 2.0 as its message format with three main types: MCP has these main types of messages:
1. **Requests** 1. **Requests** expect a response from the other side:
```typescript ```typescript
interface Request { interface Request {
method: string method: string;
params?: { params?: { ... };
_meta?: { }
progressToken?: string | number ```
}
}
}
```
2. **Notifications** 2. **Notifications** are one-way messages that don't expect a response:
```typescript ```typescript
interface Notification { interface Notification {
method: string method: string;
params?: { params?: { ... };
_meta?: Record<string, unknown> }
} ```
}
```
3. **Results** 3. **Results** are successful responses to requests:
```typescript ```typescript
interface Result { interface Result {
_meta?: Record<string, unknown> [key: string]: unknown;
[key: string]: unknown }
} ```
```
4. **Errors** indicate that a request failed:
```typescript
interface Error {
code: number;
message: string;
data?: unknown;
}
```
## Connection lifecycle ## Connection lifecycle
@ -131,19 +124,17 @@ sequenceDiagram
Note over Client,Server: Connection ready for use Note over Client,Server: Connection ready for use
``` ```
1. Client sends `initialize` request with capabilities 1. Client sends `initialize` request with protocol version and capabilities
2. Server responds with supported features 2. Server responds with its protocol version and capabilities
3. Client sends `initialized` notification 3. Client sends `initialized` notification as acknowledgment
4. Normal message exchange begins 4. Normal message exchange begins
### 2. Message exchange ### 2. Message exchange
After initialization, the following patterns are supported: After initialization, the following patterns are supported:
- **Request-Response**: Client sends request, server responds - **Request-Response**: Client or server sends requests, the other responds
- **Notifications**: Either party sends one-way messages - **Notifications**: Either party sends one-way messages
- **Progress Updates**: Long-running operations can report progress
- **Resource Updates**: Servers notify about changed resources
### 3. Termination ### 3. Termination
@ -154,19 +145,21 @@ Either party can terminate the connection:
## Error handling ## Error handling
MCP defines standard error codes and handling: MCP defines these standard error codes:
```typescript ```typescript
enum ErrorCode { enum ErrorCode {
ConnectionClosed = -1, // Standard JSON-RPC error codes
ParseError = -32700, ParseError = -32700,
InvalidRequest = -32600, InvalidRequest = -32600,
MethodNotFound = -32601, MethodNotFound = -32601,
InvalidParams = -32602, InvalidParams = -32602,
InternalError = -32603 InternalError = -32603
} }
``` ```
SDKs and applications can define their own error codes above -32000.
Errors are propagated through: Errors are propagated through:
- Error responses to requests - Error responses to requests
- Error events on transports - Error events on transports
@ -177,24 +170,28 @@ Errors are propagated through:
Here's a basic example of implementing an MCP server: Here's a basic example of implementing an MCP server:
```typescript ```typescript
import { Server } from "@modelcontextprotocol/sdk/server"; import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server({ const server = new Server({
name: "example-server", name: "example-server",
version: "1.0.0" version: "1.0.0"
}, {
capabilities: {
resources: {}
}
}); });
// Handle requests // Handle requests
server.setRequestHandler(ListResourcesRequestSchema, async () => { server.setRequestHandler(ListResourcesRequestSchema, async () => {
return { return {
resources: [ resources: [
{ {
uri: "example://resource", uri: "example://resource",
name: "Example Resource" name: "Example Resource"
} }
] ]
}; };
}); });
// Connect transport // Connect transport
@ -212,9 +209,8 @@ await server.connect(transport);
- Simple process management - Simple process management
2. **Remote communication** 2. **Remote communication**
- WebSocket for full-duplex communication - Use SSE for scenarios requiring HTTP compatibility
- SSE for scenarios requiring HTTP compatibility - Consider security implications including authentication and authorization
- Consider security implications
### Message handling ### Message handling