MCP协议实战深入解析

全面深入解析协议标准、数据格式化、错误预防及自适应调控机制,涵盖未来可扩展性要求

开始探索 MCP 协议

什么是MCP协议?

MCP(Model Context Protocol,模型上下文协议)是由Anthropic公司推出的一个开放标准,旨在实现AI应用与外部数据源和工具之间的无缝整合。您可以将MCP想象为"AI应用的USB-C端口",实现了标准化的连接方式。

MCP的核心目标: 提供一个标准化的方式,使AI应用能够与外部系统无缝地交互,读取数据,执行操作,从而增强AI系统的能力和实用性。

MCP协议的核心组件包括:

  • 主机(Hosts):启动连接的LLM应用(如Claude Desktop或IDE)
  • 客户端(Clients):在主机应用内部与服务器维持1:1连接
  • 服务器(Servers):向客户端提供上下文、工具和提示

MCP协议主要特点

开放标准,促进AI生态系统互操作性

基于JSON-RPC 2.0消息格式

强大的安全和信任机制

模块化和可扩展设计

多种SDK支持,包括Python、TypeScript、Java等

资源(Resources)

允许服务器向客户端暴露可读取的数据和内容,每个资源通过唯一URI标识,可包含文本或二进制数据。

了解更多

资源可以包括文件内容、数据库记录、API响应、实时系统数据、屏幕截图和图像等。

客户端可以通过两种主要方法发现可用资源:

  • 直接资源:通过resources/list端点
  • 资源模板:用于动态资源

MCP支持实时资源更新,服务器可以通知客户端资源列表和内容的变化。

工具(Tools)

允许服务器暴露可被客户端调用的可执行功能,使LLM能够与外部系统交互、执行计算和在现实世界中执行动作。

了解更多

工具可以包括系统操作、API集成和数据处理等功能,通过tools/list端点发现,通过tools/call端点调用。

每个工具都定义了以下结构:

  • 名称:唯一标识符
  • 描述:工具功能的描述
  • 参数:JSON Schema定义的参数
  • 注解:关于工具行为的元数据

MCP支持动态工具发现,客户端可以随时列出可用工具,服务器可以通知客户端工具变化。

提示(Prompts)

为用户提供模板化消息和工作流程,使其与语言模型进行交互。提示可以包含结构化的消息和指令。

了解更多

提示允许服务器为与语言模型交互提供结构化的模板和工作流程。

提示的主要功能:

  • 标准化用户与LLM的交互
  • 创建可复用的模板
  • 简化复杂工作流程
  • 确保一致的用户体验

提示可以包含变量和参数,允许根据特定需求进行自定义。

MCP核心架构

MCP协议建立在灵活可扩展的架构之上,使用JSON-RPC 2.0消息格式在客户端和服务器之间建立通信。该协议分为三个主要层:协议层、传输层和功能层。

MCP架构图

主机 (Host) LLM 应用 (Claude, IDE等) 客户端 (Client) (MCP连接器) 传输层 JSON-RPC 2.0 服务器 (Server) 传输层 协议处理 (请求/响应处理) 功能层 资源 工具 提示

基础协议

MCP协议的基础部分定义了客户端和服务器之间的通信方式。核心特性包括:

  • JSON-RPC消息格式 - 所有MCP通信都基于JSON-RPC 2.0,一种轻量级的远程过程调用协议
  • 状态化连接 - MCP维护客户端和服务器之间的状态连接
  • 能力协商 - 客户端和服务器在初始化时交换各自支持的功能

重要说明

MCP借鉴了语言服务器协议(LSP)的设计理念,LSP标准化了编程语言支持在各种开发工具中的实现方式。类似地,MCP标准化了如何将额外的上下文和工具集成到AI应用生态系统中。

连接生命周期

1. 初始化

客户端发送带有协议版本和能力的初始化请求,服务器响应其协议版本和能力,客户端发送初始化通知作为确认。

2. 消息交换

初始化后,支持请求-响应模式(客户端或服务器发送请求,另一方响应)和通知模式(任一方发送单向消息)。

3. 终止

任一方可通过clean关闭、传输断开或错误条件终止连接。

消息类型

请求

期望从另一方获得响应的消息

结果

对请求的成功响应

错误

表示请求失败的响应

通知

不期望响应的单向消息

传输层

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

标准输入/输出(stdio)传输

使用标准输入和输出流进行通信,特别适用于本地集成和命令行工具。

适用场景:

  • 构建命令行工具
  • 实现本地集成
  • 需要简单的进程通信
  • 处理shell脚本

服务器发送事件(SSE)传输

启用带有HTTP POST请求的服务器到客户端流,用于客户端到服务器的通信。

适用场景:

  • 只需要服务器到客户端的流
  • 处理受限制的网络
  • 实现简单的更新

安全警告:DNS重绑定攻击

SSE传输如果未正确保护,可能容易受到DNS重绑定攻击。请始终验证传入SSE连接的源头,避免绑定到所有网络接口。

交互式JSON-RPC消息格式演示

{
  "jsonrpc": "2.0",
  "id": "request-1",
  "method": "tools/list",
  "params": {}
}

MCP数据格式

MCP使用JSON-RPC 2.0作为其线路格式。传输层负责将MCP协议消息转换为JSON-RPC格式以进行传输,并将接收到的JSON-RPC消息转换回MCP协议消息。

JSON-RPC 2.0基础

JSON-RPC是一种轻量级的远程过程调用(RPC)协议,使用JSON作为数据格式。每个请求都是一个包含特定字段的JSON对象。

主要字段:

  • jsonrpc:必须是"2.0",表示JSON-RPC版本
  • id:请求标识符,响应必须包含相同的id
  • method:被调用的方法名称
  • params:传递给方法的参数(可选)
  • result:成功响应的结果(与error互斥)
  • error:错误对象(与result互斥)

MCP数据类型

资源内容

资源可以包含两种类型的内容:

文本资源

UTF-8编码的文本数据

二进制资源

base64编码的二进制数据

工具参数

工具参数使用JSON Schema定义,允许复杂的类型验证和结构。

提示模板

提示使用模板字符串,可包含变量占位符,使用JSON格式的参数。

注意: 在MCP协议中,所有JSON交换都应遵循RFC 8259标准。确保所有字符串都是有效的UTF-8,数字符合IEEE 754-2008标准,并正确处理特殊值(如NaN或Infinity)。

交互式数据格式示例

资源读取请求/响应

客户端请求
{
  "jsonrpc": "2.0",
  "id": "req-1",
  "method": "resources/read",
  "params": {
    "uri": "file:///home/user/document.txt"
  }
}
服务器响应
{
  "jsonrpc": "2.0",
  "id": "req-1",
  "result": {
    "contents": [
      {
        "type": "text",
        "text": "This is the content of document.txt.",
        "mimeType": "text/plain"
      }
    ]
  }
}

工具调用请求/响应

客户端请求
{
  "jsonrpc": "2.0",
  "id": "req-2",
  "method": "tools/call",
  "params": {
    "name": "weather",
    "parameters": {
      "location": "San Francisco",
      "units": "celsius"
    }
  }
}
服务器响应
{
  "jsonrpc": "2.0",
  "id": "req-2",
  "result": {
    "isError": false,
    "content": [
      {
        "type": "text",
        "text": "{"temperature":18,"condition":"Foggy"}",
        "mimeType": "application/json"
      }
    ]
  }
}

提示获取请求/响应

客户端请求
{
  "jsonrpc": "2.0",
  "id": "req-3",
  "method": "prompts/apply",
  "params": {
    "name": "code-review",
    "parameters": {
      "language": "python",
      "severity": "high"
    }
  }
}
服务器响应
{
  "jsonrpc": "2.0",
  "id": "req-3",
  "result": {
    "messages": [
      {
        "role": "system",
        "content": "Perform a detailed code review..."
      },
      {
        "role": "user",
        "content": "Review the Python code with high severity checks."
      }
    ]
  }
}

数据验证与安全

数据验证最佳实践

  • 使用JSON Schema - 对所有参数和响应使用JSON Schema进行验证

  • 验证UTF-8编码 - 确保所有文本资源使用有效的UTF-8编码

  • 检查数据大小 - 实现资源大小限制,避免过大的内容

  • 验证URI格式 - 验证所有资源URI的格式和结构

  • 检查MIME类型 - 使用正确的MIME类型标记内容

  • 处理无效输入 - 实现适当的错误处理,提供有用的错误消息

安全注意事项

  • 防止命令注入 - 特别是在工具执行系统命令时

  • 防止路径遍历 - 验证文件路径,防止目录遍历攻击

  • 实现访问控制 - 确保只有授权用户可以访问资源

  • 保护敏感数据 - 避免在错误消息中暴露敏感信息

  • 防止DNS重绑定 - 使用SSE传输时验证Origin标头

  • 实现速率限制 - 防止拒绝服务攻击和滥用

MCP错误处理机制

MCP定义了一系列标准错误代码,用于有效管理可能出现的问题,确保客户端和服务器可以优雅地处理异常情况。

错误处理对于MCP实现非常重要,因为它确保了通信的稳定性和可靠性。一个好的错误处理机制可以帮助客户端和服务器优雅地处理异常情况,提供有用的错误信息,并保护系统免受潜在的安全威胁。

MCP标准错误代码

JSON-RPC 2.0预定义错误码

错误码 描述
-32700 解析错误 - 收到无效的JSON
-32600 无效请求 - 发送的JSON不是有效的请求对象
-32601 方法未找到 - 方法不存在或不可用
-32602 无效参数 - 无效的方法参数
-32603 内部错误 - 内部JSON-RPC错误
-32000至-32099 服务器错误 - 保留供实现定义的服务器错误使用

MCP特定错误码

错误码 描述
-32800 请求取消 - 请求已取消
-32801 内容过大 - 内容太大

错误响应结构

MCP错误响应遵循JSON-RPC 2.0错误对象结构,包含以下字段:

字段 类型 描述
code number 错误代码(上述定义的标准代码之一)
message string 错误消息,提供有关错误的简短描述
data any(可选) 包含有关错误的额外信息的结构化数据

示例错误响应

{
  "jsonrpc": "2.0",
  "id": "req-1",
  "error": {
    "code": -32602,
    "message": "Invalid params: required parameter 'uri' is missing",
    "data": {
      "missingParam": "uri"
    }
  }
}

错误处理最佳实践

服务器端错误处理

  • 彻底验证输入

    验证所有传入的请求参数,确保它们符合预期的格式和约束。

  • 使用适当的错误代码

    选择最合适的错误代码,使客户端能够准确理解问题的性质。

  • 提供有用的错误消息

    错误消息应该清晰、具体,帮助客户端了解如何解决问题。

  • 避免泄露敏感信息

    确保错误消息不泄露系统内部细节或敏感信息。

  • 记录详细的错误信息

    在服务器端记录详细的错误信息,以便调试和监控。

客户端错误处理

  • 优雅地处理错误

    客户端应该捕获和处理所有错误,而不是崩溃或表现出不可预测的行为。

  • 实现重试机制

    对于临时错误,实现适当的重试策略,包括指数退避。

  • 向用户提供有用的反馈

    将技术错误转换为用户友好的消息,告诉用户发生了什么以及如何解决。

  • 处理连接错误

    妥善处理网络连接问题,包括超时和断连。

  • 记录和报告错误

    记录错误信息并考虑将其报告给开发团队,以便改进系统。

工具错误处理特殊情况

工具错误应在结果对象内报告,而不是作为MCP协议级别的错误。这允许LLM查看错误并可能采取纠正措施。

工具错误结果示例

{
  "jsonrpc": "2.0",
  "id": "req-2",
  "result": {
    "isError": true,
    "content": [
      {
        "type": "text",
        "text": "Unable to retrieve weather data for 'Unknown Location'. The location was not found."
      }
    ]
  }
}

这种方法允许LLM看到错误发生并可能采取纠正措施或请求人工干预。

交互式错误响应生成器

生成的错误响应:

{
  "jsonrpc": "2.0",
  "id": "request-id",
  "error": {
    "code": -32700,
    "message": "Parse error"
  }
}

MCP自适应调控机制

虽然MCP协议中没有直接提及"自适应调控机制",但该协议设计了许多机制来支持动态适应不同的需求和环境,使系统能够根据情况自动调整其行为。

动态资源管理

资源列表变更通知

服务器可以通过notifications/resources/list_changed通知客户端可用资源列表发生了变化。

这使客户端可以立即获取最新的资源列表,而不必定期轮询。

资源订阅

客户端可以订阅特定资源的更新,服务器会在资源变化时发送通知。

这使客户端能够实时跟踪重要资源的变化,无需重复请求。

动态资源模板

MCP支持资源模板,允许客户端动态构建有效的资源URI。

这使服务器能够支持大量或动态生成的资源,而无需预先列出所有可能的资源。

动态工具发现

MCP支持动态工具发现,允许工具在运行时添加或删除。这种灵活性使服务器能够适应不同的需求和环境:

  • 客户端可以随时列出可用工具,获取最新的工具集合

  • 服务器可以使用notifications/tools/list_changed通知客户端工具变化

  • 工具可以在运行时添加或删除,适应变化的需求

  • 工具定义可以更新(尽管应谨慎进行)以适应新要求

工具列表变更通知示例

{
  "jsonrpc": "2.0",
  "method": "notifications/tools/list_changed",
  "params": {
    "reason": "Tools were updated to include new weather API"
  }
}

收到此通知后,客户端应该调用tools/list方法获取更新的工具列表,以保持最新状态。

会话管理与握手

MCP使用初始化过程和能力协商,使客户端和服务器能够适应彼此的功能和限制:

1. 客户端发送初始化请求

客户端发送initialize请求,包含其协议版本和支持的功能

"capabilities": {
  "samples": true,
  "interactiveMarkdown": true
}

2. 服务器响应能力

服务器响应其协议版本和支持的功能

"capabilities": {
  "resources": true,
  "tools": true,
  "prompts": true
}

3. 会话建立

客户端发送initialized通知,会话建立,双方根据协商的能力进行交互

会话激活

这种能力协商机制允许:

  • 客户端和服务器适应彼此的功能和限制
  • 在会话开始时动态确定可用功能
  • 确保兼容性,即使客户端和服务器使用不同版本的协议
  • 渐进式增强,使用双方都支持的功能

自适应调控实例

进度报告与取消

MCP支持长时间运行操作的进度报告和取消机制,使客户端和用户能够管理复杂操作:

客户端发起长时间运行的操作

请求包含进度令牌(progress token)

服务器发送进度更新

通过notifications/progress通知提供操作进度

客户端可以取消操作

通过$/cancelRequest方法取消操作

服务器确认取消

返回错误代码-32800(请求取消)

大型内容处理

MCP包含处理大型内容的机制,如:

  • 分块读取资源,处理大型文件
  • 内容大小限制错误(-32801)
  • 分页资源列表,处理大量资源

采样(Sampling)机制

MCP的采样功能允许服务器发起与LLM的交互,这为自适应系统提供了强大的基础:

window.__genspark_remove_badge_link = "https://www.genspark.ai/api/html_badge/" + "remove_badge?token=To%2FBnjzloZ3UfQdcSaYfDtBEJgq4mXyfaIWA3z9X37txKfYGPILLjEGqvpavyFSJV2YpojXZt8W4yUWkaTDpXcgkyaB1aoHlLqjtloA16Bhq8EAKuPHctsgFOPIHyBdlYCREVe%2BDCEM5Ng%2BCMEKwvsV5edPyWMleqh1R42aDY1TzUXbPNIlu1oxmK12YPgPbgYp4rd8lDKkTMlyfoMX4OKoKoH1v4bf4EDClBCW14LSsWqezhXOg7ahFOaKz5ZZrIrcBSSXNubQVifGHpdefOWdFM1TdyaERbgv8iTk6Q1FQ%2B%2BUT11cmCTeYv2w0AE%2FBlqrteyo4URLd6hfEKNC0supp0TEENHQPumOdHV11jzdcH4NRfBoCxIiMnop9ISbaJP4uX9cbNz8xV2e6162aVyHJweNaudRbqF0eBrstbnezZLmP6InxYzr4W198JTmDoMYlkwqcagBL8OqwZuYUX460Ow6tXJUq9ah5zzPt2I2fnZH4mWQEJdBds%2FWibWwKiNisi396szUxI0o1yDQMTA%3D%3D"; window.__genspark_locale = "zh-CN"; window.__genspark_token = "To/BnjzloZ3UfQdcSaYfDtBEJgq4mXyfaIWA3z9X37txKfYGPILLjEGqvpavyFSJV2YpojXZt8W4yUWkaTDpXcgkyaB1aoHlLqjtloA16Bhq8EAKuPHctsgFOPIHyBdlYCREVe+DCEM5Ng+CMEKwvsV5edPyWMleqh1R42aDY1TzUXbPNIlu1oxmK12YPgPbgYp4rd8lDKkTMlyfoMX4OKoKoH1v4bf4EDClBCW14LSsWqezhXOg7ahFOaKz5ZZrIrcBSSXNubQVifGHpdefOWdFM1TdyaERbgv8iTk6Q1FQ++UT11cmCTeYv2w0AE/Blqrteyo4URLd6hfEKNC0supp0TEENHQPumOdHV11jzdcH4NRfBoCxIiMnop9ISbaJP4uX9cbNz8xV2e6162aVyHJweNaudRbqF0eBrstbnezZLmP6InxYzr4W198JTmDoMYlkwqcagBL8OqwZuYUX460Ow6tXJUq9ah5zzPt2I2fnZH4mWQEJdBds/WibWwKiNisi396szUxI0o1yDQMTA==";