SPB Git forge

spb/admin-ka

Public
41commits 1branches 0releases
172.9 MBsize
maindefault branch
19 days agolast push
JavaScript 65.5% Python 17.8% CSS 13% HTML 3.7%
3.1 KB · 92 lines javascript
Raw Blame History
1// perm-mcp — serveur MCP stdio minimal exposant l'outil `approve` utilisé par2// `claude --permission-prompt-tool mcp__adminka__approve`. Chaque demande de3// permission est relayée au backend admin-ka (long-poll HTTP local) qui la4// transforme en carte Autoriser/Refuser dans le chat.5import readline from 'node:readline';6import dns from 'node:dns';78const PERM_URL = process.env.ADMIN_KA_PERM_URL || 'http://127.0.0.1:3300/internal/perm';9const PERM_TOKEN = process.env.ADMIN_KA_PERM_TOKEN || '';1011// fetch (undici) échoue sur les noms Bonjour .local qui résolvent en IPv612// link-local — on force la résolution IPv4 avant l'appel.13async function resolvedPermUrl() {14  const u = new URL(PERM_URL);15  if (/^\d+\.\d+\.\d+\.\d+$/.test(u.hostname) || u.hostname === 'localhost') return PERM_URL;16  const { address } = await dns.promises.lookup(u.hostname, { family: 4 });17  u.hostname = address;18  return u.toString();19}2021const rl = readline.createInterface({ input: process.stdin });2223function send(obj) {24  process.stdout.write(JSON.stringify(obj) + '\n');25}2627rl.on('line', async (line) => {28  line = line.trim();29  if (!line) return;30  let msg;31  try { msg = JSON.parse(line); } catch { return; }32  const { id, method, params } = msg;33  if (method === 'initialize') {34    send({35      jsonrpc: '2.0', id,36      result: {37        protocolVersion: (params && params.protocolVersion) || '2024-11-05',38        capabilities: { tools: {} },39        serverInfo: { name: 'adminka', version: '1.0.0' },40      },41    });42    return;43  }44  if (method === 'notifications/initialized') return;45  if (method === 'ping') { send({ jsonrpc: '2.0', id, result: {} }); return; }46  if (method === 'tools/list') {47    send({48      jsonrpc: '2.0', id,49      result: {50        tools: [{51          name: 'approve',52          description: 'Demande de permission relayée à administration-ka.com',53          inputSchema: {54            type: 'object',55            properties: {56              tool_name: { type: 'string' },57              input: { type: 'object' },58              tool_use_id: { type: 'string' },59            },60            required: ['tool_name', 'input'],61          },62        }],63      },64    });65    return;66  }67  if (method === 'tools/call' && params && params.name === 'approve') {68    const args = params.arguments || {};69    let decision;70    try {71      const url = await resolvedPermUrl();72      const resp = await fetch(url, {73        method: 'POST',74        headers: { 'Content-Type': 'application/json' },75        body: JSON.stringify({ token: PERM_TOKEN, tool_name: args.tool_name, input: args.input, tool_use_id: args.tool_use_id }),76      });77      decision = await resp.json();78      if (decision.error) decision = { behavior: 'deny', message: 'Erreur backend: ' + decision.error };79    } catch (e) {80      decision = { behavior: 'deny', message: 'Backend admin-ka injoignable: ' + e.message };81    }82    send({83      jsonrpc: '2.0', id,84      result: { content: [{ type: 'text', text: JSON.stringify(decision) }] },85    });86    return;87  }88  if (id !== undefined) {89    send({ jsonrpc: '2.0', id, error: { code: -32601, message: 'method not found: ' + method } });90  }91});92