git_mcp_server
This commit is contained in:
parent
0b72ed20bc
commit
b354afb235
|
|
@ -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={} # 启用工具能力
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
@ -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())
|
||||||
|
|
@ -1,27 +1,10 @@
|
||||||
fastapi==0.104.1
|
anyio>=4.5
|
||||||
uvicorn==0.24.0
|
fastapi>=0.104.1
|
||||||
sqlalchemy>=2.0.49
|
uvicorn==0.31.1
|
||||||
pymysql==1.1.0
|
|
||||||
minio==7.2.0
|
|
||||||
openai>=1.12.0
|
openai>=1.12.0
|
||||||
python-multipart==0.0.6
|
|
||||||
python-dotenv~=1.2.2
|
python-dotenv~=1.2.2
|
||||||
pydantic>=2.10.0
|
pydantic>=2.10.0
|
||||||
pydantic-settings>=2.1.0
|
pydantic-settings>=2.1.0
|
||||||
httpx>=0.27.0
|
httpx>=0.27.0
|
||||||
pypandoc==1.17
|
|
||||||
MyApplication~=0.1.0
|
|
||||||
starlette~=0.27.0
|
|
||||||
requests==2.31.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
|
mcp>=1.0.0
|
||||||
Loading…
Reference in New Issue