feat(mcp): add slash command listing

This commit is contained in:
Hua
2026-03-19 13:10:07 +08:00
parent 49fbd5c15c
commit cfcfb35f81
9 changed files with 180 additions and 3 deletions

View File

@@ -81,6 +81,7 @@ def help_lines(language: Any) -> list[str]:
text(active, "cmd_persona_list"),
text(active, "cmd_persona_set"),
text(active, "cmd_skill"),
text(active, "cmd_mcp"),
text(active, "cmd_stop"),
text(active, "cmd_restart"),
text(active, "cmd_help"),

View File

@@ -191,6 +191,27 @@ class AgentLoop:
text(language, "cmd_lang_set"),
])
def _mcp_usage(self, language: str) -> str:
"""Return MCP command help text."""
return text(language, "mcp_usage")
def _group_mcp_tool_names(self) -> dict[str, list[str]]:
"""Group registered MCP tool names by configured server name."""
grouped = {name: [] for name in self._mcp_servers}
server_names = sorted(self._mcp_servers, key=len, reverse=True)
for tool_name in self.tools.tool_names:
if not tool_name.startswith("mcp_"):
continue
for server_name in server_names:
prefix = f"mcp_{server_name}_"
if tool_name.startswith(prefix):
grouped[server_name].append(tool_name.removeprefix(prefix))
break
return {name: sorted(tools) for name, tools in grouped.items()}
@staticmethod
def _decode_subprocess_output(data: bytes) -> str:
"""Decode subprocess output conservatively for CLI surfacing."""
@@ -363,6 +384,48 @@ class AgentLoop:
content = "\n\n".join(notes) if notes else text(language, "skill_command_completed", command=subcommand)
return OutboundMessage(channel=msg.channel, chat_id=msg.chat_id, content=content)
async def _handle_mcp_command(self, msg: InboundMessage, session: Session) -> OutboundMessage:
"""Handle MCP inspection commands."""
language = self._get_session_language(session)
parts = msg.content.strip().split()
if len(parts) > 1 and parts[1].lower() != "list":
return OutboundMessage(
channel=msg.channel,
chat_id=msg.chat_id,
content=self._mcp_usage(language),
)
if not self._mcp_servers:
return OutboundMessage(
channel=msg.channel,
chat_id=msg.chat_id,
content=text(language, "mcp_no_servers"),
)
await self._connect_mcp()
server_lines = "\n".join(f"- {name}" for name in self._mcp_servers)
sections = [text(language, "mcp_servers_list", items=server_lines)]
grouped_tools = self._group_mcp_tool_names()
tool_lines = "\n".join(
f"- {server}: {', '.join(tools)}"
for server, tools in grouped_tools.items()
if tools
)
sections.append(
text(language, "mcp_tools_list", items=tool_lines)
if tool_lines
else text(language, "mcp_no_tools")
)
return OutboundMessage(
channel=msg.channel,
chat_id=msg.chat_id,
content="\n\n".join(sections),
)
def _register_default_tools(self) -> None:
"""Register the default set of tools."""
allowed_dir = self.workspace if self.restrict_to_workspace else None
@@ -810,6 +873,8 @@ class AgentLoop:
return await self._handle_persona_command(msg, session)
if cmd == "/skill":
return await self._handle_skill_command(msg, session)
if cmd == "/mcp":
return await self._handle_mcp_command(msg, session)
if cmd == "/help":
return OutboundMessage(
channel=msg.channel, chat_id=msg.chat_id, content="\n".join(help_lines(language)),

View File

@@ -165,7 +165,7 @@ class TelegramChannel(BaseChannel):
name = "telegram"
display_name = "Telegram"
COMMAND_NAMES = ("start", "new", "lang", "persona", "skill", "stop", "help", "restart")
COMMAND_NAMES = ("start", "new", "lang", "persona", "skill", "mcp", "stop", "help", "restart")
@classmethod
def default_config(cls) -> dict[str, object]:
@@ -239,6 +239,7 @@ class TelegramChannel(BaseChannel):
self._app.add_handler(CommandHandler("lang", self._forward_command))
self._app.add_handler(CommandHandler("persona", self._forward_command))
self._app.add_handler(CommandHandler("skill", self._forward_command))
self._app.add_handler(CommandHandler("mcp", self._forward_command))
self._app.add_handler(CommandHandler("stop", self._forward_command))
self._app.add_handler(CommandHandler("restart", self._forward_command))
self._app.add_handler(CommandHandler("help", self._on_help))

View File

@@ -13,6 +13,7 @@
"cmd_persona_list": "/persona list — List available personas",
"cmd_persona_set": "/persona set <name> — Switch persona and start a new session",
"cmd_skill": "/skill <search|install|uninstall|list|update> ... — Manage ClawHub skills",
"cmd_mcp": "/mcp [list] — List configured MCP servers and registered tools",
"cmd_stop": "/stop — Stop the current task",
"cmd_restart": "/restart — Restart the bot",
"cmd_help": "/help — Show available commands",
@@ -27,6 +28,11 @@
"skill_command_network_failed": "ClawHub could not reach the npm registry. Check your network, proxy, or npm registry configuration and retry.",
"skill_command_completed": "ClawHub command completed: {command}",
"skill_applied_to_workspace": "Applied to workspace: {workspace}",
"mcp_usage": "Usage:\n/mcp\n/mcp list",
"mcp_no_servers": "No MCP servers are configured for this agent.",
"mcp_servers_list": "Configured MCP servers:\n{items}",
"mcp_tools_list": "Registered MCP tools:\n{items}",
"mcp_no_tools": "No MCP tools are currently registered. Check MCP server connectivity and configuration.",
"current_persona": "Current persona: {persona}",
"available_personas": "Available personas:\n{items}",
"unknown_persona": "Unknown persona: {name}\nAvailable personas: {personas}\nCreate one under {path} and add SOUL.md or USER.md.",
@@ -53,6 +59,7 @@
"lang": "Switch language",
"persona": "Show or switch personas",
"skill": "Search or install skills",
"mcp": "List MCP servers and tools",
"stop": "Stop the current task",
"help": "Show command help",
"restart": "Restart the bot"

View File

@@ -13,6 +13,7 @@
"cmd_persona_list": "/persona list — 查看可用人格",
"cmd_persona_set": "/persona set <name> — 切换人格并开始新会话",
"cmd_skill": "/skill <search|install|uninstall|list|update> ... — 管理 ClawHub skills",
"cmd_mcp": "/mcp [list] — 查看已配置的 MCP 服务和已注册工具",
"cmd_stop": "/stop — 停止当前任务",
"cmd_restart": "/restart — 重启机器人",
"cmd_help": "/help — 查看命令帮助",
@@ -27,6 +28,11 @@
"skill_command_network_failed": "ClawHub 无法连接到 npm registry。请检查网络、代理或 npm registry 配置后重试。",
"skill_command_completed": "ClawHub 命令执行完成:{command}",
"skill_applied_to_workspace": "已应用到工作区:{workspace}",
"mcp_usage": "用法:\n/mcp\n/mcp list",
"mcp_no_servers": "当前 agent 没有配置任何 MCP 服务。",
"mcp_servers_list": "已配置的 MCP 服务:\n{items}",
"mcp_tools_list": "已注册的 MCP 工具:\n{items}",
"mcp_no_tools": "当前没有已注册的 MCP 工具。请检查 MCP 服务连通性和配置。",
"current_persona": "当前人格:{persona}",
"available_personas": "可用人格:\n{items}",
"unknown_persona": "未知人格:{name}\n可用人格{personas}\n请在 {path} 下创建人格目录,并添加 SOUL.md 或 USER.md。",
@@ -53,6 +59,7 @@
"lang": "切换语言",
"persona": "查看或切换人格",
"skill": "搜索或安装技能",
"mcp": "查看 MCP 服务和工具",
"stop": "停止当前任务",
"help": "查看命令帮助",
"restart": "重启机器人"