MCP Development Framework
by aigo666
- .lh
- mcp_simple_tool
- tools
{
"sourceFile": "mcp_simple_tool/tools/README.md",
"activeCommit": 0,
"commits": [
{
"activePatchIndex": 1,
"patches": [
{
"date": 1741333431551,
"content": "Index: \n===================================================================\n--- \n+++ \n"
},
{
"date": 1741408412235,
"content": "Index: \n===================================================================\n--- \n+++ \n@@ -10,28 +10,112 @@\n │ ├── __init__.py # 定义工具基类和注册器\n │ ├── loader.py # 工具加载器,自动加载所有工具\n │ ├── url_tool.py # URL工具实现\n │ ├── pdf_tool.py # PDF解析工具实现\n-│ └── quick_pdf_tool.py # 快速PDF预览工具实现\n+│ ├── quick_pdf_tool.py # 快速PDF预览工具实现\n+│ └── word_tool.py # Word文档解析工具实现\n ├── __init__.py\n ├── __main__.py\n └── server.py # MCP服务器实现\n ```\n \n+## 核心组件\n+\n+### 1. BaseTool 基类\n+\n+所有工具都继承自`BaseTool`基类,它定义了工具的基本接口:\n+\n+```python\n+class BaseTool:\n+ \"\"\"所有工具的基类\"\"\"\n+ name: str = \"\" # 工具名称\n+ description: str = \"\" # 工具描述\n+ input_schema: dict = {} # 输入参数模式\n+ \n+ @classmethod\n+ def get_tool_definition(cls) -> types.Tool:\n+ \"\"\"获取工具定义\"\"\"\n+ return types.Tool(\n+ name=cls.name,\n+ description=cls.description,\n+ inputSchema=cls.input_schema\n+ )\n+ \n+ async def execute(self, arguments: dict) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:\n+ \"\"\"执行工具逻辑,需要在子类中实现\"\"\"\n+ raise NotImplementedError(\"Tool implementation must override execute method\")\n+```\n+\n+### 2. ToolRegistry 工具注册器\n+\n+`ToolRegistry`负责管理所有已注册的工具:\n+\n+```python\n+class ToolRegistry:\n+ \"\"\"工具注册器,用于管理所有可用工具\"\"\"\n+ _tools: Dict[str, Type[BaseTool]] = {}\n+ \n+ @classmethod\n+ def register(cls, tool_class: Type[BaseTool]) -> Type[BaseTool]:\n+ \"\"\"注册工具\"\"\"\n+ cls._tools[tool_class.name] = tool_class\n+ return tool_class\n+ \n+ @classmethod\n+ def get_tool(cls, name: str) -> Type[BaseTool]:\n+ \"\"\"获取工具类\"\"\"\n+ if name not in cls._tools:\n+ raise ValueError(f\"Unknown tool: {name}\")\n+ return cls._tools[name]\n+ \n+ @classmethod\n+ def list_tools(cls) -> List[types.Tool]:\n+ \"\"\"列出所有可用工具\"\"\"\n+ return [tool_class.get_tool_definition() for tool_class in cls._tools.values()]\n+```\n+\n+### 3. 工具加载器\n+\n+`loader.py`中的工具加载器负责自动发现和加载所有工具:\n+\n+```python\n+def load_tools() -> List[Type[BaseTool]]:\n+ \"\"\"自动加载tools目录下的所有工具模块\"\"\"\n+ # 获取当前模块的路径\n+ package_path = os.path.dirname(__file__)\n+ \n+ # 获取所有子模块\n+ for _, name, is_pkg in pkgutil.iter_modules([package_path]):\n+ # 跳过__init__.py和loader.py\n+ if name in ['__init__', 'loader']:\n+ continue\n+ \n+ # 导入模块\n+ module_name = f\"{__package__}.{name}\"\n+ importlib.import_module(module_name)\n+ \n+ # 返回所有已注册的工具类\n+ return list(ToolRegistry._tools.values())\n+```\n+\n ## 如何开发新工具\n \n-1. 在`tools`目录下创建一个新的Python文件,如`your_tool.py`\n-2. 导入必要的依赖和基类\n-3. 创建一个继承自`BaseTool`的工具类\n-4. 使用`@ToolRegistry.register`装饰器注册工具\n-5. 实现工具的`execute`方法\n+### 步骤1: 创建工具文件\n \n-### 工具模板示例\n+在`tools`目录下创建一个新的Python文件,如`your_tool.py`。\n \n+### 步骤2: 导入必要的依赖\n+\n ```python\n import mcp.types as types\n from . import BaseTool, ToolRegistry\n+```\n \n+### 步骤3: 创建工具类\n+\n+创建一个继承自`BaseTool`的工具类,并使用`@ToolRegistry.register`装饰器注册工具:\n+\n+```python\n @ToolRegistry.register\n class YourTool(BaseTool):\n \"\"\"您的工具描述\"\"\"\n name = \"your_tool_name\" # 工具的唯一标识符\n@@ -49,32 +133,147 @@\n \"description\": \"参数2的描述(可选)\",\n }\n },\n }\n+```\n+\n+### 步骤4: 实现execute方法\n+\n+实现工具的`execute`方法,处理输入参数并返回结果:\n+\n+```python\n+async def execute(self, arguments: dict) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:\n+ \"\"\"执行工具逻辑\"\"\"\n+ # 参数验证\n+ if \"param1\" not in arguments:\n+ return [types.TextContent(\n+ type=\"text\",\n+ text=\"Error: Missing required argument 'param1'\"\n+ )]\n+ \n+ # 获取参数\n+ param1 = arguments[\"param1\"]\n+ param2 = arguments.get(\"param2\", 0) # 获取可选参数,提供默认值\n \n+ # 执行工具逻辑\n+ result = f\"处理参数: {param1}, {param2}\"\n+ \n+ # 返回结果\n+ return [types.TextContent(\n+ type=\"text\",\n+ text=result\n+ )]\n+```\n+\n+## 返回类型\n+\n+工具可以返回以下类型的内容:\n+\n+1. **TextContent** - 文本内容\n+ ```python\n+ types.TextContent(type=\"text\", text=\"这是文本内容\")\n+ ```\n+\n+2. **ImageContent** - 图像内容\n+ ```python\n+ types.ImageContent(\n+ type=\"image\",\n+ format=\"jpeg\",\n+ data=base64.b64encode(image_data).decode(\"utf-8\")\n+ )\n+ ```\n+\n+3. **EmbeddedResource** - 嵌入资源\n+ ```python\n+ types.EmbeddedResource(\n+ type=\"embedded\",\n+ format=\"pdf\",\n+ data=base64.b64encode(pdf_data).decode(\"utf-8\")\n+ )\n+ ```\n+\n+## 最佳实践\n+\n+1. **参数验证**:始终验证必需的参数是否存在,并提供清晰的错误消息。\n+\n+2. **错误处理**:使用try-except块捕获异常,并返回用户友好的错误消息。\n+\n+3. **进度反馈**:对于长时间运行的任务,提供进度反馈。\n+\n+4. **资源清理**:确保在函数结束时清理所有资源(如临时文件)。\n+\n+5. **类型注解**:使用类型注解提高代码可读性和可维护性。\n+\n+6. **文档字符串**:为类和方法提供详细的文档字符串。\n+\n+## 示例工具\n+\n+### URL工具\n+\n+```python\n+@ToolRegistry.register\n+class UrlTool(BaseTool):\n+ \"\"\"URL获取工具,用于获取网站内容\"\"\"\n+ name = \"url\"\n+ description = \"Fetches a website and returns its content\"\n+ input_schema = {\n+ \"type\": \"object\",\n+ \"required\": [\"url\"],\n+ \"properties\": {\n+ \"url\": {\n+ \"type\": \"string\",\n+ \"description\": \"URL to fetch\",\n+ }\n+ },\n+ }\n+ \n async def execute(self, arguments: dict) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:\n- \"\"\"执行工具逻辑\"\"\"\n- # 参数验证\n- if \"param1\" not in arguments:\n+ \"\"\"获取网站内容\"\"\"\n+ if \"url\" not in arguments:\n return [types.TextContent(\n type=\"text\",\n- text=\"Error: Missing required argument 'param1'\"\n+ text=\"Error: Missing required argument 'url'\"\n )]\n \n- # 获取参数\n- param1 = arguments[\"param1\"]\n- param2 = arguments.get(\"param2\", 0) # 获取可选参数,提供默认值\n- \n- # 执行工具逻辑\n- result = f\"处理参数: {param1}, {param2}\"\n- \n- # 返回结果\n- return [types.TextContent(\n- type=\"text\",\n- text=result\n- )]\n+ url = arguments[\"url\"]\n+ # 实现获取网站内容的逻辑\n+ # ...\n+ return [types.TextContent(type=\"text\", text=response_text)]\n ```\n \n+### PDF工具\n+\n+```python\n+@ToolRegistry.register\n+class PdfTool(BaseTool):\n+ \"\"\"PDF解析工具,用于解析PDF文件并提取文本和图片\"\"\"\n+ name = \"file\"\n+ description = \"解析PDF文件并提取文本和图片内容\"\n+ input_schema = {\n+ \"type\": \"object\",\n+ \"required\": [\"file_path\"],\n+ \"properties\": {\n+ \"file_path\": {\n+ \"type\": \"string\",\n+ \"description\": \"PDF文件的本地路径,例如'/path/to/document.pdf'\",\n+ }\n+ },\n+ }\n+ \n+ async def execute(self, arguments: dict) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:\n+ \"\"\"解析PDF文件并提取文本和图片\"\"\"\n+ if \"file_path\" not in arguments:\n+ return [types.TextContent(\n+ type=\"text\",\n+ text=\"Error: Missing required argument 'file_path'\"\n+ )]\n+ \n+ file_path = arguments[\"file_path\"]\n+ # 实现PDF解析逻辑\n+ # ...\n+ return results\n+```\n+\n ## 注意事项\n \n 1. 每个工具必须有一个唯一的`name`\n 2. 工具描述应该清晰地说明工具的用途和使用方法\n@@ -85,9 +284,5 @@\n ## 自动加载机制\n \n 框架使用`loader.py`中的自动加载机制,在启动时自动发现和加载所有工具。您只需按照上述模板创建新工具,它将在下次启动服务器时自动注册。\n \n-无需修改`server.py`或其他任何文件,框架会自动处理工具的注册和调用。\n-\n-## 扩展示例\n-\n-您可以参考现有的工具实现(`url_tool.py`, `pdf_tool.py`, `quick_pdf_tool.py`)作为开发新工具的参考。 \n\\ No newline at end of file\n+无需修改`server.py`或其他任何文件,框架会自动处理工具的注册和调用。 \n\\ No newline at end of file\n"
}
],
"date": 1741333431551,
"name": "Commit-0",
"content": "# SEE工具框架\n\n这是一个用于SEE(Standard Extension Environment)对接的模块化工具框架。该框架允许开发者轻松创建和扩展自定义工具,并通过MCP协议与模型交互。\n\n## 框架结构\n\n```\nmcp_simple_tool/\n├── tools/\n│ ├── __init__.py # 定义工具基类和注册器\n│ ├── loader.py # 工具加载器,自动加载所有工具\n│ ├── url_tool.py # URL工具实现\n│ ├── pdf_tool.py # PDF解析工具实现\n│ └── quick_pdf_tool.py # 快速PDF预览工具实现\n├── __init__.py\n├── __main__.py\n└── server.py # MCP服务器实现\n```\n\n## 如何开发新工具\n\n1. 在`tools`目录下创建一个新的Python文件,如`your_tool.py`\n2. 导入必要的依赖和基类\n3. 创建一个继承自`BaseTool`的工具类\n4. 使用`@ToolRegistry.register`装饰器注册工具\n5. 实现工具的`execute`方法\n\n### 工具模板示例\n\n```python\nimport mcp.types as types\nfrom . import BaseTool, ToolRegistry\n\n@ToolRegistry.register\nclass YourTool(BaseTool):\n \"\"\"您的工具描述\"\"\"\n name = \"your_tool_name\" # 工具的唯一标识符\n description = \"您的工具描述\" # 工具的描述信息,将显示给用户\n input_schema = {\n \"type\": \"object\",\n \"required\": [\"param1\"], # 必需的参数\n \"properties\": {\n \"param1\": {\n \"type\": \"string\",\n \"description\": \"参数1的描述\",\n },\n \"param2\": {\n \"type\": \"integer\",\n \"description\": \"参数2的描述(可选)\",\n }\n },\n }\n \n async def execute(self, arguments: dict) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:\n \"\"\"执行工具逻辑\"\"\"\n # 参数验证\n if \"param1\" not in arguments:\n return [types.TextContent(\n type=\"text\",\n text=\"Error: Missing required argument 'param1'\"\n )]\n \n # 获取参数\n param1 = arguments[\"param1\"]\n param2 = arguments.get(\"param2\", 0) # 获取可选参数,提供默认值\n \n # 执行工具逻辑\n result = f\"处理参数: {param1}, {param2}\"\n \n # 返回结果\n return [types.TextContent(\n type=\"text\",\n text=result\n )]\n```\n\n## 注意事项\n\n1. 每个工具必须有一个唯一的`name`\n2. 工具描述应该清晰地说明工具的用途和使用方法\n3. 输入模式应该准确描述所需的参数和类型\n4. 所有参数验证应在`execute`方法中处理\n5. 工具应返回适当的`TextContent`或`ImageContent`对象列表\n\n## 自动加载机制\n\n框架使用`loader.py`中的自动加载机制,在启动时自动发现和加载所有工具。您只需按照上述模板创建新工具,它将在下次启动服务器时自动注册。\n\n无需修改`server.py`或其他任何文件,框架会自动处理工具的注册和调用。\n\n## 扩展示例\n\n您可以参考现有的工具实现(`url_tool.py`, `pdf_tool.py`, `quick_pdf_tool.py`)作为开发新工具的参考。 "
}
]
}