目录

  1. 工具注册机制
  2. 工具调用流程
  3. @tool装饰器详解
  4. 工具元数据提取与验证
  5. Context上下文注入
  6. 结构化输出配置
  7. 工具冲突检测与覆盖策略
  8. list_tools与call_tool协议方法
  9. 实现示例

工具注册机制

FastMCP框架通过@tool装饰器实现工具的注册机制。该装饰器由FastMCP类提供,用于将普通函数注册为可调用的MCP工具。工具注册的核心流程由ToolManager类管理,其内部维护一个工具字典_tools,以工具名称为键存储工具实例。

当使用@tool()装饰函数时,会触发装饰器的decorator函数,该函数调用add_tool方法将函数转换为Tool对象并添加到工具管理器中。如果启用了warn_on_duplicate_tools设置且存在同名工具,系统会发出警告。工具名称默认使用函数名,但可通过name参数显式指定。

本节来源

工具调用流程

工具调用流程始于客户端发送tools/call请求,服务器端通过call_tool协议方法处理。该方法首先获取当前请求上下文,然后委托给ToolManagercall_tool方法执行具体调用。

ToolManager.call_tool首先通过工具名称查找对应的Tool实例,若未找到则抛出ToolError异常。找到工具后,调用Tool.run方法执行实际的函数调用。执行过程中会进行参数验证、上下文注入和结果转换。最终结果根据convert_result标志决定是否进行格式转换,然后返回给客户端。

客户端 服务器 工具管理器 工具实例 发送call_tool请求 调用call_tool(name, arguments) get_tool(name) run(arguments, context) call_fn_with_arg_validation 执行原始函数 返回结果 返回转换后的结果 返回调用结果 客户端 服务器 工具管理器 工具实例

图源

@tool装饰器详解

@tool装饰器是FastMCP框架中工具注册的核心组件,提供丰富的配置选项。装饰器支持同步和异步函数,通过检查函数是否为协程函数来自动识别执行模式。

装饰器参数包括:

  • name: 工具的程序化名称,默认为函数名
  • title: 工具的可读标题,用于UI展示
  • description: 工具功能描述
  • annotations: 工具的附加注解信息
  • icons: 工具的图标列表
  • meta: 工具的元数据
  • structured_output: 控制输出是否为结构化格式

装饰器会检查是否正确调用(即使用@tool()而非@tool),若使用错误会抛出TypeError。装饰器通过闭包返回原始函数,确保函数的正常调用行为不受影响。

本节来源

工具元数据提取与验证

工具元数据提取由func_metadata.py模块中的func_metadata函数负责。该函数分析函数签名,创建包含参数验证模型和输出模型的FuncMetadata对象。

输入验证通过创建ArgModelBase子类实现,该类继承自BaseModel,包含所有参数的类型注解和默认值。系统会检查参数名是否与BaseModel属性冲突,若冲突则使用别名避免警告。

输出验证根据返回类型注解自动配置。支持多种返回类型:

  • BaseModel子类:直接使用
  • 基本类型(str, int等):包装在包含result字段的模型中
  • TypedDict:转换为Pydantic模型
  • 泛型类型(list, dict等):包装在result字段中

系统使用StrictJsonSchema生成器确保JSON模式的有效性,任何警告都会转化为异常。

True
False
开始
获取函数签名
处理参数
创建参数验证模型
检查返回类型
structured_output?
创建输出模型
无输出模型
生成JSON模式
验证模式有效性
返回FuncMetadata
结束

图源

Context上下文注入

Context上下文注入机制允许工具函数访问MCP核心功能。通过在函数参数中添加Context类型注解,系统会自动注入上下文对象。

find_context_parameter函数负责在函数签名中查找Context参数。它使用typing.get_type_hints解析类型注解,并支持Optional[Context]等泛型类型。找到参数后,Tool.run方法在调用函数时将上下文作为关键字参数传递。

Context类提供以下功能:

  • 日志记录:debug, info, warning, error方法
  • 进度报告:report_progress方法
  • 资源访问:read_resource方法
  • 用户交互:elicit方法
  • 请求信息:request_id, client_id属性

上下文对象在请求处理期间有效,确保工具只能在请求上下文中访问这些功能。

"包含"
"引用"
Context
+fastmcp : FastMCP
+request_context : RequestContext
+request_id : str
+client_id : str
+session : ServerSession
+report_progress(progress, total, message)
+read_resource(uri)
+elicit(message, schema)
+log(level, message)
+debug(message)
+info(message)
+warning(message)
+error(message)
RequestContext
+request_id : RequestId
+meta : RequestParams.Meta
+session : ServerSession
+lifespan_context : LifespanContext
+request : Request
FastMCP

图源

结构化输出配置

结构化输出配置通过structured_output参数控制。该参数有三种模式:

  • None:根据返回类型注解自动检测
  • True:强制创建结构化工具
  • False:无条件创建非结构化工具

当启用结构化输出时,系统会根据返回类型创建相应的Pydantic模型。对于字典类型且键为字符串的情况,使用RootModel;对于其他类型,包装在包含result字段的模型中。

输出转换由FuncMetadata.convert_result方法处理。该方法根据配置决定返回格式:

  • 无结构化输出:直接返回非结构化内容
  • 有结构化输出:返回包含非结构化和结构化内容的元组
  • CallToolResult:直接返回,支持完全控制输出格式

系统会验证结构化输出是否符合outputSchema,确保数据完整性。

本节来源

工具冲突检测与覆盖策略

工具管理器通过warn_on_duplicate_tools设置控制冲突检测行为。当尝试添加同名工具时,系统会检查_tools字典中是否已存在该名称的工具。

如果存在冲突且warn_on_duplicate_toolsTrue,系统会记录警告但不会覆盖现有工具。这种策略确保工具注册的稳定性,防止意外覆盖。如果需要更新工具,必须先使用remove_tool方法显式删除旧工具。

工具名称冲突检测在add_tool方法中实现,使用字典的get方法检查是否存在同名工具。系统优先保留先注册的工具,确保注册顺序的确定性。

本节来源

list_tools与call_tool协议方法

list_toolscall_tool是MCP客户端交互的核心协议方法。list_tools返回所有可用工具的元数据,包括名称、描述、输入模式和输出模式。该方法将内部Tool对象转换为符合MCP规范的MCPTool对象。

call_tool处理工具调用请求,接收工具名称和参数字典。该方法通过ToolManager调度执行,确保输入验证、上下文注入和结果转换的正确执行。两个方法都通过_setup_handlers在服务器初始化时注册到MCP协议处理器中。

客户端通过ClientSession的对应方法与这些协议交互,实现工具发现和调用功能。

"委托"
"通过协议交互"
FastMCP
+list_tools()
+call_tool(name, arguments)
+_setup_handlers()
ToolManager
+list_tools()
+call_tool(name, arguments, context) : Any
+add_tool(fn, name, ...)
+remove_tool(name)
ClientSession
+list_tools(cursor, params) : ListToolsResult
+call_tool(name, arguments, ...) : CallToolResult

图源

实现示例

工具实现应遵循最佳实践,包括参数类型注解、错误处理和进度报告。对于需要上下文的工具,应添加Context参数以访问日志、进度和资源功能。

异步工具应使用async/await语法,确保非阻塞执行。结构化输出工具应提供清晰的返回类型注解,便于客户端解析。工具应处理可能的异常,并通过上下文记录错误信息。

示例工具应包含详细的文档字符串,说明功能、参数和返回值。对于复杂逻辑,应添加进度报告以提升用户体验。

本节来源

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐