/** * Agent management MCP tools: create_agent. * * send_to_agent was removed — sending to another agent is now just * send_message(to="agent-name") since agents and channels share the * unified destinations namespace. * * create_agent is admin-only. Non-admin containers never see this tool * (see mcp-tools/index.ts). The host re-checks permission on receive. */ import { writeMessageOut } from '../db/messages-out.js'; import { registerTools } from './server.js'; import type { McpToolDefinition } from './types.js'; function log(msg: string): void { console.error(`[mcp-tools] ${msg}`); } function generateId(): string { return `msg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`; } function ok(text: string) { return { content: [{ type: 'text' as const, text }] }; } function err(text: string) { return { content: [{ type: 'text' as const, text: `Error: ${text}` }], isError: true }; } export const createAgent: McpToolDefinition = { tool: { name: 'create_agent', description: 'Create a long-lived companion sub-agent (research assistant, task manager, specialist) — the name becomes your destination for it. Admin-only. Fire-and-forget.', inputSchema: { type: 'object' as const, properties: { name: { type: 'string', description: 'Human-readable name (also becomes your destination name for this agent)' }, instructions: { type: 'string', description: 'CLAUDE.md content for the new agent (personality, role, instructions)' }, }, required: ['name'], }, }, async handler(args) { const name = args.name as string; if (!name) return err('name is required'); const requestId = generateId(); writeMessageOut({ id: requestId, kind: 'system', content: JSON.stringify({ action: 'create_agent', requestId, name, instructions: (args.instructions as string) || null, }), }); log(`create_agent: ${requestId} → "${name}"`); return ok(`Creating agent "${name}". You will be notified when it is ready.`); }, }; registerTools([createAgent]);