函数工具是MCP框架的核心组件之一,它允许开发者定义结构化的函数接口供AI模型调用。本文将深入探讨MCP的函数工具系统,介绍如何创建从简单到复杂的各类工具,包括基本函数、参数验证、枚举类型、复杂数据模型等高级特性。通过这些示例,你将掌握如何为AI应用构建强大而灵活的工具集,使AI能够执行各种复杂任务。
函数工具系统概述
MCP的函数工具系统允许开发者将Python函数暴露为可被AI调用的工具。每个工具都有明确定义的输入参数和返回值,并且可以包含详细的描述信息。MCP会自动处理参数验证、类型转换和错误处理,使开发者能够专注于实现工具的核心功能。
工具类型与实现
1. 基本函数工具
最简单的工具是直接使用Python函数并添加@mcp.tool()
装饰器:
@mcp.tool()def calculate_sum(numbers: List[float]) -> float: """计算数字列表的总和 这个函数接收一个数字列表,然后返回它们的总和。 非常适合进行简单的数学计算。 Args: numbers: 要计算总和的数字列表 Returns: 所有数字的总和 """ return sum(numbers)
MCP会自动从函数名称派生工具名称,并从文档字符串生成描述。类型注解用于指定参数和返回值的类型。
2. 自定义名称的工具
你可以通过name
参数为工具指定自定义名称:
@mcp.tool(name="高级计算器")def advanced_calculator(a: float, b: float, operation: str) -> float: """执行高级数学运算""" if operation == "+": return a + b elif operation == "-": return a - b # 其他操作...
自定义名称对于创建更易于理解和使用的工具接口非常有用,特别是当函数名称不够直观时。
3. 使用枚举进行参数验证
使用Python的Enum
类可以限制参数的可能值,提供更严格的参数验证:
class ColorFormat(str, Enum): RGB = "rgb" HEX = "hex" HSL = "hsl"@mcp.tool()def convert_color(color: str, from_format: ColorFormat, to_format: ColorFormat) -> str: """在不同的颜色格式之间转换""" # 实现颜色转换逻辑...
枚举类型确保参数只能是预定义的值之一,提高了工具的健壮性。
4. 使用Pydantic模型进行复杂参数验证
对于需要复杂验证规则的参数,可以使用Pydantic模型:
class Person(BaseModel): name: str = Field(..., description="姓名") age: int = Field(..., description="年龄", ge=0, lt=150) email: Optional[str] = Field(None, description="电子邮件地址") tags: List[str] = Field(default_factory=list, description="标签列表") @validator('email') def validate_email(cls, v): if v is not None and '@' not in v: raise ValueError('必须是有效的电子邮件地址') return vclass UserProfile(BaseModel): id: str = Field(..., description="用户ID") person: Person = Field(..., description="个人信息") created_at: datetime = Field(default_factory=datetime.now, description="创建时间")@mcp.tool()def create_user_profile(user_data: Dict) -> Dict: """创建用户档案""" # 使用Pydantic模型验证输入数据 person_data = user_data.get("person", {}) person = Person(**person_data) # 创建用户档案 profile = UserProfile( id=user_data.get("id", f"user_{hash(person.name)}"), person=person ) return profile.model_dump()
Pydantic模型提供了强大的数据验证、类型转换和默认值处理能力,非常适合处理复杂的数据结构。
5. 返回复杂结构
MCP工具可以返回复杂的数据结构,这些结构会自动转换为MCP支持的类型:
@mcp.tool()def generate_report(user_id: str, include_details: bool = False) -> Dict: """生成用户报告""" # 基本报告 report = { "user_id": user_id, "generated_at": datetime.now().isoformat(), "summary": { "login_count": 42, "last_login": "2024-03-15T08:30:00" } } # 添加详细信息 if include_details: report["details"] = { "activities": [ {"type": "login", "timestamp": "2024-03-15T08:30:00"}, # 更多活动... ], "preferences": { "theme": "dark", "notifications": True, "language": "zh-CN" } } return report
复杂的返回值允许工具提供丰富的信息,使AI能够处理更复杂的任务。
客户端调用工具
在客户端,我们可以使用session.call_tool()
方法来调用工具:
# 列出所有可用工具tools = await session.list_tools()# 调用基本工具result = await session.call_tool("calculate_sum", {"numbers": [1, 2, 3, 4, 5]})# 调用自定义名称的工具result = await session.call_tool("高级计算器", {"a": 10, "b": 3, "operation": "*"})# 调用使用枚举的工具result = await session.call_tool("convert_color", { "color": "rgb(255,0,0)", "from_format": "rgb", "to_format": "hex"})# 调用使用Pydantic模型的工具result = await session.call_tool("create_user_profile", {"user_data": json.dumps(user_data)})# 调用返回复杂结构的工具result = await session.call_tool("generate_report", {"user_id": "user1", "include_details": "true"})
如果你看到如下的输出内容,代表你已经成功的掌握了mcp的function
和tool
的使用
python .\mcp\03_function_tools.pyD:\svn\github.com\ai-learning\mcp\03_function_tools.py:113: PydanticDeprecatedSince20: Pydantic V1 style `@validator` validators are deprecated. You should migrate to Pydantic V2 style `@field_validator` validators, see the migration guide for more details. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.11/migration/ @validator('email')=== 可用工具列表 ===- ('meta', None)- ('nextCursor', None)- ('tools', [Tool(name='calculate_sum', description='计算数字列表的总和\n \n 这个函数接收一个 数字列表,然后返回它们的总和。\n 非常适合进行简单的数学计算。\n \n Args:\n numbers: 要计算总和的数字列表\n \n Returns:\n 所有数字的总和\n ', inputSchema={'properties': {'numbers': {'items': {'type': 'number'}, 'title': 'Numbers', 'type': 'array'}}, 'required': ['numbers'], 'title': 'calculate_sumArguments', 'type': 'object'}, annotations=None), Tool(name='高级计算器', description='执行高级数学运算\n \n 根据指定的操作符对两个数字执行数学运算。\n 支持的操作包括:加法(+)、减法(-)、乘法(*)、除法(/)、幂运算(**)。\n \n Args:\n a: 第一个数字\n b: 第二个数字\n operation: 要执行的操作 (+, -, *, /, **)\n \n Returns:\n 运算结果\n ', inputSchema={'properties': {'a': {'title': 'A', 'type': 'number'}, 'b': {'title': 'B', 'type': 'number'}, 'operation': {'title': 'Operation', 'type': 'string'}}, 'required': ['a', 'b', 'operation'], 'title': 'advanced_calculatorArguments', 'type': 'object'}, annotations=None), Tool(name='convert_color', description='在不同的颜色格式之间转换\n \n 支持在 RGB、HEX 和 HSL 格式之间转换颜色值。\n \n Args:\n color: 要转换的颜色值\n from_format: 源格式 (rgb, hex, hsl)\n to_format: 目标格式 (rgb, hex, hsl)\n \n Returns:\n 转换后的颜色值\n ', inputSchema={'$defs': {'ColorFormat': {'enum': ['rgb', 'hex', 'hsl'], 'title': 'ColorFormat', 'type': 'string'}}, 'properties': {'color': {'title': 'Color', 'type': 'string'}, 'from_format': {'$ref': '#/$defs/ColorFormat'}, 'to_format': {'$ref': '#/$defs/ColorFormat'}}, 'required': ['color', 'from_format', 'to_format'], 'title': 'convert_colorArguments', 'type': 'object'}, annotations=None), Tool(name='create_user_profile', description='创建用户档案\n \n 接收用户数据并创建一个验证过的用户档案。\n \n Args:\n user_data: 包含用户信息的字典\n \n Returns:\n 创建的用户档案\n ', inputSchema={'properties': {'user_data': {'additionalProperties': True, 'title': 'User Data', 'type': 'object'}}, 'required': ['user_data'], 'title': 'create_user_profileArguments', 'type': 'object'}, annotations=None), Tool(name='generate_report', description='生成 用户报告\n \n 根据用户 ID 生成一份报告,可选择是否包含详细信息。\n \n Args:\n user_id: 用户 ID\n include_details: 是否包含详细信息\n \n Returns:\n 用户报告数据\n ', inputSchema={'properties': {'user_id': {'title': 'User Id', 'type': 'string'}, 'include_details': {'default': False, 'title': 'Include Details', 'type': 'boolean'}}, 'required': ['user_id'], 'title': 'generate_reportArguments', 'type': 'object'}, annotations=None)])=== 测试基本工具 ===计算总和: meta=None content=[TextContent(type='text', text='15.0', annotations=None)] isError=False === 测试自定义名称的工具 ===高级计算 (10 * 3): meta=None content=[TextContent(type='text', text='30.0', annotations=None)] isError=False=== 测试枚举验证 ===颜色转换 (RGB -> HEX): meta=None content=[TextContent(type='text', text="转换错误: invalid literal for int() with base 10: 'rgb(255'", annotations=None)] isError=False=== 测试 Pydantic 模型验证 ===创建用户档案: meta=None content=[TextContent(type='text', text='{\n "id": "user1",\n "person": {\n "name": "张三",\n "age": 28,\n "email": "zhangsan@example.com",\n "tags": [\n "开 发",\n "Python"\n ]\n },\n "created_at": "2025-06-22T19:12:15.397796"\n}', annotations=None)] isError=False=== 测试复杂返回值 ===生成报告: meta=None content=[TextContent(type='text', text='{\n "user_id": "user1",\n "generated_at": "2025-06-22T19:12:15.397796",\n "summary": {\n "login_count": 42,\n "last_login": "2024-03-15T08:30:00"\n },\n "details": {\n "activities": [\n {\n "type": "login",\n "timestamp": "2024-03-15T08:30:00"\n },\n {\n "type": "page_view",\n "timestamp": "2024-03-15T08:32:15"\n },\n {\n "type": "download",\n "timestamp": "2024-03-15T08:45:30"\n }\n ],\n "preferences": {\n "theme": "dark",\n "notifications": true,\n "language": "zh-CN"\n }\n }\n}', annotations=None)] isError=False
MCP会自动处理参数转换和验证,确保工具接收到正确格式的输入。
工具设计最佳实践
- 明确的命名和描述:为工具提供清晰的名称和详细的描述完善的参数文档:为每个参数添加描述、类型信息和验证规则适当的错误处理:在工具函数中添加适当的错误处理和有意义的错误消息合理的默认值:为可选参数提供合理的默认值功能单一原则:每个工具应专注于单一功能,避免过于复杂参数验证:使用枚举和Pydantic模型进行严格的参数验证返回值结构化:返回结构化的数据,便于后续处理