目录
一、什么是MCP
🔌 它解决什么问题?
🏗️ 核心架构
🧰 Server 能提供什么?
⚠️ 为什么安全圈关注 MCP?
💭 一句话总结
二、MCP的官方
🏛️ 当前官方治理机构:Linux 基金会下的 AAIF
📜 最初的发起者:Anthropic
💭 对做AI Agent 的启示
三、MCP生态
🧱 官方 SDK(构建 MCP 的基础)
🚀 支持 MCP 的主流 AI 框架(消费 MCP 的上层)
📦 官方参考 Server(拿来即用的 MCP 服务)
🔌 面向特定框架的封装
四、讲解FastMCP
🧱 它是什么,谁做的
🖥️ 第一步:服务端 —— 定义工具并启动 HTTP 服务
💻 第二步:客户端 —— 通过 HTTP 调用
📋 预期输出
🔍 关键点说明
五、谁来决定调用哪个函数
🎯 核心区分:谁来做“决定调用哪个工具”这件事
🔗 两者的衔接方式
💭 比如我们有一个“医学 Agent ”的选型
一、什么是MCP
MCP 的全称是Model Context Protocol(模型上下文协议),由 Anthropic 在 2024 年底开源。你可以把它理解成AI 模型和外部工具/数据之间的“USB 接口”。
🔌 它解决什么问题?
在 MCP 之前,每个 AI 应用要接一个工具(比如查数据库、读文件、调 API),都得单独写一套适配代码。M 个模型接 N 个工具,就要写 M×N 套集成,非常麻烦。
MCP 的思路是标准化:模型这边统一用 MCP 客户端,工具那边统一用 MCP 服务器,两边都按同一套协议说话。这样 M 个模型接 N 个工具,只需要 M+N 套实现。
🏗️ 核心架构
MCP 采用客户端-服务器模式:
MCP Host:运行 AI 应用的环境,比如 Claude Desktop、你的 Agent 平台
MCP Client:Host 内部的连接器,负责和 Server 通信
MCP Server:对外暴露工具、资源、提示词的服务方
一个 Host 可以同时连多个 Server,每个 Server 提供不同的能力。
🧰 Server 能提供什么?
MCP Server 通常暴露三类东西:
Tools(工具):可执行的操作,比如查天气、发邮件、执行 SQL
Resources(资源):可读取的数据,比如文件内容、数据库记录
Prompts(提示词):预定义的提示模板,帮用户完成特定任务
⚠️ 为什么安全圈关注 MCP?
AI安全相关的产品把MCP 协议专项风险单独列为一个检测维度,原因就在这里:
工具投毒:恶意逻辑藏在正常的工具描述里,诱导 Agent 选择它
间接注入:工具返回的内容里夹带指令,操纵 Agent 后续行为
链式泄露:多个合法工具被组合使用,形成数据外泄路径
凭证暴露:MCP 配置文件里明文存放 API Key
有研究对 15 个 MCP Server 做渗透测试,发现87% 存在至少一个严重漏洞,34% 可被完全接管。
💭 一句话总结
MCP 是让 AI 模型标准化接入外部工具的协议,相当于 AI 世界的“USB-C”。它极大降低了集成成本,但也因为工具调用链的复杂性,成了 Agent 安全的新攻击面。
二、MCP的官方
MCP 的“官方”身份,需要分两个阶段来看:它由 Anthropic 发起,但目前已经归属于一个中立的基金会来管理。
🏛️ 当前官方治理机构:Linux 基金会下的 AAIF
2025 年 12 月,Anthropic 宣布将 MCP 捐赠给了Agentic AI Foundation (AAIF)。这个基金会是Linux 基金会旗下的一个定向基金,由 Anthropic、OpenAI 和 Block 共同创立,并获得了 Google、Microsoft、AWS 等公司的支持。
所以,MCP 现在的官方归属是 AAIF。这个安排是为了确保 MCP 保持开放、中立和社区驱动,避免被任何单一公司控制,类似 Kubernetes 或 PyTorch 的治理模式。
📜 最初的发起者:Anthropic
MCP 协议是由Anthropic在 2024 年 11 月首次提出并开源的。Anthropic 是 Claude 系列模型的开发公司,他们希望用 MCP 来标准化 AI 模型与外部工具/数据源的连接方式,因此常被称为 AI 时代的“USB-C 接口”。
💭 对做AI Agent 的启示
虽然 MCP 已经交由中立基金会管理,但 Anthropic 仍然在积极投资和维护它的核心基础设施,并且是社区的主要参与者。
对开发者来说,这意味着:
选型可以放心:MCP 已经渡过了“单一公司控制的早期阶段”,有了一个更稳定、中立的长期治理结构。
规范以官方为准:协议的权威定义在
modelcontextprotocol.io,这是你实现或评估 MCP Server 时的唯一标准来源。生态活跃:目前 MCP 的 SDK 月下载量超过 9700 万次,有上万个活跃的 Server,生态非常繁荣,你找到可复用医学工具的概率也更高。
三、MCP生态
MCP 的生态大致可以分成三层:底层 SDK、上层 AI 框架集成、以及现成的 Server 实现。
🧱 官方 SDK(构建 MCP 的基础)
Anthropic 官方维护了多语言 SDK,按成熟度分为不同层级:
| SDK | 层级 | 说明 |
|---|---|---|
| TypeScript | Tier 1 | 最活跃,Node/Bun/Deno 通用,有 v2 稳定版 |
| Python | Tier 1 | 生态最丰富,FastMCP 是常用封装 |
| C# / Go / Rust / Ruby | Tier 1 | 官方维护,功能完整 |
| Java / Kotlin / PHP / Swift | Tier 2-3 | 部分由社区或合作方维护 |
🚀 支持 MCP 的主流 AI 框架(消费 MCP 的上层)
这些框架让你在构建 Agent 时直接调用 MCP Server:
| 框架 | 语言 | MCP 集成方式 | 特点 |
|---|---|---|---|
| OpenAI Agents SDK | Python | MCPServerStdio/MCPServerSse | 官方支持,与 OpenAI 生态无缝 |
| LangChain / LangGraph | Python | langchain-mcp-adapters | 生态成熟,工具调用链清晰 |
| Mastra | TypeScript | 通过 stdio/SSE 连接 | 适合前后端一体化,24K stars |
| Pydantic-AI | Python | 内置 MCP 支持 | 类型安全,17K stars |
| mcp-use | Python | 专用 MCP 客户端 | 轻量,10K stars |
| Agno / Praison AI / Upsonic | Python | 一行代码接入 | 多 Agent 场景友好 |
📦 官方参考 Server(拿来即用的 MCP 服务)
MCP 官方提供了可直接运行的参考实现:
| Server | 能力 |
|---|---|
| Filesystem | 安全文件操作,可配置访问控制 |
| Git / GitHub / GitLab | 仓库读写、搜索、操作 |
| Fetch | 网页内容抓取与转换 |
| Memory | 基于知识图谱的持久化记忆 |
| PostgreSQL / SQLite / Redis | 数据库只读访问、Schema 检查 |
| Google Drive / Maps | 文件访问、位置服务 |
| Brave Search | 网页与本地搜索 |
这些 Server 用 TypeScript 或 Python 写成,通过npx或uvx就能直接跑起来。
🔌 面向特定框架的封装
还有一些专门为简化 MCP 接入而生的工具:
mcp-fastapi:把现有 FastAPI 路由自动反射成 MCP 工具,无需重写代码
Pythonium:模块化 MCP Server 框架,内置系统操作、文件操作、Web 操作等标准工具库
langchain-mcp-registry:从官方注册表发现 MCP Server 并自动转为 LangChain 工具
四、讲解FastMCP
FastMCP 是当前构建 MCP 应用最主流的 Python 框架,核心价值是把复杂的 MCP 协议细节封装掉,让你只用写普通的 Python 函数。
🧱 它是什么,谁做的
FastMCP 由Prefect 团队开发和维护。它的 1.0 版本在 2024 年被并入官方 MCP Python SDK,但团队随后继续维护独立版本(目前是 FastMCP 2.x/4.x),增加了大量生产级能力。
目前它的生态地位很突出:每天被下载超过一百万次,所有语言中约 70% 的 MCP 服务器都基于 FastMCP 的某个版本构建。
用一个完整的例子来演示:服务端定义一个医学工具,客户端通过 HTTP 调用它。
🖥️ 第一步:服务端 —— 定义工具并启动 HTTP 服务
创建medical_server.py:
from fastmcp import FastMCP # 创建 MCP 服务器实例 mcp = FastMCP("Medical Server") @mcp.tool def check_drug_interaction(drug_a: str, drug_b: str) -> str: """ 检查两种药物之间是否存在相互作用。 返回相互作用描述和风险等级。 """ # 这里模拟一个简单的药物相互作用数据库 interactions = { ("华法林", "阿司匹林"): "高风险:增加出血风险,需密切监测INR", ("二甲双胍", "碘造影剂"): "高风险:可能引起乳酸酸中毒,检查前需停药", ("阿托伐他汀", "克拉霉素"): "中风险:增加肌病风险,考虑调整剂量", } key = (drug_a, drug_b) reverse_key = (drug_b, drug_a) if key in interactions: return interactions[key] elif reverse_key in interactions: return interactions[reverse_key] else: return "未发现已知的药物相互作用" @mcp.tool def get_patient_info(patient_id: str) -> dict: """ 根据患者ID查询基本信息。 返回患者姓名、年龄、过敏史。 """ # 模拟数据,实际应连接医院FHIR系统 patients = { "P001": {"name": "张三", "age": 65, "allergies": ["青霉素"]}, "P002": {"name": "李四", "age": 42, "allergies": []}, } return patients.get(patient_id, {"error": "患者不存在"}) if __name__ == "__main__": # 启动 HTTP 服务,监听 8000 端口 mcp.run(transport="http", host="0.0.0.0", port=8000)启动服务:
python medical_server.py
服务启动后,MCP 端点默认在http://localhost:8000/mcp。
💻 第二步:客户端 —— 通过 HTTP 调用
创建medical_client.py:
import asyncio from fastmcp import Client async def main(): # 连接到 HTTP 服务端 async with Client("http://localhost:8000/mcp") as client: # 1. 发现服务器上有哪些工具 tools = await client.list_tools() print("可用工具:") for tool in tools: print(f" - {tool.name}: {tool.description}") # 2. 调用药物相互作用检查工具 result = await client.call_tool( "check_drug_interaction", {"drug_a": "华法林", "drug_b": "阿司匹林"} ) print(f"\n药物相互作用结果:{result.data}") # 3. 调用患者信息查询工具 patient = await client.call_tool( "get_patient_info", {"patient_id": "P001"} ) print(f"患者信息:{patient.data}") if __name__ == "__main__": asyncio.run(main())运行客户端:
python medical_client.py
📋 预期输出
可用工具: - check_drug_interaction: 检查两种药物之间是否存在相互作用。 - get_patient_info: 根据患者ID查询基本信息。 药物相互作用结果:高风险:增加出血风险,需密切监测INR 患者信息:{'name': '张三', 'age': 65, 'allergies': ['青霉素']}🔍 关键点说明
服务端侧:
@mcp.tool装饰器把普通 Python 函数变成 MCP 工具函数签名和类型注解自动生成工具的参数 Schema
docstring 自动成为工具描述,供客户端发现和理解
mcp.run(transport="http", ...)启动 HTTP 服务
客户端侧:
Client("http://localhost:8000/mcp")自动识别 HTTP 传输async with管理连接生命周期list_tools()发现工具,call_tool()调用工具result.data拿到结构化结果
如果服务端需要认证,客户端加一行:
client = Client("http://localhost:8000/mcp", auth="your-token")这个例子就是医学 Agent 工具层的最小可用原型。实际部署时,服务端连接医院的 FHIR 系统,客户端嵌入到你的 Agent 编排逻辑里,根据用户意图决定调用哪个工具。
五、谁来决定调用哪个函数
这个问题的答案取决于你的架构选择,两种方式都可以,但职责不同。
🎯 核心区分:谁来做“决定调用哪个工具”这件事
方式一:FastMCP Client 自己做(没有 LangChain)
FastMCP Client 本身是一个确定性的编程接口。你写代码显式调用client.call_tool("check_drug_interaction", {...}),调哪个工具、传什么参数,完全由你的代码决定。
如果你想让它“自动决定”,你需要自己写一层逻辑:把你的意图判断(可以用 LLM)和 FastMCP 的list_tools/call_tool组合起来。FastMCP 提供的是工具发现和调用能力,不提供“决策能力”。
方式二:LangChain / LangGraph 做决策,FastMCP 做执行
这是更常见的生产架构。
LangGraph 负责“理解用户意图 → 决定调哪个工具 → 传什么参数”,FastMCP Client 负责“把这个决定执行掉”。
具体分工:
LangGraph:管理对话状态、意图识别、工具选择、多步编排
langchain-mcp-adapters:把 FastMCP Server 暴露的工具转换成 LangChain 的 Tool 对象
FastMCP Client:底层实际连接 MCP Server、执行工具调用
🔗 两者的衔接方式
langchain-mcp-adapters是官方提供的桥接库,核心用法:
from langchain_mcp_adapters.client import MultiServerMCPClient async with MultiServerMCPClient({ "medical": { "url": "http://localhost:8000/mcp", "transport": "http", } }) as client: # 自动把 MCP Server 的工具转成 LangChain Tool tools = await client.get_tools() # tools 里就有 check_drug_interaction 和 get_patient_info拿到tools后,交给 LangGraph 的 Agent:
from langgraph.prebuilt import create_react_agent from langchain_openai import ChatOpenAI model = ChatOpenAI(model="gpt-4") agent = create_react_agent(model, tools) # 用户说"张三吃华法林和阿司匹林有风险吗" # LangGraph 自己决定:先调 get_patient_info 拿过敏史, # 再调 check_drug_interaction 查相互作用 result = await agent.ainvoke({ "messages": [{"role": "user", "content": "张三吃华法林和阿司匹林有风险吗"}] })💭 比如我们有一个“医学 Agent ”的选型
| 场景 | 推荐 |
|---|---|
| 工具调用逻辑固定(比如“查病历”永远调同一个工具) | 纯 FastMCP Client,代码显式调用,确定性高,无 LLM 开销 |
| 需要 LLM 根据自然语言意图动态选工具、多步编排 | LangGraph + langchain-mcp-adapters |
| 需要精细控制工具权限(不同医生角色可调工具集不同) | LangGraph 的 Tool 过滤 + FastMCP 的中间件 |
关键判断:FastMCP 解决的是“怎么连、怎么调”,LangGraph 解决的是“调什么、什么时候调”。医学场景下,如果涉及多轮对话、动态意图、复杂工作流,LangGraph 做决策层 + FastMCP 做执行层是更合理的分工。如果只是简单的“用户点按钮 → 查数据”,纯 FastMCP Client 就够了,不需要引入 LangChain 的复杂度。