// Little Blue's action tools. They run inside the MCP child, which holds NO infra // creds — only a scoped little-blue bearer + the local API URL. The main server // (which has the Proxmox/SSH creds) does the actual work behind /api/actions. function api(env = process.env) { return { base: env.VOID_API_URL, token: env.VOID_AGENT_TOKEN }; } export const listActionsTool = { name: 'list_actions', description: 'List the whitelisted fix-it actions you may take (id, label, tier).', input_schema: { type: 'object', properties: {} }, async handler(_args, _ctx, { fetchImpl = fetch } = {}) { const { base, token } = api(); const res = await fetchImpl(`${base}/api/actions`, { headers: { Authorization: `Bearer ${token}` } }); if (!res.ok) return { error: `list_actions ${res.status}` }; return res.json(); } }; export const proposeActionTool = { name: 'propose_action', description: 'Take a whitelisted action by id. SAFE actions run immediately; RISKY ones queue for the owner to approve. You can only name an id from list_actions — never a command.', input_schema: { type: 'object', properties: { action_id: { type: 'string' } }, required: ['action_id'] }, async handler({ action_id }, _ctx, { fetchImpl = fetch } = {}) { const { base, token } = api(); const res = await fetchImpl(`${base}/api/actions/${encodeURIComponent(action_id)}/run`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' } }); if (!res.ok) return { error: `propose_action ${res.status}` }; return res.json(); } };