diff --git a/apps/broker/src/telegram-ai.ts b/apps/broker/src/telegram-ai.ts
index 13c1fae..b941bf3 100644
--- a/apps/broker/src/telegram-ai.ts
+++ b/apps/broker/src/telegram-ai.ts
@@ -133,6 +133,22 @@ const TOOLS: AiTool[] = [
},
},
},
+ {
+ name: "list_services",
+ description: "List all deployed MCP services and skills in the mesh. Use when user asks about available tools, services, MCPs, skills, or capabilities.",
+ input_schema: {
+ type: "object",
+ properties: {},
+ },
+ },
+ {
+ name: "list_commands",
+ description: "Show available Telegram bot commands. Use when user asks what commands are available, what they can do, or asks for help.",
+ input_schema: {
+ type: "object",
+ properties: {},
+ },
+ },
];
// Actions that need user confirmation before executing
@@ -370,6 +386,32 @@ export function formatResult(toolName: string, result: unknown): string {
case "share_mesh":
return typeof result === "string" ? `🔗 Invite: ${result}` : "✅ Invite sent.";
+ case "list_services": {
+ const services = result as Array<{ name: string; type: string; tools: number; status: string }>;
+ if (!services || services.length === 0) return "No services deployed in this mesh.";
+ return "⚙️ Mesh services:\n\n" + services.map(s =>
+ `• ${escHtml(s.name)} (${s.type}) — ${s.tools} tool${s.tools !== 1 ? "s" : ""} [${s.status}]`
+ ).join("\n");
+ }
+
+ case "list_commands":
+ return `📋 Available commands:
+
+/connect — connect to a mesh
+/disconnect — disconnect from mesh
+/peers — list online peers
+/meshes — list connected meshes
+/dm @Name message — send direct message
+/broadcast message — send to all peers
+/status — connection status
+/help — show help
+
+Or just type naturally:
+• "who's online?"
+• "tell Nedas the API is ready"
+• "list my meshes"
+• "what services are available?"`;
+
default:
return `✅ Done: ${JSON.stringify(result)}`;
}
diff --git a/apps/broker/src/telegram-bridge.ts b/apps/broker/src/telegram-bridge.ts
index a591e6b..87795da 100644
--- a/apps/broker/src/telegram-bridge.ts
+++ b/apps/broker/src/telegram-bridge.ts
@@ -1721,6 +1721,28 @@ async function executeAiToolCall(
case "list_peers":
return conn.listPeers();
+ case "list_services": {
+ // Query deployed services from the broker DB
+ try {
+ const { listDbMeshServices } = await import("./broker");
+ const allServices: Array<{ name: string; type: string; tools: number; status: string }> = [];
+ for (const meshId of meshIds) {
+ const services = await listDbMeshServices(meshId);
+ for (const s of services) {
+ allServices.push({
+ name: s.name,
+ type: s.type ?? "mcp",
+ tools: s.tool_count ?? 0,
+ status: s.status ?? "running",
+ });
+ }
+ }
+ return allServices;
+ } catch {
+ return [];
+ }
+ }
+
case "list_meshes": {
const results: Array<{ slug: string; peers: number }> = [];
for (const meshId of meshIds) {
@@ -1738,6 +1760,9 @@ async function executeAiToolCall(
return results;
}
+ case "list_commands":
+ return null; // The formatter handles this — no execution needed
+
case "remember":
case "recall":
case "get_state":