MCP中工具概念和实现方式

本文详细阐述了MCP(Model Context Protocol)中工具(Tools)的概念和实现方式,为工具的设计、使用和安全提供了清晰的指南。以下是文档的核心要点:
工具概念
工具是MCP的一个关键组成部分,允许服务器暴露可执行的功能,供客户端和LLMs调用。通过工具,模型可以执行计算、操作外部系统,甚至与真实世界交互。
- 设计目的:工具被设计为模型可控(model-controlled),模型可以自动调用工具执行任务,但需要人类批准。
- 核心能力:
- 发现(Discovery):列出所有可用工具。
- 调用(Invocation):通过API调用工具并获取结果。
- 灵活性(Flexibility):支持从简单操作到复杂API交互。
工具定义
工具通过如下结构定义:
{
name: string; // 工具唯一标识符
description?: string; // 人类可读的描述
inputSchema: { // JSON Schema 描述输入参数
type: "object",
properties: { ... } // 工具的参数定义
}
}
工具实现
通过MCP服务器(支持TypeScript和Python),可轻松定义和实现工具。
示例工具:求和计算
TypeScript 实现:
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [{
name: "calculate_sum",
description: "Add two numbers together",
inputSchema: {
type: "object",
properties: {
a: { type: "number" },
b: { type: "number" }
},
required: ["a", "b"]
}
}]
};
});
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "calculate_sum") {
const { a, b } = request.params.arguments;
return {
content: [{ type: "text", text: String(a + b) }]
};
}
throw new Error("Tool not found");
});
Python 实现:
@app.list_tools()
async def list_tools() -> list[types.Tool]:
return [
types.Tool(
name="calculate_sum",
description="Add two numbers together",
inputSchema={
"type": "object",
"properties": {
"a": {"type": "number"},
"b": {"type": "number"}
},
"required": ["a", "b"]
}
)
]
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
if name == "calculate_sum":
return [types.TextContent(type="text", text=str(arguments["a"] + arguments["b"]))]
raise ValueError(f"Tool not found: {name}")
工具类型示例
- 系统操作:运行系统命令。
- API集成:包装外部API,如创建GitHub问题。
- 数据处理:分析CSV文件。
最佳实践
- 使用清晰的名称和描述。
- 提供详细的JSON Schema定义。
- 实现错误处理和输入校验。
- 操作应专注且原子化。
- 支持进度报告和日志记录。
安全考虑
- 输入验证:
- 校验所有参数是否符合Schema。
- 防止命令注入和路径遍历。
- 访问控制:
- 验证身份与权限。
- 实施速率限制。
- 错误处理:
- 隐藏内部错误,避免暴露敏感信息。
动态工具发现
- 客户端可以动态列出工具。
- 服务器可以实时更新工具定义,并通知客户端。
错误处理
工具的错误应通过结果对象报告,而不是MCP协议级别的错误。以下是正确处理错误的示例:
TypeScript:
try {
const result = performOperation();
return { content: [{ type: "text", text: `Success: ${result}` }] };
} catch (error) {
return { isError: true, content: [{ type: "text", text: `Error: ${error.message}` }] };
}
Python:
try:
result = perform_operation()
return types.CallToolResult(content=[types.TextContent(type="text", text=f"Success: {result}")])
except Exception as error:
return types.CallToolResult(isError=True, content=[types.TextContent(type="text", text=f"Error: {str(error)}")])
测试工具
- 功能测试:验证正确执行和错误处理。
- 集成测试:测试工具与外部系统的交互。
- 安全测试:确保输入验证和访问控制。
- 性能测试:验证负载下的行为。
- 错误测试:测试工具如何报告和处理异常。
这份文档为开发者提供了清晰的指南,让他们能够快速定义、实现和测试安全且高效的工具,同时确保模型在使用这些工具时的可靠性与安全性。