in devel
This commit is contained in:
parent
f184c199c9
commit
38dcc420b4
|
|
@ -399,32 +399,11 @@ def create_agent() -> tuple[Agent, SkillRegistry]:
|
||||||
Returns:
|
Returns:
|
||||||
(agent, registry) —— registry 需在程序退出时调用 .close()
|
(agent, registry) —— registry 需在程序退出时调用 .close()
|
||||||
"""
|
"""
|
||||||
from tools.calculator import CalculatorTool
|
|
||||||
from tools.code_executor import CodeExecutorTool
|
|
||||||
from tools.file_reader import FileReaderTool
|
|
||||||
from tools.ssh_docker import SSHDockerTool
|
|
||||||
from tools.static_analyzer import StaticAnalyzerTool
|
|
||||||
from tools.web_search import WebSearchTool
|
|
||||||
|
|
||||||
registry = SkillRegistry()
|
registry = SkillRegistry()
|
||||||
|
registry.load_local_skills(settings.skills_directory)
|
||||||
# 注册本地工具(根据 config.yaml mcp.enabled_tools 过滤)
|
registry.load_local_tools()
|
||||||
enabled = settings.mcp.enabled_tools
|
|
||||||
tool_map = {
|
|
||||||
"calculator": CalculatorTool,
|
|
||||||
"web_search": WebSearchTool,
|
|
||||||
"file_reader": FileReaderTool,
|
|
||||||
"code_executor": CodeExecutorTool,
|
|
||||||
"static_analyzer": StaticAnalyzerTool,
|
|
||||||
"ssh_docker": SSHDockerTool,
|
|
||||||
}
|
|
||||||
for name in enabled:
|
|
||||||
if name in tool_map:
|
|
||||||
registry.register_local(tool_map[name]())
|
|
||||||
|
|
||||||
# 连接在线 MCP Skill(来自 config.yaml mcp_skills)
|
# 连接在线 MCP Skill(来自 config.yaml mcp_skills)
|
||||||
registry.connect_skills()
|
registry.connect_mcp_skills()
|
||||||
|
|
||||||
agent = Agent(registry)
|
agent = Agent(registry)
|
||||||
return agent, registry
|
return agent, registry
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,7 @@ llm:
|
||||||
stream: false
|
stream: false
|
||||||
model_path: ""
|
model_path: ""
|
||||||
ollama_host: "http://localhost:11434"
|
ollama_host: "http://localhost:11434"
|
||||||
|
skills_directory: "C:\\Users\\sonto\\Workspace\\base_agent\\skills\\OpenCLI\\skills" # 新增:SKILL.md 文件所在目录
|
||||||
skills_directory: "./skills" # 新增:SKILL.md 文件所在目录
|
|
||||||
# ── 本地 MCP Server 配置 ───────────────────────────────────────
|
# ── 本地 MCP Server 配置 ───────────────────────────────────────
|
||||||
mcp:
|
mcp:
|
||||||
server_name: "DemoMCPServer"
|
server_name: "DemoMCPServer"
|
||||||
|
|
|
||||||
|
|
@ -375,7 +375,7 @@ class ConfigLoader:
|
||||||
memory=cls._build_memory(raw.get("memory", {})),
|
memory=cls._build_memory(raw.get("memory", {})),
|
||||||
logging=cls._build_logging(raw.get("logging", {})),
|
logging=cls._build_logging(raw.get("logging", {})),
|
||||||
agent=cls._build_agent(raw.get("agent", {})),
|
agent=cls._build_agent(raw.get("agent", {})),
|
||||||
skills=raw.get("skills", [])
|
skills_directory=raw.get("skills_directory", "")
|
||||||
)
|
)
|
||||||
|
|
||||||
# ── LLM ───────────────────────────────────────────────────
|
# ── LLM ───────────────────────────────────────────────────
|
||||||
|
|
|
||||||
|
|
@ -70,12 +70,6 @@ class OpenAIProvider(BaseProvider):
|
||||||
3. 当后续步骤依赖前步结果时,先完成前步再继续
|
3. 当后续步骤依赖前步结果时,先完成前步再继续
|
||||||
4. 每次只规划并调用当前最合适的工具
|
4. 每次只规划并调用当前最合适的工具
|
||||||
5. 所有工具执行完毕后,整合结果给出最终回复
|
5. 所有工具执行完毕后,整合结果给出最终回复
|
||||||
|
|
||||||
## 重要规则
|
|
||||||
- 数学计算必须使用 calculator 工具,不要自行计算
|
|
||||||
- 需要实时信息时使用 web_search 工具
|
|
||||||
- 文件操作使用 file_reader 工具
|
|
||||||
- 代码执行使用 code_executor 工具
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# 回复生成系统 Prompt
|
# 回复生成系统 Prompt
|
||||||
|
|
|
||||||
211
logs/agent.log
211
logs/agent.log
|
|
@ -6140,3 +6140,214 @@ The function `get_system_name()` uses `platform.system()` to determine the syste
|
||||||
重试 : 2 次
|
重试 : 2 次
|
||||||
2026-04-13 16:12:50 [INFO ] agent.MCP.SkillClient │ 🔌 stdio 启动子进程: python3 /Users/sontolau/Applications/hexstrike-ai/hexstrike_mcp.py --server http://localhost:8999
|
2026-04-13 16:12:50 [INFO ] agent.MCP.SkillClient │ 🔌 stdio 启动子进程: python3 /Users/sontolau/Applications/hexstrike-ai/hexstrike_mcp.py --server http://localhost:8999
|
||||||
2026-04-13 16:12:50 [INFO ] agent.MCP.SkillClient │ ✅ stdio 子进程已启动 PID=48433
|
2026-04-13 16:12:50 [INFO ] agent.MCP.SkillClient │ ✅ stdio 子进程已启动 PID=48433
|
||||||
|
2026-04-15 15:34:11 [WARNING ] agent.TOOL.SSHDocker │ ⚠️ paramiko 未安装,请执行: pip install paramiko>=3.0.0
|
||||||
|
2026-04-15 15:34:11 [WARNING ] agent.mcp.SkillLoader │ 未在opencli-autofix发现SKILL.md文件
|
||||||
|
2026-04-15 15:34:11 [WARNING ] agent.mcp.SkillLoader │ 未在opencli-browser发现SKILL.md文件
|
||||||
|
2026-04-15 15:34:11 [WARNING ] agent.mcp.SkillLoader │ 未在opencli-explorer发现SKILL.md文件
|
||||||
|
2026-04-15 15:34:11 [WARNING ] agent.mcp.SkillLoader │ 未在opencli-oneshot发现SKILL.md文件
|
||||||
|
2026-04-15 15:34:11 [WARNING ] agent.mcp.SkillLoader │ 未在opencli-usage发现SKILL.md文件
|
||||||
|
2026-04-15 15:34:11 [WARNING ] agent.mcp.SkillLoader │ 未在smart-search发现SKILL.md文件
|
||||||
|
2026-04-15 15:34:11 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: calculator
|
||||||
|
2026-04-15 15:34:11 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: web_search
|
||||||
|
2026-04-15 15:34:11 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: file_reader
|
||||||
|
2026-04-15 15:34:11 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: code_executor
|
||||||
|
2026-04-15 15:34:11 [INFO ] agent.MCP.SkillRegistry │ 🌐 开始连接在线 MCP Skills,数量=1
|
||||||
|
2026-04-15 15:34:11 [INFO ] agent.MCP.SkillClient │ 🌐 连接在线 MCP Skill: [hexstrike-ai]
|
||||||
|
传输协议: stdio
|
||||||
|
地址 : python3
|
||||||
|
超时 : 300s
|
||||||
|
重试 : 2 次
|
||||||
|
2026-04-15 15:34:11 [INFO ] agent.MCP.SkillClient │ 🔌 stdio 启动子进程: python3 /Users/sontolau/Applications/hexstrike-ai/hexstrike_mcp.py --server http://localhost:8999
|
||||||
|
2026-04-15 15:34:11 [INFO ] agent.MCP.SkillClient │ ✅ stdio 子进程已启动 PID=19704
|
||||||
|
2026-04-15 15:34:11 [WARNING ] agent.MCP.SkillClient │ ⚠️ 连接失败 (attempt 1/3),1s 后重试: stdio 子进程无响应 skill=hexstrike-ai method=initialize
|
||||||
|
2026-04-15 15:34:12 [DEBUG ] agent.MCP.SkillClient │ 🔌 stdio 子进程已关闭 skill=hexstrike-ai
|
||||||
|
2026-04-15 15:34:12 [INFO ] agent.MCP.SkillClient │ 🔌 stdio 启动子进程: python3 /Users/sontolau/Applications/hexstrike-ai/hexstrike_mcp.py --server http://localhost:8999
|
||||||
|
2026-04-15 15:34:13 [INFO ] agent.MCP.SkillClient │ ✅ stdio 子进程已启动 PID=14668
|
||||||
|
2026-04-15 15:34:13 [WARNING ] agent.MCP.SkillClient │ ⚠️ 连接失败 (attempt 2/3),2s 后重试: stdio 子进程无响应 skill=hexstrike-ai method=initialize
|
||||||
|
2026-04-15 15:34:15 [DEBUG ] agent.MCP.SkillClient │ 🔌 stdio 子进程已关闭 skill=hexstrike-ai
|
||||||
|
2026-04-15 15:34:15 [INFO ] agent.MCP.SkillClient │ 🔌 stdio 启动子进程: python3 /Users/sontolau/Applications/hexstrike-ai/hexstrike_mcp.py --server http://localhost:8999
|
||||||
|
2026-04-15 15:34:15 [INFO ] agent.MCP.SkillClient │ ✅ stdio 子进程已启动 PID=13920
|
||||||
|
2026-04-15 15:34:15 [DEBUG ] agent.MCP.SkillClient │ 🔌 stdio 子进程已关闭 skill=hexstrike-ai
|
||||||
|
2026-04-15 15:34:15 [ERROR ] agent.MCP.SkillRegistry │ ❌ Skill [hexstrike-ai] 连接失败,跳过
|
||||||
|
错误: ❌ MCP Skill [hexstrike-ai] 连接失败(已重试 2 次)
|
||||||
|
最后错误: stdio 子进程无响应 skill=hexstrike-ai method=initialize
|
||||||
|
2026-04-15 15:34:15 [DEBUG ] agent.MCP.SkillClient │ 🔌 MCP Skill [hexstrike-ai] 已断开
|
||||||
|
2026-04-15 15:34:15 [INFO ] agent.MCP.SkillRegistry │ 📊 SkillRegistry 初始化完成
|
||||||
|
本地工具 : 4 个 ['calculator', 'web_search', 'file_reader', 'code_executor']
|
||||||
|
远端工具 : 0 个 []
|
||||||
|
2026-04-15 15:34:16 [INFO ] agent.Agent │ 🤖 Agent 初始化完成
|
||||||
|
LLM : openai / gpt-4o
|
||||||
|
工具总数 : 4 个
|
||||||
|
最大步数 : 10
|
||||||
|
工具列表 :
|
||||||
|
🔵 [local ] calculator
|
||||||
|
🔵 [local ] web_search
|
||||||
|
🔵 [local ] file_reader
|
||||||
|
🔵 [local ] code_executor
|
||||||
|
2026-04-15 15:35:21 [INFO ] agent.MCP.SkillRegistry │ 🔌 SkillRegistry 已关闭所有连接
|
||||||
|
2026-04-15 15:35:23 [WARNING ] agent.TOOL.SSHDocker │ ⚠️ paramiko 未安装,请执行: pip install paramiko>=3.0.0
|
||||||
|
2026-04-15 15:35:23 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-autofix
|
||||||
|
2026-04-15 15:35:23 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-browser
|
||||||
|
2026-04-15 15:35:23 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-explorer
|
||||||
|
2026-04-15 15:35:23 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-oneshot
|
||||||
|
2026-04-15 15:35:23 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-usage
|
||||||
|
2026-04-15 15:35:23 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: smart-search
|
||||||
|
2026-04-15 15:35:23 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: calculator
|
||||||
|
2026-04-15 15:35:23 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: web_search
|
||||||
|
2026-04-15 15:35:23 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: file_reader
|
||||||
|
2026-04-15 15:35:23 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: code_executor
|
||||||
|
2026-04-15 15:35:23 [INFO ] agent.MCP.SkillRegistry │ 🌐 开始连接在线 MCP Skills,数量=1
|
||||||
|
2026-04-15 15:35:23 [INFO ] agent.MCP.SkillClient │ 🌐 连接在线 MCP Skill: [hexstrike-ai]
|
||||||
|
传输协议: stdio
|
||||||
|
地址 : python3
|
||||||
|
超时 : 300s
|
||||||
|
重试 : 2 次
|
||||||
|
2026-04-15 15:35:23 [INFO ] agent.MCP.SkillClient │ 🔌 stdio 启动子进程: python3 /Users/sontolau/Applications/hexstrike-ai/hexstrike_mcp.py --server http://localhost:8999
|
||||||
|
2026-04-15 15:35:23 [INFO ] agent.MCP.SkillClient │ ✅ stdio 子进程已启动 PID=19588
|
||||||
|
2026-04-15 15:35:23 [WARNING ] agent.MCP.SkillClient │ ⚠️ 连接失败 (attempt 1/3),1s 后重试: stdio 子进程无响应 skill=hexstrike-ai method=initialize
|
||||||
|
2026-04-15 15:35:24 [DEBUG ] agent.MCP.SkillClient │ 🔌 stdio 子进程已关闭 skill=hexstrike-ai
|
||||||
|
2026-04-15 15:35:24 [INFO ] agent.MCP.SkillClient │ 🔌 stdio 启动子进程: python3 /Users/sontolau/Applications/hexstrike-ai/hexstrike_mcp.py --server http://localhost:8999
|
||||||
|
2026-04-15 15:35:24 [INFO ] agent.MCP.SkillClient │ ✅ stdio 子进程已启动 PID=19208
|
||||||
|
2026-04-15 15:35:24 [WARNING ] agent.MCP.SkillClient │ ⚠️ 连接失败 (attempt 2/3),2s 后重试: stdio 子进程无响应 skill=hexstrike-ai method=initialize
|
||||||
|
2026-04-15 15:35:26 [DEBUG ] agent.MCP.SkillClient │ 🔌 stdio 子进程已关闭 skill=hexstrike-ai
|
||||||
|
2026-04-15 15:35:26 [INFO ] agent.MCP.SkillClient │ 🔌 stdio 启动子进程: python3 /Users/sontolau/Applications/hexstrike-ai/hexstrike_mcp.py --server http://localhost:8999
|
||||||
|
2026-04-15 15:35:26 [INFO ] agent.MCP.SkillClient │ ✅ stdio 子进程已启动 PID=19680
|
||||||
|
2026-04-15 15:35:26 [DEBUG ] agent.MCP.SkillClient │ 🔌 stdio 子进程已关闭 skill=hexstrike-ai
|
||||||
|
2026-04-15 15:35:26 [ERROR ] agent.MCP.SkillRegistry │ ❌ Skill [hexstrike-ai] 连接失败,跳过
|
||||||
|
错误: ❌ MCP Skill [hexstrike-ai] 连接失败(已重试 2 次)
|
||||||
|
最后错误: stdio 子进程无响应 skill=hexstrike-ai method=initialize
|
||||||
|
2026-04-15 15:35:26 [DEBUG ] agent.MCP.SkillClient │ 🔌 MCP Skill [hexstrike-ai] 已断开
|
||||||
|
2026-04-15 15:35:26 [INFO ] agent.MCP.SkillRegistry │ 📊 SkillRegistry 初始化完成
|
||||||
|
本地工具 : 4 个 ['calculator', 'web_search', 'file_reader', 'code_executor']
|
||||||
|
远端工具 : 6 个 ['opencli-autofix', 'opencli-browser', 'opencli-explorer', 'opencli-oneshot', 'opencli-usage', 'smart-search']
|
||||||
|
2026-04-15 15:44:33 [WARNING ] agent.TOOL.SSHDocker │ ⚠️ paramiko 未安装,请执行: pip install paramiko>=3.0.0
|
||||||
|
2026-04-15 15:44:33 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-autofix
|
||||||
|
2026-04-15 15:44:33 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-autofix', 'description': 'Automatically fix broken OpenCLI adapters when commands fail. Load this skill when an opencli command fails — it guides you through diagnosing the failure via OPENCLI_DIAGNOSTIC, patching the adapter, retrying, and filing an upstream GitHub issue after a verified fix. Works with any AI agent.', 'allowed-tools': 'Bash(opencli:*), Bash(gh:*), Read, Edit, Write'}
|
||||||
|
2026-04-15 15:44:33 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-browser
|
||||||
|
2026-04-15 15:44:33 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-browser', 'description': 'Make websites accessible for AI agents. Navigate, click, type, extract, wait — using Chrome with existing login sessions. No LLM API key needed.', 'allowed-tools': 'Bash(opencli:*), Read, Edit, Write'}
|
||||||
|
2026-04-15 15:44:33 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-explorer
|
||||||
|
2026-04-15 15:44:33 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-explorer', 'description': 'Use when creating a new OpenCLI adapter from scratch, adding support for a new website or platform, exploring a site\'s API endpoints via browser DevTools, or when a user asks to automatically generate a CLI for a website (e.g. "帮我生成 xxx.com 的 cli"). Covers automated generation, API discovery workflow, authentication strategy selection, TS adapter writing, and testing.', 'tags': ['opencli', 'adapter', 'browser', 'api-discovery', 'cli', 'web-scraping', 'automation', 'generate']}
|
||||||
|
2026-04-15 15:44:33 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-oneshot
|
||||||
|
2026-04-15 15:44:33 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-oneshot', 'description': 'Use when quickly generating a single OpenCLI command from a specific URL and goal description. 4-step process — open page, capture API, write TS adapter, test. For full site exploration, use opencli-explorer instead.', 'tags': ['opencli', 'adapter', 'quick-start', 'ts', 'cli', 'one-shot', 'automation']}
|
||||||
|
2026-04-15 15:44:33 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-usage
|
||||||
|
2026-04-15 15:44:33 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-usage', 'description': 'Use when running OpenCLI commands to interact with websites (Bilibili, Twitter, Reddit, Xiaohongshu, etc.), desktop apps (Cursor, Notion), or public APIs (HackerNews, arXiv). Covers installation, command reference, and output formats for 87+ adapters.', 'version': '1.7.0', 'author': 'jackwener', 'tags': ['opencli', 'cli', 'browser', 'web', 'chrome-extension', 'cdp', 'bilibili', 'twitter', 'reddit', 'xiaohongshu', 'github', 'youtube', 'AI', 'agent', 'automation']}
|
||||||
|
2026-04-15 15:44:33 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: smart-search
|
||||||
|
2026-04-15 15:44:33 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'smart-search', 'description': '基于 opencli 命令的智能搜索路由器。当用户想要搜索、查询、查找或研究信息时,尤其是涉及指定网站、社交媒体、技术资料、新闻、购物、旅游、求职、金融或中文内容时,务必使用此 skill'}
|
||||||
|
2026-04-15 15:44:33 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: calculator
|
||||||
|
2026-04-15 15:44:33 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: web_search
|
||||||
|
2026-04-15 15:44:33 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: file_reader
|
||||||
|
2026-04-15 15:44:33 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: code_executor
|
||||||
|
2026-04-15 15:44:33 [INFO ] agent.MCP.SkillRegistry │ 🌐 开始连接在线 MCP Skills,数量=1
|
||||||
|
2026-04-15 15:44:33 [INFO ] agent.MCP.SkillClient │ 🌐 连接在线 MCP Skill: [hexstrike-ai]
|
||||||
|
传输协议: stdio
|
||||||
|
地址 : python3
|
||||||
|
超时 : 300s
|
||||||
|
重试 : 2 次
|
||||||
|
2026-04-15 15:44:33 [INFO ] agent.MCP.SkillClient │ 🔌 stdio 启动子进程: python3 /Users/sontolau/Applications/hexstrike-ai/hexstrike_mcp.py --server http://localhost:8999
|
||||||
|
2026-04-15 15:44:33 [INFO ] agent.MCP.SkillClient │ ✅ stdio 子进程已启动 PID=19376
|
||||||
|
2026-04-15 15:44:33 [WARNING ] agent.MCP.SkillClient │ ⚠️ 连接失败 (attempt 1/3),1s 后重试: stdio 子进程无响应 skill=hexstrike-ai method=initialize
|
||||||
|
2026-04-15 15:44:34 [DEBUG ] agent.MCP.SkillClient │ 🔌 stdio 子进程已关闭 skill=hexstrike-ai
|
||||||
|
2026-04-15 15:44:34 [INFO ] agent.MCP.SkillClient │ 🔌 stdio 启动子进程: python3 /Users/sontolau/Applications/hexstrike-ai/hexstrike_mcp.py --server http://localhost:8999
|
||||||
|
2026-04-15 15:44:34 [INFO ] agent.MCP.SkillClient │ ✅ stdio 子进程已启动 PID=18048
|
||||||
|
2026-04-15 15:44:34 [WARNING ] agent.MCP.SkillClient │ ⚠️ 连接失败 (attempt 2/3),2s 后重试: stdio 子进程无响应 skill=hexstrike-ai method=initialize
|
||||||
|
2026-04-15 15:44:36 [DEBUG ] agent.MCP.SkillClient │ 🔌 stdio 子进程已关闭 skill=hexstrike-ai
|
||||||
|
2026-04-15 15:44:36 [INFO ] agent.MCP.SkillClient │ 🔌 stdio 启动子进程: python3 /Users/sontolau/Applications/hexstrike-ai/hexstrike_mcp.py --server http://localhost:8999
|
||||||
|
2026-04-15 15:44:36 [INFO ] agent.MCP.SkillClient │ ✅ stdio 子进程已启动 PID=19960
|
||||||
|
2026-04-15 15:44:36 [DEBUG ] agent.MCP.SkillClient │ 🔌 stdio 子进程已关闭 skill=hexstrike-ai
|
||||||
|
2026-04-15 15:44:36 [ERROR ] agent.MCP.SkillRegistry │ ❌ Skill [hexstrike-ai] 连接失败,跳过
|
||||||
|
错误: ❌ MCP Skill [hexstrike-ai] 连接失败(已重试 2 次)
|
||||||
|
最后错误: stdio 子进程无响应 skill=hexstrike-ai method=initialize
|
||||||
|
2026-04-15 15:44:36 [DEBUG ] agent.MCP.SkillClient │ 🔌 MCP Skill [hexstrike-ai] 已断开
|
||||||
|
2026-04-15 15:44:36 [INFO ] agent.MCP.SkillRegistry │ 📊 SkillRegistry 初始化完成
|
||||||
|
本地工具 : 4 个 ['calculator', 'web_search', 'file_reader', 'code_executor']
|
||||||
|
远端工具 : 0 个 []
|
||||||
|
2026-04-15 15:44:37 [INFO ] agent.Agent │ 🤖 Agent 初始化完成
|
||||||
|
LLM : openai / gpt-4o
|
||||||
|
工具总数 : 4 个
|
||||||
|
最大步数 : 10
|
||||||
|
工具列表 :
|
||||||
|
🔵 [local ] calculator
|
||||||
|
🔵 [local ] web_search
|
||||||
|
🔵 [local ] file_reader
|
||||||
|
🔵 [local ] code_executor
|
||||||
|
2026-04-15 16:09:20 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-autofix
|
||||||
|
2026-04-15 16:09:20 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-autofix', 'description': 'Automatically fix broken OpenCLI adapters when commands fail. Load this skill when an opencli command fails — it guides you through diagnosing the failure via OPENCLI_DIAGNOSTIC, patching the adapter, retrying, and filing an upstream GitHub issue after a verified fix. Works with any AI agent.', 'allowed-tools': 'Bash(opencli:*), Bash(gh:*), Read, Edit, Write'}
|
||||||
|
2026-04-15 16:09:20 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-browser
|
||||||
|
2026-04-15 16:09:20 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-browser', 'description': 'Make websites accessible for AI agents. Navigate, click, type, extract, wait — using Chrome with existing login sessions. No LLM API key needed.', 'allowed-tools': 'Bash(opencli:*), Read, Edit, Write'}
|
||||||
|
2026-04-15 16:09:20 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-explorer
|
||||||
|
2026-04-15 16:09:20 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-explorer', 'description': 'Use when creating a new OpenCLI adapter from scratch, adding support for a new website or platform, exploring a site\'s API endpoints via browser DevTools, or when a user asks to automatically generate a CLI for a website (e.g. "帮我生成 xxx.com 的 cli"). Covers automated generation, API discovery workflow, authentication strategy selection, TS adapter writing, and testing.', 'tags': ['opencli', 'adapter', 'browser', 'api-discovery', 'cli', 'web-scraping', 'automation', 'generate']}
|
||||||
|
2026-04-15 16:09:20 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-oneshot
|
||||||
|
2026-04-15 16:09:20 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-oneshot', 'description': 'Use when quickly generating a single OpenCLI command from a specific URL and goal description. 4-step process — open page, capture API, write TS adapter, test. For full site exploration, use opencli-explorer instead.', 'tags': ['opencli', 'adapter', 'quick-start', 'ts', 'cli', 'one-shot', 'automation']}
|
||||||
|
2026-04-15 16:09:20 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-usage
|
||||||
|
2026-04-15 16:09:20 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-usage', 'description': 'Use when running OpenCLI commands to interact with websites (Bilibili, Twitter, Reddit, Xiaohongshu, etc.), desktop apps (Cursor, Notion), or public APIs (HackerNews, arXiv). Covers installation, command reference, and output formats for 87+ adapters.', 'version': '1.7.0', 'author': 'jackwener', 'tags': ['opencli', 'cli', 'browser', 'web', 'chrome-extension', 'cdp', 'bilibili', 'twitter', 'reddit', 'xiaohongshu', 'github', 'youtube', 'AI', 'agent', 'automation']}
|
||||||
|
2026-04-15 16:09:20 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: smart-search
|
||||||
|
2026-04-15 16:09:20 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'smart-search', 'description': '基于 opencli 命令的智能搜索路由器。当用户想要搜索、查询、查找或研究信息时,尤其是涉及指定网站、社交媒体、技术资料、新闻、购物、旅游、求职、金融或中文内容时,务必使用此 skill'}
|
||||||
|
2026-04-15 16:09:28 [INFO ] agent.MCP.SkillRegistry │ 🔧 注册本地工具: ['calculator', 'web_search', 'file_reader', 'code_executor']
|
||||||
|
2026-04-15 16:10:46 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-autofix
|
||||||
|
2026-04-15 16:10:46 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-autofix', 'description': 'Automatically fix broken OpenCLI adapters when commands fail. Load this skill when an opencli command fails — it guides you through diagnosing the failure via OPENCLI_DIAGNOSTIC, patching the adapter, retrying, and filing an upstream GitHub issue after a verified fix. Works with any AI agent.', 'allowed-tools': 'Bash(opencli:*), Bash(gh:*), Read, Edit, Write'}
|
||||||
|
2026-04-15 16:10:46 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-browser
|
||||||
|
2026-04-15 16:10:46 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-browser', 'description': 'Make websites accessible for AI agents. Navigate, click, type, extract, wait — using Chrome with existing login sessions. No LLM API key needed.', 'allowed-tools': 'Bash(opencli:*), Read, Edit, Write'}
|
||||||
|
2026-04-15 16:10:46 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-explorer
|
||||||
|
2026-04-15 16:10:46 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-explorer', 'description': 'Use when creating a new OpenCLI adapter from scratch, adding support for a new website or platform, exploring a site\'s API endpoints via browser DevTools, or when a user asks to automatically generate a CLI for a website (e.g. "帮我生成 xxx.com 的 cli"). Covers automated generation, API discovery workflow, authentication strategy selection, TS adapter writing, and testing.', 'tags': ['opencli', 'adapter', 'browser', 'api-discovery', 'cli', 'web-scraping', 'automation', 'generate']}
|
||||||
|
2026-04-15 16:10:46 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-oneshot
|
||||||
|
2026-04-15 16:10:46 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-oneshot', 'description': 'Use when quickly generating a single OpenCLI command from a specific URL and goal description. 4-step process — open page, capture API, write TS adapter, test. For full site exploration, use opencli-explorer instead.', 'tags': ['opencli', 'adapter', 'quick-start', 'ts', 'cli', 'one-shot', 'automation']}
|
||||||
|
2026-04-15 16:10:46 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-usage
|
||||||
|
2026-04-15 16:10:46 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-usage', 'description': 'Use when running OpenCLI commands to interact with websites (Bilibili, Twitter, Reddit, Xiaohongshu, etc.), desktop apps (Cursor, Notion), or public APIs (HackerNews, arXiv). Covers installation, command reference, and output formats for 87+ adapters.', 'version': '1.7.0', 'author': 'jackwener', 'tags': ['opencli', 'cli', 'browser', 'web', 'chrome-extension', 'cdp', 'bilibili', 'twitter', 'reddit', 'xiaohongshu', 'github', 'youtube', 'AI', 'agent', 'automation']}
|
||||||
|
2026-04-15 16:10:46 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: smart-search
|
||||||
|
2026-04-15 16:10:46 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'smart-search', 'description': '基于 opencli 命令的智能搜索路由器。当用户想要搜索、查询、查找或研究信息时,尤其是涉及指定网站、社交媒体、技术资料、新闻、购物、旅游、求职、金融或中文内容时,务必使用此 skill'}
|
||||||
|
2026-04-15 16:10:46 [INFO ] agent.MCP.SkillRegistry │ 🔧 注册本地工具: ['calculator', 'web_search', 'file_reader', 'code_executor']
|
||||||
|
2026-04-15 16:10:53 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: calculator
|
||||||
|
2026-04-15 16:10:58 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: web_search
|
||||||
|
2026-04-15 16:10:58 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: file_reader
|
||||||
|
2026-04-15 16:10:58 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: code_executor
|
||||||
|
2026-04-15 16:12:30 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-autofix
|
||||||
|
2026-04-15 16:12:30 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-autofix', 'description': 'Automatically fix broken OpenCLI adapters when commands fail. Load this skill when an opencli command fails — it guides you through diagnosing the failure via OPENCLI_DIAGNOSTIC, patching the adapter, retrying, and filing an upstream GitHub issue after a verified fix. Works with any AI agent.', 'allowed-tools': 'Bash(opencli:*), Bash(gh:*), Read, Edit, Write'}
|
||||||
|
2026-04-15 16:12:30 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-browser
|
||||||
|
2026-04-15 16:12:30 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-browser', 'description': 'Make websites accessible for AI agents. Navigate, click, type, extract, wait — using Chrome with existing login sessions. No LLM API key needed.', 'allowed-tools': 'Bash(opencli:*), Read, Edit, Write'}
|
||||||
|
2026-04-15 16:12:30 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-explorer
|
||||||
|
2026-04-15 16:12:30 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-explorer', 'description': 'Use when creating a new OpenCLI adapter from scratch, adding support for a new website or platform, exploring a site\'s API endpoints via browser DevTools, or when a user asks to automatically generate a CLI for a website (e.g. "帮我生成 xxx.com 的 cli"). Covers automated generation, API discovery workflow, authentication strategy selection, TS adapter writing, and testing.', 'tags': ['opencli', 'adapter', 'browser', 'api-discovery', 'cli', 'web-scraping', 'automation', 'generate']}
|
||||||
|
2026-04-15 16:12:30 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-oneshot
|
||||||
|
2026-04-15 16:12:30 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-oneshot', 'description': 'Use when quickly generating a single OpenCLI command from a specific URL and goal description. 4-step process — open page, capture API, write TS adapter, test. For full site exploration, use opencli-explorer instead.', 'tags': ['opencli', 'adapter', 'quick-start', 'ts', 'cli', 'one-shot', 'automation']}
|
||||||
|
2026-04-15 16:12:30 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: opencli-usage
|
||||||
|
2026-04-15 16:12:30 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'opencli-usage', 'description': 'Use when running OpenCLI commands to interact with websites (Bilibili, Twitter, Reddit, Xiaohongshu, etc.), desktop apps (Cursor, Notion), or public APIs (HackerNews, arXiv). Covers installation, command reference, and output formats for 87+ adapters.', 'version': '1.7.0', 'author': 'jackwener', 'tags': ['opencli', 'cli', 'browser', 'web', 'chrome-extension', 'cdp', 'bilibili', 'twitter', 'reddit', 'xiaohongshu', 'github', 'youtube', 'AI', 'agent', 'automation']}
|
||||||
|
2026-04-15 16:12:30 [INFO ] agent.MCP.SkillRegistry │ 📦 加载技能: smart-search
|
||||||
|
2026-04-15 16:12:30 [WARNING ] agent.MCP.SkillRegistry │ ⚠️ 工具实例缺少 name 属性,跳过: {'name': 'smart-search', 'description': '基于 opencli 命令的智能搜索路由器。当用户想要搜索、查询、查找或研究信息时,尤其是涉及指定网站、社交媒体、技术资料、新闻、购物、旅游、求职、金融或中文内容时,务必使用此 skill'}
|
||||||
|
2026-04-15 16:12:30 [INFO ] agent.MCP.SkillRegistry │ 🔧 注册本地工具: ['calculator', 'web_search', 'file_reader', 'code_executor']
|
||||||
|
2026-04-15 16:12:30 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: calculator
|
||||||
|
2026-04-15 16:12:30 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: web_search
|
||||||
|
2026-04-15 16:12:30 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: file_reader
|
||||||
|
2026-04-15 16:12:30 [DEBUG ] agent.MCP.SkillRegistry │ 📌 注册本地工具: code_executor
|
||||||
|
2026-04-15 16:12:30 [INFO ] agent.MCP.SkillRegistry │ 🌐 开始连接在线 MCP Skills,数量=1
|
||||||
|
2026-04-15 16:12:30 [INFO ] agent.MCP.SkillClient │ 🌐 连接在线 MCP Skill: [hexstrike-ai]
|
||||||
|
传输协议: stdio
|
||||||
|
地址 : python3
|
||||||
|
超时 : 300s
|
||||||
|
重试 : 2 次
|
||||||
|
2026-04-15 16:12:30 [INFO ] agent.MCP.SkillClient │ 🔌 stdio 启动子进程: python3 /Users/sontolau/Applications/hexstrike-ai/hexstrike_mcp.py --server http://localhost:8999
|
||||||
|
2026-04-15 16:12:33 [INFO ] agent.MCP.SkillClient │ ✅ stdio 子进程已启动 PID=18196
|
||||||
|
2026-04-15 16:12:37 [WARNING ] agent.MCP.SkillClient │ ⚠️ 连接失败 (attempt 1/3),1s 后重试: [Errno 22] Invalid argument
|
||||||
|
2026-04-15 16:12:38 [DEBUG ] agent.MCP.SkillClient │ 🔌 stdio 子进程已关闭 skill=hexstrike-ai
|
||||||
|
2026-04-15 16:12:38 [INFO ] agent.MCP.SkillClient │ 🔌 stdio 启动子进程: python3 /Users/sontolau/Applications/hexstrike-ai/hexstrike_mcp.py --server http://localhost:8999
|
||||||
|
2026-04-15 16:12:38 [INFO ] agent.MCP.SkillClient │ ✅ stdio 子进程已启动 PID=14612
|
||||||
|
2026-04-15 16:12:38 [WARNING ] agent.MCP.SkillClient │ ⚠️ 连接失败 (attempt 2/3),2s 后重试: stdio 子进程无响应 skill=hexstrike-ai method=initialize
|
||||||
|
2026-04-15 16:12:40 [DEBUG ] agent.MCP.SkillClient │ 🔌 stdio 子进程已关闭 skill=hexstrike-ai
|
||||||
|
2026-04-15 16:12:40 [INFO ] agent.MCP.SkillClient │ 🔌 stdio 启动子进程: python3 /Users/sontolau/Applications/hexstrike-ai/hexstrike_mcp.py --server http://localhost:8999
|
||||||
|
2026-04-15 16:12:40 [INFO ] agent.MCP.SkillClient │ ✅ stdio 子进程已启动 PID=7028
|
||||||
|
2026-04-15 16:12:40 [DEBUG ] agent.MCP.SkillClient │ 🔌 stdio 子进程已关闭 skill=hexstrike-ai
|
||||||
|
2026-04-15 16:12:40 [ERROR ] agent.MCP.SkillRegistry │ ❌ Skill [hexstrike-ai] 连接失败,跳过
|
||||||
|
错误: ❌ MCP Skill [hexstrike-ai] 连接失败(已重试 2 次)
|
||||||
|
最后错误: stdio 子进程无响应 skill=hexstrike-ai method=initialize
|
||||||
|
2026-04-15 16:12:40 [DEBUG ] agent.MCP.SkillClient │ 🔌 MCP Skill [hexstrike-ai] 已断开
|
||||||
|
2026-04-15 16:12:40 [INFO ] agent.MCP.SkillRegistry │ 📊 SkillRegistry 初始化完成
|
||||||
|
本地工具 : 4 个 ['calculator', 'web_search', 'file_reader', 'code_executor']
|
||||||
|
远端工具 : 0 个 []
|
||||||
|
2026-04-15 16:12:42 [INFO ] agent.Agent │ 🤖 Agent 初始化完成
|
||||||
|
LLM : openai / gpt-4o
|
||||||
|
工具总数 : 4 个
|
||||||
|
最大步数 : 10
|
||||||
|
工具列表 :
|
||||||
|
🔵 [local ] calculator
|
||||||
|
🔵 [local ] web_search
|
||||||
|
🔵 [local ] file_reader
|
||||||
|
🔵 [local ] code_executor
|
||||||
|
2026-04-15 16:19:35 [INFO ] agent.MCP.SkillRegistry │ 🔌 SkillRegistry 已关闭所有连接
|
||||||
|
|
|
||||||
148
main.py
148
main.py
|
|
@ -60,78 +60,78 @@ def run_mcp_server() -> None:
|
||||||
server.run_stdio()
|
server.run_stdio()
|
||||||
|
|
||||||
|
|
||||||
def run_check() -> None:
|
# def run_check() -> None:
|
||||||
"""检查配置和依赖完整性"""
|
# """检查配置和依赖完整性"""
|
||||||
print("=" * 60)
|
# print("=" * 60)
|
||||||
print(" 🔍 项目依赖检查")
|
# print(" 🔍 项目依赖检查")
|
||||||
print("=" * 60)
|
# print("=" * 60)
|
||||||
|
#
|
||||||
checks = [
|
# checks = [
|
||||||
("pyyaml", "yaml", "pip install pyyaml"),
|
# ("pyyaml", "yaml", "pip install pyyaml"),
|
||||||
("openai", "openai", "pip install openai>=1.0.0"),
|
# ("openai", "openai", "pip install openai>=1.0.0"),
|
||||||
("httpx", "httpx", "pip install httpx>=0.27.0"),
|
# ("httpx", "httpx", "pip install httpx>=0.27.0"),
|
||||||
("httpx-sse", "httpx_sse", "pip install httpx-sse>=0.4.0"),
|
# ("httpx-sse", "httpx_sse", "pip install httpx-sse>=0.4.0"),
|
||||||
("paramiko", "paramiko", "pip install paramiko>=3.0.0"),
|
# ("paramiko", "paramiko", "pip install paramiko>=3.0.0"),
|
||||||
]
|
# ]
|
||||||
|
#
|
||||||
all_ok = True
|
# all_ok = True
|
||||||
for pkg_name, import_name, install_cmd in checks:
|
# for pkg_name, import_name, install_cmd in checks:
|
||||||
try:
|
# try:
|
||||||
__import__(import_name)
|
# __import__(import_name)
|
||||||
print(f" ✅ {pkg_name:<15} 已安装")
|
# print(f" ✅ {pkg_name:<15} 已安装")
|
||||||
except ImportError:
|
# except ImportError:
|
||||||
print(f" ❌ {pkg_name:<15} 未安装 → {install_cmd}")
|
# print(f" ❌ {pkg_name:<15} 未安装 → {install_cmd}")
|
||||||
all_ok = False
|
# all_ok = False
|
||||||
|
#
|
||||||
print()
|
# print()
|
||||||
|
#
|
||||||
# 配置检查
|
# # 配置检查
|
||||||
try:
|
# try:
|
||||||
from config.settings import settings
|
# from config.settings import settings
|
||||||
print(" ✅ config/settings.py 加载成功")
|
# print(" ✅ config/settings.py 加载成功")
|
||||||
print(f" LLM : {settings.llm.provider} / {settings.llm.model_name}")
|
# print(f" LLM : {settings.llm.provider} / {settings.llm.model_name}")
|
||||||
print(f" 本地工具: {settings.mcp.enabled_tools}")
|
# print(f" 本地工具: {settings.mcp.enabled_tools}")
|
||||||
skills = settings.enabled_mcp_skills
|
# skills = settings.enabled_mcp_skills
|
||||||
if skills:
|
# if skills:
|
||||||
print(f" 在线Skill: {[s.name for s in skills]}")
|
# print(f" 在线Skill: {[s.name for s in skills]}")
|
||||||
else:
|
# else:
|
||||||
print(" 在线Skill: (未配置)")
|
# print(" 在线Skill: (未配置)")
|
||||||
except Exception as e:
|
# except Exception as e:
|
||||||
print(f" ❌ 配置加载失败: {e}")
|
# print(f" ❌ 配置加载失败: {e}")
|
||||||
all_ok = False
|
# all_ok = False
|
||||||
|
#
|
||||||
print()
|
# print()
|
||||||
|
#
|
||||||
# 工具注册检查
|
# # 工具注册检查
|
||||||
try:
|
# try:
|
||||||
from mcp.skill_registry import SkillRegistry
|
# from mcp.skill_registry import SkillRegistry
|
||||||
from tools.calculator import CalculatorTool
|
# from tools.calculator import CalculatorTool
|
||||||
from tools.code_executor import CodeExecutorTool
|
# from tools.code_executor import CodeExecutorTool
|
||||||
from tools.file_reader import FileReaderTool
|
# from tools.file_reader import FileReaderTool
|
||||||
from tools.ssh_docker import SSHDockerTool
|
# from tools.ssh_docker import SSHDockerTool
|
||||||
from tools.static_analyzer import StaticAnalyzerTool
|
# from tools.static_analyzer import StaticAnalyzerTool
|
||||||
from tools.web_search import WebSearchTool
|
# from tools.web_search import WebSearchTool
|
||||||
|
#
|
||||||
registry = SkillRegistry()
|
# registry = SkillRegistry()
|
||||||
registry.register_local_many(
|
# registry.register_local_many(
|
||||||
CalculatorTool(), WebSearchTool(), FileReaderTool(),
|
# CalculatorTool(), WebSearchTool(), FileReaderTool(),
|
||||||
CodeExecutorTool(), StaticAnalyzerTool(), SSHDockerTool(),
|
# CodeExecutorTool(), StaticAnalyzerTool(), SSHDockerTool(),
|
||||||
)
|
# )
|
||||||
tools = registry.list_all_tools()
|
# tools = registry.list_all_tools()
|
||||||
print(f" ✅ 本地工具注册 共 {len(tools)} 个:")
|
# print(f" ✅ 本地工具注册 共 {len(tools)} 个:")
|
||||||
for t in tools:
|
# for t in tools:
|
||||||
print(f" 🔵 {t['name']}: {t['description'][:50]}")
|
# print(f" 🔵 {t['name']}: {t['description'][:50]}")
|
||||||
except Exception as e:
|
# except Exception as e:
|
||||||
print(f" ❌ 工具注册失败: {e}")
|
# print(f" ❌ 工具注册失败: {e}")
|
||||||
all_ok = False
|
# all_ok = False
|
||||||
|
#
|
||||||
print()
|
# print()
|
||||||
print("=" * 60)
|
# print("=" * 60)
|
||||||
if all_ok:
|
# if all_ok:
|
||||||
print(" ✅ 所有检查通过,项目可正常运行")
|
# print(" ✅ 所有检查通过,项目可正常运行")
|
||||||
else:
|
# else:
|
||||||
print(" ⚠️ 存在问题,请按提示安装缺失依赖")
|
# print(" ⚠️ 存在问题,请按提示安装缺失依赖")
|
||||||
print("=" * 60)
|
# print("=" * 60)
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
|
|
@ -151,8 +151,8 @@ def main() -> None:
|
||||||
run_agent()
|
run_agent()
|
||||||
case "mcp":
|
case "mcp":
|
||||||
run_mcp_server()
|
run_mcp_server()
|
||||||
case "check":
|
# case "check":
|
||||||
run_check()
|
# run_check()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
||||||
|
|
@ -6,30 +6,12 @@ mcp/mcp_server.py
|
||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from config.settings import settings
|
from config.settings import settings
|
||||||
from mcp.skill_registry import SkillRegistry
|
from mcp.skill_registry import SkillRegistry
|
||||||
from tools.calculator import CalculatorTool
|
|
||||||
from tools.code_executor import CodeExecutorTool
|
|
||||||
from tools.file_reader import FileReaderTool
|
|
||||||
from tools.ssh_docker import SSHDockerTool
|
|
||||||
from tools.static_analyzer import StaticAnalyzerTool
|
|
||||||
from tools.web_search import WebSearchTool
|
|
||||||
from utils.logger import get_logger
|
from utils.logger import get_logger
|
||||||
|
|
||||||
logger = get_logger("MCP.Server")
|
logger = get_logger("MCP.Server")
|
||||||
|
|
||||||
# 本地工具类映射表
|
|
||||||
_LOCAL_TOOL_CLASSES: dict[str, type] = {
|
|
||||||
"calculator": CalculatorTool,
|
|
||||||
"web_search": WebSearchTool,
|
|
||||||
"file_reader": FileReaderTool,
|
|
||||||
"code_executor": CodeExecutorTool,
|
|
||||||
"static_analyzer": StaticAnalyzerTool,
|
|
||||||
"ssh_docker": SSHDockerTool,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class MCPServer:
|
class MCPServer:
|
||||||
"""
|
"""
|
||||||
本地 MCP Server
|
本地 MCP Server
|
||||||
|
|
@ -48,17 +30,37 @@ class MCPServer:
|
||||||
def _setup(self) -> None:
|
def _setup(self) -> None:
|
||||||
"""初始化:注册本地工具 + 连接在线 Skill"""
|
"""初始化:注册本地工具 + 连接在线 Skill"""
|
||||||
# ── 注册本地工具 ──────────────────────────────────────
|
# ── 注册本地工具 ──────────────────────────────────────
|
||||||
enabled = settings.mcp.enabled_tools
|
# enabled = settings.mcp.enabled_tools
|
||||||
logger.info(f"🔧 注册本地工具: {enabled}")
|
# logger.info(f"🔧 注册本地工具: {enabled}")
|
||||||
for tool_name in enabled:
|
# for tool_name in enabled:
|
||||||
cls = _LOCAL_TOOL_CLASSES.get(tool_name)
|
# tool_path = f"tools/{tool_name}.py"
|
||||||
if cls:
|
# if not os.path.exists(tool_path):
|
||||||
self.registry.register_local(cls())
|
# continue
|
||||||
else:
|
# # module_name = filename[:-3] # 去掉 .py 后缀
|
||||||
logger.warning(f"⚠️ 未知工具: {tool_name},跳过")
|
# # module_path = os.path.join(directory_path, filename)
|
||||||
|
#
|
||||||
|
# # 动态加载模块
|
||||||
|
# spec = importlib.util.spec_from_file_location(tool_name, tool_path)
|
||||||
|
# module = importlib.util.module_from_spec(spec)
|
||||||
|
# spec.loader.exec_module(module)
|
||||||
|
#
|
||||||
|
# if not hasattr(module, "Tool"):
|
||||||
|
# continue
|
||||||
|
#
|
||||||
|
# cls = getattr(module, 'Tool')
|
||||||
|
# if not isinstance(cls, BaseTool):
|
||||||
|
# continue
|
||||||
|
#
|
||||||
|
# # tool_classes.append(tool_class)
|
||||||
|
# # cls = _LOCAL_TOOL_CLASSES.get(tool_name)
|
||||||
|
# if cls:
|
||||||
|
# self.registry.register_local(cls())
|
||||||
|
# else:
|
||||||
|
# logger.warning(f"⚠️ 未知工具: {tool_name},跳过")
|
||||||
|
self.registry.load_local_tools()
|
||||||
|
self.registry.load_local_skills(settings.skills_directory)
|
||||||
# ── 连接在线 MCP Skill ────────────────────────────────
|
# ── 连接在线 MCP Skill ────────────────────────────────
|
||||||
skill_map = self.registry.connect_skills()
|
skill_map = self.registry.connect_mcp_skills()
|
||||||
if skill_map:
|
if skill_map:
|
||||||
logger.info(
|
logger.info(
|
||||||
"🌐 在线 Skill 注册汇总:\n" +
|
"🌐 在线 Skill 注册汇总:\n" +
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,10 @@ class SkillLoader:
|
||||||
def load_skills_from_directory(directory: str) -> Dict[str, Any]:
|
def load_skills_from_directory(directory: str) -> Dict[str, Any]:
|
||||||
skills = {}
|
skills = {}
|
||||||
for skill_directory in os.listdir(directory):
|
for skill_directory in os.listdir(directory):
|
||||||
skill_md = f"{skill_directory}/SKILL.md"
|
skill_md = f"{directory}/{skill_directory}/SKILL.md"
|
||||||
if not os.path.isfile(skill_md):
|
if not os.path.isfile(skill_md):
|
||||||
logger.warning(f"未在{skill_directory}发现SKILL.md文件")
|
logger.warning(f"未在{skill_directory}发现SKILL.md文件")
|
||||||
continue
|
continue
|
||||||
skill_name = os.path.basename(skill_directory) # 去掉 .md 后缀
|
|
||||||
skill_info = SkillLoader.load_skill(skill_md)
|
skill_info = SkillLoader.load_skill(skill_md)
|
||||||
if not skill_info:
|
if not skill_info:
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@ mcp/skill_registry.py
|
||||||
- dispatch() → 根据工具名路由到本地或远端执行
|
- dispatch() → 根据工具名路由到本地或远端执行
|
||||||
- refresh_skills() → 重新拉取在线 Skill 工具列表
|
- refresh_skills() → 重新拉取在线 Skill 工具列表
|
||||||
"""
|
"""
|
||||||
|
import importlib
|
||||||
|
import os
|
||||||
import time
|
import time
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
@ -16,6 +17,7 @@ from typing import Any
|
||||||
from config.settings import settings
|
from config.settings import settings
|
||||||
from mcp.mcp_skill_client import MCPSkillClient, RemoteTool, ToolCallResult
|
from mcp.mcp_skill_client import MCPSkillClient, RemoteTool, ToolCallResult
|
||||||
from mcp.skill_loader import SkillLoader
|
from mcp.skill_loader import SkillLoader
|
||||||
|
from tools.base_tool import BaseTool
|
||||||
from utils.logger import get_logger
|
from utils.logger import get_logger
|
||||||
|
|
||||||
logger = get_logger("MCP.SkillRegistry")
|
logger = get_logger("MCP.SkillRegistry")
|
||||||
|
|
@ -82,15 +84,37 @@ class SkillRegistry:
|
||||||
self._remote: dict[str, tuple[MCPSkillClient, RemoteTool]] = {}
|
self._remote: dict[str, tuple[MCPSkillClient, RemoteTool]] = {}
|
||||||
# 在线 Skill 客户端列表(用于生命周期管理)
|
# 在线 Skill 客户端列表(用于生命周期管理)
|
||||||
self._clients: list[MCPSkillClient] = []
|
self._clients: list[MCPSkillClient] = []
|
||||||
# 指定 SKILL.md 文件所在目录
|
|
||||||
self.load_skills_from_md(settings.skills_directory)
|
|
||||||
|
|
||||||
def load_skills_from_md(self, directory: str) -> None:
|
|
||||||
|
def load_local_skills(self, directory: str) -> None:
|
||||||
skills = SkillLoader.load_skills_from_directory(directory)
|
skills = SkillLoader.load_skills_from_directory(directory)
|
||||||
for skill_name, skill_info in skills.items():
|
for skill_name, skill_info in skills.items():
|
||||||
logger.info(f"📦 加载技能: {skill_name}")
|
logger.info(f"📦 加载技能: {skill_name}")
|
||||||
# 将技能注册到远端工具表
|
# 将技能注册到远端工具表
|
||||||
self._remote[skill_name] = skill_info
|
#self._remote[skill_name] = skill_info
|
||||||
|
self.register_local(skill_info)
|
||||||
|
|
||||||
|
def load_local_tools(self):
|
||||||
|
enabled = settings.mcp.enabled_tools
|
||||||
|
logger.info(f"🔧 注册本地工具: {enabled}")
|
||||||
|
for tool_name in enabled:
|
||||||
|
tool_path = f"tools/{tool_name}.py"
|
||||||
|
if not os.path.exists(tool_path):
|
||||||
|
continue
|
||||||
|
# 动态加载模块
|
||||||
|
spec = importlib.util.spec_from_file_location(tool_name, tool_path)
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
if not hasattr(module, "Tool"):
|
||||||
|
continue
|
||||||
|
cls = getattr(module, 'Tool')
|
||||||
|
if not issubclass(cls, BaseTool):
|
||||||
|
continue
|
||||||
|
if cls:
|
||||||
|
self.register_local(cls())
|
||||||
|
else:
|
||||||
|
logger.warning(f"⚠️ 未知工具: {tool_name},跳过")
|
||||||
|
|
||||||
|
|
||||||
# ── 注册本地工具 ──────────────────────────────────────────
|
# ── 注册本地工具 ──────────────────────────────────────────
|
||||||
|
|
||||||
|
|
@ -117,7 +141,7 @@ class SkillRegistry:
|
||||||
|
|
||||||
# ── 连接在线 MCP Skill ────────────────────────────────────
|
# ── 连接在线 MCP Skill ────────────────────────────────────
|
||||||
|
|
||||||
def connect_skills(self) -> dict[str, list[str]]:
|
def connect_mcp_skills(self) -> dict[str, list[str]]:
|
||||||
"""
|
"""
|
||||||
连接所有 config.yaml 中 enabled=true 的在线 MCP Skill
|
连接所有 config.yaml 中 enabled=true 的在线 MCP Skill
|
||||||
并将其工具注册到远端工具表
|
并将其工具注册到远端工具表
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import operator
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from config.settings import settings
|
from config.settings import settings
|
||||||
|
from tools.base_tool import BaseTool
|
||||||
from utils.logger import get_logger
|
from utils.logger import get_logger
|
||||||
|
|
||||||
logger = get_logger("TOOL.Calculator")
|
logger = get_logger("TOOL.Calculator")
|
||||||
|
|
@ -18,7 +19,7 @@ def _cfg(key: str, fallback=None):
|
||||||
return settings.tools['calculator'].get(key, fallback)
|
return settings.tools['calculator'].get(key, fallback)
|
||||||
|
|
||||||
|
|
||||||
class CalculatorTool:
|
class Tool(BaseTool):
|
||||||
name = "calculator"
|
name = "calculator"
|
||||||
description = (
|
description = (
|
||||||
"执行数学计算,支持四则运算、幂运算、开方、三角函数、对数等。"
|
"执行数学计算,支持四则运算、幂运算、开方、三角函数、对数等。"
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import traceback
|
||||||
from contextlib import redirect_stderr, redirect_stdout
|
from contextlib import redirect_stderr, redirect_stdout
|
||||||
|
|
||||||
from config.settings import settings
|
from config.settings import settings
|
||||||
|
from tools.base_tool import BaseTool
|
||||||
from utils.logger import get_logger
|
from utils.logger import get_logger
|
||||||
|
|
||||||
logger = get_logger("TOOL.CodeExecutor")
|
logger = get_logger("TOOL.CodeExecutor")
|
||||||
|
|
@ -21,7 +22,7 @@ def _cfg(key: str, fallback=None):
|
||||||
return settings.tools['code_executor'].get(key, fallback)
|
return settings.tools['code_executor'].get(key, fallback)
|
||||||
|
|
||||||
|
|
||||||
class CodeExecutorTool:
|
class Tool(BaseTool):
|
||||||
name = "code_executor"
|
name = "code_executor"
|
||||||
description = (
|
description = (
|
||||||
"在安全沙箱中执行 Python 代码片段,返回标准输出和执行结果。"
|
"在安全沙箱中执行 Python 代码片段,返回标准输出和执行结果。"
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from config.settings import settings
|
from config.settings import settings
|
||||||
|
from tools.base_tool import BaseTool
|
||||||
from utils.logger import get_logger
|
from utils.logger import get_logger
|
||||||
|
|
||||||
logger = get_logger("TOOL.FileReader")
|
logger = get_logger("TOOL.FileReader")
|
||||||
|
|
@ -19,7 +20,7 @@ def _cfg(key: str, fallback=None):
|
||||||
return settings.tools['file_reader'].get(key, fallback)
|
return settings.tools['file_reader'].get(key, fallback)
|
||||||
|
|
||||||
|
|
||||||
class FileReaderTool:
|
class Tool(BaseTool):
|
||||||
name = "file_reader"
|
name = "file_reader"
|
||||||
description = (
|
description = (
|
||||||
"读取本地文件内容,支持 .txt / .md / .py / .json / .csv / .yaml / .log 等文本文件。"
|
"读取本地文件内容,支持 .txt / .md / .py / .json / .csv / .yaml / .log 等文本文件。"
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import time
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
from config.settings import settings
|
from config.settings import settings
|
||||||
|
from tools.base_tool import BaseTool
|
||||||
from utils.logger import get_logger
|
from utils.logger import get_logger
|
||||||
|
|
||||||
logger = get_logger("TOOL.SSHDocker")
|
logger = get_logger("TOOL.SSHDocker")
|
||||||
|
|
@ -324,7 +325,7 @@ class DockerExecutor:
|
||||||
# 主工具类
|
# 主工具类
|
||||||
# ════════════════════════════════════════════════════════════════
|
# ════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
class SSHDockerTool:
|
class Tool(BaseTool):
|
||||||
"""
|
"""
|
||||||
SSH 远程 Docker 部署工具
|
SSH 远程 Docker 部署工具
|
||||||
所有配置均通过 settings.tools['ssh_docker'][key] 读取
|
所有配置均通过 settings.tools['ssh_docker'][key] 读取
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ from dataclasses import dataclass, field
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from config.settings import settings
|
from config.settings import settings
|
||||||
|
from tools.base_tool import BaseTool
|
||||||
from utils.logger import get_logger
|
from utils.logger import get_logger
|
||||||
|
|
||||||
logger = get_logger("TOOL.StaticAnalyzer")
|
logger = get_logger("TOOL.StaticAnalyzer")
|
||||||
|
|
@ -281,7 +282,7 @@ _TOOL_REGISTRY: dict[str, type] = {
|
||||||
# 主工具类
|
# 主工具类
|
||||||
# ════════════════════════════════════════════════════════════════
|
# ════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
class StaticAnalyzerTool:
|
class Tool(BaseTool):
|
||||||
"""
|
"""
|
||||||
C/C++ 静态分析工具
|
C/C++ 静态分析工具
|
||||||
所有配置均通过 settings.tools['static_analyzer'][key] 读取
|
所有配置均通过 settings.tools['static_analyzer'][key] 读取
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
from tools.base_tool import BaseTool, ToolResult
|
|
||||||
|
|
||||||
|
|
||||||
class ToolGeneratorTool(BaseTool):
|
|
||||||
name = "tool_generator"
|
|
||||||
description = "生成agent工具代码"
|
|
||||||
parameters = {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "tool name",
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "tool description"
|
|
||||||
|
|
||||||
},
|
|
||||||
"parameters": {
|
|
||||||
"type": "object",
|
|
||||||
"description": """tool parameters descriptions"""
|
|
||||||
},
|
|
||||||
"code": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "the code that the LLM generated"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def execute(self, name: str, description: str, parameters: dict, code: str) -> ToolResult:
|
|
||||||
pass
|
|
||||||
|
|
@ -9,6 +9,7 @@ import time
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
from config.settings import settings
|
from config.settings import settings
|
||||||
|
from tools.base_tool import BaseTool
|
||||||
from utils.logger import get_logger
|
from utils.logger import get_logger
|
||||||
|
|
||||||
logger = get_logger("TOOL.WebSearch")
|
logger = get_logger("TOOL.WebSearch")
|
||||||
|
|
@ -29,7 +30,7 @@ class SearchResult:
|
||||||
return f"[{self.rank}] {self.title}\n {self.url}\n {self.snippet}"
|
return f"[{self.rank}] {self.title}\n {self.url}\n {self.snippet}"
|
||||||
|
|
||||||
|
|
||||||
class WebSearchTool:
|
class Tool(BaseTool):
|
||||||
name = "web_search"
|
name = "web_search"
|
||||||
description = (
|
description = (
|
||||||
"在互联网上搜索信息,返回相关网页的标题、链接和摘要。"
|
"在互联网上搜索信息,返回相关网页的标题、链接和摘要。"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue