/** * MCP JSON-RPC response parsing. No Bare imports / no network. */ function extractJson(text) { const raw = String(text || '').trim(); if (!raw) throw new Error('empty MCP response'); if (raw[0] === '{' || raw[0] === '[') { return JSON.parse(raw); } const lines = raw.split('\n'); for (const line of lines) { const t = line.trim(); if (t.indexOf('data:') === 0) { const payload = t.slice(5).trim(); if (payload && payload !== '[DONE]') return JSON.parse(payload); } } const m = raw.match(/\{[\s\S]*\}/); if (!m) throw new Error('MCP response was not JSON'); return JSON.parse(m[0]); } function unwrapResult(body) { if (body && body.error) { const msg = body.error.message || JSON.stringify(body.error); throw new Error(String(msg)); } if (body && Object.prototype.hasOwnProperty.call(body, 'result')) return body.result; return body; } function normalizeTools(result) { const list = result && result.tools ? result.tools : Array.isArray(result) ? result : []; return list .map((t) => { if (!t) return null; if (typeof t === 'string') return { name: t, description: '' }; const name = t.name || (t.function && t.function.name); if (!name) return null; return { name: String(name), description: String(t.description || (t.function && t.function.description) || ''), inputSchema: t.inputSchema || t.parameters || (t.function && t.function.parameters) || undefined, }; }) .filter(Boolean); } module.exports = { extractJson, unwrapResult, normalizeTools };