news 2026/7/7 9:52:47

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/7/7 19:07:35

day25 异常处理

Python的异常处理机制为程序提供了强大的容错能力 (fault tolerance)。当程序在运行时遇到意外情况&#xff08;即异常&#xff09;&#xff0c;它不会直接崩溃&#xff0c;而是可以被设计成优雅地处理这些错误&#xff0c;并可能继续执行后续逻辑&#xff08;如果设计允许&…

作者头像 李华
网站建设 2026/7/7 2:39:08

10 个自考开题演讲稿工具,AI 工具推荐优化写作效率

10 个自考开题演讲稿工具&#xff0c;AI 工具推荐优化写作效率 论文写作的重压&#xff0c;你真的扛得住吗&#xff1f; 对于自考学生来说&#xff0c;撰写开题演讲稿、文献综述乃至整篇毕业论文&#xff0c;往往是一场与时间赛跑的持久战。在有限的时间内&#xff0c;既要完成…

作者头像 李华
网站建设 2026/7/7 5:17:56

2006-2024年《中国城乡建设统计年鉴》Excel+pdf版

资源介绍 今日数据&#xff1a;《中国城乡建设统计年鉴-2006-2024》 一、数据介绍 (本年鉴【出版年份】【数据年份】&#xff09; 《中国城乡建设统计年鉴》是一部全面反映我国城乡市政公用设施建设与发展状况&#xff0c;中国城乡建设全貌的统计年鉴。 此年鉴的统计范围&a…

作者头像 李华
网站建设 2026/7/7 2:06:54

板凳----------(枯藤 )vs2026+win10(第五章-2)

致谢&#xff1a; VS2026配置x86/x64调用32位和64位汇编语言动态库环境 参考 https://blog.csdn.net/chenyijun/article/details/148952640 Lrvine64.obj 外部库可以在这里下载 链接: https://pan.baidu.com/s/1ljbseUDxpBcG_rrnhAiMEA 提取码: skbd;------------------------…

作者头像 李华
网站建设 2026/7/7 2:47:34

车载系统开发:DeepSeek 辅助编写 ADAS 功能需求文档与测试用例

车载ADAS功能开发&#xff1a;需求文档与测试用例编写指南引言随着汽车智能化水平的不断提升&#xff0c;高级驾驶辅助系统已成为现代车辆不可或缺的核心组成部分。ADAS通过融合传感器、控制器和执行器&#xff0c;为驾驶员提供预警、辅助控制甚至部分自动化功能&#xff0c;显…

作者头像 李华
网站建设 2026/7/7 4:31:53

数据库设计全景指南:从核心原则到现代分布式实践

数据库设计全景指南:从核心原则到现代分布式实践 数据库设计是任何成功软件系统的基石。一个优秀的数据库设计不仅保证数据的准确性与完整性,也直接影响系统性能、可扩展性和维护成本。本指南提供一份全面、详尽的数据库设计详解,涵盖核心原则、设计流程、九大核心策略、现…

作者头像 李华