MCP 模型上下文协议实战:用统一协议连接大模型与工具

MCP(Model Context Protocol,模型上下文协议)是 2024 年底由 Anthropic 提出的开放标准,用来给大模型统一接入数据源与工具。在 MCP 出现之前,每个 AI 应用都要为数据库、文件系统、第三方 API 各写一套私有适配;MCP 用一套客户端-服务器协议把这些能力标准化,让同一个 MCP Server 能被任意支持 MCP 的客户端复用。本文从协议动机讲到动手搭建一个 MCP Server,并给出生产落地的工程建议。

一、为什么需要 MCP:N×M 的集成困境

假设你有 5 个大模型客户端(Claude Desktop、VS Code 插件、自研 Agent)和 8 个数据源(MySQL、PostgreSQL、文件系统、GitHub、Slack、内部 API……)。如果每种客户端都直接对接每个数据源,你需要写 5×8 = 40 套集成代码,而且任何一端升级都要同步改全部。这就是 AI 应用早期的”N×M 集成地狱”。

MCP 的解法是引入一层标准协议:数据源侧实现一次 MCP Server,客户端侧实现一次 MCP Client,二者通过统一的原语通信。集成复杂度从 N×M 降到 N+M。它和当年 LSP(语言服务器协议)统一编辑器与编程语言插件的思路如出一辙——把”能力提供方”和”能力消费方”解耦。

二、MCP 的三层架构:Host / Client / Server

理解 MCP 只需记住三个角色:

  • Host(宿主):用户直接使用的 AI 应用,例如 Claude Desktop、Cursor、或你自己的 Agent 进程。它负责发起对话、调度模型。
  • Client(客户端):Host 内部为每个 Server 启动的一个连接实例,遵循一对一关系——一个 Client 只连一个 Server,负责收发 JSON-RPC 消息。
  • Server(服务端):暴露能力的进程,可以是本地脚本(stdio 传输)或远程 HTTP 服务,提供工具、资源、提示模板三类原语。

协议本身跑在 JSON-RPC 2.0 之上,对传输层不挑——本地用标准输入输出(stdio),远程用 Streamable HTTP(基于 SSE 双向流)。这意味着同一个 Server 既能给桌面客户端用,也能挂到云端给 SaaS 用,只需换传输方式。

三、三个核心原语:Resources / Tools / Prompts

MCP Server 能对外提供三类能力,这是它和单纯”函数调用”最大的区别:

1. Resources(资源):可被读取的上下文

资源是只读的、由应用侧主动拉取的数据,类似”给模型的参考资料”。例如一个 file:// 资源返回某份文档内容,一个 db://orders/recent 资源返回最近订单。资源用 URI 寻址,模型不直接”调用”它,而是由 Host 在合适时机注入上下文。

2. Tools(工具):可被模型执行的操作

工具是可写、可副作用的操作,例如”查询天气””执行 SQL””发 Slack 消息”。每个工具带名称、描述和 JSON Schema 形参,模型根据描述决定是否调用、填什么参数。工具是 MCP 最常用、也最容易踩安全红线的部分。

3. Prompts(提示模板):可复用的交互流程

提示模板是预定义的对话骨架,例如”把这段代码转成带单测的版本”。用户点一下就能把结构化提示灌进对话,适合把团队最佳实践固化成一键动作。

四、动手搭一个 MCP Server(Python + FastMCP)

官方 Python SDK 提供了 FastMCP 高层封装,几行代码就能暴露工具。下面这个示例注册了一个查询订单的工具和一个配置资源:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("demo-server")

@mcp.tool()
def query_orders(days: int) -> str:
    """查询最近 N 天的订单总量(演示用)"""
    # 真实场景这里查数据库;注意:不要在工具里直接拼接 SQL
    return f"近 {days} 天订单共 1280 笔"

@mcp.resource("config://app")
def app_config() -> str:
    return "env=prod region=cn-hangzhou"

if __name__ == "__main__":
    mcp.run()  # 默认 stdio 传输

装好依赖 pip install mcp 后,python server.py 就会以 stdio 方式启动并等待客户端连接。@mcp.tool() 装饰的函数会自动生成 JSON Schema,模型看到的只有函数名、描述与参数,调用时 SDK 负责序列化往返。

五、客户端如何接入:配置即连接

桌面客户端(如 Claude Desktop)只需在配置文件里声明 Server 的启动命令,Host 会自行拉起子进程并维护 Client 连接。一个本地 stdio Server 的配置如下:

{
  "mcpServers": {
    "demo": {
      "command": "python",
      "args": ["/abs/path/server.py"]
    }
  }
}

如果你用 TypeScript SDK 自建客户端,流程是”建传输→连 Client→列工具”:

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";

const transport = new StdioClientTransport({ command: "python", args: ["server.py"] });
const client = new Client({ name: "my-client", version: "1.0.0" });
await client.connect(transport);
const tools = await client.listTools();

远程部署时改用 Streamable HTTP 传输,客户端用 POST 发 JSON-RPC,服务端以 SSE 回推事件流:

curl -X POST http://localhost:8000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

六、MCP 与 Function Calling、LangChain Tools 有何不同

很多人会问:模型本来就有 Function Calling,LangChain 也有 Tool 抽象,MCP 多此一举吗?关键在”标准化”与”复用”两个词。Function Calling 是厂商私有格式,换模型要改适配;LangChain Tools 绑定框架,换框架要重写;MCP 是开放协议,Server 一次编写、任意客户端复用。

维度Function CallingLangChain ToolsMCP
标准化程度厂商私有框架私有开放标准
复用范围绑定单一模型绑定单一框架跨客户端复用
传输方式模型 HTTP 接口进程内调用stdio / HTTP
生态各自实现社区集成统一注册表

实践中三者并不互斥:很多 Agent 框架(如 LangChain)已经能直接把 MCP Server 包装成自己的 Tool 来用,见 LangChain Agent 实战:工具调用与自主编排。MCP 解决的是”能力怎么被统一暴露”,上层编排仍可用你熟悉的框架。

七、传输层怎么选:stdio 还是 Streamable HTTP

维度StdioStreamable HTTP
部署位置本地子进程远程服务
适用场景桌面 / 单机多用户 / SaaS
鉴权进程级,无需网络需令牌与 HTTPS
运维随客户端启停独立部署可水平扩展

个人工具、本地文件检索优先 stdio,零运维;要把能力开放给团队或多租户,就上 Streamable HTTP,但务必加鉴权、限流与日志,避免成为新的攻击面。关于服务入口的缓冲与代理配置,可参考 Nginx 反向代理实战:从配置到性能调优

八、生产落地:安全清单

MCP 把”执行权”交给了模型,安全是头等大事。上线前至少过一遍下面的清单:

风险缓解措施
工具被诱导执行危险操作写操作加人工确认;危险工具(删库、发消息)默认关闭
Server 返回污染内容对资源内容做校验与长度上限,防止提示注入
远程 Server 未鉴权Streamable HTTP 必须 HTTPS + 令牌,按租户隔离
工具描述被劫持Server 来源可信白名单,不从公网随意拉第三方 Server
凭据泄露密钥走环境变量 / 密钥管理,禁止硬编码进工具代码

特别提醒:模型看到的”工具描述”本身就可能成为提示注入入口——恶意 Server 可以在描述里藏指令诱导模型。只接入可信来源的 Server,是 MCP 落地的最低防线。关于 AI 应用的安全攻防,可延伸阅读 大模型提示注入攻防:AI 应用安全实战

九、生态与选型

官方维护了一个 MCP Server 注册表(如 GitHub 上的 modelcontextprotocol/servers),社区已贡献数据库、浏览器、文件系统、Git、Slack 等大量现成 Server。选型时遵循两条原则:优先用官方/高星社区 Server,少自己造轮子;对核心业务数据源(订单库、用户库),宁可自研一个最小 Server 并严格收窄权限,也不要直接挂一个权限过大的通用 Server。若你想把私有知识库也暴露成工具,可结合 2026 年搭建私有 AI 知识库:Dify + Ollama 本地部署 的思路,把检索能力包成 MCP 资源。

十、小结

MCP 的本质是用”开放协议”取代”私有集成”,把 AI 应用连接外部世界的能力标准化、可复用化。对开发者而言,它意味着少写几十套适配、多专注业务逻辑;对团队而言,它意味着工具能力可以像组件一样沉淀和共享。上手路径很清晰:先用 FastMCP 写一个小 Server 跑通 stdio,再按需迁移到 Streamable HTTP 服务化,全程把安全清单当成上线门槛。当你的 Agent 需要记忆与编排时,MCP 还能和 AI 智能体记忆系统Agent 评测 组合成完整闭环。MCP 不会取代你的 Agent 框架,而是让框架之下那层”能力插座”终于统一了。

上一篇 响应式编程 Reactor 实战:异步数据流与背压
下一篇 磁盘 IO 被打满:一次写入阻塞导致接口雪崩的排查实录