跳到主要内容

核心架构

模型上下文协议(MCP)建立在灵活、可扩展的架构之上,使LLM应用程序和集成之间能够无缝通信。本文档涵盖核心架构组件和概念。

概述

MCP遵循客户端-服务器架构,其中:

  • 主机是发起连接的LLM应用程序(如Claude Desktop或IDE)
  • 客户端在主机应用程序内与服务器保持1:1连接
  • 服务器向客户端提供上下文、工具和提示

核心组件

协议层

协议层处理消息帧、请求/响应链接和高级通信模式。

class Protocol<Request, Notification, Result> {
    // 处理传入请求
    setRequestHandler<T>(schema: T, handler: (request: T, extra: RequestHandlerExtra) => Promise<Result>): void

    // 处理传入通知
    setNotificationHandler<T>(schema: T, handler: (notification: T) => Promise<void>): void

    // 发送请求并等待响应
    request<T>(request: Request, schema: T, options?: RequestOptions): Promise<T>

    // 发送单向通知
    notification(notification: Notification): Promise<void>
}

关键类包括:

  • Protocol
  • Client
  • Server

传输层

传输层处理客户端和服务器之间的实际通信。MCP支持多种传输机制:

  1. Stdio传输

    • 使用标准输入/输出进行通信
    • 适用于本地进程
  2. HTTP with SSE传输

    • 使用服务器发送事件进行服务器到客户端的消息传递
    • 使用HTTP POST进行客户端到服务器的消息传递

所有传输都使用JSON-RPC 2.0来交换消息。有关模型上下文协议消息格式的详细信息,请参见规范

消息类型

MCP有以下主要类型的消息:

  1. 请求期望从另一方获得响应:

    interface Request {
      method: string;
      params?: { ... };
    }
    
  2. 结果是对请求的成功响应:

    interface Result {
      [key: string]: unknown;
    }
    
  3. 错误表示请求失败:

    interface Error {
      code: number;
      message: string;
      data?: unknown;
    }
    
  4. 通知是不期望响应的单向消息:

    interface Notification {
      method: string;
      params?: { ... };
    }
    

连接生命周期

1. 初始化

  1. 客户端发送带有协议版本和能力的initialize请求
  2. 服务器响应其协议版本和能力
  3. 客户端发送initialized通知作为确认
  4. 开始正常的消息交换

2. 消息交换

初始化后,支持以下模式:

  • 请求-响应:客户端或服务器发送请求,另一方响应
  • 通知:任一方发送单向消息

3. 终止

任一方都可以终止连接:

  • 通过close()进行清理关闭
  • 传输断开连接
  • 错误条件

错误处理

MCP定义了这些标准错误代码:

enum ErrorCode {
  // 标准JSON-RPC错误代码
  ParseError = -32700,
  InvalidRequest = -32600,
  MethodNotFound = -32601,
  InvalidParams = -32602,
  InternalError = -32603
}

SDK和应用程序可以在-32000以上定义自己的错误代码。

错误通过以下方式传播:

  • 对请求的错误响应
  • 传输上的错误事件
  • 协议级错误处理器

实现示例

这是实现MCP服务器的基本示例:

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const server = new Server({
  name: "example-server",
  version: "1.0.0"
}, {
  capabilities: {
    resources: {}
  }
});

// 处理请求
server.setRequestHandler(ListResourcesRequestSchema, async () => {
  return {
    resources: [
      {
        uri: "example://resource",
        name: "示例资源"
      }
    ]
  };
});

// 连接传输
const transport = new StdioServerTransport();
await server.connect(transport);

最佳实践

在实现MCP时:

  1. 遵循协议规范
  2. 实现适当的错误处理
  3. 使用类型安全
  4. 处理连接生命周期
  5. 实现重连机制
  6. 添加日志记录
  7. 考虑性能优化
  8. 实现安全措施
  9. 测试边界情况
  10. 保持代码可维护性

安全考虑

在实现MCP时:

  • 加密通信
  • 验证消息完整性
  • 实现访问控制
  • 防止消息注入
  • 处理敏感数据
  • 监控异常活动
  • 实现速率限制
  • 审计系统日志