FastAPI-MCP:FastAPI 接口转 MCP 工具网关部署实践指南
【免费下载链接】fastapi_mcpExpose your FastAPI endpoints as Model Context Protocol (MCP) tools, with Auth!项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi_mcp
需要把已有的 FastAPI 接口暴露给大模型 Agent 直接调用时,FastAPI-MCP 可以零配置地把每个端点转换成模型上下文协议(MCP)工具,并支持挂载到同一应用或独立部署为 MCP 网关。这份指南从最小示例出发,覆盖部署、传输协议选择与生产要点,读完你可以:
- 跑通同应用挂载与独立网关两种部署
- 理解 HTTP 与 SSE 传输的取舍依据
- 配置工具白名单、认证与超时
- 避开注册时机等常见坑
项目定位与适用边界
FastAPI-MCP 解决的问题很具体:把一个现成的 FastAPI 应用自动生成为 MCP 服务器,端点即工具,请求/响应模型(Schema)与接口文档原样保留。它不做服务发现,不提供负载均衡与路由能力,也不能替代 API 网关,这些仍由前置基础设施承担。
关键特性:
- 零配置:指向应用即生成工具
- 原生认证:复用 FastAPI 的
Depends() - ASGI 传输:进程内调用,无网络开销
- 灵活部署:同应用挂载或独立网关
环境依赖与安装
硬性依赖:
- Python 3.10+(官方推荐 3.12)
- FastAPI 0.100.0+(随
fastapi-mcp自动安装) - mcp 1.12.0+(随
fastapi-mcp自动安装)
主安装方式(uv):
uv add fastapi-mcp备选方式(pip):
pip install fastapi-mcp核心实操
最小示例:把已有 FastAPI 应用接入 MCP
下面的代码在一个已有接口上生成 MCP 服务器,并用mount_http()挂载流式 HTTP 传输(Streamable HTTP),端点默认在/mcp:
from fastapi import FastAPI from fastapi_mcp import FastApiMCP app = FastAPI(title="物品服务") @app.get("/items/{item_id}", operation_id="get_item") async def read_item(item_id: int): """根据 ID 查询物品详情,404 表示不存在""" return {"item_id": item_id} # 1. 用现有 FastAPI 应用生成 MCP 服务器 mcp = FastApiMCP(app) # 2. 挂载 HTTP 传输,端点位于 /mcp mcp.mount_http() if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)启动后,MCP 客户端连接http://localhost:8000/mcp,list_tools返回get_item工具,其描述来自接口的 docstring。工具被调用时,请求通过 httpx 的 ASGI 传输直接打到应用的路由上,不经过真实网络请求,因此延迟很低。
⚠️ 常见误区:0.4.0 起旧的
mount()方法已弃用,必须显式使用mount_http()(推荐)或mount_sse()。旧代码升级后继续调用mount()会在未来版本直接报错。
MCP 客户端侧的配置:
{ "mcpServers": { "fastapi-mcp": { "url": "http://localhost:8000/mcp" } } }独立部署网关的完整步骤
大型系统中建议把 MCP 网关与业务接口分离,业务 API 不再对外暴露,只通过 MCP 提供能力。步骤如下:
- 导入业务 FastAPI 应用,用它构造 MCP 实例
- 创建一个全新的网关应用
- 用
mount_http(mcp_app)把 MCP 挂到网关上 - 分别以不同端口启动网关(业务应用随网关进程内运行)
from fastapi import FastAPI from examples.shared.apps.items import app as items_api # 业务服务 from fastapi_mcp import FastApiMCP # 1. 业务应用只作为工具生成源 mcp = FastApiMCP(items_api) # 2. 创建独立的网关应用 mcp_app = FastAPI(title="独立MCP网关") # 3. 挂到网关应用,业务 REST 接口不暴露在网关上 mcp.mount_http(mcp_app) if __name__ == "__main__": import uvicorn uvicorn.run(mcp_app, host="0.0.0.0", port=8000)uvicorn mcp_gateway:mcp_app --host 0.0.0.0 --port 8000运行效果:客户端只连得到/mcp端点,业务 REST 路由不在网关应用中注册。
⚠️ 所谓"独立部署"是独立的 ASGI 应用与端口,不是跨进程 RPC:
FastApiMCP通过 ASGI 在进程内调用业务应用对象,因此业务应用必须能被网关进程 import。两个服务无法分属不同主机后仅靠网络互通。
HTTP 与 SSE 传输怎么选
mount_http()实现的是 Streamable HTTP 规范,带状态化会话管理,0.4.0 起是默认推荐方式,端点为/mcp。mount_sse()面向旧版客户端,端点为/sse,消息走{路径}/messages/子路由。新客户端一律选 HTTP;仅当必须兼容不支持 Streamable HTTP 的旧客户端时才用 SSE。两者都支持传入自定义APIRouter并指定挂载路径:
from fastapi import APIRouter router = APIRouter(prefix="/api/v1") # 挂到自定义路径,最终端点为 /api/v1/my-mcp-service mcp.mount_http(router, mount_path="/my-mcp-service") app.include_router(router)工具清单的精细控制与注册时机
工具集合在FastApiMCP(app)构造时一次性生成,支持按 tag 或 operation_id 过滤(两组参数各自互斥):
# 只暴露 items 标签的接口,搜索接口不进工具列表 mcp = FastApiMCP(items_api, include_tags=["items"])构造之后再新增的端点不会自动出现,需要手动刷新:
@app.get("/new/endpoint/", operation_id="new_endpoint") async def new_endpoint(): """构造后新增的端点""" return {"message": "Hello, world!"} # 重新生成工具列表,新端点才会出现在 list_tools 中 mcp.setup_server()⚠️ 工具注册时机是最高频的坑:忘记调用
mcp.setup_server()时,客户端会看到一份永远缺最新接口的工具列表,且没有任何报错。
配置与扩展能力
只列有决策价值的配置项(FastApiMCP构造参数):
| 配置项 | 默认值 | 说明 | 适用场景 |
|---|---|---|---|
include_tags/exclude_tags | None | 按标签过滤工具,二者互斥 | 只暴露部分模块接口 |
include_operations/exclude_operations | None | 按 operation_id 过滤工具,二者互斥 | 精确到单个接口的取舍 |
headers | ["authorization"] | 工具调用时透传给后端的请求头白名单 | 认证接口的身份传递 |
http_client | ASGI 传输,超时 10 秒 | 自定义httpx.AsyncClient | 慢接口调大超时,如timeout=20 |
describe_all_responses/describe_full_response_schema | False | 是否把所有响应 Schema 写入工具描述 | 提升模型对返回结构的推断 |
auth_config | None | OAuth 2.0 配置:dependencies、issuer、setup_proxies等 | 对接企业级 OAuth 提供方 |
mount_path | /mcp(HTTP)//sse(SSE) | 挂载路径,可配合自定义APIRouter | 多版本网关的路径规划 |
auth_config依赖 OAuth 2.0 规范(2025-03-26 版):setup_proxies=True时会自动在你现有 OAuth 提供方周围生成 MCP 合规的代理端点,并默认启用模拟动态客户端注册。
生产落地要点
高可用
- 网关实例多副本部署在负载均衡之后:0.4.0 引入有状态会话管理,扩容前先验证同一客户端的会话是否会落到同一实例,避免会话状态丢失。
- 由于工具调用走进程内 ASGI,网关与业务应用是同一进程整体,扩容时以进程为单位整体复制,无需为两者单独规划容量。
安全
- 给
AuthConfig传入会抛出 401/403 的Depends()依赖,这是触发 MCP 客户端发起 OAuth 流程的必要条件,认证逻辑直接复用你 FastAPI 里现成的依赖。 - 对外一律走 HTTPS;
headers透传白名单保持最小化,默认只透传authorization,不要随意扩大。
可观测
- 启用
examples/shared/setup.py提供的setup_logging(),网关启动时会输出 MCP 挂载路径与监听状态,方便确认注册结果。 - 盯住工具调用的超时率与耗时:内部调用受
http_client超时(默认 10 秒)约束,超时率突增是后端接口变慢的第一信号。
排错速查
| 现象 | 原因 | 解决方式 |
|---|---|---|
客户端连/mcp返回 404/405 | 使用了弃用的mount()或传输协议与路径不匹配 | 改用mount_http(),确认客户端指向/mcp |
| 新增接口不出现在工具列表 | 工具列表在构造时一次性生成 | 调用mcp.setup_server()重新注册 |
| 慢接口调用报超时 | 内部调用默认超时 10 秒 | 传入httpx.AsyncClient(timeout=20) |
构造时抛ValueError | include与exclude两组过滤参数同时传入 | 只保留一组过滤参数 |
| 启用认证后客户端不触发 OAuth 流程 | AuthConfig.dependencies未配置,无法返回 401 | 传入抛出 401/403 的Depends()依赖 |
收尾
项目当前版本 0.4.0,Streamable HTTP 传输为默认方式,SSE 保留做向后兼容,后续演进集中在 mcp SDK 版本跟进与有状态会话管理。深度阅读可从examples/目录的九组示例、docs/advanced/deploy.mdx独立部署文档,以及CONTRIBUTING.md贡献指南入手。
【免费下载链接】fastapi_mcpExpose your FastAPI endpoints as Model Context Protocol (MCP) tools, with Auth!项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi_mcp
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考