自学教程 从零学编程

MCP 协议

Model Context Protocol(MCP,模型上下文协议)

协议版本:2025-11-25(稳定版)
关键字:MUST(必须)、MUST NOT(禁止)、REQUIRED(必填)、SHALL(应)、SHALL NOT(不应)、SHOULD(建议)、SHOULD NOT(不建议)、RECOMMENDED(推荐)、NOT RECOMMENDED(不推荐)、MAY(可选)、OPTIONAL(可选),遵循 BCP14(RFC2119)定义。

1. 概述

Model Context Protocol(MCP,模型上下文协议)是开放标准化协议,用于大模型应用与外部数据源、工具之间安全、可互操作的上下文交互。
MCP 目标:

  1. 向大模型应用安全共享外部上下文数据;
  2. 对外暴露可被模型调用的工具能力;
  3. 构建可组合、可插拔的AI工作流。

MCP 基于 JSON-RPC 2.0 构建,采用宿主-客户端-服务端三层架构,分离AI应用、连接器、外部能力服务,维持清晰安全边界。

1.1 角色定义

  • 宿主 Host:承载LLM的主应用(如Claude Desktop、Cursor IDE)。宿主管理多个MCP客户端、权限策略、会话生命周期,负责用户授权与模型采样调度。
  • 客户端 Client:宿主内的连接器实例,一对一绑定单个MCP服务端,负责会话协商、消息路由、订阅管理。一个宿主可同时启动多个Client,对接多个MCP Server。
  • 服务端 Server:提供外部能力的独立服务进程,向外暴露工具Tools、资源Resources、提示模板Prompts三类核心原语。服务端可以本地子进程(stdio)或远程HTTP服务运行。

类比:LSP(语言服务器协议)用于IDE和语言解析器;MCP用于AI应用和外部上下文/工具。

2. 协议分层

MCP采用模块化分层,基础协议、生命周期管理为强制实现;其余组件按需实现。

  1. 基础协议:JSON-RPC 2.0消息基础结构,请求/响应/通知消息模型;
  2. 生命周期管理:连接初始化、版本协商、能力集协商、会话控制;
  3. 传输层:消息承载通道(stdio / Streamable HTTP);
  4. 原语层(Server侧能力):Tools、Resources、Prompts;
  5. 客户端侧能力:采样Sampling、根目录Roots、用户交互询问Elicitation;
  6. 辅助组件:日志、参数补全、订阅通知;
  7. 认证授权:HTTP传输下的OAuth/OpenID Connect授权框架。

3. 基础消息规范(JSON-RPC 2.0)

MCP全部消息均为JSON对象,分为三类:请求、响应、通知。

3.1 请求 Request(Client → Server,可双向)

请求携带唯一ID,期望收到响应。

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

字段说明:

  • jsonrpc:固定字符串"2.0",必填;
  • id:字符串/数字,本次请求唯一标识;
  • method:MCP方法名,采用domain/action命名;
  • params:可选,方法参数对象。

3.2 响应 Response

与请求ID一一对应,成功返回result,失败返回error。

成功响应示例:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [{"name": "read_file", "description": "读取文件", "inputSchema": {...}}]
  }
}

错误响应示例:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32000,
    "message": "初始化失败",
    "data": {}
  }
}

3.3 通知 Notification

单向消息,无id,不需要对方回复,用于事件推送、日志、状态变更。

{
  "jsonrpc": "2.0",
  "method": "notifications/logging/message",
  "params": { "level": "info", "message": "服务启动完成" }
}

4. 会话生命周期与版本协商

4.1 版本规则

协议版本采用 YYYY-MM-DD 日期字符串。

  • 兼容升级不修改版本号;
  • 破坏性变更才会更新版本日期;
  • 会话初始化阶段协商版本,两端必须达成一致版本;协商失败则终止连接。

4.2 初始化流程(握手)

  1. Client 向 Server 发送 initialize 请求,携带:
    • 客户端支持的协议版本;
    • 客户端能力集(如支持sampling、roots);
    • 客户端信息(名称、版本)。
  2. Server 返回 initialize 响应,携带:
    • 服务端选定的协议版本;
    • 服务端能力集(是否支持tools/resources/prompts);
    • 服务端名称、版本。
  3. Client 发送 initialized 通知,告知服务端握手完成,会话正式就绪。

握手完成后,才允许调用工具、读取资源等业务方法。

4.3 会话终止

任意一端发送shutdown请求,完成会话关闭;或直接断开传输通道。

5. 三大核心原语(Server对外暴露能力)

5.1 Tools 工具(可执行函数)

工具是可被LLM调用的动作,例如文件读写、数据库查询、调用第三方API。

  • tools/list:列举服务端所有可用工具,返回工具元信息(名称、描述、JSON Schema入参);
  • tools/call:执行指定工具,传入参数,返回结果内容块;
  • 结果支持多类型内容:text文本、image图片、binary二进制数据。

安全说明:宿主负责做权限校验、用户确认,Server不能绕过宿主直接执行高危操作。

5.2 Resources 资源(只读上下文数据)

资源是可供模型读取的上下文数据源,使用URI唯一标识,如本地文件、数据库记录、网页内容。

  • resources/list:列出所有可用资源;
  • resources/read:按URI读取资源内容;
  • resources/subscribe(可选):订阅资源变更,资源更新时Server推送通知给Client。

5.3 Prompts 提示模板(可复用Prompt模板)

预定义的提示词模板,支持参数填充,快速生成系统提示、少样本示例、Agent任务模板。

  • prompts/list:列举所有模板;
  • prompts/get:获取模板,传入参数,展开得到完整消息列表。

6. 客户端侧能力(Client可对外提供,Server可主动调用)

这部分是Server主动向Client发起请求,实现Agent递归调用、模型采样。

  1. Sampling 采样:Server请求宿主LLM执行推理。用于Agent自递归、多轮思考。Server向Client提交消息,宿主调用大模型并返回模型输出。
  2. Roots 根目录:Server询问宿主允许访问的文件系统根URI,限定文件访问边界,用于安全沙箱。
  3. Elicitation 用户询问:Server请求宿主向终端用户收集输入(交互式确认、表单输入)。

7. 传输层 Transport

传输层负责承载JSON-RPC消息,同一套协议消息可复用在不同传输通道。

7.1 Stdio(本地子进程,推荐本地开发)

  • Client拉起Server作为子进程;
  • 使用标准输入stdin发消息,标准输出stdout收消息;stderr用于日志(不能承载MCP协议消息);
  • 适合本地MCP服务,隔离进程。

7.2 Streamable HTTP(远程网络传输,替代旧SSE)

服务端提供单一MCP端点,同时支持GET/POST:

  • POST:Client发送请求消息;
  • GET:建立SSE长连接,接收Server推送的通知、Server发起的请求;
    支持跨网络远程MCP服务,可配合OAuth授权。

旧版本HTTP+SSE已废弃。

8. 订阅与通知机制

Server可在资源、工具状态变更时,主动推送通知给Client,无需客户端轮询。
典型场景:文件变更通知、日志消息、进度更新。
订阅流程:Client发送subscribe,Server在事件触发时推送notification。

9. 错误码规范

  • -32700:解析错误(JSON非法)
  • -32600:无效请求
  • -32601:方法不存在
  • -32602:参数非法
  • -32603:内部错误
  • -32000 ~ -32099:MCP自定义服务端错误码

10. 安全模型

  1. 宿主是安全决策中心:所有高危操作(文件写入、网络调用)必须由宿主做权限控制、用户确认;Server不具备独立权限。
  2. 资源隔离:Roots机制限制文件访问范围。
  3. 输入校验:所有工具入参必须使用JSON Schema校验。
  4. 远程HTTP传输必须配套认证(OAuth),禁止裸HTTP公网暴露。
  5. 消息隔离:不同会话之间状态隔离。

11. 常用方法总览表

分组方法名方向作用
生命周期initializeClient→Server握手、版本&能力协商
initializedClient→Server通知握手完成(通知)
Toolstools/listClient→Server查询可用工具列表
tools/callClient→Server调用工具执行动作
Resourcesresources/listClient→Server列出资源
resources/readClient→Server读取指定URI资源
resources/subscribeClient→Server订阅资源变更
Promptsprompts/listClient→Server列出提示模板
prompts/getClient→Server获取并渲染模板
客户端能力sampling/createMessageServer→Client请求LLM采样推理
roots/listServer→Client查询宿主允许的根目录

12. 简单交互示例(调用工具)

  1. Client 查询可用工具
{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}
  1. Server 返回工具列表
{
  "jsonrpc":"2.0",
  "id":1,
  "result":{
    "tools":[
      {
        "name":"get_file",
        "description":"读取文本文件",
        "inputSchema":{"type":"object","properties":{"path":{"type":"string"}}}
      }
    ]
  }
}
  1. Client 调用工具
{
  "jsonrpc":"2.0",
  "id":2,
  "method":"tools/call",
  "params":{"name":"get_file","arguments":{"path":"/test.txt"}}
}
  1. Server 返回结果
{
  "jsonrpc":"2.0",
  "id":2,
  "result":{"content":[{"type":"text","text":"文件内容..."}]}
}

标签:

0 条笔记