写点什么

AI 智能体 - 模型上下文协议

作者:Hernon AI
  • 2025-12-02
    浙江
  • 本文字数:7189 字

    阅读完需:约 24 分钟

AI 智能体 - 模型上下文协议

📖 引言:从“孤岛”到“互联”

在 AI 智能体(AI Agents)爆发的前夜,我们面临着一个巨大的互操作性危机


每一家公司、每一个开发者都在构建自己的智能体。有的智能体能查天气,有的能写代码,有的能操作数据库。但问题是,这些智能体就像一个个孤岛,彼此之间无法沟通,也无法复用。如果你想让一个 ChatGPT 智能体去访问你的 Google Drive,你需要写一套专用的插件;如果你想让 Claude 智能体做同样的事,你又得写另一套。


为了连接 N 个模型和 M 个数据源,我们需要维护 个集成接口。这是一场工程噩梦。


模型上下文协议 (MCP) 的出现,就是为了终结这场噩梦。它由 Anthropic 在 2024 年底开源,迅速成为行业事实标准。MCP 旨在成为 AI 时代的 USB 协议——通过一个标准化的接口,让任何大模型都能即插即用地连接任何数据源和工具。


本篇将带你深入 MCP 的内核,解构其客户端-服务器架构,剖析它与传统 Function Calling 的本质区别,并手把手教你使用 FastMCPLangChain 构建企业级的 MCP 服务。



第一部分:MCP 协议的架构哲学

1.1 核心定义:AI 的 USB 接口

MCP 是一个开放标准,它规范了 AI 模型(客户端)与外部数据/工具(服务器)之间的通信方式。


  • 没有 MCP 的世界:你需要为 OpenAI 写一个 WeatherPlugin,为 Gemini 写一个 WeatherTool,为 LangChain 写一个 WeatherTool。代码重复,维护困难。

  • 有 MCP 的世界:你只需要写一个标准的 MCP Weather Server。OpenAI、Claude、Gemini、LangChain 都可以直接连接这个服务器,自动发现并使用其中的工具。

1.2 架构三要素:资源、提示词、工具

MCP 将外部世界的能力抽象为三个核心概念:


  1. 资源 (Resources)

  2. 定义:类似于文件或数据库记录的被动数据

  3. 例子:日志文件、API 文档、数据库中的一张表。

  4. 交互:客户端可以“读取”资源,也可以订阅资源的更新(实时数据流)。

  5. URI:每个资源都有唯一的 URI,例如 xxx://xxx/x

  6. 提示词 (Prompts)

  7. 定义:预定义的、可复用的交互模板

  8. 例子:一个“代码审查”提示词,它自动加载当前 Git 仓库的 diff 作为上下文。

  9. 价值:将复杂的 Prompt Engineering 封装在服务器端,客户端只需调用 get_prompt("code_review")

  10. 工具 (Tools)

  11. 定义:可执行的函数或操作

  12. 例子send_emailexecute_sqlresize_image

  13. 交互:客户端发送参数(JSON),服务器执行逻辑并返回结果。这是最接近传统 Function Calling 的部分。

1.3 客户端-主机-服务器模型

MCP 的运行架构通常包含三个角色:


  • MCP Host (主机):这是运行 AI 模型的应用程序(如 Claude Desktop App、Cursor IDE、或你自己写的 LangChain 应用)。它负责发起连接。

  • MCP Client (客户端):Host 内部用于与 Server 通信的协议实现层(1:1 对应)。

  • MCP Server (服务器):提供数据和工具的独立进程。它可以运行在本地(Stdio 传输),也可以运行在远程(SSE/HTTP 传输)。



第二部分:MCP vs. 传统 Function Calling

很多开发者会问:“我已经会写 LangChain Tools 了,为什么还要学 MCP?”



比喻


  • Function Calling 就像是你随身携带的瑞士军刀。方便,但你得一直带着它。

  • MCP 就像是墙上的电源插座。你不需要随身带发电机,到了任何有插座的地方,插上就能用电。



第三部分:实战 FastMCP —— 极速构建服务器

FastMCP 是一个由社区驱动的 Python 框架(类似 FastAPI),专门用于简化 MCP Server 的开发。它利用 Python 的类型注解自动生成协议所需的 Schema。

3.1 环境准备

pip install fastmcp
复制代码

3.2 场景一:构建一个“系统运维” MCP 服务器

假设我们需要一个 MCP 服务器,它能提供服务器的实时日志(资源),并允许执行重启服务的操作(工具)。


from fastmcp import FastMCP, Contextimport subprocessimport os
# 初始化 Server# dependencies 参数允许你声明该 Server 运行所需的依赖,FastMCP 会自动管理环境mcp = FastMCP("DevOps Server", dependencies=["psutil"])
# --- 1. 定义资源 (Resources) ---# 资源通常是只读的数据流@mcp.resource("system://logs/{service_name}")def get_service_logs(service_name: str) -> str: """获取指定服务的最近 50 行日志""" log_path = f"/var/log/{service_name}.log" if not os.path.exists(log_path): return "Log file not found." # 模拟读取日志 try: # 在真实场景中,这里可能是 tail -n 50 with open(log_path, "r") as f: lines = f.readlines()[-50:] return "".join(lines) except Exception as e: return f"Error reading logs: {str(e)}"
# --- 2. 定义工具 (Tools) ---# 工具是可以改变系统状态的操作@mcp.tool()def restart_service(service_name: str, force: bool = False) -> str: """ 重启指定的系统服务。 Args: service_name: 服务名称 (如 nginx, postgresql) force: 是否强制重启 (kill -9) """ # 简单的安全检查(在真实 MCP 中,可以在 Client 端做鉴权) allowed_services = ["nginx", "app_worker"] if service_name not in allowed_services: return f"Error: Service '{service_name}' is not allowed to be managed via MCP."
cmd = ["systemctl", "restart", service_name] if force: # 仅作演示,实际生产中需谨慎 pass try: # 执行命令 result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode == 0: return f"Service '{service_name}' restarted successfully." else: return f"Failed to restart: {result.stderr}" except Exception as e: return f"Execution error: {str(e)}"
# --- 3. 定义提示词 (Prompts) ---# 预定义的交互模板,帮助 LLM 更好地使用这些工具@mcp.prompt("diagnose_error")def diagnose_prompt(service_name: str) -> str: """生成用于诊断服务错误的 Prompt""" return f""" 请作为一名资深运维工程师,分析以下服务的状态。 1. 首先,使用 `get_service_logs` 读取资源 `xxx://logs/{service_name}`。 2. 分析日志中的 ERROR 或 WARNING 信息。 3. 如果认为是临时故障,调用 `restart_service` 工具。 4. 如果是配置错误,请给出修改建议。 """
if __name__ == "__main__": # 启动服务器(默认使用 Stdio 模式,适合本地 CLI 集成) mcp.run()
复制代码

3.3 运行与调试

FastMCP 提供了一个内置的 Inspector(调试器),这是开发 MCP Server 的神器。


# 在终端运行fastmcp inspect my_server.py
复制代码


这将启动一个 Web 界面,你可以在里面:


  1. 查看服务器暴露的所有 Resources, Prompts 和 Tools。

  2. 模拟 LLM 调用这些工具,查看返回值。

  3. 查看 JSON-RPC 协议的通信日志。



第四部分:在 LangChain 中集成 MCP

虽然 Claude Desktop App 原生支持 MCP,但作为开发者,我们更关心如何在自己的 Python 代码(LangChain/LangGraph 应用)中连接这些 MCP Server。


LangChain v0.3 中,官方提供了 langchain-mcp-adapters(或者社区实现),但核心逻辑其实是通用的:将 MCP Client 包装为 LangChain Tools

4.1 架构设计

  1. MCP Client:负责与 MCP Server 建立连接(Stdio 或 SSE)。

  2. 适配器 (Adapter)

  3. 调用 client.list_tools() 获取工具列表。

  4. 将每个 MCP Tool 转换为 langchain_core.tools.StructuredTool

  5. 将 MCP Resources 转换为 LangChain 的 RetrieverDocumentLoader

4.2 实战代码:构建通用 MCP 连接器

以下是一个基于 langchainmcp 官方 SDK 的通用连接器实现。


环境准备


pip install mcp langchain-openai langgraph
复制代码


核心代码实现


import asynciofrom contextlib import AsyncExitStackfrom typing import List
from langchain_core.tools import StructuredToolfrom langchain_openai import ChatOpenAIfrom langgraph.prebuilt import create_react_agent
# MCP 官方 SDKfrom mcp import ClientSession, StdioServerParametersfrom mcp.client.stdio import stdio_client
class LangChainMCPClient: """ 一个通用的适配器,将 MCP Server 转换为 LangChain 可用的组件。 """ def __init__(self, command: str, args: List[str]): self.params = StdioServerParameters(command=command, args=args) self.session: ClientSession | None = None self.exit_stack = AsyncExitStack()
async def connect(self): """建立与 MCP Server 的连接""" # 启动子进程并建立通信通道 read, write = await self.exit_stack.enter_async_context(stdio_client(self.params)) self.session = await self.exit_stack.enter_async_context( ClientSession(read, write) ) await self.session.initialize() # 发现工具 tools_list = await self.session.list_tools() print(f"🔗 Connected to MCP Server. Found {len(tools_list.tools)} tools.") return tools_list
async def get_langchain_tools(self) -> List[StructuredTool]: """将 MCP Tools 转换为 LangChain Tools""" if not self.session: await self.connect() mcp_tools = (await self.session.list_tools()).tools langchain_tools = []
for tool in mcp_tools: # 闭包捕获 tool.name async def _tool_wrapper( tool_name=tool.name, **kwargs ): # 实际调用 MCP Server result = await self.session.call_tool(tool_name, arguments=kwargs) # MCP 返回的是 Content 列表,通常我们要提取文本 return result.content[0].text
# 构建 LangChain Tool lc_tool = StructuredTool.from_function( func=None, coroutine=_tool_wrapper, # 使用异步调用 name=tool.name, description=tool.description, # MCP 的 inputSchema 是 JSON Schema,LangChain 可以直接用(或稍作转换) # 这里为了简化,我们依赖 LangChain 的自动推断,或者你需要手动转换 Pydantic ) langchain_tools.append(lc_tool) return langchain_tools
async def cleanup(self): await self.exit_stack.aclose()
# --- 业务逻辑 ---
async def main(): # 假设我们有一个运行 SQLite 的 MCP Server # (你可以使用官方的 @modelcontextprotocol/server-sqlite) # 这里我们连接到一个本地运行的 Python MCP Server client = LangChainMCPClient( command="python", args=["my_devops_server.py"] # 上一节写的 Server )
try: # 1. 获取工具 tools = await client.get_langchain_tools() # 2. 初始化 LLM llm = ChatOpenAI(model="gpt-4o", temperature=0) # 3. 构建 LangGraph Agent (ReAct 模式) agent_executor = create_react_agent(llm, tools) # 4. 执行任务 print("\n🤖 Agent 启动...") query = "请检查 nginx 服务的日志,如果发现错误,请帮我重启它。" # Stream 模式查看执行过程 async for event in agent_executor.astream( {"messages": [("user", query)]} ): for value in event.values(): print("--- Step ---") print(value["messages"][-1].content) finally: await client.cleanup()
if __name__ == "__main__": asyncio.run(main())
复制代码


代码解析


  1. stdio_client:这是 MCP 的核心传输层。它启动子进程(你的 Python Server),并通过标准输入输出(Stdin/Stdout)进行 JSON-RPC 通信。

  2. list_tools:客户端向服务器发送握手请求,获取工具清单(Schema)。

  3. 适配层:我们动态创建了 Python 函数 _tool_wrapper,它内部调用 session.call_tool。这样 LangChain 就会认为这只是一个普通的 Async Tool。

  4. create_react_agent:LangGraph 的预构建 Agent,它能够理解 Tools 的描述,规划调用顺序(先查日志 -> 分析 -> 重启),这正是第十篇的核心应用。



第五部分:Google ADK 的 MCP 原生支持

Google 的 ADK 对 MCP 的支持更加原生和开箱即用。它提供了一个 MCPToolset 类,封装了上述的所有连接逻辑。

5.1 实战:ADK 连接文件系统 MCP

假设你想让 Gemini 智能体能够读写你电脑上的文件。你可以使用官方的 filesystem MCP Server(Node.js 实现)。


import osfrom google.adk.agents import LlmAgentfrom google.adk.tools.mcp_tool.mcp_toolset import MCPToolset, StdioServerParameters
# 1. 准备目标目录TARGET_DIR = os.path.abspath("./workspace")os.makedirs(TARGET_DIR, exist_ok=True)
# 2. 定义智能体agent = LlmAgent( model='gemini-2.0-flash', name='FileAssistant', instruction=f'你是一个文件管理助手。你可以读写 {TARGET_DIR} 目录下的文件。', # 3. 注入 MCP 工具集 tools=[ MCPToolset( connection_params=StdioServerParameters( # 使用 npx 运行社区提供的 MCP Server command='npx', args=[ "-y", "@modelcontextprotocol/server-filesystem", TARGET_DIR ], ), # 可选:权限控制,只暴露读接口,隐藏写接口 # tool_filter=['list_directory', 'read_file'] ) ])
# 注意:ADK 会自动处理 Server 的启动、保活和关闭
复制代码

5.2 进阶:远程 HTTP 连接 (SSE)

除了本地进程(Stdio),MCP 还支持远程连接(Server-Sent Events, SSE)。这对于分布式系统非常有用。


from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset, HttpServerParameters
remote_tools = MCPToolset( connection_params=HttpServerParameters( url="http://mcp-database-service.internal:8000/sse" ))
复制代码



第六部分:企业级 MCP 架构设计模式

在企业内部落地 MCP 时,不仅仅是写几个 Tool 那么简单。我们需要考虑整体架构。

6.1 模式一:Sidecar 模式 (Local Stdio)

  • 架构:每个 Agent 实例启动时,作为子进程拉起所需的 MCP Server。

  • 适用:本地文件操作、Git 操作、单机数据分析。

  • 优点:低延迟,安全(Server 只对当前 Agent 可见)。

  • 缺点:资源消耗大(每个 Agent 都要起一套 Server),无法共享状态。

6.2 模式二:Gateway 模式 (Remote HTTP/SSE)

  • 架构:部署一个中心化的 MCP Gateway 集群。所有 Agent 通过 HTTP 连接到 Gateway。

  • 适用:企业知识库(RAG)、核心数据库操作、昂贵的 API 代理。

  • 优点:资源共享(连接池复用)、统一鉴权、日志审计。

  • 缺点:网络延迟,增加了中心化故障点。

6.3 模式三:Agent as a Server (递归 MCP)

这是一个非常有趣的高级模式。


  • 概念:一个构建好的 Agent 本身,也可以通过 MCP 协议暴露出去,变成另一个 Agent 的“工具”。

  • 场景

  • 你构建了一个复杂的“法律顾问 Agent”(包含 RAG、推理、反思)。

  • 你可以用 FastMCP 把它包装成一个 Server。

  • 外部的“总助 Agent”连接这个 Server,把它当作一个 consult_lawyer() 工具来调用。

  • 实现:FastMCP 支持直接将 LangGraph 应用注册为 Tool。


# 伪代码示例@mcp.tool()async def consult_legal_department(query: str) -> str:    """咨询法律部门(这是一个子智能体)"""    # 内部调用 LangGraph Agent    response = await legal_agent.ainvoke({"messages": [query]})    return response["messages"][-1].content
复制代码



结语:互联互通的 AI 生态

模型上下文协议 (MCP) 不仅仅是一个技术标准,它是一种生态宣言


  • 对于工具开发者(如 Linear, Notion, Stripe):只需维护一套 MCP Server,就能接入所有 AI 模型。

  • 对于模型开发者(如 Anthropic, Google):只需支持 MCP Client,就能立刻拥有海量的外部能力。

  • 对于应用开发者(我们):可以像搭积木一样,自由组合最好的模型和最好的数据源。


随着 MCP 生态的成熟,未来的 AI 应用开发将不再是编写一个个孤立的 Bot,而是编排一个由无数 MCP Server 组成的庞大协作网络。


这就是 AI 的“万物互联”时代。

参考资料

因为 InfoQ 平台风控机制会导致有些文章莫名其妙的被吞下架,后续主要在 CSDN 平台更新,可以去 CSDN 搜索同名 Hernon

1.Model Context Protocol (MCP) Documentation. (Latest). Model Context Protocol (MCP). https://google.github.io/adk-docs/mcp/

2.FastMCP Documentation. FastMCP. https://github.com/jlowin/fastmcp

3.MCP Tools for Genmedia Services. MCP Tools for Genmedia Services. https://google.github.io/adk-docs/mcp/#mcp-servers-for-google-cloud-genmedia

4.MCP Toolbox for Databases Documentation. (Latest). MCP Toolbox for Databases. https://google.github.io/adk-docs/mcp/databases/

发布于: 2025-12-02阅读数: 3
用户头像

Hernon AI

关注

创意心中美好世界 2020-08-19 加入

AI爱好者

评论

发布
暂无评论
AI 智能体 - 模型上下文协议_AI智能体_Hernon AI_InfoQ写作社区