一、从一个真实场景说起
假设你在构建一个通用 AI 助理,它需要覆盖外卖点餐、日历管理、邮件处理、数据查询四个领域。
你打开代码,开始注册工具:外卖域 10 个、日历 8 个、邮件 12 个、数据查询 15 个,加上每个域的 prompt 和 skill 文件......
第一周还好。第二周新增一个电商域,你开始在代码库里找该改哪几个文件。第三周有人反馈 Agent 回答质量下降,你意识到上下文里塞了 4 万 token 的工具定义。第四周安全团队告诉你,有几个从网上下载的 skill 文件行为可疑。
这不是极端案例。这是多 Agent 系统规模稍大之后的常态。
二、三个被低估的工程问题
问题 1:工具上下文膨胀
多工具 Agent 系统最直接的问题:所有域的工具定义被一次性注入主 Agent 的上下文。
每个 tool 定义通常消耗数百 token。50 个工具轻松吃掉 3-5 万 token,而用户的实际请求可能只涉及其中 1 个域的 8 个工具。大量无关工具定义占据上下文,推理质量下降,成本上升,这两件事同时发生。
diff
用户:"帮我点个午饭"
主 Agent 的上下文:
- 外卖工具 ×10
- 日历工具 ×8 ← 完全无关
- 邮件工具 ×12 ← 完全无关
- 数据查询工具 ×15 ← 完全无关
= 45 个工具定义,实际用到 10 个
这个问题在 Anthropic 的 Claude Code 开源社区 issue #4476 中有 182 个 upvote,有用户反馈单次对话 MCP 工具定义就消耗了 4 万 token,强需求,官方尚未解决。
问题 2:Agent 定义碎片化,业务方无法主动提供标准化能力
创建一个领域 Agent,通常需要准备三类内容:
- Prompt:角色定义和行为规范
- Tools:可调用的接口能力
- Skills:领域知识、操作指南、业务规则
在现有框架下,这三类内容分散在代码库各处------prompt 在某个字符串变量里,tools 在另一个注册文件里,skill 文件在某个目录下。用户需要自己组装,业务方想主动提供完整的 Agent 能力包,几乎没有标准化的方式。
更麻烦的是:每次接入新领域,都需要修改框架代码,重新注册工具,更新 prompt,调整路由逻辑。
如果麦当劳想为开发者提供一个"标准麦当劳 Agent"------包含它自己维护的点餐流程、菜单查询逻辑、优惠券规则------现在没有一个通用的方式让它发布这个能力,让任何 Agent 框架开箱接入。
问题 3:Skills 来源混乱,安全性和业务适配性难以保证
随着 Agent Skill 生态的兴起(OpenClaw 的社区 skill 市场已有 5700+ 插件),开发者面临新的问题:从哪里获取 skill,质量和安全性如何保证?
Cisco AI 安全研究团队近期测试了一个第三方 OpenClaw skill,发现其在用户无感知的情况下执行了数据外泄和 prompt 注入。skill 仓库缺乏有效审核机制,恶意 skill 可以伪装成普通功能。
更实际的问题是业务适配性:从社区下载的通用 skill 往往和具体业务的逻辑、术语、数据格式不匹配,开发者需要二次修改,反而增加维护成本。
三、一个洞察:MCP Server 本身就是完整的 Agent 定义
解决以上三个问题,我们需要重新看待 MCP(Model Context Protocol)。
一个 MCP Server 天然包含三类信息:
| MCP 能力 | Agent 角色 |
|---|---|
| Prompts | 定义 Agent 的角色和行为规范 |
| Resources | 提供领域知识和 Skills |
| Tools | 暴露可执行的接口能力 |
这意味着,一个 MCP Server 本身就是一个完整的领域 Agent 定义。
IBM 在《MCP Architecture Patterns for Multi-Agent AI Systems》中明确写道:"each MCP server acts as one AI agent"。MCP 2025-11 规范新增的 Sampling with Tools (SEP-1577) 也在协议层面支持了 MCP Server 作为 Agent 执行 multi-step 推理的能力。
这个洞察,直接给出了一种新的 multi-agent 构建方式:MCP 地址即 Agent,配置即接入。
四、解法:MCP Server as Agent
基于上述洞察,我设计了 MCP Server as Agent,核心是一个通用 Plugin 层,动态将 MCP Server 实例化为域 Agent。
架构
核心思路是:每个 MCP Server 被封装为一个标准 LangChain StructuredTool(即 MCPTool) ,主 Agent 的 tools 列表就是 MCPTool 列表。主 Agent 通过 tool 的 description(来自 MCP 的 init prompt)做意图路由,调用 MCPTool 时才 lazy 创建子 Agent。
这个设计让 MCPTool 与任意 LangChain Agent 框架完全兼容------它本质上是一个标准 tool,用户可以把它混入任何现有的 tools 列表,无需迁移现有 Agent 代码。
接入新领域,只需一行配置:
yaml
mcp_servers:
- name: food
url: https://mcp.mcdonalds.cn
- name: calendar
url: https://mcp.calendar-service.com
- name: new_domain # ← 新增领域,仅此两行
url: https://mcp.new-service.com
接入新领域,只需一行配置:
yaml
mcp_servers:
- name: food
url: https://mcp.mcdonalds.cn
- name: calendar
url: https://mcp.calendar-service.com
- name: new_domain # ← 新增领域,仅此两行
url: https://mcp.new-service.com
三个问题的对应解法
问题 1 → 工具上下文隔离:子 Agent 仅加载自己域的 tools,主 Agent 只持有各域能力的轻量摘要。用户说"帮我点外卖",进入上下文的只有外卖域的 10 个工具。
问题 2 → 业务方可以主动发布标准化 Agent:业务方只需部署一个 MCP Server,将自己的 prompt、skill 文件(作为 resources)、tools 一并封装进去。任何接入 MCP Server as Agent 的系统,通过配置 MCP 地址即可获得完整能力。麦当劳、滴滴、美团可以各自维护自己的 MCP Server,开发者不需要了解任何内部细节。
问题 3 → Skills 来自 MCP Server,安全可信:skill 文件由 MCP Server 的业务方直接提供,不经过第三方社区,来源可验证,内容与业务强适配,避免了平台 skill 市场的安全风险。
五、场景演示
以下 demo 基于一个外卖域的 mock MCP Server,用 fastmcp 启动,5 分钟可以本地跑通。
搭建 mock MCP Server(外卖域)
python
# food_agent_server.py
import fastmcp
mcp = fastmcp.FastMCP("food-agent")
@mcp.prompt(name="init")
def init_prompt() -> str:
return "你是一个外卖助手,帮助用户查询菜单、下单。下单前先确认地址和预算。"
@mcp.resource("skill:///ordering-guide", description="外卖点餐标准流程:确认地址 → 查菜单 → 下单")
def ordering_guide() -> str:
return "# 点餐指南\n1. 调用 query_menu 获取菜单\n2. 根据预算筛选\n3. 调用 create_order 下单"
@mcp.tool()
def query_menu(max_price: float = 50.0) -> list[dict]:
"""查询菜单,返回价格在 max_price 以内的套餐"""
return [
{"id": "m1", "name": "麦辣鸡腿堡套餐", "price": 28.9},
{"id": "m2", "name": "双层牛堡套餐", "price": 35.0},
]
@mcp.tool()
def create_order(meal_id: str, address: str) -> dict:
"""创建外卖订单"""
return {"order_id": "ORD_001", "status": "confirmed", "eta": "30分钟"}
if __name__ == "__main__":
mcp.run(transport="streamable-http", host="127.0.0.1", port=8765)
场景 A:MCPTool + 标准 create_agent
MCPTool 是一个标准 StructuredTool,可以直接传给任意 LangChain agent,不改任何现有代码:
python
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from mcp_broker import MCPTool
model = ChatOpenAI(model="deepseek-chat", base_url="https://api.deepseek.com/v1")
# 将 MCP Server 封装为标准 tool,description 自动从 init prompt 读取
tools = [MCPTool.from_mcp("http://127.0.0.1:8765/mcp", model, name="food_agent")]
# 完全标准的 LangChain 用法
agent = create_agent(model, tools=tools)
result = agent.invoke({"messages": [HumanMessage(content="帮我查一下 30 元以内的套餐")]})
print(result["messages"][-1].content)
# → 根据查询结果,30元以内的套餐有:麦辣鸡腿堡套餐(28.9元)...
主 Agent 上下文里只有 food_agent 这一个 tool 的 description(来自 init prompt),而不是外卖域的所有工具定义。进入 food_agent 子 Agent 后,才加载 query_menu、create_order 等工具。
场景 B:MCPAgentLinker 便捷封装(多域)
python
from mcp_broker import MCPAgentLinker
# 传入多个 MCP 地址,主 Agent 自动按意图路由
agent = MCPAgentLinker(
model=model,
mcp_urls=[
"http://mcp.food-service.com/mcp",
"http://mcp.calendar-service.com/mcp",
],
)
result = agent.invoke({
"messages": [HumanMessage(content="查一下今天下午有没有空,有空帮我点个外卖")]
})
子 Agent 之间不直接通信,由主 Agent 编排。
场景 C:业务方发布标准 Agent
某 SaaS 公司想让自己的企业客户在任意 Agent 框架里使用自家的工单系统:
yaml
# 他们只需要部署一个 MCP Server,包含:
Prompts:
- name: init
content: "你是工单助手,负责创建、查询、更新工单..."
Resources:
- uri: skill:///ticket-guide
content: "工单创建规范:优先级定义、SLA 要求..."
Tools:
- create_ticket
- query_ticket
- update_status
接入方在配置里加一行 MCP 地址,自动获得完整的工单 Agent 能力,无需了解内部实现。
六、与现有方案对比
| 方案 | 工具加载 | 新域接入 | Agent 定义 | Skills 来源 |
|---|---|---|---|---|
| LangGraph | 全量加载 | 改代码 | 散落代码库 | 自行管理 |
| CrewAI | 全量加载 | 改代码 | 散落代码库 | 自行管理 |
| AutoGen | 全量加载 | 改 prompt | 散落代码库 | 自行管理 |
| mcp-agent | 按 agent 分配 | 改配置 | 部分标准化 | 自行管理 |
| MCP Server as Agent | 按域隔离 | 加一行配置 | MCP Server 自包含 | 业务方直接提供 |
七、当前进展与开放问题
MCP Server as Agent 目前核心组件已完成并通过集成测试:
MCPLoader:从 MCP Server 读取 prompt / tools / skills,返回结构化的AgentDefMCPTool:将 MCP Server 封装为标准 LangChainStructuredTool,完全兼容create_agent,可混入任意现有 tools 列表MCPAgentLinker:便捷封装,传入 MCP 地址列表直接返回可执行 Agent
其中 MCPTool 是这次设计迭代的核心------相比之前继承 CompiledStateGraph 的方式,MCPTool 不依赖任何框架内部机制,用户可以用完全标准的 LangChain 方式使用它。
还有一些开放问题值得探讨:
- 子 Agent 实例的生命周期管理:复用 vs 每次新建,如何权衡延迟和内存?
- 意图误路由的处理:主 Agent 识别错域时如何优雅降级?
- MCP Resources 作为 Skills 的约定:是否需要推动形成社区规范?
项目地址:mcp-broker
欢迎交流,如果你也在做 MCP 相关的工程,非常想听你的想法。