UNPKG

mcp-chrome-bridge

Version:

Chrome Native-Messaging host (Node)

145 lines 6.29 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.setupTools = void 0; const types_js_1 = require("@modelcontextprotocol/sdk/types.js"); const native_messaging_host_1 = __importDefault(require("../native-messaging-host")); const chrome_mcp_shared_1 = require("chrome-mcp-shared"); async function listDynamicFlowTools() { try { const response = await native_messaging_host_1.default.sendRequestToExtensionAndWait({}, 'rr_list_published_flows', 20000); if (response && response.status === 'success' && Array.isArray(response.items)) { const tools = []; for (const item of response.items) { const name = `flow.${item.slug}`; const description = (item.meta && item.meta.tool && item.meta.tool.description) || item.description || 'Recorded flow'; const properties = {}; const required = []; for (const v of item.variables || []) { const desc = v.label || v.key; const typ = (v.type || 'string').toLowerCase(); const prop = { description: desc }; if (typ === 'boolean') prop.type = 'boolean'; else if (typ === 'number') prop.type = 'number'; else if (typ === 'enum') { prop.type = 'string'; if (v.rules && Array.isArray(v.rules.enum)) prop.enum = v.rules.enum; } else if (typ === 'array') { // default array of strings; can extend with itemType later prop.type = 'array'; prop.items = { type: 'string' }; } else { prop.type = 'string'; } if (v.default !== undefined) prop.default = v.default; if (v.rules && v.rules.required) required.push(v.key); properties[v.key] = prop; } // Run options properties['tabTarget'] = { type: 'string', enum: ['current', 'new'], default: 'current' }; properties['refresh'] = { type: 'boolean', default: false }; properties['captureNetwork'] = { type: 'boolean', default: false }; properties['returnLogs'] = { type: 'boolean', default: false }; properties['timeoutMs'] = { type: 'number', minimum: 0 }; const tool = { name, description, inputSchema: { type: 'object', properties, required }, }; tools.push(tool); } return tools; } return []; } catch (e) { return []; } } const setupTools = (server) => { // List tools handler server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => { const dynamicTools = await listDynamicFlowTools(); return { tools: [...chrome_mcp_shared_1.TOOL_SCHEMAS, ...dynamicTools] }; }); // Call tool handler server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => handleToolCall(request.params.name, request.params.arguments || {})); }; exports.setupTools = setupTools; const handleToolCall = async (name, args) => { try { // If calling a dynamic flow tool (name starts with flow.), proxy to common flow-run tool if (name && name.startsWith('flow.')) { // We need to resolve flow by slug to ID try { const resp = await native_messaging_host_1.default.sendRequestToExtensionAndWait({}, 'rr_list_published_flows', 20000); const items = (resp && resp.items) || []; const slug = name.slice('flow.'.length); const match = items.find((it) => it.slug === slug); if (!match) throw new Error(`Flow not found for tool ${name}`); const flowArgs = { flowId: match.id, args }; const proxyRes = await native_messaging_host_1.default.sendRequestToExtensionAndWait({ name: 'record_replay_flow_run', args: flowArgs }, chrome_mcp_shared_1.NativeMessageType.CALL_TOOL, 120000); if (proxyRes.status === 'success') return proxyRes.data; return { content: [{ type: 'text', text: `Error calling dynamic flow tool: ${proxyRes.error}` }], isError: true, }; } catch (err) { return { content: [ { type: 'text', text: `Error resolving dynamic flow tool: ${(err === null || err === void 0 ? void 0 : err.message) || String(err)}`, }, ], isError: true, }; } } // 发送请求到Chrome扩展并等待响应 const response = await native_messaging_host_1.default.sendRequestToExtensionAndWait({ name, args, }, chrome_mcp_shared_1.NativeMessageType.CALL_TOOL, 120000); if (response.status === 'success') { return response.data; } else { return { content: [ { type: 'text', text: `Error calling tool: ${response.error}`, }, ], isError: true, }; } } catch (error) { return { content: [ { type: 'text', text: `Error calling tool: ${error.message}`, }, ], isError: true, }; } }; //# sourceMappingURL=register-tools.js.map