From 9d54ca8116cd79a1a274647f47209df9ed8ac042 Mon Sep 17 00:00:00 2001 From: Hoan Luu Huu <110280845+xquanluu@users.noreply.github.com> Date: Thu, 24 Apr 2025 17:50:53 +0700 Subject: [PATCH] Jambonz support Model context protocol (MCP) (#1150) * Jambonz support Model context protocol (MCP) * merged mcp tools with existing llmOptions.tools * support list of mcp servers * wip * wip * wip * fix voice agent * fix open-ai * fix review comment * fix deepgram voice agent * update verb specification version --- lib/tasks/llm/index.js | 21 + lib/tasks/llm/llms/elevenlabs_s2s.js | 31 +- lib/tasks/llm/llms/openai_s2s.js | 49 +- lib/tasks/llm/llms/ultravox_s2s.js | 72 ++- lib/tasks/llm/llms/voice_agent_s2s.js | 42 +- lib/utils/llm-mcp.js | 103 +++++ package-lock.json | 613 ++++++++++++++++++++++++-- package.json | 3 +- 8 files changed, 882 insertions(+), 52 deletions(-) create mode 100644 lib/utils/llm-mcp.js diff --git a/lib/tasks/llm/index.js b/lib/tasks/llm/index.js index d16ec721..daf79518 100644 --- a/lib/tasks/llm/index.js +++ b/lib/tasks/llm/index.js @@ -4,6 +4,7 @@ const TaskLlmOpenAI_S2S = require('./llms/openai_s2s'); const TaskLlmVoiceAgent_S2S = require('./llms/voice_agent_s2s'); const TaskLlmUltravox_S2S = require('./llms/ultravox_s2s'); const TaskLlmElevenlabs_S2S = require('./llms/elevenlabs_s2s'); +const LlmMcpService = require('../../utils/llm-mcp'); class TaskLlm extends Task { constructor(logger, opts) { @@ -18,6 +19,8 @@ class TaskLlm extends Task { // delegate to the specific llm model this.llm = this.createSpecificLlm(); + // MCP + this.mcpServers = this.data.mcpServers || []; } get name() { return this.llm.name ; } @@ -28,14 +31,32 @@ class TaskLlm extends Task { get ep() { return this.cs.ep; } + get mcpService() { + return this.llmMcpService; + } + + get isMcpEnabled() { + return this.mcpServers.length > 0; + } + async exec(cs, {ep}) { await super.exec(cs, {ep}); + + // create the MCP service if we have MCP servers + if (this.isMcpEnabled) { + this.llmMcpService = new LlmMcpService(this.logger, this.mcpServers); + await this.llmMcpService.init(); + } await this.llm.exec(cs, {ep}); } async kill(cs) { super.kill(cs); await this.llm.kill(cs); + // clean up MCP clients + if (this.isMcpEnabled) { + await this.mcpService.close(); + } } createSpecificLlm() { diff --git a/lib/tasks/llm/llms/elevenlabs_s2s.js b/lib/tasks/llm/llms/elevenlabs_s2s.js index 984addb7..58e2a0fb 100644 --- a/lib/tasks/llm/llms/elevenlabs_s2s.js +++ b/lib/tasks/llm/llms/elevenlabs_s2s.js @@ -244,13 +244,36 @@ class TaskLlmElevenlabs_S2S extends Task { /* tool calls */ else if (type === 'client_tool_call') { this.logger.debug({evt}, 'TaskLlmElevenlabs_S2S:_onServerEvent - function_call'); - if (!this.toolHook) { + const {tool_name: name, tool_call_id: call_id, parameters: args} = evt.client_tool_call; + + const mcpTools = this.parent.isMcpEnabled ? await this.parent.mcpService.getAvailableMcpTools() : []; + if (mcpTools.some((tool) => tool.name === name)) { + this.logger.debug({name, args}, 'TaskLlmElevenlabs_S2S:_onServerEvent - calling mcp tool'); + try { + const res = await this.parent.mcpService.callMcpTool(name, args); + this.logger.debug({res}, 'TaskLlmElevenlabs_S2S:_onServerEvent - function_call - mcp result'); + this.processToolOutput(ep, call_id, { + data: { + type: 'client_tool_result', + tool_call_id: call_id, + result: res.content?.length ? res.content[0] : res.content, + is_error: false + } + }); + return; + } + catch (err) { + this.logger.info({err, evt}, 'TaskLlmElevenlabs_S2S - error calling mcp tool'); + this.results = { + completionReason: 'client error calling mcp function', + error: err + }; + endConversation = true; + } + } else if (!this.toolHook) { this.logger.warn({evt}, 'TaskLlmElevenlabs_S2S:_onServerEvent - no toolHook defined!'); } else { - const {client_tool_call} = evt; - const {tool_name: name, tool_call_id: call_id, parameters: args} = client_tool_call; - try { await this.parent.sendToolHook(call_id, {name, args}); } catch (err) { diff --git a/lib/tasks/llm/llms/openai_s2s.js b/lib/tasks/llm/llms/openai_s2s.js index a98376ad..36ceb19d 100644 --- a/lib/tasks/llm/llms/openai_s2s.js +++ b/lib/tasks/llm/llms/openai_s2s.js @@ -235,6 +235,23 @@ class TaskLlmOpenAI_S2S extends Task { /* send immediate session.update if present */ else if (this.session_update) { + if (this.parent.isMcpEnabled) { + this.logger.debug('TaskLlmOpenAI_S2S:_sendInitialMessage - mcp enabled'); + const tools = await this.parent.mcpService.getAvailableMcpTools(); + if (tools && tools.length > 0 && this.session_update) { + const convertedTools = tools.map((tool) => ({ + name: tool.name, + type: 'function', + description: tool.description, + parameters: tool.inputSchema + })); + + this.session_update.tools = [ + ...convertedTools, + ...(this.session_update.tools || []) + ]; + } + } obj = {type: 'session.update', session: this.session_update}; this.logger.debug({obj}, 'TaskLlmOpenAI_S2S:_sendInitialMessage - sending session.update'); if (!await this._sendClientEvent(ep, obj)) { @@ -299,13 +316,37 @@ class TaskLlmOpenAI_S2S extends Task { /* tool calls */ else if (type === 'response.output_item.done' && evt.item?.type === 'function_call') { this.logger.debug({evt}, 'TaskLlmOpenAI_S2S:_onServerEvent - function_call'); - if (!this.toolHook) { + const {name, call_id} = evt.item; + const args = JSON.parse(evt.item.arguments); + + const mcpTools = this.parent.isMcpEnabled ? await this.parent.mcpService.getAvailableMcpTools() : []; + if (mcpTools.some((tool) => tool.name === name)) { + this.logger.debug({call_id, name, args}, 'TaskLlmOpenAI_S2S:_onServerEvent - calling mcp tool'); + try { + const res = await this.parent.mcpService.callMcpTool(name, args); + this.logger.debug({res}, 'TaskLlmOpenAI_S2S:_onServerEvent - function_call - mcp result'); + this.processToolOutput(ep, call_id, { + type: 'conversation.item.create', + item: { + type: 'function_call_output', + call_id, + output: res.content[0]?.text || 'There is no output from the function call', + } + }); + return; + } catch (err) { + this.logger.info({err, evt}, 'TaskLlmOpenAI_S2S - error calling function'); + this.results = { + completionReason: 'client error calling mcp function', + error: err + }; + endConversation = true; + } + } + else if (!this.toolHook) { this.logger.warn({evt}, 'TaskLlmOpenAI_S2S:_onServerEvent - no toolHook defined!'); } else { - const {name, call_id} = evt.item; - const args = JSON.parse(evt.item.arguments); - try { await this.parent.sendToolHook(call_id, {name, args}); } catch (err) { diff --git a/lib/tasks/llm/llms/ultravox_s2s.js b/lib/tasks/llm/llms/ultravox_s2s.js index c87b7f1f..1823c2ac 100644 --- a/lib/tasks/llm/llms/ultravox_s2s.js +++ b/lib/tasks/llm/llms/ultravox_s2s.js @@ -67,7 +67,50 @@ class TaskLlmUltravox_S2S extends Task { } } + /** + * Converts a JSON Schema to the dynamic parameters format used in the Ultravox API + * @param {Object} jsonSchema - A JSON Schema object defining parameters + * @param {string} locationDefault - Default location value for parameters (default: 'PARAMETER_LOCATION_BODY') + * @returns {Array} Array of dynamic parameters objects + */ + transformSchemaToParameters(jsonSchema, locationDefault = 'PARAMETER_LOCATION_BODY') { + if (jsonSchema.properties) { + const required = jsonSchema.required || []; + + return Object.entries(jsonSchema.properties).map(([name]) => { + return { + name, + location: locationDefault, + required: required.includes(name) + }; + }); + } + + return []; + } + async createCall() { + const mcpTools = this.parent.isMcpEnabled ? await this.parent.mcpService.getAvailableMcpTools() : []; + if (mcpTools && mcpTools.length > 0) { + const convertedTools = mcpTools.map((tool) => { + return { + temporaryTool: { + modelToolName: tool.name, + description: tool.description, + dynamicParameters: this.transformSchemaToParameters(tool.inputSchema), + // use client tool that ultravox call tool via freeswitch module. + client: {} + } + }; + } + ); + // merge with any existing tools + this.data.llmOptions.selectedTools = [ + ...convertedTools, + ...(this.data.llmOptions.selectedTools || []) + ]; + } + const payload = { ...this.data.llmOptions, model: this.model, @@ -182,12 +225,35 @@ class TaskLlmUltravox_S2S extends Task { /* tool calls */ else if (type === 'client_tool_invocation') { this.logger.debug({evt}, 'TaskLlmUltravox_S2S:_onServerEvent - function_call'); - if (!this.toolHook) { + const {toolName: name, invocationId: call_id, parameters: args} = evt; + + const mcpTools = this.parent.isMcpEnabled ? await this.parent.mcpService.getAvailableMcpTools() : []; + if (mcpTools.some((tool) => tool.name === name)) { + this.logger.debug({ + name, + input: args + }, 'TaskLlmUltravox_S2S:_onServerEvent - function_call - mcp tool'); + try { + const res = await this.parent.mcpService.callMcpTool(name, args); + this.logger.debug({res}, 'TaskLlmUltravox_S2S:_onServerEvent - function_call - mcp result'); + this.processToolOutput(_ep, call_id, { + type: 'client_tool_result', + invocation_id: call_id, + result: res.content + }); + return; + } catch (err) { + this.logger.info({err, evt}, 'TaskLlmUltravox_S2S - error calling mcp tool'); + this.results = { + completionReason: 'client error calling mcp function', + error: err + }; + endConversation = true; + } + } else if (!this.toolHook) { this.logger.info({evt}, 'TaskLlmUltravox_S2S:_onServerEvent - no toolHook defined!'); } else { - const {toolName: name, invocationId: call_id, parameters: args} = evt; - try { await this.parent.sendToolHook(call_id, {name, args}); } catch (err) { diff --git a/lib/tasks/llm/llms/voice_agent_s2s.js b/lib/tasks/llm/llms/voice_agent_s2s.js index 1a353045..0b6a3473 100644 --- a/lib/tasks/llm/llms/voice_agent_s2s.js +++ b/lib/tasks/llm/llms/voice_agent_s2s.js @@ -193,6 +193,19 @@ class TaskLlmVoiceAgent_S2S extends Task { } async _sendInitialMessage(ep) { + const mcpTools = this.parent.isMcpEnabled ? await this.parent.mcpService.getAvailableMcpTools() : []; + if (mcpTools && mcpTools.length > 0 && this.settingsConfiguration.agent?.think) { + const convertedTools = mcpTools.map((tool) => ({ + name: tool.name, + description: tool.description, + parameters: tool.inputSchema + })); + + this.settingsConfiguration.agent.think.functions = [ + ...convertedTools, + ...(this.settingsConfiguration.agent.think?.functions || []) + ]; + } if (!await this._sendClientEvent(ep, this.settingsConfiguration)) { this.notifyTaskDone(); } @@ -254,13 +267,34 @@ class TaskLlmVoiceAgent_S2S extends Task { /* tool calls */ else if (type === 'FunctionCallRequest') { this.logger.debug({evt}, 'TaskLlmVoiceAgent_S2S:_onServerEvent - function_call'); - if (!this.toolHook) { + const {function_name:name, function_call_id:call_id, input: args} = evt; + + const mcpTools = this.parent.isMcpEnabled ? await this.parent.mcpService.getAvailableMcpTools() : []; + if (mcpTools.some((tool) => tool.name === name)) { + this.logger.debug({call_id, name, args}, 'TaskLlmVoiceAgent_S2S:_onServerEvent - calling mcp tool'); + try { + const res = await this.parent.mcpService.callMcpTool(name, args); + this.logger.debug({res}, 'TaskLlmVoiceAgent_S2S:_onServerEvent - function_call - mcp result'); + this.processToolOutput(_ep, call_id, { + data: { + type: 'FunctionCallResponse', + function_call_id: call_id, + output: res.content[0]?.text || 'There is no output from the function call', + } + }); + return; + } catch (err) { + this.logger.info({err, evt}, 'TaskLlmVoiceAgent_S2S - error calling function'); + this.results = { + completionReason: 'client error calling mcp function', + error: err + }; + endConversation = true; + } + } else if (!this.toolHook) { this.logger.warn({evt}, 'TaskLlmVoiceAgent_S2S:_onServerEvent - no toolHook defined!'); } else { - const {function_name:name, function_call_id:call_id} = evt; - const args = evt.input; - try { await this.parent.sendToolHook(call_id, {name, args}); } catch (err) { diff --git a/lib/utils/llm-mcp.js b/lib/utils/llm-mcp.js new file mode 100644 index 00000000..a77fed89 --- /dev/null +++ b/lib/utils/llm-mcp.js @@ -0,0 +1,103 @@ +const { Client } = require('@modelcontextprotocol/sdk/client/index.js'); + +class LlmMcpService { + + constructor(logger, mcpServers) { + this.logger = logger; + this.mcpServers = mcpServers || []; + this.mcpClients = []; + } + + // make sure we call init() before using any of the mcp clients + // this is to ensure that we have a valid connection to the MCP server + // and that we have collected the available tools. + async init() { + if (this.mcpClients.length > 0) { + return; + } + const { SSEClientTransport } = await import('@modelcontextprotocol/sdk/client/sse.js'); + for (const server of this.mcpServers) { + const { url } = server; + if (url) { + try { + const transport = new SSEClientTransport(new URL(url), {}); + const client = new Client({ name: 'Jambonz MCP Client', version: '1.0.0' }); + await client.connect(transport); + // collect available tools + const { tools } = await client.listTools(); + this.mcpClients.push({ + url, + client, + tools + }); + } catch (err) { + this.logger.error(`LlmMcpService: Failed to connect to MCP server at ${url}: ${err.message}`); + } + } + } + } + + async getAvailableMcpTools() { + // returns a list of available tools from all MCP clients + const tools = []; + for (const mcpClient of this.mcpClients) { + const {tools: availableTools} = mcpClient; + if (availableTools) { + tools.push(...availableTools); + } + } + return tools; + } + + async getMcpClientByToolName(name) { + for (const mcpClient of this.mcpClients) { + const { tools } = mcpClient; + if (tools && tools.some((tool) => tool.name === name)) { + return mcpClient.client; + } + } + return null; + } + + async getMcpClientByToolId(id) { + for (const mcpClient of this.mcpClients) { + const { tools } = mcpClient; + if (tools && tools.some((tool) => tool.id === id)) { + return mcpClient.client; + } + } + return null; + } + + async callMcpTool(name, input) { + const client = await this.getMcpClientByToolName(name); + if (client) { + try { + const result = await client.callTool({ + name, + arguments: input, + }); + this.logger.debug({result}, 'LlmMcpService - result'); + return result; + } catch (err) { + this.logger.error({err}, 'LlmMcpService - error calling tool'); + throw err; + } + } + } + + async close() { + for (const mcpClient of this.mcpClients) { + const { client } = mcpClient; + if (client) { + await client.close(); + this.logger.debug({url: mcpClient.url}, 'LlmMcpService - mcp client closed'); + } + } + this.mcpClients = []; + } + +} + +module.exports = LlmMcpService; + diff --git a/package-lock.json b/package-lock.json index e79d8f8d..06cb4bc0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,8 @@ "@jambonz/speech-utils": "^0.2.6", "@jambonz/stats-collector": "^0.1.10", "@jambonz/time-series": "^0.2.13", - "@jambonz/verb-specifications": "^0.0.102", + "@jambonz/verb-specifications": "^0.0.103", + "@modelcontextprotocol/sdk": "^1.9.0", "@opentelemetry/api": "^1.8.0", "@opentelemetry/exporter-jaeger": "^1.23.0", "@opentelemetry/exporter-trace-otlp-http": "^0.50.0", @@ -1504,9 +1505,10 @@ } }, "node_modules/@jambonz/verb-specifications": { - "version": "0.0.102", - "resolved": "https://registry.npmjs.org/@jambonz/verb-specifications/-/verb-specifications-0.0.102.tgz", - "integrity": "sha512-hpxzrzmSv3uRjjI503lFsDddVhfI5oFHWfGaym2RCUuKhv+hX5UKjW1joU1MRXyG2ZX4Oh5BRMAcjEI9lTxoLA==", + "version": "0.0.103", + "resolved": "https://registry.npmjs.org/@jambonz/verb-specifications/-/verb-specifications-0.0.103.tgz", + "integrity": "sha512-LwAjG1T1DnUKr8F5s42TDw/fCJD945PV70rfItdQP552gweb1nnxQy9cKtbszDiqhSDUUVRlGhdfCh8N5XSXLQ==", + "license": "MIT", "dependencies": { "debug": "^4.3.4", "pino": "^8.8.0" @@ -1605,6 +1607,293 @@ "node": ">= 0.4" } }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.9.0.tgz", + "integrity": "sha512-Jq2EUCQpe0iyO5FGpzVYDNFR6oR53AIrwph9yWl7uSc7IWUMsrmpmSaTGra5hQNunXpM+9oit85p924jWuHzUA==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.3", + "eventsource": "^3.0.2", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/@opentelemetry/api": { "version": "1.8.0", "license": "Apache-2.0", @@ -3051,6 +3340,7 @@ }, "node_modules/call-bind": { "version": "1.0.7", + "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -3066,6 +3356,35 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "dev": true, @@ -3261,9 +3580,21 @@ "version": "1.0.2", "license": "MIT" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -3338,10 +3669,12 @@ } }, "node_modules/debug": { - "version": "4.3.4", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -3419,6 +3752,7 @@ }, "node_modules/define-data-property": { "version": "1.1.4", + "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -3647,6 +3981,20 @@ "node": ">=8" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/duplexify": { "version": "4.1.3", "license": "MIT", @@ -3779,11 +4127,10 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { "node": ">= 0.4" } @@ -3815,8 +4162,9 @@ } }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "dev": true, + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -4160,6 +4508,27 @@ "node": ">=0.8.x" } }, + "node_modules/eventsource": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.6.tgz", + "integrity": "sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==", + "license": "MIT", + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz", + "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/expect": { "version": "27.5.1", "license": "MIT", @@ -4217,6 +4586,21 @@ "url": "https://opencollective.com/express" } }, + "node_modules/express-rate-limit": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", + "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": "^4.11 || 5 || ^5.0.0-beta.1" + } + }, "node_modules/express-validator": { "version": "7.0.1", "license": "MIT", @@ -4639,14 +5023,21 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -4663,6 +5054,19 @@ "node": ">=8.0.0" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-symbol-description": { "version": "1.0.2", "dev": true, @@ -4789,10 +5193,12 @@ "license": "(BSD-3-Clause AND Apache-2.0)" }, "node_modules/gopd": { - "version": "1.0.1", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4845,6 +5251,7 @@ }, "node_modules/has-property-descriptors": { "version": "1.0.2", + "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" @@ -4855,6 +5262,7 @@ }, "node_modules/has-proto": { "version": "1.0.3", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -4864,7 +5272,9 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -5441,6 +5851,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, "node_modules/is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", @@ -5594,7 +6010,6 @@ }, "node_modules/isexe": { "version": "2.0.0", - "dev": true, "license": "ISC" }, "node_modules/isstream": { @@ -6045,6 +6460,15 @@ "semver": "bin/semver.js" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/md5": { "version": "2.3.0", "license": "BSD-3-Clause", @@ -6249,7 +6673,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/mysql2": { @@ -6530,6 +6956,15 @@ "node": ">=6" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-hash": { "version": "3.0.0", "license": "MIT", @@ -6538,8 +6973,13 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6777,7 +7217,6 @@ }, "node_modules/path-key": { "version": "3.1.1", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -6869,6 +7308,15 @@ "version": "6.2.1", "license": "MIT" }, + "node_modules/pkce-challenge": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", + "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "dev": true, @@ -7258,6 +7706,31 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/router/node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, "node_modules/safe-array-concat": { "version": "1.1.2", "dev": true, @@ -7384,10 +7857,6 @@ "node": ">= 0.8" } }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "license": "MIT" - }, "node_modules/seq-queue": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", @@ -7413,6 +7882,7 @@ }, "node_modules/set-function-length": { "version": "1.2.2", + "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -7446,7 +7916,6 @@ }, "node_modules/shebang-command": { "version": "2.0.0", - "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -7457,7 +7926,6 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -7490,13 +7958,69 @@ } }, "node_modules/side-channel": { - "version": "1.0.6", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -8415,7 +8939,6 @@ }, "node_modules/which": { "version": "2.0.2", - "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -8608,6 +9131,24 @@ "engines": { "node": ">=12" } + }, + "node_modules/zod": { + "version": "3.24.2", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", + "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.24.5", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", + "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.24.1" + } } } } diff --git a/package.json b/package.json index e98a7417..9df3562e 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,8 @@ "@jambonz/speech-utils": "^0.2.6", "@jambonz/stats-collector": "^0.1.10", "@jambonz/time-series": "^0.2.13", - "@jambonz/verb-specifications": "^0.0.102", + "@jambonz/verb-specifications": "^0.0.103", + "@modelcontextprotocol/sdk": "^1.9.0", "@opentelemetry/api": "^1.8.0", "@opentelemetry/exporter-jaeger": "^1.23.0", "@opentelemetry/exporter-trace-otlp-http": "^0.50.0",