一、概念:什么是 MCP?
MCP(Model Context Protocol)是 Anthropic 推出的开放协议,定义了 LLM 应用与外部工具、数据源之间的标准通信接口。
一个类比就够了:MCP 是 AI 时代的 USB-C。
USB-C 之前,每个设备厂商自建接口——Lightning、Micro-USB、Mini-USB……你出门要带一包线。USB-C 统一之后,一根线走天下。
MCP 之前也一样:每个 LLM 应用要对接 GitHub,就得写一套 GitHub 集成;要对接数据库,再写一套数据库适配。N 个应用 x M 个工具 = NxM 套集成代码。MCP 的目标:写一次适配,所有 LLM 应用通用。
核心定义:
术语 | 含义 |
|---|---|
| MCP Server | 暴露工具/数据的服务端(如 filesystem server、github server) |
| MCP Client | 连接 Server 并消费其能力的客户端(如 LangChain Agent) |
| Protocol | Client 与 Server 之间的 JSON-RPC 通信协议 |
MCP 不是 LangChain 的私有协议——它是 Anthropic 开源、社区驱动的标准,任何 LLM 框架都可以接入。
一句话总结:MCP 是 AI 时代的 USB-C——用统一协议替代 NxM 集成,一次实现,处处可用。
二、价值:为什么不能继续各写各的?
1. 解决 NxM 集成爆炸
没有 MCP 的世界:
5 个 LLM 应用 x 10 个工具 = 50 套集成代码有 MCP 的世界:
10 个 MCP Server(每个工具写一次) 5 个 MCP Client(每个应用接一次协议) = 10 + 5 = 15,而不是 50从 NxM 降到 N+M,这就是标准协议的威力。
2. 生态复用:一次实现,处处可用
社区写好了一个mcp-server-github,所有支持 MCP 的框架都能用——LangChain、Claude Desktop、Cursor、Cline……你不需要为每个框架重新写 GitHub 集成。
3. 与 Function Calling 的差异
维度 | Function Calling | MCP |
|---|---|---|
| 定义方 | 各模型厂商自定义 | Anthropic 开源协议,社区标准 |
| 工具在哪 | 嵌在应用代码里 | 独立 Server,可远程部署 |
| 跨模型 | 每个模型的格式不同 | 统一协议,跨模型通用 |
| 跨应用 | 不可复用 | 一次实现,所有应用可用 |
| 动态发现 | 需硬编码工具列表 | Client 运行时发现 Server 的能力 |
Function Calling 解决的是"模型怎么调工具",MCP 解决的是"工具怎么暴露给所有模型"——两者互补,不冲突。
4. 跨厂商兼容
MCP 不绑定任何模型厂商。OpenAI、Anthropic、Google、DeepSeek 的模型都能通过 MCP 协议访问同一组工具。工具实现一次,模型随意切换。
核心价值:MCP 把集成成本从 NxM 降到 N+M,工具一次实现、生态复用、跨厂商兼容——标准化的网络效应。
三、用法:四种典型接入方式
用法 1:用 langchain-mcp-adapters 连接已有 MCP Server
社区已有大量现成的 MCP Server,直接连:
from langchain_mcp_adapters.client import MultiServerMCPClientfrom langchain.agents import create_agent# 连接 filesystem MCP Server(官方提供)async with MultiServerMCPClient({"filesystem": {"command": "npx","args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],"transport": "stdio",}}) as client:tools = client.get_tools()agent = create_agent(model="deepseek:deepseek-chat",tools=tools,)result = await agent.ainvoke({"messages": [{"role": "user", "content": "列出 /tmp 下的文件"}]})print(result)
不需要自己写任何工具代码——MCP Server 已经实现好了,langchain-mcp-adapters自动把 MCP Tools 转成 LangChain Tools。
用法 2:把 MCP Tools 装进 create_agent
MCP Tools 可以和普通 LangChain Tools 混用:
from langchain_mcp_adapters.client import MultiServerMCPClientfrom langchain.agents import create_agentfrom langchain_core.tools import tool# 自定义 LangChain 工具@tooldef calculate(expression: str) -> str:"""计算数学表达式"""return str(eval(expression))# MCP 工具 + 自定义工具混用async with MultiServerMCPClient({"github": {"command": "npx","args": ["-y", "@modelcontextprotocol/server-github"],"transport": "stdio","env": {"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxx"},}}) as client:mcp_tools = client.get_tools() # GitHub MCP 工具all_tools = mcp_tools + [calculate] # 混合工具列表agent = create_agent(model="deepseek:deepseek-chat",tools=all_tools,)result = await agent.ainvoke({"messages": [{"role": "user", "content": "查看 langchain 仓库的 star 数,再算一下它的平方"}]})print(result)
Agent 会自动选择用 GitHub 工具查 star,再用 calculate 工具算平方——MCP 工具和原生工具对 Agent 来说没有区别。
用法 3:MultiServerMCPClient 连接多个 Server
一个 Agent 同时访问文件系统、数据库、GitHub:
from langchain_mcp_adapters.client import MultiServerMCPClientfrom langchain.agents import create_agentserver_config = {"filesystem": {"command": "npx","args": ["-y", "@modelcontextprotocol/server-filesystem", "/data"],"transport": "stdio",},"postgres": {"command": "npx","args": ["-y", "@modelcontextprotocol/server-postgres","postgresql://user:pass@localhost/mydb"],"transport": "stdio",},"github": {"command": "npx","args": ["-y", "@modelcontextprotocol/server-github"],"transport": "stdio","env": {"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxx"},},}async with MultiServerMCPClient(server_config) as client:# 自动汇聚三个 Server 的所有工具all_tools = client.get_tools()print(f"可用工具: {[t.name for t in all_tools]}")agent = create_agent(model="deepseek:deepseek-chat",tools=all_tools,)result = await agent.ainvoke({"messages": [{"role": "user","content": "从 GitHub 读取 config.json,写入数据库的 config 表"}]})
三个 Server 的工具自动汇聚,Agent 跨 Server 编排——读文件、查数据库、操作 GitHub,一条指令搞定。
用法 4:自己写一个 MCP Server
用 MCP Python SDK 暴露自定义能力:
# server.py —— 一个简单的待办事项 MCP Serverfrom mcp.server.fastmcp import FastMCPmcp = FastMCP("todo-server")# 用内存存储(演示用)todos: dict[int, dict] = {}_next_id = 1@mcp.tool()def add_todo(title: str, priority: str = "medium") -> str:"""添加一条待办事项"""global _next_idtodos[_next_id] = {"title": title, "priority": priority, "done": False}_next_id += 1return f"已添加: [{priority}] {title} (id={_next_id - 1})"@mcp.tool()def list_todos() -> str:"""列出所有待办事项"""if not todos:return "暂无待办事项"lines = []for tid, t in todos.items():status = "DONE" if t["done"] else "TODO"lines.append(f" {status} [{t['priority']}] {t['title']} (id={tid})")return "\n".join(lines)@mcp.tool()def complete_todo(todo_id: int) -> str:"""将待办事项标记为已完成"""if todo_id not in todos:return f"未找到 id={todo_id} 的待办事项"todos[todo_id]["done"] = Truereturn f"已完成: {todos[todo_id]['title']}"if __name__ == "__main__":mcp.run() # 默认 stdio 传输
然后在 LangChain 中连接:
from langchain_mcp_adapters.client import MultiServerMCPClientfrom langchain.agents import create_agentasync with MultiServerMCPClient({"todo": {"command": "python","args": ["server.py"],"transport": "stdio",}}) as client:agent = create_agent(model="deepseek:deepseek-chat",tools=client.get_tools(),)result = await agent.ainvoke({"messages": [{"role": "user","content": "帮我添加一个高优先级待办:写 MCP 教程,然后列出所有待办"}]})print(result)
自己写的 Server 和社区 Server 对 Agent 来说完全一样——这就是协议标准化的威力。
四、原理:MCP 的协议设计与转换机制
1. MCP 三大原语
MCP Server 通过三种原语暴露能力:
原语 | 作用 | 类比 |
|---|---|---|
| Tools | 可被模型调用的函数 | HTTP POST —— 执行操作,有副作用 |
| Resources | 可被读取的数据/文件 | HTTP GET —— 读取信息,无副作用 |
| Prompts | 预定义的提示词模板 | 书签 —— 快速加载常用 prompt |
最常用的是Tools——这也是 LangChain 适配器主要转换的部分。Resources 提供结构化数据(如数据库 Schema),Prompts 提供领域模板(如"代码审查"模板)。
2. 传输层:三种方式
传输方式 | 场景 | 特点 |
|---|---|---|
| stdio | 本地进程通信 | 最简单,Client 启动 Server 子进程,通过 stdin/stdout 通信 |
| SSE | 远程 HTTP 服务 | Server-Sent Events,适合已有 HTTP 基础设施 |
| Streamable HTTP | 新一代远程通信 | MCP 2025-03 规范引入,支持双向流、无状态部署 |
本地开发用 stdio 最方便——不需要起服务,Client 自动拉起 Server 进程。生产部署用 HTTP 传输,Server 独立部署、水平扩展。
3. Client-Server 模型
+-------------+ +-------------+ +-------------+| LLM | | MCP Client | | MCP Server || (LangChain)|---->| (适配层) |---->| (工具/数据) |+-------------+ +-------------+ +-------------+1. Agent 调用 2. 协议转换 3. 执行并返回LangChain Tool JSON-RPC 工具结果
流程:
Agent 看到的是 LangChain Tool,正常调用
MCP Client 把 Tool 调用翻译成 JSON-RPC 请求,发送给 Server
Server 执行操作,返回结果
Client 把结果包装成 LangChain ToolMessage,返回给 Agent
Agent 完全不知道背后是 MCP——它只看到 LangChain Tool。
4. 与 LangChain Tools 的转换关系
langchain-mcp-adapters做的核心事情:
MCP Tool Schema LangChain Tool Schema------------------- ---------------------{ @tool def xxx(...):"name": "add_todo", -> """添加待办事项""""description": "...", def add_todo(title: str, ...):"inputSchema": { ..."type": "object","properties": {...}}}
转换规则:
name → 函数名description → 工具 docstring(模型靠这个判断何时调用)inputSchema → 函数参数(Pydantic 模型)调用时的参数 → JSON-RPC 请求的
params.arguments
反过来也可以:LangChain Tool 可以包装成 MCP Server 暴露出去——让其他 MCP Client 也能用你的工具。
5. 动态发现机制
MCP Client 连接 Server 后,第一步是discovery(发现):
Client ----"tools/list"----> Server Client <---[{name, description, inputSchema}, ...]--- Server不需要硬编码工具列表——Client 运行时自动发现 Server 提供了哪些工具。这意味着:
Server 升级加了新工具,Client 自动感知
不同 Server 可以提供同名工具(Client 负责消歧)
按需连接,不用时断开
小结
视角 | 一句话 |
|---|---|
概念 | Anthropic 推出的开放协议,定义 LLM 应用与工具/数据源的标准通信接口——AI 时代的 USB-C |
价值 | 把集成成本从 NxM 降到 N+M,一次实现生态复用,跨厂商兼容,与 Function Calling 互补 |
用法 | langchain-mcp-adapters 连接已有 Server;MCP Tools 混入 create_agent;MultiServerMCPClient 聚合多 Server;FastMCP 自建 Server |
原理 | 三大原语(Tools/Resources/Prompts);三种传输(stdio/SSE/HTTP);Client-Server 模型自动发现;MCP Tool <-> LangChain Tool 双向转换 |
记住一件事:MCP 的核心原则是"用标准协议替代碎片集成"——就像 USB-C 统一了充电接口,MCP 统一了 AI 工具接口,让一次实现成为生态资产。
系列完结:高阶模式
三篇走完,LangChain 的"高阶模式"体系就位了:
# | 概念 | 角色 |
|---|---|---|
1 | Multi-agent | 协作——多个 Agent 分工协同 |
2 | 垂类 Agent | 专精——领域知识 + 专用工具链 |
3 | MCP | 连接——标准协议打通工具生态 |
Multi-agent 解决"谁来做",垂类 Agent 解决"做得专",MCP 解决"用什么"——三者协同,Agent 才能从玩具走向生产。