如何在 MCP 中定义工具和验证参数?
MCP 的工具定义和参数验证是确保系统稳定性和可用性的关键部分。以下是详细的实现方法:工具定义结构每个 MCP 工具都需要定义以下属性:{ "name": "tool_name", "description": "工具的详细描述", "inputSchema": { "type": "object", "properties": { "param1": { "type": "string", "description": "参数1的描述" }, "param2": { "type": "number", "description": "参数2的描述", "minimum": 0, "maximum": 100 } }, "required": ["param1"] }}1. 参数类型定义MCP 支持以下参数类型:string:字符串类型number:数字类型(整数或浮点数)integer:整数类型boolean:布尔类型array:数组类型object:对象类型null:空值{ "name": "search_database", "inputSchema": { "type": "object", "properties": { "query": { "type": "string", "description": "搜索查询字符串", "minLength": 1, "maxLength": 500 }, "limit": { "type": "integer", "description": "返回结果数量限制", "minimum": 1, "maximum": 100, "default": 10 }, "filters": { "type": "object", "description": "过滤条件", "properties": { "category": {"type": "string"}, "date_range": { "type": "object", "properties": { "start": {"type": "string", "format": "date"}, "end": {"type": "string", "format": "date"} } } } }, "sort_by": { "type": "string", "enum": ["relevance", "date", "popularity"], "description": "排序方式" } }, "required": ["query"] }}2. 参数验证实现from typing import Any, Dict, Listimport reclass ParameterValidator: def __init__(self, schema: Dict[str, Any]): self.schema = schema def validate(self, params: Dict[str, Any]) -> tuple[bool, str]: """验证参数""" # 检查必需参数 required = self.schema.get("required", []) for param in required: if param not in params: return False, f"缺少必需参数: {param}" # 验证每个参数 properties = self.schema.get("properties", {}) for param_name, param_value in params.items(): if param_name not in properties: return False, f"未知参数: {param_name}" param_schema = properties[param_name] is_valid, error = self._validate_param( param_value, param_schema ) if not is_valid: return False, f"参数 '{param_name}' 验证失败: {error}" return True, "" def _validate_param(self, value: Any, schema: Dict[str, Any]) -> tuple[bool, str]: """验证单个参数""" param_type = schema.get("type") # 类型验证 if param_type == "string": if not isinstance(value, str): return False, "期望字符串类型" # 字符串长度验证 if "minLength" in schema and len(value) < schema["minLength"]: return False, f"字符串长度不能少于 {schema['minLength']}" if "maxLength" in schema and len(value) > schema["maxLength"]: return False, f"字符串长度不能超过 {schema['maxLength']}" # 正则表达式验证 if "pattern" in schema: if not re.match(schema["pattern"], value): return False, "格式不匹配" elif param_type == "number": if not isinstance(value, (int, float)): return False, "期望数字类型" if "minimum" in schema and value < schema["minimum"]: return False, f"数值不能小于 {schema['minimum']}" if "maximum" in schema and value > schema["maximum"]: return False, f"数值不能大于 {schema['maximum']}" elif param_type == "integer": if not isinstance(value, int): return False, "期望整数类型" elif param_type == "boolean": if not isinstance(value, bool): return False, "期望布尔类型" elif param_type == "array": if not isinstance(value, list): return False, "期望数组类型" if "minItems" in schema and len(value) < schema["minItems"]: return False, f"数组长度不能少于 {schema['minItems']}" if "maxItems" in schema and len(value) > schema["maxItems"]: return False, f"数组长度不能超过 {schema['maxItems']}" elif param_type == "object": if not isinstance(value, dict): return False, "期望对象类型" # 枚举值验证 if "enum" in schema and value not in schema["enum"]: return False, f"值必须是以下之一: {schema['enum']}" return True, ""3. 工具描述最佳实践# 好的工具描述示例{ "name": "execute_sql_query", "description": """在数据库中执行 SQL 查询并返回结果。 此工具支持 SELECT 查询,可以用于检索、聚合和分析数据。 查询结果将以表格形式返回,包含列名和数据行。 注意事项: - 只支持 SELECT 查询,不支持 INSERT、UPDATE、DELETE - 查询超时时间为 30 秒 - 返回结果最多 1000 行 """, "inputSchema": { "type": "object", "properties": { "query": { "type": "string", "description": "SQL 查询语句(仅支持 SELECT)", "minLength": 1 }, "database": { "type": "string", "description": "数据库名称", "enum": ["production", "staging", "analytics"] } }, "required": ["query"] }}4. 高级参数验证class AdvancedValidator(ParameterValidator): def _validate_param(self, value: Any, schema: Dict[str, Any]) -> tuple[bool, str]: # 调用父类验证 is_valid, error = super()._validate_param(value, schema) if not is_valid: return False, error # 自定义验证 if "format" in schema: is_valid, error = self._validate_format(value, schema["format"]) if not is_valid: return False, error if "customValidator" in schema: is_valid, error = schema["customValidator"](value) if not is_valid: return False, error return True, "" def _validate_format(self, value: Any, format_type: str) -> tuple[bool, str]: """验证格式""" if format_type == "email": if not re.match(r'^[^@]+@[^@]+\.[^@]+$', value): return False, "无效的邮箱格式" elif format_type == "uri": if not re.match(r'^https?://', value): return False, "无效的 URI 格式" elif format_type == "date": try: from datetime import datetime datetime.strptime(value, "%Y-%m-%d") except ValueError: return False, "无效的日期格式 (YYYY-MM-DD)" return True, ""5. 错误处理def handle_tool_call(tool_name: str, params: Dict[str, Any]) -> Dict[str, Any]: """处理工具调用""" try: # 获取工具定义 tool = get_tool_definition(tool_name) # 验证参数 validator = ParameterValidator(tool["inputSchema"]) is_valid, error = validator.validate(params) if not is_valid: return { "success": False, "error": f"参数验证失败: {error}", "error_code": "INVALID_PARAMS" } # 执行工具 result = execute_tool(tool_name, params) return { "success": True, "result": result } except Exception as e: return { "success": False, "error": f"工具执行失败: {str(e)}", "error_code": "EXECUTION_ERROR" }通过完善的工具定义和参数验证机制,可以确保 MCP 系统的稳定性和可靠性。