MCP高级应用:构建智能函数工具

函数工具是MCP框架的核心组件之一,它允许开发者定义结构化的函数接口供AI模型调用。本文将深入探讨MCP的函数工具系统,介绍如何创建从简单到复杂的各类工具,包括基本函数、参数验证、枚举类型、复杂数据模型等高级特性。通过这些示例,你将掌握如何为AI应用构建强大而灵活的工具集,使AI能够执行各种复杂任务。

函数工具系统概述

MCP的函数工具系统允许开发者将Python函数暴露为可被AI调用的工具。每个工具都有明确定义的输入参数和返回值,并且可以包含详细的描述信息。MCP会自动处理参数验证、类型转换和错误处理,使开发者能够专注于实现工具的核心功能。

工具类型与实现

1. 基本函数工具

最简单的工具是直接使用Python函数并添加@mcp.tool()装饰器:

python 复制代码
@mcp.tool()
def calculate_sum(numbers: List[float]) -> float:
    """计算数字列表的总和
    
    这个函数接收一个数字列表,然后返回它们的总和。
    非常适合进行简单的数学计算。
    
    Args:
        numbers: 要计算总和的数字列表
        
    Returns:
        所有数字的总和
    """
    return sum(numbers)

MCP会自动从函数名称派生工具名称,并从文档字符串生成描述。类型注解用于指定参数和返回值的类型。

2. 自定义名称的工具

你可以通过name参数为工具指定自定义名称:

python 复制代码
@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类可以限制参数的可能值,提供更严格的参数验证:

python 复制代码
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模型:

python 复制代码
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 v

class 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支持的类型:

python 复制代码
@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()方法来调用工具:

python 复制代码
# 列出所有可用工具
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的functiontool的使用

bash 复制代码
python .\mcp\03_function_tools.py
D:\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会自动处理参数转换和验证,确保工具接收到正确格式的输入。

工具设计最佳实践

  1. 明确的命名和描述:为工具提供清晰的名称和详细的描述
  2. 完善的参数文档:为每个参数添加描述、类型信息和验证规则
  3. 适当的错误处理:在工具函数中添加适当的错误处理和有意义的错误消息
  4. 合理的默认值:为可选参数提供合理的默认值
  5. 功能单一原则:每个工具应专注于单一功能,避免过于复杂
  6. 参数验证:使用枚举和Pydantic模型进行严格的参数验证
  7. 返回值结构化:返回结构化的数据,便于后续处理
相关推荐
饭勺oO1 天前
AI 编程配置太头疼?ACP 帮你一键搞定,再也不用反复折腾!
ai·prompt·agent·acp·mcp·skills·agent skill
AlienZHOU1 天前
MCP 是最大骗局?Skills 才是救星?
agent·mcp·vibecoding
Linux内核拾遗1 天前
人人都在聊 MCP,它到底解决了什么?
aigc·ai编程·mcp
谷哥的小弟1 天前
SQLite MCP服务器安装以及客户端连接配置
服务器·数据库·人工智能·sqlite·大模型·源码·mcp
tyw151 天前
解决 Trae MySQL MCP 连接失败(Fail to start)
mcp·trae·fail to start·mysql mcp·mcp兼容
谷哥的小弟2 天前
File System MCP服务器安装以及客户端连接配置
服务器·人工智能·大模型·file system·mcp·ai项目
啊湘2 天前
vscode 使用 github (适用CURSOR等使用)
ide·vscode·github·cursor·mcp
小小呱呱蛙2 天前
Claude Code 自下而上分析(Slash/Sub Agents/Skills/MCP)带来的启发
agent·claude·mcp
callJJ2 天前
MCP配置与实战:深入理解现代开发工具链
javascript·node.js·vue·mcp·windsurf
谷哥的小弟3 天前
Brave Search MCP服务器安装以及客户端连接配置
搜索引擎·大模型·spring ai·mcp·brave search