news 2026/5/27 22:13:05

FastMCP之Tools

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FastMCP之Tools

在MCP中,Tools是一个函数,它可以被用于执行动作或者访问外部系统。

一、如何创建一个Tools?

最简单的方法就是用@mcp.tool注解一个python的函数。

服务端

fromfastmcpimportFastMCP mcp=FastMCP(name="CalculatorServer")@mcp.tooldefadd(a:int,b:int)->int:"""Adds two integer numbers together."""returna+bif__name__=="__main__":mcp.run(transport="http",# 使用HTTP传输host="0.0.0.0",# 允许外部访问port=8000# 端口)

带有 * args 或 **kwargs 的函数不支持作为工具。存在这一限制是因为 FastMCP 需要为 MCP 协议生成完整的参数 schema,而这对于可变参数列表来说是无法实现的。

客户端

importasynciofromfastmcpimportClient client=Client("http://localhost:8000/mcp")asyncdefcall_tool(name:str):asyncwithclient:result=awaitclient.call_tool(name,{"a":2,"b":3})print(result)asyncio.run(call_tool("add"))

装饰器参数说明

  • name str | None 设置通过 MCP 暴露的明确工具名称。如果未提供,则使用函数名称
  • description str | None 提供通过 MCP 公开的描述。如果设置了此描述,那么函数的文档字符串将为此目的而被忽略。
  • tags set[str] | None 一组用于对工具进行分类的字符串。服务器以及在某些情况下的客户端可以使用这些字符串来筛选或分组可用的工具。
  • enabled bool default:“True” 一个用于启用或禁用该工具的布尔值。

二、同步与异步

FastMCP 是一个优先支持异步的框架,它能无缝支持异步(async def)和同步(def)函数作为工具。对于 I/O 密集型操作,异步工具是更优选择,可保持服务器的响应性。
虽然同步工具在 FastMCP 中能无缝运行,但在执行过程中可能会阻塞事件循环。对于 CPU 密集型或可能存在阻塞的同步操作,可考虑其他策略。一种方法是使用 anyio(FastMCP 内部已在使用)将它们包装为异步函数。

同步示例在第一章节已经有了,这里举一个异步的例子

服务端

importasyncioimportanyiofromfastmcpimportFastMCP mcp=FastMCP()defcpu_intensive_task(data:str)->str:# Some heavy computation that could block the event loopreturndata@mcp.toolasyncdefwrapped_cpu_task(data:str)->str:"""CPU-intensive task wrapped to prevent blocking."""returnawaitanyio.to_thread.run_sync(cpu_intensive_task,data)# 服务启动入口asyncdefmain():# 方式1:启动 FastMCP 本地服务(默认基于 HTTP 或 WebSocket,取决于 FastMCP 版本)# 如需自定义端口/地址,可传入参数,例如:host="0.0.0.0", port=8000awaitmcp.run_http_async(host="127.0.0.1",# 绑定本地地址,外部访问可改为 0.0.0.0port=8000,# 服务端口)if__name__=="__main__":asyncio.run(main())

客户端

importasynciofromfastmcpimportClient client=Client("http://localhost:8000/mcp")asyncdefcall_tool(name:str):asyncwithclient:result=awaitclient.call_tool("wrapped_cpu_task",{"data":name})print(result)if__name__=="__main__":asyncio.run(call_tool("apple"))

三、类型声明

FastMCP 支持多种类型注解,包括所有的 Pydantic 类型, 在定义Tool函数的时候,建议添加上类型:
比如:name: str, [str] 就是类型声明。

Type AnnotationExampleDescription
Basic typesint, float, str, boolSimple scalar values
Binary databytesBinary content (raw strings, not auto-decoded base64)
Date and Timedatetime, date, timedeltaDate and time objects (ISO format strings)
Collection typeslist[str], dict[str, int], set[int]Collections of items
Optional typesfloatNone, Optional[float]
Union typesstrint, Union[str, int]
Constrained typesLiteral[“A”, “B”], EnumParameters with specific allowed values
PathsPathFile system paths (auto-converted from strings)
UUIDsUUIDUniversally unique identifiers (auto-converted from strings)
Pydantic modelsUserDataComplex structured data with validation

四、验证模式

在LLM调用Tools的时候,需要传参,默认情况下,FastMCP 采用 Pydantic 的灵活验证机制,会将兼容的输入强制转换为与类型注解匹配的形式。这提高了与大型语言模型客户端的兼容性,这些客户端可能会发送值的字符串表示形式(例如,对于整数参数发送 “10”)。
如果需要更严格的验证以拒绝任何类型不匹配的情况,您可以启用严格输入验证。严格模式使用 MCP SDK 内置的 JSON 模式验证,在将输入传递给函数之前,根据精确的模式对其进行验证:

4.1 宽松的验证

Tools定义的类型是int, 在调用的时候,传str类型,MCP自动转换int类型。

服务端

fromfastmcpimportFastMCP mcp=FastMCP("StrictServer",strict_input_validation=False)@mcp.tooldefadd_numbers(a:int,b:int)->int:"""Add two numbers."""returna+bif__name__=="__main__":mcp.run(transport="http",# 使用HTTP传输host="0.0.0.0",# 允许外部访问port=8000# 端口)

客户端

importasynciofromfastmcpimportClient client=Client("http://localhost:8000/mcp")asyncdefcall_tool(name:str):asyncwithclient:result=awaitclient.call_tool(name,{"a":"2","b":"3"})print(result)asyncio.run(call_tool("add_numbers"))

4.2 严格的验证

服务端

fromfastmcpimportFastMCP mcp=FastMCP("StrictServer",strict_input_validation=True)@mcp.tooldefadd_numbers(a:int,b:int)->int:"""Add two numbers."""returna+bif__name__=="__main__":mcp.run(transport="http",# 使用HTTP传输host="0.0.0.0",# 允许外部访问port=8000# 端口)

客户端

importasynciofromfastmcpimportClient client=Client("http://localhost:8000/mcp")asyncdefcall_tool(name:str):asyncwithclient:result=awaitclient.call_tool(name,{"a":"2","b":"3"})print(result)asyncio.run(call_tool("add_numbers"))

调用的时候,将会报异常:

Traceback(most recent call last):File"D:\code\mcp-demo\tools\flexible_client.py",line17,in<module>asyncio.run(call_tool("add_numbers"))~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^File"D:\Python\Python313\Lib\asyncio\runners.py",line195,inrunreturnrunner.run(main)~~~~~~~~~~^^^^^^File"D:\Python\Python313\Lib\asyncio\runners.py",line118,inrunreturnself._loop.run_until_complete(task)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^File"D:\Python\Python313\Lib\asyncio\base_events.py",line725,inrun_until_completereturnfuture.result()~~~~~~~~~~~~~^^File"D:\code\mcp-demo\tools\flexible_client.py",line14,incall_tool result=awaitclient.call_tool(name,{"a":"2","b":"3"})^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File"D:\code\mcp-demo\.venv\Lib\site-packages\fastmcp\client\client.py",line969,incall_toolraiseToolError(msg)fastmcp.exceptions.ToolError:Input validation error:'3'isnotoftype'integer'

五、参数元数据

可以通过多种方式提供有关参数的额外元数据:

5.1 简单字符串描述

fromtypingimportAnnotated@mcp.tooldefprocess_image(image_url:Annotated[str,"URL of the image to process"],resize:Annotated[bool,"Whether to resize the image"]=False,width:Annotated[int,"Target width in pixels"]=800,format:Annotated[str,"Output image format"]="jpeg")->dict:"""Process an image with optional resizing."""# Implementation...

5.2 使用Field进行描述

方式一: 在Annotated中使用Field

fromtypingimportAnnotatedfrompydanticimportField@mcp.tooldefprocess_image(image_url:Annotated[str,Field(description="URL of the image to process")],resize:Annotated[bool,Field(description="Whether to resize the image")]=False,width:Annotated[int,Field(description="Target width in pixels",ge=1,le=2000)]=800,format:Annotated[Literal["jpeg","png","webp"],Field(description="Output image format")]="jpeg")->dict:"""Process an image with optional resizing."""# Implementation...

方式二:将 Field 用作默认值,不过更推荐使用 Annotated 方法:

@mcp.tooldefsearch_database(query:str=Field(description="Search query string"),limit:int=Field(10,description="Maximum number of results",ge=1,le=100))->list:"""Search the database with the provided query."""# Implementation...

5.3 对LLM隐藏参数

要在运行时注入值而不将其暴露给 LLM(例如用户 ID、凭据或数据库连接),请使用带有 Depends () 的依赖注入。使用 Depends () 的参数会自动从工具架构中排除:

fromfastmcpimportFastMCPfromfastmcp.dependenciesimportDepends mcp=FastMCP()defget_user_id()->str:return"user_123"# Injected at runtime@mcp.tooldefget_user_details(user_id:str=Depends(get_user_id))->str:# user_id is injected by the server, not provided by the LLMreturnf"Details for{user_id}"

六、返回值

FastMCP 工具可以以两种互补的格式返回数据:传统内容块(如文本和图像)和结构化输出(机器可读取的 JSON)。当你添加返回类型注释时,FastMCP 会自动生成输出模式来验证结构化数据,并使客户端能够将结果反序列化为 Python 对象。

6.1 Content

FastMCP 会自动将工具返回值转换为适当的 MCP 内容块:

返回类型转换后的MCP内容块
strSent as TextContent
bytesBase64 encoded and sent as BlobResourceContents (within an EmbeddedResource)
fastmcp.utilities.types.ImageSent as ImageContent
fastmcp.utilities.types.AudioSent as AudioContent
fastmcp.utilities.types.FileSent as base64-encoded EmbeddedResource

示例

fromfastmcp.utilities.typesimportImage,Audio,File@mcp.tooldefget_chart()->Image:"""Generate a chart image."""returnImage(path="chart.png")@mcp.tooldefget_multiple_charts()->list[Image]:"""Return multiple charts."""return[Image(path="chart1.png"),Image(path="chart2.png")]

注意事项(以上类型转换的条件)

  1. 直接返回
  2. 作为List的一部分返回
  3. 其他情况需要手动转换
# ✅ Automatic conversionreturnImage(path="chart.png")return[Image(path="chart1.png"),"text content"]# ❌ Will not be automatically convertedreturn{"image":Image(path="chart.png")}# ✅ Manual conversion for nested usereturn{"image":Image(path="chart.png").to_image_content()}

6.2 结构化输出

当你的工具返回具有 JSON 对象表示形式的数据时,FastMCP 会自动创建与传统内容并存的结构化输出。这提供了机器可读取的 JSON 数据,客户端可以将其反序列化为 Python 对象。

自动结构化内容规则:

  • 类对象结果(dict、Pydantic 模型、dataclasses)→ 始终成为结构化内容(即使没有输出模式)
  • 非对象结果(int、str、list)→ 只有存在用于验证 / 序列化它们的输出模式时,才会成为结构化内容
  • 所有结果 → 为了向后兼容,始终成为传统内容块
6.2.1 返回类对象(dict、Pydantic 模型、dataclasses)

当你的工具返回字典、数据类或 Pydantic 模型时,FastMCP 会自动从中创建结构化内容。这种结构化内容包含实际的对象数据,便于客户端反序列化为原生对象。

返回

@mcp.tooldefget_user_data(user_id:str)->dict:"""Get user data."""return{"name":"Alice","age":30,"active":True}

结构化返回

{"content":[{"type":"text","text":"{\n \"name\": \"Alice\",\n \"age\": 30,\n \"active\": true\n}"}],"structuredContent":{"name":"Alice","age":30,"active":true}}
6.2.2返回非对象结果(int、str、list)
6.2.2.1 不带类型注解(没有说明函数返回的类型)

返回

@mcp.tooldefcalculate_sum(a:int,b:int):"""Calculate sum without return annotation."""returna+b# Returns 8

实际结果

CallToolResult(content=[TextContent(type='text',text='5',annotations=None,meta=None)],structured_content=None,meta=None,data=None,is_error=False)
6.2.2.2 带类型注解(没有说明函数返回的类型)

返回

@mcp.tooldefcalculate_sum(a:int,b:int)->int:"""Calculate sum without return annotation."""returna+b# Returns 8

实际结果

CallToolResult(content=[TextContent(type='text',text='5',annotations=None,meta=None)],structured_content={'result':5},meta=None,data=5,is_error=False)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/24 21:49:21

通信系统仿真:数字调制与解调技术_(22).瑞利衰落信道

瑞利衰落信道 在无线通信系统中&#xff0c;信道的特性对信号传输性能有着至关重要的影响。瑞利衰落信道是一种常见的模型&#xff0c;用于描述多径传播环境下的信号衰落。本节将详细介绍瑞利衰落信道的原理和仿真方法&#xff0c;并通过具体的代码示例来说明如何在MATLAB中实现…

作者头像 李华
网站建设 2026/5/24 0:12:46

Firefox 浏览器:自由与安全的互联网探索工具

Firefox 浏览器:自由与安全的互联网探索工具 引言 在互联网时代,浏览器作为连接用户与网络世界的桥梁,扮演着至关重要的角色。Firefox 浏览器,作为一款深受用户喜爱的免费开源浏览器,凭借其卓越的性能、丰富的功能以及坚定的隐私保护理念,赢得了全球用户的青睐。本文将…

作者头像 李华
网站建设 2026/5/26 10:37:21

通信系统仿真:数字调制与解调技术_(25).通信系统仿真工具

通信系统仿真工具 在现代通信系统的设计和分析中&#xff0c;仿真工具扮演着至关重要的角色。它们不仅能够帮助工程师和研究人员验证通信系统的性能&#xff0c;还可以在设计阶段发现潜在的问题&#xff0c;从而节省时间和成本。本节将详细介绍常用的通信系统仿真工具&#xff…

作者头像 李华
网站建设 2026/5/24 10:25:04

Memcached stats items 命令详解

Memcached stats items 命令详解 概述 Memcached 是一款高性能的分布式内存对象缓存系统,它通过在内存中存储数据来减少对数据库的访问,从而提高应用的性能。stats items 命令是 Memcached 提供的一个用于获取缓存项统计信息的命令。本文将详细介绍该命令的用法、参数以及返…

作者头像 李华
网站建设 2026/5/22 13:34:29

关于“此电脑”的小工具,让你的Windows的瞬间不一样

今天给大家推荐两款处理“此电脑”的实用软件&#xff0c;感兴趣的小伙伴们赶紧保存吧&#xff01; ONE MyComputerManager 最近我打开“此电脑”&#xff0c;发现里面有三个网盘的快捷方式&#xff0c;简直让我这个有点强迫症的人受不了。 因此&#xff0c;我找到了今天要推…

作者头像 李华
网站建设 2026/5/26 13:24:34

企业估值中的AI驱动的自动化科学文献综述平台评估

企业估值中的AI驱动的自动化科学文献综述平台评估 关键词&#xff1a;企业估值、AI驱动、自动化科学文献综述平台、评估指标、应用场景 摘要&#xff1a;本文聚焦于企业估值领域中AI驱动的自动化科学文献综述平台的评估。首先介绍了研究的背景&#xff0c;包括目的、预期读者、…

作者头像 李华