Phase 7-10: CustomHookLoader, MCPSkillLoader, SkillTriggerDetector, TeamMember, WebSocketManager
This commit is contained in:
169
backend/app/agents/skills/loaders/mcp_loader.py
Normal file
169
backend/app/agents/skills/loaders/mcp_loader.py
Normal file
@@ -0,0 +1,169 @@
|
||||
"""MCP Skill 加载器 - Phase 9.2
|
||||
|
||||
从 MCP (Model Context Protocol) 服务器发现和加载 Skills。
|
||||
"""
|
||||
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
from app.agents.skills.metadata import SkillMetadata
|
||||
|
||||
|
||||
class MCPSkillLoader:
|
||||
"""MCP Skill 加载器
|
||||
|
||||
从 MCP 服务器发现可用的 Skills。
|
||||
"""
|
||||
|
||||
def __init__(self, mcp_servers: list[dict[str, Any]] | None = None):
|
||||
"""
|
||||
Args:
|
||||
mcp_servers: MCP 服务器列表,每项包含 name, command, env 等
|
||||
"""
|
||||
self.mcp_servers = mcp_servers or []
|
||||
self._discovered_skills: dict[str, SkillMetadata] = {}
|
||||
|
||||
def discover_skills(self) -> list[SkillMetadata]:
|
||||
"""从所有配置的 MCP 服务器发现 Skills
|
||||
|
||||
Returns:
|
||||
发现的 Skill 列表
|
||||
"""
|
||||
skills = []
|
||||
|
||||
for server in self.mcp_servers:
|
||||
server_skills = self._discover_from_server(server)
|
||||
skills.extend(server_skills)
|
||||
|
||||
return skills
|
||||
|
||||
def _discover_from_server(self, server: dict[str, Any]) -> list[SkillMetadata]:
|
||||
"""从单个 MCP 服务器发现 Skills
|
||||
|
||||
Args:
|
||||
server: 服务器配置
|
||||
|
||||
Returns:
|
||||
Skill 列表
|
||||
"""
|
||||
skills = []
|
||||
server_name = server.get("name", "unknown")
|
||||
|
||||
# 模拟从 MCP 服务器获取工具列表
|
||||
# 实际实现时,这里会调用 MCP 服务器的 list_tools 接口
|
||||
try:
|
||||
tools = self._call_mcp_list_tools(server)
|
||||
for tool in tools:
|
||||
skill = self._tool_to_skill(tool, server_name)
|
||||
if skill:
|
||||
skills.append(skill)
|
||||
self._discovered_skills[skill.name] = skill
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return skills
|
||||
|
||||
def _call_mcp_list_tools(self, server: dict[str, Any]) -> list[dict[str, Any]]:
|
||||
"""调用 MCP 服务器的 list_tools 接口
|
||||
|
||||
Args:
|
||||
server: 服务器配置
|
||||
|
||||
Returns:
|
||||
工具列表
|
||||
"""
|
||||
# TODO: 实现实际的 MCP 协议调用
|
||||
# 目前返回空列表,实际使用时需要实现 MCP 客户端
|
||||
return []
|
||||
|
||||
def _tool_to_skill(self, tool: dict[str, Any], server: str) -> SkillMetadata | None:
|
||||
"""将 MCP 工具转换为 Skill
|
||||
|
||||
Args:
|
||||
tool: MCP 工具定义
|
||||
server: 服务器名
|
||||
|
||||
Returns:
|
||||
Skill 元数据或 None
|
||||
"""
|
||||
tool_name = tool.get("name")
|
||||
if not tool_name:
|
||||
return None
|
||||
|
||||
return SkillMetadata(
|
||||
id=f"mcp_{server}_{tool_name}",
|
||||
name=f"{server}:{tool_name}",
|
||||
description=tool.get("description", f"MCP tool: {tool_name}"),
|
||||
version="1.0.0",
|
||||
content=self._generate_skill_content(tool),
|
||||
triggers=[f"@{server}", f"/{tool_name}"],
|
||||
tools=[tool_name],
|
||||
tags=["mcp", server],
|
||||
enabled=True,
|
||||
)
|
||||
|
||||
def _generate_skill_content(self, tool: dict[str, Any]) -> str:
|
||||
"""生成 Skill 内容
|
||||
|
||||
Args:
|
||||
tool: MCP 工具定义
|
||||
|
||||
Returns:
|
||||
Skill 内容字符串
|
||||
"""
|
||||
name = tool.get("name", "unknown")
|
||||
description = tool.get("description", "No description")
|
||||
input_schema = tool.get("inputSchema", {})
|
||||
|
||||
content = f"""# MCP Tool: {name}
|
||||
|
||||
**Description**: {description}
|
||||
|
||||
**Server**: {tool.get("server", "unknown")}
|
||||
|
||||
**Input Schema**:
|
||||
```json
|
||||
{input_schema}
|
||||
```
|
||||
|
||||
**Usage**:
|
||||
Use the `/{name}` command or `@{tool.get("server", "server")}` to invoke this tool.
|
||||
|
||||
**Examples**:
|
||||
```
|
||||
/{name} arg1=value1 arg2=value2
|
||||
@{tool.get("server", "server")} {name} --arg1 value1
|
||||
```
|
||||
"""
|
||||
return content
|
||||
|
||||
def get_skill(self, name: str) -> SkillMetadata | None:
|
||||
"""获取已发现的 Skill
|
||||
|
||||
Args:
|
||||
name: Skill 名称
|
||||
|
||||
Returns:
|
||||
Skill 元数据或 None
|
||||
"""
|
||||
return self._discovered_skills.get(name)
|
||||
|
||||
def list_skills(self) -> list[SkillMetadata]:
|
||||
"""列出所有已发现的 Skills
|
||||
|
||||
Returns:
|
||||
Skill 列表
|
||||
"""
|
||||
return list(self._discovered_skills.values())
|
||||
|
||||
|
||||
# 全局加载器
|
||||
_loader: MCPSkillLoader | None = None
|
||||
|
||||
|
||||
def get_mcp_skill_loader() -> MCPSkillLoader:
|
||||
"""获取全局 MCP Skill 加载器"""
|
||||
global _loader
|
||||
if _loader is None:
|
||||
_loader = MCPSkillLoader()
|
||||
return _loader
|
||||
Reference in New Issue
Block a user