工具
将函数作为可执行能力暴露给你的MCP客户端。
工具是核心构建模块,使您的LLM能够与外部系统交互、执行代码并访问其训练数据之外的数据。在FastMCP中,工具是通过MCP协议向LLM公开的Python函数。
什么是工具?
FastMCP中的工具将常规Python函数转换为LLM在对话中可以调用的能力。当LLM决定使用工具时:
- 它根据工具的架构发送带有参数的请求。
- FastMCP会针对您函数的签名验证这些参数。
- 您的函数将使用经过验证的输入执行。
- 结果返回给LLM,它可以在其响应中使用该结果。
这使得LLM能够执行诸如查询数据库、调用API、进行计算或访问文件等任务,从而将其能力扩展到训练数据之外。
工具
@tool 装饰器
创建一个工具就像用@mcp.tool()装饰一个Python函数一样简单:
当这个工具注册后,FastMCP会自动:
- 使用函数名称(
add)作为工具名称。 - 使用函数的文档字符串(
Adds two integer numbers...)作为工具描述。 - 根据函数的参数和类型注解生成输入模式。
- 处理参数验证和错误报告。
定义Python函数的方式决定了该工具在LLM客户端中的显示和行为方式。
不支持将带有*args或**kwargs参数的函数作为工具使用。这一限制是因为FastMCP需要为MCP协议生成完整的参数模式,而可变参数列表无法实现这一点。
参数
注释
参数的类型注释对于工具的正常功能至关重要。它们:
- 向LLM告知每个参数的预期数据类型
- 启用FastMCP来验证来自客户端的输入数据
- 为MCP协议生成准确的JSON模式
为参数使用标准的Python类型注解:
参数元数据
您可以使用Pydantic的Field类结合Annotated来提供关于参数的额外元数据。这种方法更受推荐,因为它更为现代,并且能将类型提示与验证规则分开:
你也可以将Field用作默认值,不过更推荐使用Annotated注解方式:
Field 提供了多种验证和文档功能:
description: 参数的人类可读解释(展示给大语言模型)ge/gt/le/lt: 大于/小于(或等于)约束min_length/max_length: 字符串或集合的长度约束pattern: 用于字符串验证的正则表达式模式default: 如果省略参数时的默认值
支持的类型
FastMCP 支持广泛的类型注解,包括所有 Pydantic 类型:
| 类型注解 | 示例 | 描述 |
|---|---|---|
| Basic types | int, float, str, bool | Simple scalar values - see Built-in Types |
| Binary data | bytes | Binary content - see Binary Data |
| Date and Time | datetime, date, timedelta | Date and time objects - see Date and Time Types |
| Collection types | list[str], dict[str, int], set[int] | Collections of items - see Collection Types |
| Optional types | float | None, Optional[float] | Parameters that may be null/omitted - see Union and Optional Types |
| Union types | str | int, Union[str, int] | Parameters accepting multiple types - see Union and Optional Types |
| Constrained types | Literal["A", "B"], Enum | Parameters with specific allowed values - see Constrained Types |
| Paths | Path | File system paths - see Paths |
| UUIDs | UUID | Universally unique identifiers - see UUIDs |
| Pydantic models | UserData | Complex structured data - see Pydantic Models |
如需查看此处未列出的其他类型注解,请参阅下方的参数类型部分以获取更详细的信息和示例。
可选参数
FastMCP遵循Python的标准函数参数约定。没有默认值的参数是必填的,而有默认值的参数则是可选的。
在这个示例中,LLM必须提供一个query参数,而如果没有明确提供max_results、sort_by和category参数,则会使用它们的默认值。
元数据
虽然FastMCP会从您的函数中推断名称和描述,但您可以通过@mcp.tool装饰器的参数来覆盖这些内容并添加标签:
name: 设置通过MCP公开的显式工具名称。description: 提供通过MCP暴露的描述信息。如果设置此项,将忽略函数的文档字符串用于此目的。tags: 用于对工具进行分类的一组字符串。客户端可能会使用标签来筛选或分组可用工具。
异步工具
FastMCP无缝支持标准(def)和异步(async def)函数作为工具。
当您的工具需要执行可能等待外部系统(网络请求、数据库查询、文件访问)的操作时,使用async def来保持服务器的响应性。
返回值
FastMCP会自动将您的函数返回的值转换为适合客户端的MCP内容格式:
str: 作为TextContent发送。dict,list, PydanticBaseModel: 序列化为JSON字符串并以TextContent形式发送。bytes: 经过Base64编码后作为BlobResourceContents发送(通常包含在EmbeddedResource中)。fastmcp.Image: 一个用于轻松返回图像数据的辅助类。以ImageContent形式发送。None: 返回空响应(不向客户端发送任何内容)。
FastMCP会尝试将其他类型序列化为字符串(如果可能)。
目前,FastMCP仅响应您工具返回的值,而非返回的注解。
错误处理
New in version: 2.3.4
如果你的工具遇到错误,可以抛出标准的Python异常(ValueError、TypeError、FileNotFoundError、自定义异常等)或FastMCP的ToolError。
在所有情况下,异常都会被记录并转换为MCP错误响应返回给客户端LLM。出于安全考虑,默认情况下错误消息不会包含在响应中。但是,如果您抛出ToolError,则异常内容会包含在响应中。这允许您选择性地向客户端LLM提供有意义的错误信息,帮助LLM理解故障并做出适当反应。
注释
New in version: 2.2.7
FastMCP允许您通过注解为工具添加专门的元数据。这些注解向客户端应用程序传达工具的行为方式,而无需在LLM提示中消耗令牌上下文。
注释在客户端应用程序中有多种用途:
- 添加用户友好的标题用于显示
- 指示工具是否会修改数据或系统
- 描述工具的安全特性(破坏性 vs 非破坏性)
- 标记工具是否与外部系统交互
你可以通过在@mcp.tool()装饰器中使用annotations参数来为工具添加注释:
FastMCP支持以下标准注解:
| 注解 | 类型 | 默认值 | 用途 |
|---|---|---|---|
title | string | - | Display name for user interfaces |
readOnlyHint | boolean | false | Indicates if the tool only reads without making changes |
destructiveHint | boolean | true | For non-readonly tools, signals if changes are destructive |
idempotentHint | boolean | false | Indicates if repeated identical calls have the same effect as a single call |
openWorldHint | boolean | true | Specifies if the tool interacts with external systems |
请记住,注释有助于提升用户体验,但应视为建议性提示。它们能帮助客户端应用程序呈现适当的UI元素和安全控制,但本身不会强制执行安全边界。始终专注于让您的注释准确反映fastmcp工具的实际功能。
MCP上下文
工具可以通过Context对象访问MCP功能,如日志记录、读取资源或报告进度。要使用它,请在你的工具函数中添加一个类型提示为Context的参数。
Context对象提供以下访问权限:
- 日志记录:
ctx.debug(),ctx.info(),ctx.warning(),ctx.error() - 进度报告:
ctx.report_progress(progress, total) - 资源访问:
ctx.read_resource(uri) - LLM采样:
ctx.sample(...) - 请求信息:
ctx.request_id,ctx.client_id
有关Context对象及其所有功能的完整文档,请参阅Context文档。
参数类型
FastMCP支持多种参数类型,让您在设计工具时拥有更大的灵活性。
FastMCP 通常支持 Pydantic 支持的所有类型作为字段,包括所有 Pydantic 自定义类型。这意味着您可以在工具参数中使用任何能被 Pydantic 验证和解析的类型。
FastMCP在可能的情况下支持类型强制转换。这意味着如果客户端发送的数据与预期类型不匹配,FastMCP会尝试将其转换为适当类型。例如,如果客户端为标注为int的参数发送字符串,FastMCP会尝试将其转换为整数。如果转换不可行,FastMCP将返回验证错误。
内置类型
最常见的参数类型是Python的内置标量类型:
这些类型为LLM提供了关于可接受值的明确预期,并允许FastMCP正确验证输入。即使客户端提供像"42"这样的字符串,对于标注为int的参数,它也会被强制转换为整数。
日期与时间类型
FastMCP 支持来自 datetime 模块的各种日期和时间类型:
datetime- 接受ISO格式字符串(例如:"2023-04-15T14:30:00")date- 接受ISO格式的日期字符串(例如:"2023-04-15")timedelta- 接受整数秒或timedelta对象
集合类型
FastMCP 支持所有标准的 Python 集合类型:
所有集合类型都可以用作参数注解:
list[T]- 有序的项目序列dict[K, V]- 键值映射set[T]- 无序的唯一项集合tuple[T1, T2, ...]- 固定长度的序列,可能包含不同类型
集合类型可以嵌套和组合以表示复杂的数据结构。与预期结构匹配的JSON字符串将被自动解析并转换为适当的Python集合类型。
联合类型与可选类型
对于可以接受多种类型或可能被省略的参数:
现代Python语法(str | int)比旧式的Union[str, int]形式更受推荐。同样地,str | None也比Optional[str]更受青睐。
约束类型
当一个参数必须是一组预定义值中的一个时,您可以使用字面量类型或枚举类型:
字面量
字面量将参数限制为特定的值集合:
字面量类型:
- 直接在类型注解中指定允许的确切值
- 帮助LLMs准确理解哪些数值是可接受的
- 提供输入验证(对无效值报错)
- 为客户创建清晰的模式
枚举类型
对于更结构化的约束值集合,请使用Python的Enum类:
使用枚举类型时:
- 客户端应提供枚举的值(例如"red"),而不是枚举成员名称(例如"RED")
- FastMCP 会自动将字符串值转换为相应的枚举对象
- 您的函数接收实际的枚举成员(例如
Color.RED) - 对于不在枚举中的值会引发验证错误
二进制数据
处理工具参数中的二进制数据有两种方法:
字节
当您将参数标注为bytes时,FastMCP会:
- 将原始字符串直接转换为字节
- 验证输入可以正确表示为字节
fastmcp不会自动解码base64编码的字符串作为bytes参数。如果您需要接受base64编码的数据,应该按照如下方式手动处理解码。
Base64编码字符串
当您预期会从客户端接收到base64编码的二进制数据时,推荐采用这种方法。
路径
Path 类型来自 pathlib 模块,可用于文件系统路径:
当客户端发送一个字符串路径时,FastMCP会自动将其转换为Path对象。
UUID
UUID 类型来自 uuid 模块,可用于生成唯一标识符:
当客户端发送一个字符串形式的UUID(例如"123e4567-e89b-12d3-a456-426614174000")时,FastMCP会自动将其转换为UUID对象。
Pydantic 模型
对于具有嵌套字段和验证的复杂结构化数据,使用Pydantic模型:
使用Pydantic模型提供以下优势:
- 为复杂输入提供清晰、自文档化的结构
- 内置数据验证
- 为LLM自动生成详细的JSON模式
- 支持从字典/JSON输入自动转换
客户端可以为Pydantic模型参数提供以下两种形式的数据:
- 一个JSON对象(字符串)
- 一个具有适当结构的字典
- 以适当格式嵌套的参数
Pydantic字段
FastMCP通过Pydantic的Field类支持强大的参数验证功能。这对于确保输入值不仅满足类型要求,还符合特定条件特别有用。
请注意,字段可以在Pydantic模型之外使用,以提供元数据和验证约束。推荐的方法是使用Annotated与Field结合:
你也可以使用Field作为默认值,不过更推荐Annotated这种方式:
常见的验证选项包括:
| 验证 | 类型 | 描述 |
|---|---|---|
ge, gt | Number | Greater than (or equal) constraint |
le, lt | Number | Less than (or equal) constraint |
multiple_of | Number | Value must be a multiple of this number |
min_length, max_length | String, List, etc. | Length constraints |
pattern | String | Regular expression pattern constraint |
description | Any | Human-readable description (appears in schema) |
当客户端发送无效数据时,FastMCP会返回一个验证错误,说明参数验证失败的原因。
服务器行为
重复工具
New in version: 2.1.0
当您尝试注册多个同名工具时,可以控制FastMCP服务器的行为方式。这通过在创建FastMCP实例时使用on_duplicate_tools参数进行配置。
重复行为选项包括:
"warn"(默认值): 记录警告日志并用新工具替换旧工具。"error": 抛出ValueError错误,阻止重复注册。"replace": 静默地用新工具替换现有工具。"ignore": 保留原始工具并忽略新的注册尝试。
移除工具
New in version: 2.3.4
您可以使用remove_tool方法动态地从服务器移除工具:
传统JSON解析
New in version: 2.2.10
FastMCP 1.0 和 2.2.10 之前的版本依赖一个临时解决方案,该方案试图通过自动解析工具参数中的字符串化JSON(例如将"[1,2,3]"转换为[1,2,3])来规避LLM的限制。从FastMCP 2.2.10开始,此行为默认被禁用,因为它绕过了类型验证并可能导致意外的类型强制转换问题(例如将"true"解析为布尔值,而尝试调用期望字符串的工具,这将无法通过类型验证)。
大多数现代LLM能够正确格式化JSON,但如果使用的模型会不必要地将JSON字符串化(如2024年末的Claude Desktop版本),您可以通过在服务器上设置环境变量FASTMCP_TOOL_ATTEMPT_PARSE_JSON_ARGS=1来重新启用此功能。
除非必要,我们强烈建议保持此选项禁用。