FastMCP 实战——从本地 stdio 到生产级 HTTP + 鉴权 + 后台任务

本地跑得好好的 MCP Server,一部署到服务器就懵了:stdio transport 根本没法远程访问,HTTP 模式直接裸奔,工具调用一超时就断连。这些坑,FastMCP 2.14 都给你填好了。

stdio 够用吗?不够

FastMCP 默认用 stdio transport------进程间通过标准输入输出通信。本地开发很香,Claude Desktop 直接配个启动命令就能用:

json 复制代码
{
  "mcpServers": {
    "calculator": {
      "command": "python",
      "args": ["/path/to/server.py"]
    }
  }
}

但一上生产就卡了:stdio 只能单机单进程,远程客户端接不进来,没法做负载均衡,日志全混在标准输出里。你需要 HTTP transport。

HTTP Transport 基础版

FastMCP 2.0 开始支持 HTTP,把 mcp.run() 改成 mcp.run(transport="http", port=8000) 就行:

python 复制代码
from fastmcp import FastMCP

mcp = FastMCP("Calculator")

@mcp.tool
def add(a: int, b: int) -> int:
    return a + b

if __name__ == "__main__":
    mcp.run(transport="http", port=8000, host="0.0.0.0")

客户端连 http://your-server:8000/mcp 就能调工具了。但这是裸奔------任何人都能调你的 API。

生产第一课:加鉴权

FastMCP 2.11 引入了完整的 OAuth 2.1 支持。最简单的方案是 JWT 验证:你的网关或认证服务签发 JWT,MCP Server 只验证不签发。

python 复制代码
from fastmcp import FastMCP
from fastmcp.server.auth.providers.jwt import JWTVerifier

# 配置 JWT 验证器(对接你的 IdP 的 JWKS endpoint)
verifier = JWTVerifier(
    jwks_url="https://your-idp.com/.well-known/jwks.json",
    issuer="https://your-idp.com",
    audience="your-mcp-server"
)

mcp = FastMCP("SecureCalculator", auth=verifier)

@mcp.tool
def add(a: int, b: int) -> int:
    return a + b

if __name__ == "__main__":
    mcp.run(transport="http", port=8000, host="0.0.0.0")

客户端请求时带上 Authorization: Bearer <token> 头,FastMCP 自动验证签名、过期时间、audience。验证失败直接返回 401,工具不会执行。

踩坑1:JWKS 缓存失效

JWTVerifier 默认缓存 JWKS 公钥 5 分钟。如果你的 IdP 频繁轮换密钥,会出现短暂的验证失败窗口。解决办法:

python 复制代码
verifier = JWTVerifier(
    jwks_url="https://your-idp.com/.well-known/jwks.json",
    issuer="https://your-idp.com",
    audience="your-mcp-server",
    cache_maxsize=128,  # 增加缓存容量
    cache_ttl=300       # 5分钟TTL(可调)
)

生产环境建议开启密钥轮换的 grace period,新旧密钥共存一段时间。

Streamable HTTP:告别 SSE 的断连噩梦

FastMCP 2.14 支持了 MCP 规范新增的 Streamable HTTP transport。之前的 SSE (Server-Sent Events) transport 有个硬伤:长时间工具调用(比如跑个 5 分钟的数据分析)容易被中间代理(nginx、CDN)超时断连。

Streamable HTTP 用双向流 + chunked encoding 解决了这个问题:

python 复制代码
from fastmcp import FastMCP

mcp = FastMCP("DataAnalyzer")

@mcp.tool
async def analyze_large_dataset(file_path: str) -> str:
    # 模拟长时间运行的任务
    import asyncio
    await asyncio.sleep(300)  # 5分钟
    return "Analysis complete"

if __name__ == "__main__":
    # 同时支持 SSE 和 Streamable HTTP,向后兼容
    mcp.run(transport="http", port=8000)

FastMCP 的 HTTP transport 现在同时处理 SSE 和 Streamable HTTP 请求,客户端根据自己的能力选协议。老客户端继续用 SSE,新客户端用 Streamable HTTP。

踩坑2:Nginx 代理配置

Streamable HTTP 要求代理不能缓冲响应体,否则又回到超时断连的老路。Nginx 配置:

nginx 复制代码
location /mcp {
    proxy_pass http://localhost:8000;
    proxy_buffering off;           # 关键:禁用缓冲
    proxy_request_buffering off;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    chunked_transfer_encoding on;
}

Background Tasks:工具调用不再阻塞

FastMCP 2.14 引入了 MCP 规范的后台任务支持。之前如果工具执行时间长,客户端只能傻等;现在可以让工具在后台跑,客户端轮询进度或等通知。

python 复制代码
from fastmcp import FastMCP

mcp = FastMCP("AsyncCalculator")

@mcp.tool(task=True)  # 标记为后台任务
async def compute_fibonacci(n: int) -> int:
    """计算第 n 个斐波那契数(假装很慢)"""
    import asyncio
    await asyncio.sleep(10)
    
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a

if __name__ == "__main__":
    mcp.run(transport="http", port=8000)

客户端调用 compute_fibonacci 时,FastMCP 立即返回一个 task_id,任务在后台执行。客户端可以:

  • 轮询任务状态(GET /mcp/tasks/{task_id}
  • 等待任务完成并获取结果

默认用内存队列(重启丢失),生产环境建议用 Redis:

python 复制代码
from fastmcp import FastMCP
from docket.brokers import RedisBroker

broker = RedisBroker("redis://localhost:6379/0")
mcp = FastMCP("AsyncCalculator", task_broker=broker)

# 其余代码不变

Redis broker 支持水平扩展:多个 FastMCP 实例共享任务队列,任何实例都能处理任务。

踩坑3:任务清理

后台任务完成后会保留在队列里,时间长了内存爆炸。FastMCP 2.14.5 修了内存泄漏,但你还需要配置任务过期:

python 复制代码
from docket.brokers import MemoryBroker

broker = MemoryBroker(
    result_ttl=3600  # 任务结果保留1小时后删除
)
mcp = FastMCP("AsyncCalculator", task_broker=broker)

Redis broker 自带 TTL,不用额外配置。

生产清单

把这些坑踩一遍,总结出生产部署检查清单:

  1. 网络绑定host="0.0.0.0" 允许外部访问,但必须配鉴权
  2. 鉴权方式:JWT 验证器(对接 IdP)或 OAuth 提供商(WorkOS、Auth0)
  3. Transport:用 HTTP,自动支持 SSE + Streamable HTTP
  4. 代理配置:Nginx 禁用 buffering,支持 chunked encoding
  5. 后台任务 :长时间工具标记 task=True,生产用 Redis broker
  6. 监控日志:FastMCP 输出结构化日志,接入 ELK/Grafana
  7. 错误处理:工具函数抛异常会返回错误消息,不会让服务崩溃

代码全景

最后贴个生产级配置的完整示例:

python 复制代码
import asyncio
from fastmcp import FastMCP
from fastmcp.server.auth.providers.jwt import JWTVerifier
from docket.brokers import RedisBroker

# JWT 鉴权
verifier = JWTVerifier(
    jwks_url="https://your-idp.com/.well-known/jwks.json",
    issuer="https://your-idp.com",
    audience="calculator-mcp"
)

# Redis 后台任务队列
broker = RedisBroker("redis://localhost:6379/0")

mcp = FastMCP("ProductionCalculator", auth=verifier, task_broker=broker)

@mcp.tool
def add(a: int, b: int) -> int:
    """快速工具:同步返回"""
    return a + b

@mcp.tool(task=True)
async def heavy_compute(n: int) -> int:
    """慢速工具:后台执行"""
    await asyncio.sleep(30)
    return n * n

if __name__ == "__main__":
    mcp.run(transport="http", port=8000, host="0.0.0.0")

配套 Nginx:

nginx 复制代码
upstream mcp_backend {
    server 127.0.0.1:8000;
    server 127.0.0.1:8001;  # 水平扩展
}

server {
    listen 443 ssl;
    server_name mcp.example.com;

    location /mcp {
        proxy_pass http://mcp_backend;
        proxy_buffering off;
        proxy_request_buffering off;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        chunked_transfer_encoding on;
    }
}

从本地 stdio 到生产 HTTP,FastMCP 的路径很清晰:先让工具跑起来,再加鉴权,最后上后台任务。每个特性都解决实际痛点,不是堆概念。

MCP Server 不是玩具,生产部署要考虑安全、可靠、可扩展。FastMCP 2.14 把这些都做成了开箱即用的功能,剩下的就是你的业务逻辑了。

相关推荐
Sirius Wu41 分钟前
OpenClaw SubAgent 三层安全约束完整详解
人工智能·安全·ai·架构·aigc
wangruofeng9 小时前
AGENTS.md 告诉 Agent 怎么写代码,DESIGN.md 告诉它怎么长得好看
aigc·ai编程
feiyu_gao15 小时前
别再让 AI 从零开始了
人工智能·架构·aigc
anyup16 小时前
这一套绝了!AI 大模型写故事,星云 SDK 驱动 3D 数字人实时演绎
前端·人工智能·aigc
墨风如雪16 小时前
WorkBuddy小白教程
aigc
穷人小水滴16 小时前
(科幻) 备用肉身虫 (Backup Body Bug, BBB) 系列设定 (202607 更新)
aigc·bug·科幻
AI创界者21 小时前
【最新】FaceFusion 5.0 一键整合包发布!免环境配置,解压即用(附超详细小白保姆级教程)
人工智能·aigc
网易云信1 天前
抢先剧透!网易智企即将亮相 2026 WAIC,这次我们带来了什么?
人工智能·aigc·线下活动
用户30742971671581 天前
LLM 推理到底是怎么跑起来的?
aigc
leeyi1 天前
Token 账单怎么看:给 Agent 加用量统计(第51篇-E37)
aigc·agent·ai编程