Skip to main content
Glama
leeguooooo
by leeguooooo
TOOL_REGISTRY_FIX.md8.58 kB
# Tool Registry Fix - MCP Types Integration **Date**: 2025-10-15 **Issue**: MCP Server 无法获取工具列表 **Status**: ✅ Fixed **Tests**: ✅ 35/35 Passed --- ## 🐛 问题描述 ### 根本原因 `tool_registry.list_tools()` 返回普通的 `dict` 对象,而 MCP 的 `Server.list_tools()` 装饰器期望访问 `tool.name` 等属性。 **问题流程**: 1. IDE 启动 MCP server 并发送 `list_tools` 请求 2. Server 调用 `tool_registry.list_tools()` 获取工具列表 3. 返回值是 `List[Dict]` 而不是 `List[types.Tool]` 4. MCP Server 尝试访问 `tool.name` 属性失败(dict 没有 name 属性) 5. 服务端抛出异常 6. 客户端(Anthropic/Smithery IDE)收到失败回复 7. IDE 标记该 server 为 "**No tools**" ### 错误表现 ```python # Before - 错误的实现 def list_tools(self) -> List[Dict[str, Any]]: """List all registered tools with their schemas""" return [ { "name": name, "description": tool.description, "inputSchema": tool.schema } for name, tool in self._tools.items() ] # MCP Server 尝试访问: for tool in tools: print(tool.name) # ❌ AttributeError: 'dict' object has no attribute 'name' ``` --- ## ✅ 解决方案 ### 修改 `tool_registry.py` #### 1. 导入 MCP types ```python from mcp import types ``` #### 2. 返回 `List[types.Tool]` ```python def list_tools(self) -> List[types.Tool]: """List all registered tools with their schemas""" return [ types.Tool( name=name, description=tool.description, inputSchema=tool.schema, ) for name, tool in self._tools.items() ] ``` ### 修改 `mcp_tools.py` #### 保持向后兼容性 `get_tool_definitions()` 方法用于测试,需要返回 dict: ```python def get_tool_definitions(self) -> List[Dict[str, Any]]: """Return all registered tool definitions""" return [tool.model_dump() for tool in tool_registry.list_tools()] ``` #### MCP Server Handler 直接返回 `types.Tool` 实例: ```python @self.server.list_tools() async def handle_list_tools(): return tool_registry.list_tools() # ✅ 返回 List[types.Tool] ``` --- ## 🔄 工作流程 ### Before (错误) ``` tool_registry.list_tools() ↓ List[Dict] ❌ ↓ MCP Server 尝试访问 dict.name ↓ AttributeError ↓ IDE: "No tools" ``` ### After (正确) ``` tool_registry.list_tools() ↓ List[types.Tool] ✅ ↓ MCP Server 访问 tool.name ↓ 成功获取工具列表 ↓ IDE: 显示所有工具 ``` --- ## 📝 代码变更 ### src/core/tool_registry.py ```python # Added import from mcp import types # Updated method signature and implementation def list_tools(self) -> List[types.Tool]: """List all registered tools with their schemas""" return [ types.Tool( name=name, description=tool.description, inputSchema=tool.schema, ) for name, tool in self._tools.items() ] ``` ### src/mcp_tools.py ```python # Updated for backward compatibility with tests def get_tool_definitions(self) -> List[Dict[str, Any]]: """Return all registered tool definitions""" return [tool.model_dump() for tool in tool_registry.list_tools()] # Server handler remains simple @self.server.list_tools() async def handle_list_tools(): return tool_registry.list_tools() ``` --- ## ✅ 验证 ### 单元测试 ```bash $ uv run pytest tests/test_mcp_tools.py -v ============================== 8 passed in 0.23s =============================== ✅ 所有 MCP tools 测试通过 ``` ### 完整测试 ```bash $ uv run pytest tests/ -v ============================== 35 passed in 0.68s ============================== ✅ 所有 35 个测试通过 ``` ### 类型检查 ```python # types.Tool 的结构 @dataclass class Tool: name: str description: str inputSchema: Dict[str, Any] def model_dump(self) -> Dict[str, Any]: return { "name": self.name, "description": self.description, "inputSchema": self.inputSchema } ``` --- ## 🚀 使用指南 ### 重新启动 MCP Server #### 方法 1: IDE 中重启 **Anthropic Claude Desktop**: 1. 打开 Settings → Developer → MCP Servers 2. 找到 `email` server 3. 点击 "Remove" 删除 4. 点击 "Add Server" 重新添加 5. 重启 Claude Desktop **或者**: 1. 直接重启 Claude Desktop 2. IDE 会自动重新连接所有 MCP servers #### 方法 2: 命令行测试 ```bash # 测试脚本启动 ./run.sh # 应该看到: # INFO - Starting MCP Email Service # INFO - Registered tool: list_emails # INFO - Registered tool: send_email # ... (所有工具) # INFO - Server running with stdio transport ``` ### 验证工具列表 启动成功后,IDE 应该能看到所有工具: **Expected tools** (20+ tools): - ✅ list_emails - ✅ get_email_detail - ✅ mark_emails - ✅ mark_email_read - ✅ mark_email_unread - ✅ batch_mark_read - ✅ delete_emails - ✅ delete_email - ✅ batch_delete_emails - ✅ search_emails - ✅ send_email - ✅ reply_email - ✅ forward_email - ✅ list_folders - ✅ move_emails_to_folder - ✅ flag_email - ✅ get_email_attachments - ✅ check_connection - ✅ list_accounts - ✅ sync_emails (如果安装了 schedule) --- ## 🔍 故障排查 ### 问题 1: 仍然显示 "No tools" **可能原因**: IDE 缓存了失败状态 **解决方案**: ```bash # 1. 完全移除 server # 2. 清理 IDE 缓存 (如果有选项) # 3. 重启 IDE # 4. 重新添加 server ``` ### 问题 2: 启动失败 **检查日志**: ```bash # macOS tail -f ~/Library/Logs/Claude/mcp*.log # 查找错误信息 grep -i error ~/Library/Logs/Claude/mcp*.log ``` **常见错误**: - `No module named 'mcp'` → 运行 `uv pip install mcp` - `relative import error` → 确保使用 `./run.sh` 或 `python -m src.main` ### 问题 3: 工具列表不完整 **可能原因**: 某些工具注册失败 **检查**: ```bash # 运行测试 uv run pytest tests/test_mcp_tools.py::TestMCPTools::test_tool_definitions -v # 应该显示所有注册的工具 ``` --- ## 📊 影响分析 ### 功能影响 - ✅ **无破坏性变更**: 所有现有功能保持不变 - ✅ **向后兼容**: 测试代码继续使用 dict (通过 model_dump) - ✅ **MCP 兼容**: Server 获得正确的 types.Tool 对象 ### 性能影响 - ✅ **无性能影响**: `types.Tool` 是轻量级数据类 - ✅ **内存使用**: 与 dict 基本相同 - ✅ **启动时间**: 无显著变化 ### 测试影响 - ✅ **所有测试通过**: 35/35 - ✅ **无需修改测试**: `get_tool_definitions()` 保持返回 dict --- ## 🎓 技术细节 ### MCP Types.Tool `mcp.types.Tool` 是 MCP 协议定义的标准工具类型: ```python from mcp import types # 创建工具 tool = types.Tool( name="example_tool", description="An example tool", inputSchema={ "type": "object", "properties": { "param": {"type": "string"} } } ) # 访问属性 print(tool.name) # ✅ "example_tool" print(tool.description) # ✅ "An example tool" # 转换为 dict tool_dict = tool.model_dump() # ✅ {"name": "example_tool", ...} ``` ### 装饰器行为 MCP Server 的 `@server.list_tools()` 装饰器: ```python @server.list_tools() async def handle_list_tools(): # 返回值必须是 List[types.Tool] # Server 会遍历列表并访问每个 tool 的属性 return [ types.Tool(name="tool1", ...), types.Tool(name="tool2", ...), ] # Server 内部处理: tools = await handle_list_tools() for tool in tools: # 访问 tool.name, tool.description, tool.inputSchema # 如果是 dict,这里会失败 validate_tool(tool) ``` --- ## 📚 相关文档 ### MCP 协议 - [MCP Specification](https://modelcontextprotocol.io) - [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) ### 项目文档 - **ARCHITECTURE.md** - 架构说明 - **QUICK_REFERENCE.md** - 快速参考 - **src/core/tool_registry.py** - Registry 实现 --- ## ✨ 总结 ### 问题 - ❌ `tool_registry.list_tools()` 返回 `List[Dict]` - ❌ MCP Server 无法访问 dict 属性 - ❌ IDE 显示 "No tools" ### 解决 - ✅ 返回 `List[types.Tool]` - ✅ MCP Server 正确获取工具列表 - ✅ IDE 显示所有工具 ### 验证 - ✅ 35/35 测试通过 - ✅ 向后兼容 - ✅ 生产就绪 --- **Status**: ✅ **FIXED AND VERIFIED** MCP Server 现在能够正确获取和显示所有工具!🎉

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/leeguooooo/email-mcp-service'

If you have feedback or need assistance with the MCP directory API, please join our Discord server