一、背景痛点
现在开发基于大模型的Agent、RAG系统,工具调用是核心能力,例如个税计算、数据库查询、文件解析、第三方接口封装等业务工具。绝大多数项目初期会把工具函数直接写在Agent主进程内部,这种模式存在几个明显问题:
- 代码耦合严重:工具逻辑和Agent业务逻辑混在同一工程,新增/修改工具需要改动Agent主代码,回归测试范围变大。
- 发布强绑定:修改一个工具,就要重新部署整个Agent服务,小改动也要全量发布。
- 无法复用:多个Agent服务想要使用同一套工具,需要复制多份代码,维护成本高。
- 资源隔离差:部分工具存在CPU、IO密集计算,会抢占Agent主进程资源,影响大模型推理响应速度。
- 传统SSE传输局限:老版SSE仅支持服务端单向流式,负载均衡、代理网关兼容性差,长连接空闲容易被网关切断,生产环境问题较多。
理想架构:工具作为独立MCP服务,独立开发、独立部署,Agent只做大模型推理、规划逻辑,通过Streamable‑HTTP 网络调用外部MCP工具,实现工具能力插拔式接入,不需要修改Agent一行代码,即可新增、下线工具。
MCP(Model Context Protocol)模型上下文协议正是为解决大模型工具调用而生,FastMCP是轻量实现库。Streamable‑HTTP是官方推荐生产传输协议,替代传统SSE,基于标准HTTP实现双向流式通信,对网关、负载均衡、鉴权体系更加友好。
二、MCP插拔式架构设计
2.1 整体架构图逻辑
[Agent/RAG主服务]
↕ Streamable‑HTTP 双向HTTP流式调用
[独立MCP工具服务集群]
├─个税计算MCP服务
├─文件解析MCP服务
└─数据库查询MCP服务
- Agent/RAG主体:只负责大模型对话、思考规划、接收MCP返回结果,不包含任何业务工具实现。
- MCP工具服务:独立进程、独立端口,封装具体业务函数,对外暴露
/mcp标准Streamable‑HTTP端点。 - 通信方式:Streamable‑HTTP,复用标准HTTP,Agent自动发现服务内所有注册的tool,无需手动编写function‑call的schema。
2.2 插拔能力核心特性
- 热插拔新增工具:新增业务只需要开发、部署新MCP服务,Agent配置HTTP地址即可接入,无需修改Agent代码、无需重启Agent进程。
- 独立迭代发布:MCP服务可以单独修改、单独发布,不影响正在运行的Agent/RAG业务。
- 多Agent共享工具:多个智能体应用可以同时连接同一个MCP服务,复用工具逻辑。
- 资源隔离:工具计算消耗在MCP子服务,不会阻塞Agent大模型推理流程。
- 网关友好:Streamable‑HTTP走标准HTTP协议,天然适配Nginx、Ingress、鉴权中间件、负载均衡组件,解决传统SSE长连接被网关切断问题。
2.3 Streamable‑HTTP vs 传统SSE对比
| 传输方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Streamable‑HTTP | 标准HTTP双向流,网关/代理友好;支持会话管理、自动重连;支持鉴权Header;官方生产首选 | 相比stdio多一层网络开销 | 生产分布式Agent/RAG项目(本文采用) |
| Legacy SSE | 简单长流实现 | 单向流式,网关容易掐断空闲连接,生产坑多 | 历史项目兼容,新项目不推荐 |
| Stdio | 无网络开销,本地调用 | 只能单机子进程调用,不能跨机器部署 | 本地Demo测试 |
三、最简实战:实现个税计算MCP可插拔服务(Streamable‑HTTP)
业务场景:Agent需要具备劳务报酬个税预扣预缴计算能力。我们不把计算函数写在Agent内部,而是封装为独立MCP服务,Agent通过Streamable‑HTTP远程调用。
3.1 依赖安装
pip install fastmcp uvicorn
3.2 MCP服务端代码(mcp_tax_server.py)
简化版本,去掉内部复杂业务组件,保留MCP核心能力,可以直接运行测试,transport使用
http即启用Streamable‑HTTP模式,默认暴露端点[http://127.0.0.1:9341/mcp](http://127.0.0.1:9341/mcp)。
"""
个税计算MCP工具服务,独立进程,Streamable‑HTTP对外提供工具调用
端点地址:[http://127.0.0.1:9341/mcp](http://127.0.0.1:9341/mcp)
"""
from fastmcp import FastMCP
import json
# 实例化MCP服务
mcp = FastMCP("tax_mcp_service")
def calc_labor_tax(income: float) -> dict:
"""劳务报酬预扣预缴计算简化逻辑"""
if income <= 0:
return {"income": income, "taxable":0, "tax":0, "after_tax":income, "rate":"0%"}
if income <= 4000:
taxable = income - 800
else:
taxable = income * 0.8
taxable = max(taxable, 0)
if taxable <=20000:
tax = taxable * 0.2
rate = "20%"
elif taxable <=50000:
tax = taxable *0.3 -2000
rate = "30%(速算扣除2000)"
else:
tax = taxable *0.4 -7000
rate = "40%(速算扣除7000)"
tax = max(tax,0)
after_tax = income - tax
return {
"income":round(income,2),
"taxable":round(taxable,2),
"tax":round(tax,2),
"after_tax":round(after_tax,2),
"rate":rate
}
# 将普通函数注册为MCP可远程调用工具
@mcp.tool
def calculate_labor_tax(income: float) -> str:
"""
根据劳务税前收入计算劳务报酬预扣预缴个税
:param income: 税前劳务收入,单位元
:return: json字符串,包含应纳税所得额、预扣税额、税后收入等
"""
return json.dumps(calc_labor_tax(income), ensure_ascii=False)
@mcp.tool
def get_tax_rule() -> str:
"""获取劳务报酬个税预扣预缴规则说明"""
rule_text = """
劳务报酬预扣预缴规则:
1.收入≤4000:减除800元费用;
2.收入>4000:减除20%费用;
3.应纳税所得额≤2万,预扣率20%;
4.2万<应纳税所得额≤5万,预扣率30%,速算扣除2000;
5.应纳税所得额>5万,预扣率40%,速算扣除7000。
"""
return rule_text
if __name__ == "__main__":
# transport="http" 启用 Streamable‑HTTP,默认访问路径 /mcp
print("MCP个税工具服务(Streamable‑HTTP)启动,端口:9341,端点:/mcp")
mcp.run(transport="http", host="0.0.0.0", port=9341)
运行服务:
python mcp_tax_server.py
此时MCP服务启动,Streamable‑HTTP访问地址:[http://127.0.0.1:9341/mcp](http://127.0.0.1:9341/mcp),对外暴露两个工具:calculate_labor_tax、get_tax_rule。
也可以导出ASGI对象交给uvicorn部署(生产容器推荐方式):
app = mcp.streamable_http_app() # 命令行:uvicorn mcp_tax_server:app --host 0.0.0.0 --port 9341
3.3 Agent/RAG客户端接入(插拔关键)
Agent不需要实现个税任何计算逻辑,只需要填入Streamable‑HTTP的url地址即可自动拉取全部工具定义并调用。FastMCP内部自动使用StreamableHttpTransport,无需手动指定传输类。伪代码示例(agent_client.py):
import asyncio
from fastmcp import Client
async def agent_run():
# 接入外部MCP服务,仅仅配置Streamable‑HTTP端点完成插拔
client = Client("[http://127.0.0.1:9341/mcp](http://127.0.0.1:9341/mcp)")
async with client:
# 直接调用远程MCP工具,就像调用本地函数
resp = await client.call_tool("calculate_labor_tax", {"income":10000})
print("个税计算返回:", resp.content)
if __name__ == "__main__":
asyncio.run(agent_run())
插拔效果演示
- 想新增能力:开发新MCP服务,例如文件解析服务,启动之后Agent只需要增加一行Client连接配置,立刻拥有文件解析工具,不需要修改Agent内部业务代码,不需要重启Agent进程(视客户端实现)。
- 想下线工具:停止对应MCP服务即可,Agent感知工具不可用;
- 更新个税计算逻辑:修改mcp_tax_server.py,单独重启MCP服务,Agent完全不用改动。
四、生产落地关键要点
4.1 日志与链路追踪
MCP作为独立服务,一定要埋点独立日志、TraceID,每个工具调用记录入参、返回值、耗时,便于排查线上问题。参考示例源码中,生产环境会接入日志组件、trace转发,把工具调用链路和Agent主链路打通,完整还原一次对话全流程。
4.2 部署方式
- 开发环境:本地直接启动MCP脚本;
- 生产环境:导出
streamable_http_app()ASGI对象,配合uvicorn容器化部署;每个MCP工具服务一个独立Docker镜像,可以单独扩缩容; - 网络:Agent与MCP服务内网互通,
/mcp端点内网暴露,不对外网开放;可前置Nginx/Ingress做鉴权、限流。
4.3 鉴权与参数校验
- Streamable‑HTTP支持自定义请求Header,可传入
Authorization: Bearer xxx做接口鉴权; - MCP服务端必须做参数合法性校验,不要信任Agent传入参数,防止恶意入参;敏感操作在MCP服务层增加权限拦截。
4.4 长耗时任务处理
Streamable‑HTTP内置轮询恢复机制,当工具执行耗时很长,网关空闲切断连接,客户端会自动重连继续接收结果,解决传统SSE长连接被代理掐断的痛点,适合执行数据库查询、文件处理等慢任务。
4.5 与传统Function‑Call对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 工具硬编码Agent内部 | 调用简单,无网络开销 | 耦合高,发布绑定,不可插拔 | 简单Demo,工具很少的玩具项目 |
| MCP‑Streamable‑HTTP独立服务 | 解耦、插拔、独立发布、资源隔离;网关代理友好,支持鉴权 | 增加一层网络调用 | 生产级Agent/RAG,工具多、迭代频繁项目 |
五、适用业务场景总结
- 企业内部Agent平台,多智能体需要复用同一批业务工具;
- 工具逻辑复杂、CPU/IO密集,需要和推理服务做资源隔离;
- 不同团队分工:AI团队维护Agent主体,业务团队维护各自MCP工具服务;
- 工具能力动态变化,经常新增、下线业务工具,不想频繁发布Agent主服务;
- 部署环境存在Nginx、Ingress等网关代理,不适合传统SSE长连接。
六、总结
MCP协议搭配FastMCP的Streamable‑HTTP传输,可以极低成本把业务能力封装成独立可插拔工具服务,打破Agent/RAG项目中工具函数与主逻辑强耦合的局面。将工具能力抽离为独立MCP服务,Agent只聚焦大模型的思考规划,工具服务独立开发部署,真正实现"工具即插件"的架构模式。
Streamable‑HTTP作为MCP官方生产推荐传输,相比老旧SSE,更好兼容现有HTTP中间件体系,更适合企业生产环境落地。本文案例仅演示个税计算,按照同样模式,可以封装SQL查询、文档解析、第三方API、数据导出等任意业务能力接入Agent系统。
七、写在最后
对应项目在平台内已上线**《** 大模型 入门精品课》+ 简历和面试指导 (对于小白和想转行小伙伴而已,如果没有简历和面试辅导是很难通过面试的),课程内容包括:
-
纯干货一个月学完,没有冗余的理论,项目都是大型企业项目,非demo。
-
覆盖 RAG、智能体、Lora微调实战项目、vLLM私有化部署大模型、模型压缩(剪枝、量化、蒸馏)。
-
感兴趣的小伙伴可以前往主页了解!课程地址: https://edu.csdn.net/course/detail/41422