理解 MCP:模型上下文协议的架构、机制与工程实践
开篇:MCP 在解决什么问题
关于 MCP(Model Context Protocol,模型上下文协议),开发者社区中有两种常见看法。一部分人认为 MCP 是重要进展:「MCP 让我们不用再手写胶水代码。」另一部分人觉得它没有新意:「这不就是把获取工具列表封装了一下吗?」
这两种看法都有其道理,但也都有局限。在深入之前,需要先明确一点:MCP 不是让 AI 自动适配任意外部工具的通用方案,也不会自动把已有业务 API 变成 AI 工具。
MCP 的核心流程:
- 你对 Claude(Host)说:「查一下生产环境日志。」
- Claude 内置的 MCP Client 通过协议询问外部的 MCP Server:「你有相关资源或工具吗?」
- Server 回复:「我有一个叫 prod_logs 的资源。」
- Claude 提取资源,交给大模型去阅读分析,最后给你回答。
在这整个过程中,你不需要为 Claude 单独写对接或爬取日志的胶水代码。
一、核心概念:MCP 到底在规范什么?
很多人以为 MCP 只是用来「调接口」的。MCP 定义了三大核心能力,它不仅是动作的集合,也是资源与上下文的统管:
Tools(工具):赋予模型「行动力」
- 本质:改变外部世界状态的可执行动作(Actions)。
- 特征:比如
query_db()、restart_server()。Server 必须提供严格的 JSON Schema,告诉大模型这个工具需要什么参数。
Resources(资源):赋予模型「透视眼」
- 本质:供模型读取的上下文数据。
- 特征:比如
file:///logs/app.log或postgres://users/schema。注意:资源获取的具体方式(是通过直接读本地文件、调用内部 API 还是查库)取决于 Server 端的代码实现,MCP 只负责统一定义这些资源的数据结构。这种只读特性是 MCP 与传统 Plugin 最大的区别之一。
Prompts(提示词模板):赋予模型「规范化思维」
- 本质:服务端预定义的标准化指令模板。
- 特征:很多 MCP Server 甚至不提供具体的 Tool,只暴露如「企业代码审查标准模板」供宿主拉取,确保模型在特定场景下的输出符合业务规范。
Tools/Resources/Prompts 具体示例
以下是各概念的 JSON Schema / 代码实例,展示实际使用时如何定义:
Tools(JSON Schema 定义示例)
{ "name": "query_db", "description": "执行 SQL 查询,返回结果集", "inputSchema": { "type": "object", "properties": { "query": { "type": "string", "description": "SELECT 语句,禁止 INSERT/UPDATE/DELETE" }, "limit": { "type": "integer", "default": 100, "maximum": 1000 } }, "required": ["query"] }}Resources(URI 模式示例)
file:///var/log/nginx/access.log → MCP Server 读取并返回日志内容postgres://db-prod/users/{user_id}/profile → 按 user_id 参数返回用户档案config://app/settings → 返回 JSON 格式的运行时配置Prompts(提示词模板示例)
{ "name": "code_review_standard", "description": "企业代码审查标准模板", "arguments": [ { "name": "language", "description": "编程语言", "required": true } ]}二、运行机制:组件模型与协作流程
理解 MCP 需要理清各组件的边界。智能与执行被分离:
| 组件 | 职责 |
|---|---|
| Host(宿主) | 比如 Claude Desktop 或 Cursor,负责提供用户界面、会话管理以及最终的执行决策。 |
| LLM(大模型) | 存在于云端或本地的唯一智能体,负责「理解意图」。 |
| MCP Client(客户端) | 通常作为 SDK 或中间件直接内嵌在 Host 应用程序内部。它没有智能,只负责维护连接、动态发现服务端能力(Discovery)、发送调用请求并接收结果。 |
| MCP Server(服务端) | 独立运行的轻量级外部程序,暴露出具体的业务能力。 |
MCP 消息流:JSON-RPC 请求/响应示例
MCP 基于 JSON-RPC 2.0 协议通信。以下是一次完整工具调用的消息序列:
1. 初始化握手 (initialize)
{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2024-11-05", "capabilities": { "roots": { "listChanged": true }, "sampling": {} }, "clientInfo": { "name": "Claude Code", "version": "2.0.0" } }}{ "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "2024-11-05", "capabilities": { "tools": { "listChanged": true }, "resources": { "subscribe": true, "listChanged": true }, "prompts": { "listChanged": true } }, "serverInfo": { "name": "deepseek-mcp-server", "version": "0.6.1" } }}2. 工具发现 (tools/list)
{ "jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {} }{ "jsonrpc": "2.0", "id": 2, "result": { "tools": [ { "name": "chat_completion", "description": "调用 DeepSeek 模型进行对话补全", "inputSchema": { "type": "object", "properties": { "messages": { "type": "array", "description": "对话消息列表" }, "model": { "type": "string", "default": "deepseek-v4-flash" } }, "required": ["messages"] } } ] }}3. 工具调用 (tools/call)
{ "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "chat_completion", "arguments": { "messages": [ { "role": "user", "content": "写一个 Python 冒泡排序" } ], "model": "deepseek-v4-flash" } }}{ "jsonrpc": "2.0", "id": 3, "result": { "content": [ { "type": "text", "text": "def bubble_sort(arr):\n ..." } ] }}注意:以上是 stdio 传输模式(本地进程间通信)的消息格式。 SSE 或 HTTP 传输模式下,消息会包装在 HTTP 请求体中,但 JSON-RPC 结构不变。
MCP vs Function Calling vs Plugin:三种扩展模式的对比
MCP 常被拿来和 OpenAI 的 Function Calling 或 ChatGPT Plugin 比较。以下是三种模式的系统性对比:
| 维度 | MCP | Function Calling | Plugin(ChatGPT) |
|---|---|---|---|
| 制定者 | Anthropic(开放标准) | OpenAI | OpenAI |
| 传输层 | stdio / SSE / WebSocket / HTTP | 无独立传输—内嵌在 API 请求中 | HTTP REST + OpenAPI Schema |
| 工具发现 | 动态发现(tools/list, resources/list) | 手动声明(在 API 请求中指定 tools 数组) | 清单文件(ai-plugin.json + OpenAPI) |
| 上下文管理 | Resources 提供只读上下文、Prompts 提供模板 | 依赖用户 prompt 中插入 | 通过 API 返回值拼接 |
| 安全模型 | 用户批准(user consent)+ 工具级权限 | 开发者自行实现 | OAuth + 用户授权 |
| 跨 Host | 一次编写,Claude/Cursor/Windsurf/Gemini CLI 通用 | 各厂商实现不同,需适配 | 仅 ChatGPT |
| 资源/状态 | Resources(只读上下文)+ 状态持久化 | 无状态(stateless) | 通过 API 维护状态 |
传输层:stdio vs SSE vs WebSocket
MCP 支持多种传输方式,选择取决于部署场景:
| 传输方式 | 适用场景 | 限制 |
|---|---|---|
| stdio | 本地 MCP Server,子进程通信。Claude Code 默认 | 仅本机,无法远程 |
| SSE | 远程 MCP Server,服务器→客户端推送。Cursor/Windsurf 支持 | 单向推送,客户端请求仍需 HTTP POST |
| Streamable HTTP | 远程部署,双向通信。MCP 规范 2025 年新增 | 需要独立 HTTP 服务部署,运维成本增加 |
三、行业痛点:实际使用的两项挑战
当机构开始接入 MCP 时,面临的主要困难不在协议本身:
上下文爆炸(Context Explosion)与工具选择失效
这是当前 Agent 架构中一个需要正视的问题。如果把企业内部的 ERP、CRM、GitLab 的几百个工具全挂进 MCP,Client 会在每次对话前将庞大的 Tool List 传给大模型。后果是:
- Token 消耗暴涨
- 响应延迟翻倍
- Tool Selection Failure:由于候选工具过多、描述重叠,大模型挑花眼从而选错工具或产生幻觉
因此,高级工程实践往往会引入 Tool Router(工具路由)或动态加载机制。
注册中心(Registry)与合规性(Compliance)
目前缺乏成熟的统一 MCP 注册中心。机构在将内部数据源暴露给 MCP Server 时,需要自行解决权限隔离、Token 鉴权和访问审计问题。
四、主流 AI 工具的 MCP 接入方案指南
Claude Desktop
Claude 的桌面端是跑通 MCP 的标准测试环境。
- 核心逻辑:修改 Claude 内部的
claude_desktop_config.json,让 Claude 在启动时拉起你的脚本。 - 传输解耦:目前阶段它主要强制采用 stdio(标准输入输出)进行本地进程间通信,但随着协议演进,未来 Host 端完全可能支持远程配置。
Cursor / Windsurf(IDE 场景)
- 核心逻辑:IDE 原生内置了 MCP 客户端配置面板。它展现了 MCP 在传输层(Transport)的灵活性:不仅支持本地 command 启动,也支持通过 SSE (Server-Sent Events) 连接远端的 MCP Server。
- 适用场景:将企业内部的代码审查规范以 Resources 形式挂载,或将团队自建的 API 测试沙盒以 Tools 形式注入到程序员的开发助手中。
五、落地实战:标准 MCP Server 的开发与排坑
以下使用官方最新的 Python SDK(mcp 库)演示基础架构。
Server 结构代码(server.py)
from mcp.server.fastmcp import FastMCPmcp = FastMCP("my_enterprise_tools")@mcp.tool()def get_user_data(user_id: str) -> str: """ 根据用户ID查询内部系统用户状态。 Args: user_id: 标准的员工工号,如 "EMP001" """ return f"User {user_id} is Active."@mcp.resource("config://app/settings")def get_settings() -> str: """获取当前系统的核心配置项,供模型分析时参考""" return '{"max_connections": 100, "timeout": 30}'if __name__ == "__main__": mcp.run()常见问题与排查指南
痛点 1:Client 提示 “Failed to connect” 且没有日志
- 原因:stdio 通信要求标准输出 (stdout) 不含其他内容。如果代码中有
print(“Server started”),这行文本会被混入 MCP 的 JSON RPC 协议流中,导致客户端解析错误。 - 解法:在 Server 代码中,不使用标准的 print()。所有日志应重定向到 stderr(标准错误)或外部文件。
痛点 2:找不到执行环境(Command not found)
- 原因:Host 在启动子进程时,并不完全继承你终端里的环境变量。
- 解法:在配置文件中,建议使用解释器或执行程序的绝对路径。例如:
“command”: “/Users/admin/.pyenv/shims/python”。
痛点 3:工具调用效果差、模型频繁传错参数(Tool Selection Failure)
- 原因:Tool Schema 或 Description 定义模糊。例如描述写着「查询数据」,模型无法确定查询对象和字段格式。
- 解法:MCP 的核心是规范。需要详细编写工具注释(包括参数边界、默认值和业务含义)。这些注释会被转化为严格的 Schema 传给大模型,注释越清晰,调用错误率越低。
快速上手
MCP 的安装步骤和配置方法见 《MCP 配置避坑指南》,扩展机制全览见 《Claude Code 扩展机制》。
结语
MCP 解决的是标准化接入问题,而不是模型能力问题。它本身不创造智能。但如果标准被广泛采用,开发者可以不再为每个工具单独编写对接代码,把精力集中到模型优化和业务逻辑上。
备注与免责声明
备注 1:本文基于 2026 年 6 月 MCP 协议公开规范与各工具当前版本编写。MCP 协议本身处于快速演进阶段,各 Host 应用的具体配置方式可能随版本迭代变更,请以官方最新文档为准。
备注 2:文中所涉代码示例和技术方案仅限个人学习研究用途。企业级部署请遵守所在组织的安全合规要求。