FastMCP — 架构与原理
30 秒导读: FastMCP 是一套 Python 框架,让你只写一个普通函数、加上类型注解,就得到一台符合 MCP(Model Context Protocol,模型上下文协议)规范的服务器——参数校验、JSON schema、协议握手、stdio/HTTP 传输全部自动生成。它同时提供一个对称的 Client,以及把多台服务器拼在一起(挂载、代理、从 OpenAPI 生成)的能力。
本项目体量大、子系统多(服务器、客户端、providers、中间件、传输、任务 、鉴权……),所以文档拆成多章。本页是 Layer 0(这是什么)+ Layer 1(顶层全景)+ 阅读地图;各机制细节见分章。
1. 这是什么(零基础也能懂)
一句话定义
FastMCP = 「写一个 Python 函数 → 得到一个 AI 能调用的工具」 的框架。它把「让大模型安全地调用你的代码 / 读你的数据」这件事的所有协议脏活包掉。
先搞清背景:MCP 是什么、为什么需要它
大模型本身只会生成文本。要让它「查天气」「读数据库」「调你的 API」,得有一个标准协议规定:
- 模型端怎么知道有哪些工具可用(工具列表、每个工具的参数长啥样);
- 模型想调用某工具时,请求/响应怎么在两端传递。
这个标准就是 MCP(由 Anthropic 提出)。它规定了 tools/list、tools/call、resources/read 等一批 JSON-RPC 方法。FastMCP 是 MCP 在 Python 里最主流的实现——README 自称「some version of FastMCP powers 70% of MCP servers」,且 FastMCP 1.0 已被并入官方 MCP Python SDK(README.md)。
解决什么问题 / 给谁用
给任何想把自己的函数、API、数据暴露给 AI的 Python 工程师用。手写 MCP 服务器要自己:定义每个工具的 JSON schema、校验模型传来的参数、处理协议握手与生命周期、选传输方式……FastMCP 的主张是:
这些你都不该写。你只写业务函数,FastMCP 从函数签名 + 类型注解 + docstring 里把上面这些全部推导出来。
用起来什么样
这是一个完整可跑的 MCP 服务器(取自 README.md):
from fastmcp import FastMCP
mcp = FastMCP("Demo 🚀") # 建一台服务器
@mcp.tool # 把函数注册成工具
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
if __name__ == "__main__":
mcp.run() # 起服务(默认 stdio 传输)
就这几行,你得到了:一个名为 add 的工具、{a: int, b: int} 的输入 schema、"Add two numbers" 的描述、参数类型校验、以及一台能被任意 MCP 客户端连上的服务器。你没写一行协 议代码。
一句话直觉 / 类比
把 FastMCP 想成 MCP 世界的 FastAPI。FastAPI 让你写个带类型注解的函数 + 装饰器,就得到一个带自动 OpenAPI 文档、自动请求校验的 HTTP 端点;FastMCP 让你写个带类型注解的函数 + @mcp.tool,就得到一个带自动 JSON schema、自动参数校验的 MCP 工具。两者都靠 pydantic 从类型注解生成 schema,套路一模一样——只是目标协议从 HTTP 换成了 MCP。
本节不碰底层。记住一句话就行:FastMCP 的价值 = 「函数签名 → MCP 协议」的自动翻译。
2. 顶层全景(它大概怎么转)
三大支柱
README 把 FastMCP 分成三块,正好是理解全局的骨架:
| 支柱 | 干什么 | 主要代码位置 |
|---|---|---|
| Servers(服务器) | 把工具 / 资源 / 提示暴露给大模型 | fastmcp_slim/fastmcp/server/ |
| Clients(客户端) | 用统一 API 连接任意 MCP 服务器 | fastmcp_slim/fastmcp/client/ |
| 组合 / 集成 | 挂载、代理、从 OpenAPI / FastAPI 生成 | fastmcp/server/server.py(mount/as_proxy/from_openapi) |
注意仓库布局:真正的包代码在
fastmcp_slim/fastmcp/下(这是 v3 的 uv workspace 结构,pyproject.toml的[tool.uv.workspace]列出fastmcp_slim、fastmcp_remote)。顶层的fastmcp只是个聚合发行壳。本文所有引用都以克隆根为基准,即fastmcp_slim/fastmcp/...。
一张图:一次工具调用怎么流动
怎么读这张图:从上到下是一次 tools/call 的生命周期;左边是「注册期」(启动时发生一次),右边是「运行期」(每次调用)。
注册期(启动一次) 运行期(每次调用)
┌───────────────────────────────┐ ┌──────────────────────────────────┐
│ @mcp.tool │ │ MCP 客户端发来 tools/call │
│ def add(a:int,b:int)->int │ │ │ │
│ │ │ │ ▼ │
│ ▼ │ │ ① 低层 SDK 服务器收 JSON-RPC │
│ ① 解析函数签名 │ │ (LowLevelServer) │
│ ParsedFunction.from_function│ │ │ │
│ │ │ │ ▼ │
│ ▼ │ │ ② 中间件洋葱(可选) │
│ ② pydantic 生成 JSON schema │ │ │ │
│ │ │ │ ▼ │
│ ▼ │ │ ③ 找到 Tool(providers 聚合) │
│ ③ 存进 LocalProvider 注册表 │─────▶│ │ │
│ │ │ ▼ │
└───────────────────────────────┘ │ ④ 依赖注入 + pydantic 校验参数 │
│ │ │
│ ▼ │
│ ⑤ 调用你的 add(),转成 MCP 结果 │
└──────────────────────────────────┘
部件一句话职责
| 部件 | 干什么 | 在哪个文件 |
|---|---|---|
FastMCP | 服务器门面对象,你所有 @mcp.tool 都挂它上面 | server/server.py:314(class FastMCP) |
LocalProvider | 存放「装饰器注册的」工具/资 源/提示的本地注册表 | server/providers/local_provider/local_provider.py:51 |
Provider / AggregateProvider | 组件来源的统一抽象;FastMCP 本身就是个聚合 provider | server/providers/base.py:57、server/providers/aggregate.py:47 |
ParsedFunction | 把函数签名解析成 name/描述/输入 schema/输出 schema | tools/function_parsing.py:169 |
FunctionTool / Tool | 一个工具的运行时对象,负责校验参数并执行 | tools/function_tool.py:191、tools/base.py:180 |
LowLevelServer | 包住官方 MCP SDK 的低层服务器,接 JSON-RPC | server/low_level.py:157 |
Context | 工具运行时能拿到的「与客户端对话的能力」(日志/进度/sampling/elicitation) | server/context.py:137 |
Client | 对称的客户端,一个入参推断出传输方式 | client/client.py:130 |
Middleware | 横切逻辑(鉴权/限流/日志)的洋葱链 | server/middleware/middleware.py:88 |
主线走一遍(高层)
- 你写函数 +
@mcp.tool→ FastMCP 在注册期解析签名、生成 schema、把FunctionTool存进LocalProvider。 mcp.run()→ 起一台传输(stdio / HTTP),内部是官方 MCP SDK 的LowLevelServer,FastMCP 把tools/list、tools/call等处理函数接上去(server/mixins/mcp_operations.py:54的_setup_handlers)。- 客户端调用 → 请求进
call_tool,穿过中间件链,经 providers 聚合找到工具,做依赖注入 + pydantic 参数校验,执行你的函数,把返回值转成 MCP 的内容块。
3. 阅读地图(按这个顺序读)
| 顺序 | 章节 | 讲什么 | 适合想搞懂…… |
|---|---|---|---|
| 1 | 01-server-and-decorators.md | 服务器对象 + 三个装饰器的注册机制 | 「@mcp.tool 到底做了什么」 |
| 2 | 02-schema-generation.md | 函数 → JSON schema 的核心魔法 | 「schema/校验是怎么凭空长出来的」(全项目最精华) |
| 3 | 03-request-lifecycle.md | 一次调用的完整链路 + 依赖注入 + 错误分类 | 「请求进来后经过哪些环节」 |
| 4 | 04-providers-and-composition.md | Provider 抽象、挂载/代理/OpenAPI | 「怎么把多台服务器拼一起 / 动态提供工具」 |
| 5 | 05-client-and-transports.md | Client 与传输推断、内存测试 | 「怎么连服务器 / 怎么写测试」 |
| 6 | 06-context-middleware-boundaries.md | Context 能力、中间件、边界与代码地图 | 「工具里怎么反向调用大模型 / 加横切逻辑」 |
只想快速判断相关性的 agent: 你要找的十有八九是第 2 章(schema 生成)或第 3 章(调用链路)——那是 FastMCP 区别于「手写 SDK」的核心价值所在。