跳到主要内容

第 1 章:服务器对象与三个装饰器

本章讲清:FastMCP 这个对象是怎么拼出来的,以及 @mcp.tool / @mcp.resource / @mcp.prompt 三个装饰器在注册期到底做了什么。看完你会知道「装饰器不是魔法,只是一条流水线」。

1.1 FastMCP 是什么组成的

FastMCP 不是一个从零写的大类,而是多个能力拼装出来的门面(server/server.py:314):

class FastMCP(
AggregateProvider, # 组件注册表 + 从多个来源聚合工具/资源/提示
LifespanMixin, # 启动/关闭生命周期
MCPOperationsMixin, # 把 tools/list、tools/call 等接到低层 SDK
TransportMixin, # run / run_stdio / run_http
Generic[LifespanResultT],
):

这个继承表就是一张「FastMCP 会做哪几件事」的目录:

基类带来的能力定义处
AggregateProvider「我有哪些工具/资源/提示」——聚合本地注册表 + 外部 providersserver/providers/aggregate.py:47
LifespanMixinlifespan 上下文:启动时初始化、关闭时清理server/mixins/lifespan.py
MCPOperationsMixin把 MCP 协议方法接到官方 SDK 的低层服务器server/mixins/mcp_operations.py
TransportMixinrun() / run_stdio_async() / run_http_async()server/mixins/transport.py

构造函数在 server/server.py:321(def __init__),关键一步是建了个官方 SDK 的低层服务器实例:self._mcp_server = LowLevelServer[...](server/server.py:412),并在末尾调 self._setup_handlers()(server/server.py:458)把协议处理函数接上去。

直觉: FastMCP 是「用户友好的外壳」,LowLevelServer(官方 MCP SDK)是「真正收发 JSON-RPC 的引擎」。FastMCP 负责把你的函数翻译成引擎认识的处理函数。

1.2 组件的共同基类:FastMCPComponent

工具、资源、资源模板、提示——四种东西共享一个基类 FastMCPComponent(utilities/components.py:74)。它规定了每个组件都有:

  • name / version / title / description / icons / tags / meta(都是 pydantic 字段);
  • enabled 开关,配 enable() / disable()(utilities/components.py:209:216)——可以运行时下线一个工具;
  • 一个带类型前缀的 key(utilities/components.py:139),形如 tool:addresource:weather://x,用来在注册表里避免不同类型重名撞车(make_key:130,前缀由子类 KEY_PREFIX 定义)。

为什么要类型前缀 key: 工具叫 add、资源 URI 也可能叫 add,如果用裸名字做注册表 key 就会撞。KEY_PREFIX 把它们隔到 tool:addresource:add 两个命名空间里。

1.3 @mcp.tool 做了什么(注册期流水线)

@mcp.tool 定义在 server/server.py:1737(def tool)。它支持五种调用写法(@tool@tool()@tool("name")@tool(name=...)tool(fn, name=...)),但核心逻辑很短——它自己几乎不干活,而是委托给 LocalProvider:

# server/server.py:1737 def tool —— 简化后的核心
def tool(self, name_or_fn=None, *, name=None, ...):
# (先把 app/ui 配置塞进 meta,略)
result = self._local_provider.tool( # ← 委托给本地注册表
name_or_fn, name=name, version=version, ...
)
return result

真正的三步流水线发生在下游:

@mcp.tool


① FunctionTool.from_function(fn) 解析函数 → 建 Tool 对象
│ └─ 内部调 ParsedFunction.from_function() 抽 schema(见第 2 章)

② LocalProvider._add_component(tool) 存进注册表(按 key 去重/版本检查)


③ 返回 FunctionTool(不是原函数!)
  • 第 ① 步tools/function_tool.py:211(FunctionTool.from_function):把函数变成一个 FunctionTool 运行时对象,顺带生成输入/输出 schema。这是第 2 章的主题。
  • 第 ② 步server/providers/local_provider/local_provider.py:178(_add_component):存进内部字典,并做版本混用检查(_check_version_mixing,:134)——同一个名字要么全带版本、要么全不带,不能混。
  • 第 ③ 步:装饰器返回的是 FunctionTool 实例,不是你原来的函数。所以 add 这个名字之后指向的是工具对象,而工具对象仍可当函数调用(FunctionTool 实现了 __call__,见 tools/function_tool.py:134DecoratedTool 协议)。

关键细节: 装饰器「吃掉」你的函数换成工具对象,这也是为什么给 lambda 注册工具会报错——from_function 里显式检查 func_name == "<lambda>" 并要求你显式起名(tools/function_tool.py:317)。

1.4 @mcp.resource 与「资源 vs 资源模板」

资源装饰器在 server/server.py:1862(def resource)。资源是「模型能读的数据」(相当于 GET 端点)。这里有个巧妙的自动分流:

  • URI 里没有 {参数} → 生成一个静态 FunctionResource(固定内容);
  • URI 里 {参数}(如 weather://{city}/current)→ 生成一个 ResourceTemplate(参数化,按需实例化)。

分流逻辑在 resources/function_resource.py:278(create_resource)。模板的 URI 匹配靠 resources/template.py:233(matches)→ match_uri_template(resources/template.py:80),它把 weather://{city}/current 编译成正则去匹配来访 URI 并抽出 city 参数。

类比: 资源模板之于资源,就像 Web 框架里 /users/{id} 之于 /about——一个是带路径参数的动态路由,一个是静态页面。

1.5 @mcp.prompt 简述

提示装饰器在 server/server.py:1993(def prompt)。「提示(prompt)」是 MCP 里可复用的消息模板:函数返回一段(或多段)消息,客户端可以把它渲染出来喂给模型。机制和工具同构——都走「解析函数 → 建组件 → 存 LocalProvider」,只是产物是 Prompt 而非 Tool

1.6 小结:三个装饰器是同一条流水线

装饰器产物类型建对象的入口存哪
@mcp.toolFunctionTooltools/function_tool.py:211LocalProvider
@mcp.resource(无参 URI)FunctionResourceresources/function_resource.py:90LocalProvider
@mcp.resource(带参 URI)ResourceTemplateresources/template.py:194LocalProvider
@mcp.promptPromptprompts/(from_function)LocalProvider

记住: 三个装饰器都不含协议逻辑,它们只做「函数 → 组件对象 → 进注册表」。协议对接在 mcp_operations.py 里,运行才发生(第 3 章)。真正有含金量的「函数 → schema」在第 2 章。

代码地图

主题文件路径符号名
服务器门面类fastmcp_slim/fastmcp/server/server.pyFastMCP
构造 + 接线fastmcp_slim/fastmcp/server/server.pyFastMCP.__init___setup_handlers
tool 装饰器fastmcp_slim/fastmcp/server/server.pyFastMCP.tool
resource 装饰器fastmcp_slim/fastmcp/server/server.pyFastMCP.resource
prompt 装饰器fastmcp_slim/fastmcp/server/server.pyFastMCP.prompt
本地注册表fastmcp_slim/fastmcp/server/providers/local_provider/local_provider.pyLocalProvider_add_component_check_version_mixing
组件基类fastmcp_slim/fastmcp/utilities/components.pyFastMCPComponentmake_keyenabledisable
资源分流fastmcp_slim/fastmcp/resources/function_resource.pycreate_resource
模板 URI 匹配fastmcp_slim/fastmcp/resources/template.pymatch_uri_templateResourceTemplate.matches