diff --git a/app/tools/base_mcp_server.py b/app/tools/base_mcp_server.py new file mode 100644 index 0000000..50f1907 --- /dev/null +++ b/app/tools/base_mcp_server.py @@ -0,0 +1,152 @@ +""" +MCP Server 基类 +提供通用的 MCP 服务器基础设施 + +设计说明: +- McpServer: 通用 MCP 服务器基类 + - 子类在 __init__ 中通过 self.tools = [...] 赋值工具实例 + - 提供工具列表展示、调用处理、服务器启动等通用逻辑 + +使用示例: + class MyServer(McpServer): + def __init__(self): + super().__init__("my-mcp", "1.0.0") + # 直接赋值工具实例列表 + self.tools = [MyTool1(), MyTool2()] + + # 启动服务器 + server = MyServer() + await server.run_stdio() +""" +import asyncio +from typing import Any, Dict, List, Optional + +from mcp.server import Server +from mcp.server.models import InitializationOptions +from mcp.types import ( + Tool, + TextContent, + ImageContent, + EmbeddedResource, + ServerCapabilities, +) + + +class BaseMcpServer: + """ + 通用 MCP 服务器基类 + + 子类在 __init__ 中通过 self.tools 属性赋值工具实例列表。 + 封装了工具列表展示、调用处理、结果格式化、服务器启动等通用逻辑。 + """ + + def __init__(self, server_name: str, version: str = "1.0.0"): + """ + 初始化 MCP 服务器 + + Args: + server_name: 服务器名称 + version: 服务器版本 + """ + self.server_name = server_name + self.version = version + self.server = Server(server_name) + + # 工具列表(子类在 __init__ 中赋值) + self.tools: List[Any] = [] + + # 注册处理器 + self.server.list_tools()(self._handle_list_tools) + self.server.call_tool()(self._handle_call_tool) + + async def _handle_list_tools(self) -> list[Tool]: + """列出所有可用的工具""" + return [ + Tool( + name=tool.name, + description=tool.description, + inputSchema=tool.parameters_schema, + ) + for tool in self.tools + ] + + async def _handle_call_tool( + self, name: str, arguments: Optional[dict[str, Any]] = None + ) -> list[TextContent | ImageContent | EmbeddedResource]: + """处理工具调用""" + if not arguments: + arguments = {} + + # 查找工具 + tool = next((t for t in self.tools if t.name == name), None) + if not tool: + return [TextContent(type="text", text=f"未知工具:{name}")] + + try: + result = tool.execute(**arguments) + response_text = self._format_tool_result(result) + return [TextContent(type="text", text=response_text)] + + except ValueError as e: + return [TextContent(type="text", text=f"❌ 参数错误:{str(e)}")] + except RuntimeError as e: + return [TextContent(type="text", text=f"❌ 执行失败:{str(e)}")] + except Exception as e: + return [TextContent(type="text", text=f"❌ 未知错误:{str(e)}")] + + @staticmethod + def _format_tool_result(result: Any) -> str: + """ + 格式化工具执行结果 + + 支持多种返回格式: + - 包含 message/data 属性的对象 + - 字典(包含 message/data 键) + - 其他类型(直接转为字符串) + """ + response_text = "" + + # 提取消息 + message = getattr(result, 'message', None) + if message: + response_text += f"✅ {message}\n\n" + elif isinstance(result, dict) and 'message' in result: + response_text += f"✅ {result['message']}\n\n" + + # 提取数据 + data = getattr(result, 'data', None) + if data is None and isinstance(result, dict): + data = result.get('data') + + if data: + response_text += "详情:\n" + if isinstance(data, dict): + for key, value in data.items(): + response_text += f" - {key}: {value}\n" + else: + response_text += f" {data}\n" + + # 如果没有消息也没有数据,直接返回结果的字符串形式 + if not response_text: + response_text = str(result) + + return response_text + + async def run_stdio(self): + """ + 启动服务器,使用标准输入输出通信 + """ + from mcp.server.stdio import stdio_server + + async with stdio_server() as (read_stream, write_stream): + await self.server.run( + read_stream, + write_stream, + InitializationOptions( + server_name=self.server_name, + server_version=self.version, + capabilities=ServerCapabilities( + tools={} # 启用工具能力 + ), + ), + ) diff --git a/app/tools/git/git_mcp_server.py b/app/tools/git/git_mcp_server.py new file mode 100644 index 0000000..6ec7132 --- /dev/null +++ b/app/tools/git/git_mcp_server.py @@ -0,0 +1,47 @@ +""" +Git MCP 服务器 +整合所有 Git 工具为 MCP Server + +设计说明: +- GitServer 继承自 McpServer,提供 Git 相关的工具 +- 在 __init__ 中直接实例化并赋值工具列表 +- 工具定义在各自的文件中,git_server 负责组装 +""" +import asyncio +from app.tools.base_mcp_server import BaseMcpServer +from app.tools.git.git_clone_tool import GitCloneTool +from app.tools.git.git_checkout_tool import GitCheckoutTool +from app.tools.git.git_add_tool import GitAddTool +from app.tools.git.git_commit_tool import GitCommitTool +from app.tools.git.git_push_tool import GitPushTool + + +class GitMcpServer(BaseMcpServer): + """ + Git MCP 服务器 + + 继承 McpServer,在 __init__ 中直接赋值 Git 工具实例列表。 + """ + + def __init__(self): + # 初始化父类,设置服务器名称和版本 + super().__init__(server_name="git-mcp", version="1.0.0") + + # 直接赋值工具实例列表 + self.tools = [ + GitCloneTool(), + GitCheckoutTool(), + GitAddTool(), + GitCommitTool(), + GitPushTool(), + ] + + +async def main(): + """启动 Git MCP 服务器""" + server = GitMcpServer() + await server.run_stdio() + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/requirements.txt b/requirements.txt index feeab56..c16c0bb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,27 +1,10 @@ -fastapi==0.104.1 -uvicorn==0.24.0 -sqlalchemy>=2.0.49 -pymysql==1.1.0 -minio==7.2.0 +anyio>=4.5 +fastapi>=0.104.1 +uvicorn==0.31.1 openai>=1.12.0 -python-multipart==0.0.6 python-dotenv~=1.2.2 pydantic>=2.10.0 pydantic-settings>=2.1.0 httpx>=0.27.0 -pypandoc==1.17 -MyApplication~=0.1.0 -starlette~=0.27.0 requests==2.31.0 -beautifulsoup4==4.12.2 -pdfplumber==0.10.3 -python-docx==1.1.0 -pywin32==311 -markitdown~=0.0.2 -bs4~=0.0.2 -docxcompose~=2.1.0 -docxtpl~=0.20.2 -asyncio~=4.0.0 -vosk~=0.3.45 -pydub~=0.25.1 mcp>=1.0.0 \ No newline at end of file