MCP(Model Context Protocol,模型上下文协议)是当前 AI Agent 工程体系中核心的基础技术之一。对于希望让 AI agent(如 OpenAI Codex)不仅完成代码理解,还能主动读取项目状态、调用测试工具、操作业务系统、诊断问题并辅助研发的场景,MCP 提供了标准化的能力接入范式。
一、MCP协议概述
1.1 定义
MCP 是一种开放协议,用于标准化大语言模型应用与外部数据源、工具和服务之间的集成方式。
简单来说,MCP 为 AI 应用访问外部世界定义了一套统一的交互接口规范。它规定的是 AI 应用如何发现外部能力、如何描述工具、如何传递参数、如何获取结果,以及如何协商能力与权限。
1.2 解决的问题
假设我们正在开发一款 AI 编程助手,希望它能够:
- 访问 GitHub 仓库,读取 Issue、PR 与代码文件
- 运行单元测试,查询测试报告与覆盖率
- 获取 ALS 平台的项目状态、标注任务与模型训练进度
- 调用工业相机诊断接口,读取设备运行参数
如果没有 MCP,需要分别为 GitHub API、测试系统、ALS 后端、硬件控制服务做定制化适配,每种 AI 应用都要重复一次工具对接工作。
MCP 的价值在于在 AI 应用与外部工具之间建立统一的协议边界:开发者将已有业务能力封装为 MCP Server,即可被所有兼容 MCP 的 Host 调用,本质是软件工程中"封装差异、标准化接口"思想在 AI 工具领域的延伸。
1.3 协议定位
MCP 的设计思路深受 Language Server Protocol(LSP)启发:
- LSP 让 VS Code 等编辑器通过统一协议使用语言服务器的补全、跳转、诊断能力
- MCP 让 AI 应用通过统一协议接入外部上下文与工具能力
二者功能不同,但采用了一致的"协议解耦"设计思想。因此:
- MCP 不负责提升模型能力,负责定义模型应用连接外部能力的方式
- MCP 不替代 REST API,通常在已有 API 之上增加 AI 可发现、可调用的适配层
二、架构:Host、Client、Server 三级角色
MCP 采用 Client-Server 架构,但其角色定义与传统 Web 体系存在差异,是理解协议的第一道门槛。
2.1 三类角色
MCP Host:AI 应用宿主
即面向用户的 AI 应用,例如 Codex、Claude Code、VS Code Agent 或自研 AI Agent。承担整个交互流程的控制职责:用户交互、模型推理、上下文管理、工具调度、权限审批。一个 Host 可以管理多个 MCP Client,分别对接不同的能力提供方。
MCP Client:协议客户端
Host 内部负责 MCP 通信的组件,实现协议通信、服务端能力发现、工具调用与结果接收。一个 Host 通常创建多个 MCP Client,每个 Client 对应一个 MCP Server。Client 是软件组件,不一定是独立进程。
MCP Server:能力提供方
负责暴露可访问的数据、工具与提示模板。它可以是:
- 本地启动的 Python 进程
- 部署在远端的 HTTP 服务
- 封装现有数据库/REST API 的适配层
- 对接设备诊断接口的本地服务
MCP Server 并不要求部署在远程机器上,一个本地运行的程序同样可以作为 MCP Server。
2.2 MCP Server 与业务后端的关系
MCP Server 不重复实现原有业务逻辑。
以 ALS 平台为例,其已有 FastAPI 后端、任务调度、模型管理与数据存储体系,合理的架构是:
AI Host → ALS MCP Server(协议转换、参数校验、权限控制、结果结构化)→ 现有 FastAPI 业务后端
MCP 优先作为 AI 接入层存在,而非替代业务层。例如 get_training_status 工具仅负责调用现有训练任务查询接口,将后端返回值转换为适合 AI 消费的结构化结果,避免维护两套业务实现。
三、底层通信原理:数据层与传输层分层设计
MCP 的通信机制分为两层:
- 数据层(Data Layer):定义消息结构与交互语义
- 传输层(Transport Layer):定义消息的物理传递方式
3.1 数据层:基于 JSON-RPC 2.0
MCP 以 JSON-RPC 2.0 作为基础消息协议。JSON-RPC 是一种轻量远程过程调用协议:调用方通过 JSON 消息指定目标方法与参数,被调用方返回对应结果。
基础请求结构示例:
json
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_training_status",
"arguments": {
"task_id": "train_001"
}
}
}
注:以上示例省略了新版 MCP 要求的
_meta元数据字段,符合 2026-07-28 规范的请求还需携带协议版本、客户端能力等信息。
字段说明:
| 字段 | 含义 |
|---|---|
jsonrpc |
JSON-RPC 协议版本,固定为 2.0 |
id |
请求标识,用于关联请求与响应 |
method |
待执行的远程操作名称 |
params |
请求参数,包含工具名、调用参数等 |
result |
响应中的执行结果(成功时存在) |
error |
协议层错误信息(出错时存在) |
简化响应示例:
json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"content": [
{
"type": "text",
"text": "Training completed"
}
],
"isError": false
}
}
请求与响应通过相同的 id 关联。除了 Request/Response 模式,JSON-RPC 还定义了 Notification(无 id 字段,不要求响应),MCP 基于此进一步约定了 tools/list、tools/call、resources/read 等方法的语义与消息结构。
3.2 传输层:stdio 与 Streamable HTTP
目前 MCP 支持两种主流传输方式。
(1)stdio(标准输入/输出)
Host 启动一个本地子进程,通过标准输入(stdin)与标准输出(stdout)交换协议消息。
- 场景:Codex 调用本地 Python 工具、项目诊断脚本、开发机自动化程序
- 注意:stdout 是协议通道,不可用于调试日志输出,否则会破坏消息流;调试日志应输出至 stderr 或通过 SDK 规范化日志机制处理。
(2)Streamable HTTP(可流式传输 HTTP)
通过 HTTP POST 传递 JSON-RPC 消息,结合 SSE(Server-Sent Events)实现服务端到客户端的流式事件推送。
- 场景:远程服务、团队共享能力、多客户端接入、生产环境部署
- 注意:旧版独立 SSE Transport 已被 Streamable HTTP 取代,新项目不建议使用旧式 SSE 传输;但 SSE 技术本身仍在新传输中作为事件通道使用。
3.3 2026-07-28 版:无状态通信
早期 MCP 包含 initialize 握手流程,协商版本与能力并建立会话上下文;新版采用无状态协议:
- 协议版本与客户端能力随每个请求的
_meta字段携带 - 每个请求原则上可由不同的服务实例处理,无需依赖协议级会话状态
请求元数据示例:
json
{
"jsonrpc": "2.0",
"id": 10,
"method": "tools/list",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {},
"io.modelcontextprotocol/clientInfo": {
"name": "als-agent",
"version": "1.0.0"
}
}
}
}
无状态协议 ≠ 业务应用不能保存状态。训练任务、用户权限等业务状态仍可存储在数据库中,通过标识访问;改变的是通信层的会话依赖,而非所有业务都必须无状态化。
新版同时提供 server/discover 方法用于发现协议版本与服务端能力,客户端可选择直接发起业务请求,并非每次调用前都必须执行发现流程。
3.4 工具调用流程
以查询 ALS 训练进度为例,完整链路如下:
- 用户向 Host 提出查询需求
- Host 调用 MCP Client 执行
tools/list获取可用工具 - Server 返回工具定义与 JSON Schema
- Host 将工具描述注入模型上下文
- 模型根据用户意图选择
get_training_status工具并生成参数 - Host 通过 Client 发起
tools/call请求 - MCP Server 调用后端业务接口查询任务状态
- Server 返回结构化执行结果
- Host 将结果交付模型进行分析
- 模型生成最终回答呈现给用户
分层逻辑:模型负责决策(用哪个工具、传什么参数),协议层负责执行(发请求、收结果),业务层负责真实操作。这三层解耦是设计可测试、可维护 AI Agent 的关键。
四、三大能力:Tools、Resources、Prompts
Tools、Resources、Prompts 是 MCP 定义的三类服务器端能力,分别对应"执行操作、提供数据、引导交互"三类场景。
4.1 Tools:让 AI 执行外部操作
Tool 是可被 AI 应用调用的函数,是 MCP 最关键的能力。Server 对外公布工具的名称、描述与输入参数结构,客户端通过 tools/list 发现、tools/call 执行。
Tool 的核心是 inputSchema,基于 JSON Schema 描述合法输入参数,让 AI 不仅知道"有这个函数",还知道"需要什么参数、参数是什么类型、什么时候该调用"。
工具定义示例:
json
{
"name": "get_training_status",
"description": "Get the status of a training task",
"inputSchema": {
"type": "object",
"properties": {
"task_id": {
"type": "string",
"description": "Training task identifier"
}
},
"required": ["task_id"]
}
}
调用后 Server 可返回文本、结构化数据或其他内容块,也可通过 outputSchema 描述预期输出结构。Tool 不限于修改型操作,查询类操作同样可以封装为 Tool,区别在于它以"可调用函数"的形式提供能力。
4.2 Resources:为 AI 提供上下文数据
Resource 是 MCP Server 对外提供的可读取数据资源,通过 URI 唯一标识,例如:
bash
als://config/classes
als://projects/1001/summary
als://training/1001/metrics
客户端通过 resources/list 查看资源列表,通过 resources/read 读取资源内容。同时支持 URI 模板(如 als://projects/{project_id}/summary),无需为每个实例单独注册资源。
Resource 的定位是向 AI 提供项目配置、文档、数据摘要、数据库结构等上下文信息,由 Host 决定呈现、选择与加载策略。
4.3 Prompts:提供可复用交互模板
Prompts 是由 MCP Server 提供的提示模板,面向用户而非模型。用户从客户端菜单中选择模板、填写参数后,渲染结果直接进入对话。
例如 ALS 可提供 analyze_training_failure、review_annotation_quality、generate_dataset_report 等模板,用户选择后自动生成标准化的问题引导。对应方法为 prompts/list 与 prompts/get。
4.4 能力对比
| 比较维度 | Tools | Resources | Prompts |
|---|---|---|---|
| 作用 | 执行函数操作 | 提供上下文数据 | 提供交互模板 |
| 触发主体 | 模型自动选用 | Host 策略加载 | 用户/应用选择 |
| 标识方式 | 工具名称 | URI | 模板名称 |
| 方法 | tools/call |
resources/read |
prompts/get |
| ALS 场景示例 | 运行测试、启动训练 | 读取类别配置、项目摘要 | 诊断训练失败、生成数据报告 |
注:以上为标准交互定位,并非刚性规则。例如 Host 可自动选取资源,Tool 也可仅执行只读操作。
五、高级协议机制
Tools Resources Prompts定义了"提供什么能力",高级机制则解决"如何可靠、高效地运行这些能力"。
5.1 动态能力发现与缓存
MCP 可通过 server/discover、tools/list、resources/list、prompts/list 动态获取当前可用能力。服务端能力变更时,可通过通知机制主动同步。
2026-07-28 规范为列表响应引入缓存提示:
json
{
"ttlMs": 300000,
"cacheScope": "private"
}
ttlMs:缓存建议有效期(毫秒)cacheScope:缓存共享范围
缓存机制可减少重复加载开销,降低协议调用成本。对于开发助手类场景,工具列表的稳定性还会影响上下文占用与 Prompt Cache 效率,因此并非暴露的工具越多越好。
5.2 Multi Round-Trip Requests:多轮往返请求
针对需要用户确认、补充信息的场景(如删除项目前的二次确认),新版 MCP 引入 Multi Round-Trip Requests(MRTR)机制:
- 客户端发起操作请求
- 服务端返回
input_required结果,包含待补充信息与requestState - Host 向用户征求确认或补充输入
- 客户端携带输入结果与
requestState重新发起请求 - 服务端验证后处理并返回最终结果
该设计更适配无状态 HTTP 服务,无需依赖长连接反向调用通道。但 Elicitation 仅负责交互机制,不替代业务安全校验------操作前仍需在服务端验证权限、对象与有效性。
5.3 Subscriptions:变化通知订阅
MCP 支持服务端向客户端推送数据变化通知。客户端通过 subscriptions/listen 建立订阅流,指定接收的通知类型;资源更新、工具列表变化等事件可通过通知机制传递。
对于高吞吐实时数据(如逐帧图像、高频指标),不应将 MCP 作为数据总线;更合理的方案是原有传输链路保留数据采集能力,MCP 仅提供查询入口、摘要订阅或结果引用。
5.4 Extensions:扩展机制
2026 版 MCP 正式建立扩展框架,特殊能力可独立演进,无需全部纳入协议核心。值得关注的扩展包括:
| 扩展 | 用途 | ALS 适用场景 |
|---|---|---|
| Tasks | 长时间异步任务管理与结果轮询 | 模型训练、批量标注 |
| MCP Apps | 在支持的 Host 中展示交互 UI | 训练指标看板、质检报表 |
| Skills over MCP | 提供可发现的 Agent 工作流指导 | 故障诊断与运维流程 |
扩展均为可选能力,不能默认所有 Host 都完整支持。以 Tasks 为例,它允许服务端返回持久任务句柄,客户端通过接口查询进度与结果,适合长时间数据集处理等场景,比同步阻塞调用更合理。
六、实战开发:基于 Python SDK v2 开发 MCP Server
本节使用官方 Python SDK v2 完成最小 MCP Server 开发。Python 适合快速封装已有 API、文件系统与开发工具;即使业务后端为 C++,也可使用 Python 编写 MCP 适配层,通过既有接口调用后端服务。
6.1 开发环境搭建
官方 Python SDK v2 要求 Python 3.11 及以上。
使用 uv 安装:
bash
mkdir als-mcp-demo && cd als-mcp-demo
uv init
uv add "mcp[cli]"
使用 pip 安装:
bash
python -m pip install "mcp[cli]"
注意:v2 版本服务端主类为
from mcp.server import MCPServer
6.2 最小服务实现
新建 als_mcp_server.py:
python
from mcp.server import MCPServer
from mcp.server.mcpserver.exceptions import ToolError
mcp = MCPServer("ALS-Demo")
# 演示数据,实际场景对接后端API
TASKS = {
"train_001": {
"status": "running",
"epoch": 42,
"total_epochs": 100,
"loss": 0.185,
}
}
@mcp.tool()
def get_training_status(task_id: str) -> dict:
"""Return the current status of an ALS training task."""
if task_id not in TASKS:
raise ToolError(f"Task not found: {task_id}")
return {
"task_id": task_id,
**TASKS[task_id],
}
@mcp.resource("als://project/overview")
def get_project_overview() -> str:
"""Read the ALS demo project overview."""
return (
"Project: ALS Demo\n"
"Framework: MCP Python SDK v2\n"
"Data source: in-memory demonstration\n"
)
@mcp.prompt()
def diagnose_training(task_id: str) -> str:
"""Start a training failure diagnosis workflow."""
return f"请分析训练任务 {task_id} 的失败原因,先查询状态与错误日志,再检查数据集配置与运行环境,最后给出修复建议。"
if __name__ == "__main__":
mcp.run()
该示例已覆盖三类核心能力:
@mcp.tool():根据函数签名与类型注解自动生成输入 Schema@mcp.resource():将 URI 映射到资源处理函数@mcp.prompt():注册可复用提示模板
6.3 使用 MCP Inspector 调试
官方提供 MCP Inspector 调试工具,启动命令:
bash
uv run mcp dev als_mcp_server.py
该命令启动调试 UI(依赖 Node.js 与 npx),可在界面中测试工具调用、资源读取与提示渲染,验证协议交互正确性。
6.4 切换为 HTTP 服务
若需通过网络访问,可修改启动方式:
python
if __name__ == "__main__":
mcp.run(
transport="streamable-http",
host="127.0.0.1",
port=8000,
)
或通过 CLI 指定传输方式:
bash
uv run mcp run als_mcp_server.py --transport streamable-http
默认 HTTP 端点为 [http://127.0.0.1:8000/mcp](http://127.0.0.1:8000/mcp),仅用于本地开发,不可直接暴露公网。
6.5 客户端开发示例
MCP 独立于大语言模型,普通 Python 程序也可作为 Client 调用服务:
python
import asyncio
from mcp import Client
async def main():
async with Client("[http://127.0.0.1:8000/mcp](http://127.0.0.1:8000/mcp)") as client:
# 查询可用工具
tools = await client.list_tools()
for tool in tools.tools:
print(f"{tool.name}: {tool.description}")
# 调用工具
result = await client.call_tool(
"get_training_status",
{"task_id": "train_001"},
)
print(result.structured_content)
if __name__ == "__main__":
asyncio.run(main())
6.6 与 FastAPI 集成
若已有 FastAPI/Starlette 后端,MCP Server 无需独立部署。官方 SDK 可生成 ASGI 应用:
python
mcp_app = mcp.streamable_http_app()
该 ASGI 应用可独立运行,也可挂载到现有应用中。注意 :挂载场景下必须由父应用管理 MCP 生命周期,显式进入 mcp.session_manager.run(),否则会出现会话管理器未初始化错误。生产环境还需配置主机校验、认证与授权机制。
七、集成实践:接入 OpenAI Codex
Codex 可作为 MCP Host,连接本地或远程 MCP Server,将工具能力融入编程助手工作流。
7.1 接入本地 stdio Server
使用 Codex CLI 添加本地服务:
bash
codex mcp add als-demo -- python /absolute/path/als_mcp_server.py
建议使用虚拟环境中 Python 解释器的绝对路径,确保依赖环境正确。
也可通过配置文件 ~/.codex/config.toml 配置:
toml
[mcp_servers.als_demo]
command = "/absolute/path/.venv/bin/python"
args = ["/absolute/path/als_mcp_server.py"]
enabled = true
enabled_tools = ["get_training_status"]
default_tools_approval_mode = "prompt"
执行 codex mcp list 查看已配置服务,在 Codex TUI 中使用 /mcp 命令查看可用服务。
7.2 接入 HTTP Server
若已启动本地 HTTP 服务:
bash
codex mcp add als-http --url [http://127.0.0.1:8000/mcp](http://127.0.0.1:8000/mcp)
与 stdio 模式的区别:HTTP 模式需服务端预先运行;stdio 模式由 Codex 自动启动子进程。
7.3 工具权限与审批管控
Codex 支持工具白名单、禁用工具、超时、审批模式等配置,例如:
toml
[mcp_servers.als_demo]
command = "/absolute/path/.venv/bin/python"
args = ["/absolute/path/als_mcp_server.py"]
enabled_tools = ["get_training_status"]
default_tools_approval_mode = "prompt"
tool_timeout_sec = 30
安全原则:Host 层审批只是第一道防线,不能替代 MCP Server 自身的权限控制。有副作用的操作必须在业务服务层独立验证身份与授权。
八、技术边界
MCP 常与 Function Calling、REST API、RAG、Agent 等概念同时出现,但其定位与解决的问题各不相同。
8.1 与 Function Calling
Function Calling 是模型与应用之间的工具调用机制,解决"模型如何生成结构化工具调用请求 ";MCP 是应用与外部工具服务之间的标准协议,解决"如何通过标准协议发现和调用外部工具"。
完整链路:
用户 → Codex/Agent → 模型推理 → Function Calling → MCP Client → MCP Server → 业务API → 返回结果
二者可组合使用,但无必然绑定关系------MCP Client 完全可在没有大模型的场景下独立调用服务。
8.2 与 REST API
REST API 是面向通用业务客户端的服务接口风格;MCP 将同样的业务能力封装为 AI 可发现、可调用的工具形式。MCP Server 内部仍可调用 REST API,二者是封装关系而非替代关系。
为现有系统增加 MCP 能力时,无需将全部接口改写为 MCP,仅需对 AI 场景所需的能力做适配封装。
8.3 与 RAG
RAG(检索增强生成)是通过检索外部知识增强模型回答的方法;MCP 可为检索系统提供标准化的工具接入接口。
链路示例:
Agent → MCP Tool: search_project_knowledge → 全文/向量检索 → 返回文档片段 → 模型分析生成
RAG 是知识检索与生成方案,MCP 是接入检索系统的协议层。
8.4 与 AI Agent
AI Agent 通常包含目标理解、任务规划、工具使用、状态管理、结果评估等完整能力;MCP 主要为其中的工具与上下文接入提供标准接口。
各技术核心职责:
| 技术 | 职责 |
|---|---|
| LLM | 语言理解、推理与内容生成 |
| Function Calling | 生成结构化工具调用参数 |
| MCP | 标准化外部能力的发现、访问与调用 |
| REST API | 提供通用业务服务 |
| RAG | 检索外部知识,增强生成效果 |
| Agent | 围绕任务协调模型、工具与执行过程 |
MCP 只解决工具连接标准化问题,Agent 的可靠性还取决于任务分解、状态管理、错误恢复、反馈闭环、权限体系与执行验证。
九、安全与工程化设计
MCP 工具可能具备文件读写、数据库访问、命令执行甚至设备控制能力,安全边界设计至关重要。官方规范强调用户控制、数据隐私、工具安全与授权机制四大原则。
9.1 威胁模型
#mermaid-svg-YaWyO6TwEYWYMrKB{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YaWyO6TwEYWYMrKB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YaWyO6TwEYWYMrKB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YaWyO6TwEYWYMrKB .error-icon{fill:#552222;}#mermaid-svg-YaWyO6TwEYWYMrKB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YaWyO6TwEYWYMrKB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YaWyO6TwEYWYMrKB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YaWyO6TwEYWYMrKB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YaWyO6TwEYWYMrKB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YaWyO6TwEYWYMrKB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YaWyO6TwEYWYMrKB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YaWyO6TwEYWYMrKB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YaWyO6TwEYWYMrKB .marker.cross{stroke:#333333;}#mermaid-svg-YaWyO6TwEYWYMrKB svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YaWyO6TwEYWYMrKB p{margin:0;}#mermaid-svg-YaWyO6TwEYWYMrKB .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-YaWyO6TwEYWYMrKB .cluster-label text{fill:#333;}#mermaid-svg-YaWyO6TwEYWYMrKB .cluster-label span{color:#333;}#mermaid-svg-YaWyO6TwEYWYMrKB .cluster-label span p{background-color:transparent;}#mermaid-svg-YaWyO6TwEYWYMrKB .label text,#mermaid-svg-YaWyO6TwEYWYMrKB span{fill:#333;color:#333;}#mermaid-svg-YaWyO6TwEYWYMrKB .node rect,#mermaid-svg-YaWyO6TwEYWYMrKB .node circle,#mermaid-svg-YaWyO6TwEYWYMrKB .node ellipse,#mermaid-svg-YaWyO6TwEYWYMrKB .node polygon,#mermaid-svg-YaWyO6TwEYWYMrKB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YaWyO6TwEYWYMrKB .rough-node .label text,#mermaid-svg-YaWyO6TwEYWYMrKB .node .label text,#mermaid-svg-YaWyO6TwEYWYMrKB .image-shape .label,#mermaid-svg-YaWyO6TwEYWYMrKB .icon-shape .label{text-anchor:middle;}#mermaid-svg-YaWyO6TwEYWYMrKB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-YaWyO6TwEYWYMrKB .rough-node .label,#mermaid-svg-YaWyO6TwEYWYMrKB .node .label,#mermaid-svg-YaWyO6TwEYWYMrKB .image-shape .label,#mermaid-svg-YaWyO6TwEYWYMrKB .icon-shape .label{text-align:center;}#mermaid-svg-YaWyO6TwEYWYMrKB .node.clickable{cursor:pointer;}#mermaid-svg-YaWyO6TwEYWYMrKB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-YaWyO6TwEYWYMrKB .arrowheadPath{fill:#333333;}#mermaid-svg-YaWyO6TwEYWYMrKB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-YaWyO6TwEYWYMrKB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-YaWyO6TwEYWYMrKB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YaWyO6TwEYWYMrKB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YaWyO6TwEYWYMrKB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YaWyO6TwEYWYMrKB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-YaWyO6TwEYWYMrKB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-YaWyO6TwEYWYMrKB .cluster text{fill:#333;}#mermaid-svg-YaWyO6TwEYWYMrKB .cluster span{color:#333;}#mermaid-svg-YaWyO6TwEYWYMrKB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-YaWyO6TwEYWYMrKB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YaWyO6TwEYWYMrKB rect.text{fill:none;stroke-width:0;}#mermaid-svg-YaWyO6TwEYWYMrKB .icon-shape,#mermaid-svg-YaWyO6TwEYWYMrKB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YaWyO6TwEYWYMrKB .icon-shape p,#mermaid-svg-YaWyO6TwEYWYMrKB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-YaWyO6TwEYWYMrKB .icon-shape .label rect,#mermaid-svg-YaWyO6TwEYWYMrKB .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YaWyO6TwEYWYMrKB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-YaWyO6TwEYWYMrKB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-YaWyO6TwEYWYMrKB :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-YaWyO6TwEYWYMrKB .host>*{fill:#EEF4FF!important;stroke:#4C7DF0!important;stroke-width:1.5px!important;color:#1B3A8F!important;}#mermaid-svg-YaWyO6TwEYWYMrKB .host span{fill:#EEF4FF!important;stroke:#4C7DF0!important;stroke-width:1.5px!important;color:#1B3A8F!important;}#mermaid-svg-YaWyO6TwEYWYMrKB .host tspan{fill:#1B3A8F!important;}#mermaid-svg-YaWyO6TwEYWYMrKB .guard>*{fill:#FFF6E5!important;stroke:#E8A33D!important;stroke-width:2px!important;color:#8A5200!important;}#mermaid-svg-YaWyO6TwEYWYMrKB .guard span{fill:#FFF6E5!important;stroke:#E8A33D!important;stroke-width:2px!important;color:#8A5200!important;}#mermaid-svg-YaWyO6TwEYWYMrKB .guard tspan{fill:#8A5200!important;}#mermaid-svg-YaWyO6TwEYWYMrKB .mcp>*{fill:#EAF8F0!important;stroke:#2FA36B!important;stroke-width:1.5px!important;color:#14603C!important;}#mermaid-svg-YaWyO6TwEYWYMrKB .mcp span{fill:#EAF8F0!important;stroke:#2FA36B!important;stroke-width:1.5px!important;color:#14603C!important;}#mermaid-svg-YaWyO6TwEYWYMrKB .mcp tspan{fill:#14603C!important;}#mermaid-svg-YaWyO6TwEYWYMrKB .target>*{fill:#F4F0FF!important;stroke:#7B61FF!important;stroke-width:1.5px!important;color:#3B2A8C!important;}#mermaid-svg-YaWyO6TwEYWYMrKB .target span{fill:#F4F0FF!important;stroke:#7B61FF!important;stroke-width:1.5px!important;color:#3B2A8C!important;}#mermaid-svg-YaWyO6TwEYWYMrKB .target tspan{fill:#3B2A8C!important;} MCP Server
LLM / Host
受控访问
请求
放行
安全控制边界
身份认证
授权
参数验证
人工确认
不可信决策输入
工具调用申请
受限工具能力
业务 API · 数据库 · 设备
原则:模型生成的参数不能直接等同于经过授权的操作指令。即使参数符合 JSON Schema,也必须在服务端独立校验权限、操作范围与有效性。
9.2 主要风险
| 风险类型 | 场景 | 防护方式 |
|---|---|---|
| Prompt Injection | 外部文档诱导模型执行危险操作 | 将工具返回内容视为不可信数据,做输出校验 |
| 越权访问 | 工具读取其他用户数据 | 服务端权限校验、数据隔离 |
| 路径穿越 | 通过路径参数访问任意文件 | 路径规范化、限制允许访问目录 |
| SSRF | 通过 URL 工具访问内网资源 | 地址校验、网络访问限制 |
| 凭证泄露 | 日志或结果包含 Token | 凭证隔离、敏感信息脱敏 |
| 任意代码执行 | 工具提供不受限 Shell 能力 | 沙盒隔离、命令白名单、最小权限原则 |
对于本地 stdio Server,需注意其由 Host 启动,恶意 Server 可获得对应进程权限;对于 HTTP Server,生产环境必须配置 HTTPS、认证授权、目标服务限制与安全检查。
9.3 工业设备的操作边界
对于机械臂、工业相机、PLC 等实体设备,建议将 AI 能力划分为三级:
- 只读观察:读取设备状态、日志、参数、诊断数据,优先开放
- 受控验证:在仿真/测试环境执行预定义操作,严格授权
- 真实执行:真实设备运动、参数写入、生产控制,独立安全联锁
涉及真实物理操作时,设备控制器的安全联锁、运动边界、工况校验、操作员确认必须独立生效,不能由模型决策绕过。
9.4 可观测性设计
生产级 MCP Server 至少应记录:工具名称、请求标识、执行耗时、调用结果、错误分类、业务任务标识、权限决策。可通过 Python logging、结构化日志、OpenTelemetry 实现。
高频调用场景需配置超时、并发限制、速率限制与缓存策略。避免将大规模图片、点云、完整日志直接塞入单次工具响应,优先返回统计信息、摘要或可按需读取的资源引用。
总结
| 层次 | 知识 | 工程目标 |
|---|---|---|
| 基础层 | Host、Client、Server 角色定义 | 理解架构职责边界 |
| 协议层 | JSON-RPC、stdio、Streamable HTTP | 理解完整调用链路 |
| 核心能力 | Tools、Resources、Prompts | 设计合理的 MCP 接口 |
| 高级机制 | 能力发现、MRTR、Tasks、订阅 | 处理复杂交互场景 |
| 开发层 | 官方 Python SDK v2 | 编写与调试服务端 |
| 安全层 | 授权、输入校验、最小权限原则 | 规避危险操作 |
| 集成层 | Codex、FastAPI、现有业务 API | 接入实际项目 |
| 工程层 | 日志、测试、超时、状态管理 | 保障长期可靠运行 |
从协议本身看,MCP 的核心并不复杂,它是建立在 JSON-RPC 之上的一套标准化能力描述与交互机制。
真正的难点不在于写出 @mcp.tool(),而在于如何将复杂软件的内部能力,转换为语义明确、参数受控、结果可验证、权限可管理的工具接口。