@elizaos/plugin-mcp 1.7.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -667,6 +667,33 @@ async function handleMcpError(state, mcpProvider, error, runtime2, message, type
667
667
  };
668
668
  }
669
669
 
670
+ // src/utils/handler.ts
671
+ async function handleNoToolAvailable(callback, toolSelection) {
672
+ const responseText = "I don't have a specific tool that can help with that request. Let me try to assist you directly instead.";
673
+ const thoughtText = "No appropriate MCP tool available for this request. Falling back to direct assistance.";
674
+ if (callback && toolSelection?.noToolAvailable) {
675
+ await callback({
676
+ text: responseText,
677
+ thought: thoughtText,
678
+ actions: ["REPLY"]
679
+ });
680
+ }
681
+ return {
682
+ text: responseText,
683
+ values: {
684
+ success: true,
685
+ noToolAvailable: true,
686
+ fallbackToDirectAssistance: true
687
+ },
688
+ data: {
689
+ actionName: "CALL_MCP_TOOL",
690
+ noToolAvailable: true,
691
+ reason: toolSelection?.reasoning || "No appropriate tool available"
692
+ },
693
+ success: true
694
+ };
695
+ }
696
+
670
697
  // src/utils/processing.ts
671
698
  import {
672
699
  ContentType,
@@ -736,82 +763,54 @@ Your response (written as if directly to the user):
736
763
  `;
737
764
 
738
765
  // src/utils/mcp.ts
766
+ var NO_DESC = "No description";
739
767
  async function createMcpMemory(runtime2, message, type, serverName, content, metadata) {
740
768
  const memory = await runtime2.addEmbeddingToMemory({
741
769
  entityId: message.entityId,
742
770
  agentId: runtime2.agentId,
743
771
  roomId: message.roomId,
744
772
  content: {
745
- text: `Used the "${type}" from "${serverName}" server.
746
- Content: ${content}`,
747
- metadata: {
748
- ...metadata,
749
- serverName
750
- }
773
+ text: `Used "${type}" from "${serverName}". Content: ${content}`,
774
+ metadata: { ...metadata, serverName }
751
775
  }
752
776
  });
753
777
  await runtime2.createMemory(memory, type === "resource" ? "resources" : "tools", true);
754
778
  }
755
779
  function buildMcpProviderData(servers) {
756
- const mcpData = {};
757
- let textContent = "";
758
780
  if (servers.length === 0) {
759
- return {
760
- values: { mcp: {} },
761
- data: { mcp: {} },
762
- text: "No MCP servers are currently connected."
763
- };
781
+ return { values: { mcp: {} }, data: { mcp: {} }, text: "No MCP servers connected." };
764
782
  }
783
+ const mcpData = {};
784
+ const lines = [`# MCP Configuration
785
+ `];
765
786
  for (const server of servers) {
766
- mcpData[server.name] = {
767
- status: server.status,
768
- tools: {},
769
- resources: {}
770
- };
771
- textContent += `## Server: ${server.name} (${server.status})
772
-
773
- `;
774
- if (server.tools && server.tools.length > 0) {
775
- textContent += `### Tools:
776
-
777
- `;
778
- for (const tool of server.tools) {
779
- mcpData[server.name].tools[tool.name] = {
780
- description: tool.description || "No description available",
781
- inputSchema: tool.inputSchema || {}
782
- };
783
- textContent += `- **${tool.name}**: ${tool.description || "No description available"}
784
- `;
785
- }
786
- textContent += `
787
- `;
788
- }
789
- if (server.resources && server.resources.length > 0) {
790
- textContent += `### Resources:
791
-
792
- `;
793
- for (const resource of server.resources) {
794
- mcpData[server.name].resources[resource.uri] = {
795
- name: resource.name,
796
- description: resource.description || "No description available",
797
- mimeType: resource.mimeType
798
- };
799
- textContent += `- **${resource.name}** (${resource.uri}): ${resource.description || "No description available"}
800
- `;
801
- }
802
- textContent += `
803
- `;
804
- }
805
- }
806
- return {
807
- values: { mcp: mcpData, mcpText: `# MCP Configuration
808
-
809
- ${textContent}` },
810
- data: { mcp: mcpData },
811
- text: `# MCP Configuration
812
-
813
- ${textContent}`
814
- };
787
+ const tools = {};
788
+ const resources = {};
789
+ lines.push(`## ${server.name} (${server.status})
790
+ `);
791
+ if (server.tools?.length) {
792
+ lines.push(`### Tools
793
+ `);
794
+ for (const t of server.tools) {
795
+ tools[t.name] = { description: t.description || NO_DESC, inputSchema: t.inputSchema || {} };
796
+ lines.push(`- **${t.name}**: ${t.description || NO_DESC}`);
797
+ }
798
+ lines.push("");
799
+ }
800
+ if (server.resources?.length) {
801
+ lines.push(`### Resources
802
+ `);
803
+ for (const r of server.resources) {
804
+ resources[r.uri] = { name: r.name, description: r.description || NO_DESC, mimeType: r.mimeType };
805
+ lines.push(`- **${r.name}** (${r.uri}): ${r.description || NO_DESC}`);
806
+ }
807
+ lines.push("");
808
+ }
809
+ mcpData[server.name] = { status: server.status, tools, resources };
810
+ }
811
+ const text = lines.join(`
812
+ `);
813
+ return { values: { mcp: mcpData, mcpText: text }, data: { mcp: mcpData }, text };
815
814
  }
816
815
 
817
816
  // src/utils/processing.ts
@@ -1413,33 +1412,6 @@ function createFeedbackPrompt2(originalResponse, errorMessage, itemType, itemsDe
1413
1412
  User request: ${userMessage}`;
1414
1413
  }
1415
1414
 
1416
- // src/utils/handler.ts
1417
- async function handleNoToolAvailable(callback, toolSelection) {
1418
- const responseText = "I don't have a specific tool that can help with that request. Let me try to assist you directly instead.";
1419
- const thoughtText = "No appropriate MCP tool available for this request. Falling back to direct assistance.";
1420
- if (callback && toolSelection?.noToolAvailable) {
1421
- await callback({
1422
- text: responseText,
1423
- thought: thoughtText,
1424
- actions: ["REPLY"]
1425
- });
1426
- }
1427
- return {
1428
- text: responseText,
1429
- values: {
1430
- success: true,
1431
- noToolAvailable: true,
1432
- fallbackToDirectAssistance: true
1433
- },
1434
- data: {
1435
- actionName: "CALL_MCP_TOOL",
1436
- noToolAvailable: true,
1437
- reason: toolSelection?.reasoning || "No appropriate tool available"
1438
- },
1439
- success: true
1440
- };
1441
- }
1442
-
1443
1415
  // src/actions/callToolAction.ts
1444
1416
  var callToolAction = {
1445
1417
  name: "CALL_MCP_TOOL",
@@ -1501,7 +1473,7 @@ ${JSON.stringify(toolSelectionArgument, null, 2)}`);
1501
1473
  const result = await mcpService.callTool(serverName, toolName, toolSelectionArgument.toolArguments);
1502
1474
  const { toolOutput, hasAttachments, attachments } = processToolResult(result, serverName, toolName, runtime2, message.entityId);
1503
1475
  const replyMemory = await handleToolResponse(runtime2, message, serverName, toolName, toolSelectionArgument.toolArguments, toolOutput, hasAttachments, attachments, composedState, mcpProvider, callback);
1504
- return {
1476
+ const actionResult = {
1505
1477
  text: `Successfully called tool: ${serverName}/${toolName}. Reasoned response: ${replyMemory.content.text}`,
1506
1478
  values: {
1507
1479
  success: true,
@@ -1522,6 +1494,15 @@ ${JSON.stringify(toolSelectionArgument, null, 2)}`);
1522
1494
  },
1523
1495
  success: true
1524
1496
  };
1497
+ logger5.info({
1498
+ serverName,
1499
+ toolName,
1500
+ hasOutput: !!toolOutput,
1501
+ outputLength: toolOutput?.length || 0,
1502
+ hasAttachments,
1503
+ reasoning: toolSelectionName.reasoning
1504
+ }, `[CALL_MCP_TOOL] Action result`);
1505
+ return actionResult;
1525
1506
  } catch (error) {
1526
1507
  return await handleMcpError(composedState, mcpProvider, error, runtime2, message, "tool", callback);
1527
1508
  }
@@ -1763,19 +1744,20 @@ var readResourceAction = {
1763
1744
  };
1764
1745
 
1765
1746
  // src/provider.ts
1747
+ var createEmptyProvider = () => ({
1748
+ values: { mcp: {} },
1749
+ data: { mcp: {} },
1750
+ text: "No MCP servers available."
1751
+ });
1766
1752
  var provider = {
1767
1753
  name: "MCP",
1768
- description: "Information about connected MCP servers, tools, and resources",
1754
+ description: "Connected MCP servers, tools, and resources",
1769
1755
  get: async (runtime2, _message, _state) => {
1770
- const mcpService = runtime2.getService(MCP_SERVICE_NAME);
1771
- if (!mcpService) {
1772
- return {
1773
- values: { mcp: {} },
1774
- data: { mcp: {} },
1775
- text: "No MCP servers are available."
1776
- };
1777
- }
1778
- return mcpService.getProviderData();
1756
+ const svc = runtime2.getService(MCP_SERVICE_NAME);
1757
+ if (!svc)
1758
+ return createEmptyProvider();
1759
+ await svc.waitForInitialization();
1760
+ return svc.getProviderData();
1779
1761
  }
1780
1762
  };
1781
1763
 
@@ -1784,6 +1766,9 @@ import { Service, logger as logger7 } from "@elizaos/core";
1784
1766
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
1785
1767
  import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
1786
1768
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
1769
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
1770
+ var errMsg = (e) => e instanceof Error ? e.message : String(e);
1771
+
1787
1772
  class McpService extends Service {
1788
1773
  static serviceType = MCP_SERVICE_NAME;
1789
1774
  capabilityDescription = "Enables the agent to interact with MCP (Model Context Protocol) servers";
@@ -1800,7 +1785,6 @@ class McpService extends Service {
1800
1785
  initializationPromise = null;
1801
1786
  constructor(runtime2) {
1802
1787
  super(runtime2);
1803
- logger7.info("[McpService] Constructor called, starting initialization...");
1804
1788
  this.initializationPromise = this.initializeMcpServers();
1805
1789
  }
1806
1790
  static async start(runtime2) {
@@ -1816,116 +1800,70 @@ class McpService extends Service {
1816
1800
  }
1817
1801
  }
1818
1802
  async stop() {
1819
- for (const [name] of this.connections) {
1803
+ for (const name of this.connections.keys()) {
1820
1804
  await this.deleteConnection(name);
1821
1805
  }
1822
- this.connections.clear();
1823
- for (const state of this.connectionStates.values()) {
1806
+ for (const [name, state] of this.connectionStates.entries()) {
1824
1807
  if (state.pingInterval)
1825
1808
  clearInterval(state.pingInterval);
1826
1809
  if (state.reconnectTimeout)
1827
1810
  clearTimeout(state.reconnectTimeout);
1811
+ this.connectionStates.delete(name);
1828
1812
  }
1829
- this.connectionStates.clear();
1830
1813
  }
1831
1814
  async initializeMcpServers() {
1832
- logger7.info("[McpService] Starting MCP server initialization...");
1833
1815
  try {
1834
1816
  const mcpSettings = this.getMcpSettings();
1835
- const serverCount = mcpSettings?.servers ? Object.keys(mcpSettings.servers).length : 0;
1836
- const serverNames = mcpSettings?.servers ? Object.keys(mcpSettings.servers) : [];
1837
- logger7.info(`[McpService] Getting MCP settings... hasSettings=${!!mcpSettings} hasServers=${!!mcpSettings?.servers} serverCount=${serverCount} servers=${JSON.stringify(serverNames)}`);
1838
- if (!mcpSettings || !mcpSettings.servers) {
1839
- logger7.info("[McpService] No MCP servers configured.");
1840
- this.mcpProvider = buildMcpProviderData([]);
1841
- return;
1842
- }
1843
- if (Object.keys(mcpSettings.servers).length === 0) {
1844
- logger7.info("[McpService] MCP settings exist but no servers configured.");
1817
+ if (!mcpSettings?.servers || Object.keys(mcpSettings.servers).length === 0) {
1845
1818
  this.mcpProvider = buildMcpProviderData([]);
1846
1819
  return;
1847
1820
  }
1848
- logger7.info(`[McpService] Connecting to ${Object.keys(mcpSettings.servers).length} MCP servers: ${JSON.stringify(Object.keys(mcpSettings.servers))}`);
1849
1821
  const connectionStartTime = Date.now();
1850
1822
  await this.updateServerConnections(mcpSettings.servers);
1851
1823
  const connectionDuration = Date.now() - connectionStartTime;
1852
1824
  const servers = this.getServers();
1853
- const connectedServers = servers.filter((s) => s.status === "connected");
1854
- const failedServers = servers.filter((s) => s.status !== "connected");
1855
- if (connectedServers.length > 0) {
1856
- const toolCounts = connectedServers.map((s) => `${s.name}:${s.tools?.length || 0}tools`).join(", ");
1857
- logger7.info(`[McpService] ✓ Successfully connected ${connectedServers.length}/${servers.length} servers in ${connectionDuration}ms: ${toolCounts}`);
1825
+ const connected = servers.filter((s) => s.status === "connected");
1826
+ const failed = servers.filter((s) => s.status !== "connected");
1827
+ if (connected.length > 0) {
1828
+ logger7.info(`[MCP] Connected ${connected.length}/${servers.length} in ${connectionDuration}ms (${connected.map((s) => `${s.name}:${s.tools?.length || 0}`).join(", ")})`);
1858
1829
  }
1859
- if (failedServers.length > 0) {
1860
- const failedDetails = failedServers.map((s) => `${s.name}(${s.error || "unknown error"})`).join(", ");
1861
- logger7.warn(`[McpService] ⚠️ Failed to connect to ${failedServers.length}/${servers.length} servers: ${failedDetails}`);
1830
+ if (failed.length > 0) {
1831
+ logger7.warn(`[MCP] Failed: ${failed.map((s) => s.name).join(", ")}`);
1862
1832
  }
1863
- if (connectedServers.length === 0 && servers.length > 0) {
1864
- logger7.error(`[McpService] ALL MCP servers failed to connect! MCP tools will NOT be available.`);
1833
+ if (connected.length === 0 && servers.length > 0) {
1834
+ logger7.error(`[MCP] All servers failed`);
1865
1835
  }
1866
1836
  this.mcpProvider = buildMcpProviderData(servers);
1867
- const mcpDataKeys = Object.keys(this.mcpProvider.data?.mcp || {});
1868
- logger7.info(`[McpService] MCP provider data built: ${mcpDataKeys.length} server(s) available`);
1869
1837
  } catch (error) {
1870
- logger7.error({ error: error instanceof Error ? error.message : String(error) }, "❌ Failed to initialize MCP servers - MCP tools will NOT be available");
1838
+ logger7.error({ error: errMsg(error) }, "[MCP] Initialization failed");
1871
1839
  this.mcpProvider = buildMcpProviderData([]);
1872
1840
  }
1873
1841
  }
1874
1842
  getMcpSettings() {
1875
- const rawSettings = this.runtime.getSetting("mcp");
1876
- let settings = rawSettings;
1877
- logger7.info(`[McpService] getSetting("mcp") result: type=${typeof rawSettings} isNull=${rawSettings === null} hasServers=${!!settings?.servers}`);
1878
- if (!settings || !settings.servers) {
1879
- const characterSettings = this.runtime.character?.settings;
1880
- if (characterSettings?.mcp) {
1881
- logger7.info("[McpService] Found MCP settings in character.settings.mcp (fallback)");
1882
- settings = characterSettings.mcp;
1883
- }
1884
- }
1885
- if (!settings || !settings.servers) {
1886
- const runtimeSettings = this.runtime.settings;
1887
- if (runtimeSettings?.mcp) {
1888
- logger7.info("[McpService] Found MCP settings in runtime.settings.mcp (fallback)");
1889
- settings = runtimeSettings.mcp;
1890
- }
1843
+ let settings = this.runtime.getSetting("mcp");
1844
+ if (!settings || typeof settings === "object" && !settings.servers) {
1845
+ settings = this.runtime.character?.settings?.mcp;
1891
1846
  }
1892
- if (settings && typeof settings === "object" && settings.servers) {
1893
- logger7.info(`[McpService] MCP settings found with ${Object.keys(settings.servers).length} server(s)`);
1894
- return settings;
1847
+ if (!settings || typeof settings === "object" && !settings.servers) {
1848
+ settings = this.runtime.settings?.mcp;
1895
1849
  }
1896
- logger7.info("[McpService] No valid MCP settings found");
1897
- return;
1850
+ return settings && typeof settings === "object" && settings.servers ? settings : undefined;
1898
1851
  }
1899
1852
  async updateServerConnections(serverConfigs) {
1900
- const currentNames = new Set(this.connections.keys());
1901
1853
  const newNames = new Set(Object.keys(serverConfigs));
1902
- for (const name of currentNames) {
1903
- if (!newNames.has(name)) {
1854
+ for (const name of this.connections.keys()) {
1855
+ if (!newNames.has(name))
1904
1856
  await this.deleteConnection(name);
1905
- logger7.info(`Deleted MCP server: ${name}`);
1906
- }
1907
1857
  }
1908
- const connectionPromises = Object.entries(serverConfigs).map(async ([name, config]) => {
1909
- const currentConnection = this.connections.get(name);
1910
- if (!currentConnection) {
1911
- try {
1912
- await this.initializeConnection(name, config);
1913
- logger7.info(`✓ Connected to MCP server: ${name}`);
1914
- } catch (error) {
1915
- logger7.error({ error: error instanceof Error ? error.message : String(error), serverName: name }, `✗ Failed to connect to new MCP server ${name}`);
1916
- }
1917
- } else if (JSON.stringify(config) !== currentConnection.server.config) {
1918
- try {
1919
- await this.deleteConnection(name);
1920
- await this.initializeConnection(name, config);
1921
- logger7.info(`✓ Reconnected MCP server with updated config: ${name}`);
1922
- } catch (error) {
1923
- logger7.error({ error: error instanceof Error ? error.message : String(error), serverName: name }, `✗ Failed to reconnect MCP server ${name}`);
1924
- }
1858
+ await Promise.allSettled(Object.entries(serverConfigs).map(async ([name, config]) => {
1859
+ const current = this.connections.get(name);
1860
+ if (!current) {
1861
+ await this.initializeConnection(name, config).catch((e) => logger7.error({ error: errMsg(e), serverName: name }, `[MCP] Failed: ${name}`));
1862
+ } else if (JSON.stringify(config) !== current.server.config) {
1863
+ await this.deleteConnection(name);
1864
+ await this.initializeConnection(name, config).catch((e) => logger7.error({ error: errMsg(e), serverName: name }, `[MCP] Failed: ${name}`));
1925
1865
  }
1926
- });
1927
- await Promise.allSettled(connectionPromises);
1928
- logger7.info(`[McpService] All server connection attempts completed`);
1866
+ }));
1929
1867
  }
1930
1868
  async initializeConnection(name, config) {
1931
1869
  await this.deleteConnection(name);
@@ -1939,19 +1877,19 @@ class McpService extends Service {
1939
1877
  const client = new Client({ name: "ElizaOS", version: "1.0.0" }, { capabilities: {} });
1940
1878
  const transport = config.type === "stdio" ? await this.buildStdioClientTransport(name, config) : await this.buildHttpClientTransport(name, config);
1941
1879
  const connection = {
1942
- server: {
1943
- name,
1944
- config: JSON.stringify(config),
1945
- status: "connecting"
1946
- },
1880
+ server: { name, config: JSON.stringify(config), status: "connecting" },
1947
1881
  client,
1948
1882
  transport
1949
1883
  };
1950
1884
  this.connections.set(name, connection);
1951
1885
  this.setupTransportHandlers(name, connection, state);
1952
- await client.connect(transport);
1886
+ const connectPromise = client.connect(transport);
1887
+ connectPromise.catch(() => {});
1888
+ await Promise.race([
1889
+ connectPromise,
1890
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`Timeout connecting to ${name}`)), 60000))
1891
+ ]);
1953
1892
  const capabilities = client.getServerCapabilities();
1954
- logger7.debug(`[${name}] Server capabilities:`, JSON.stringify(capabilities || {}));
1955
1893
  const tools = await this.fetchToolsList(name);
1956
1894
  const resources = capabilities?.resources ? await this.fetchResourcesList(name) : [];
1957
1895
  const resourceTemplates = capabilities?.resources ? await this.fetchResourceTemplatesList(name) : [];
@@ -1969,7 +1907,6 @@ class McpService extends Service {
1969
1907
  state.reconnectAttempts = 0;
1970
1908
  state.consecutivePingFailures = 0;
1971
1909
  this.startPingMonitoring(name);
1972
- logger7.info(`Successfully connected to MCP server: ${name}`);
1973
1910
  } catch (error) {
1974
1911
  state.status = "disconnected";
1975
1912
  state.lastError = error instanceof Error ? error : new Error(String(error));
@@ -1979,26 +1916,21 @@ class McpService extends Service {
1979
1916
  }
1980
1917
  setupTransportHandlers(name, connection, state) {
1981
1918
  const config = JSON.parse(connection.server.config);
1982
- const isHttpTransport = config.type !== "stdio";
1919
+ const isHttp = config.type !== "stdio";
1983
1920
  connection.transport.onerror = async (error) => {
1984
- const errorMessage = error?.message || String(error);
1985
- const isExpectedTimeout = isHttpTransport && (errorMessage === "undefined" || errorMessage === "" || errorMessage.includes("SSE error") || errorMessage.includes("timeout"));
1986
- if (isExpectedTimeout) {
1987
- logger7.debug({ serverName: name }, `SSE connection timeout for "${name}" (expected, will reconnect)`);
1988
- } else {
1989
- logger7.error({ error, serverName: name }, `Transport error for "${name}"`);
1921
+ const msg = error?.message || String(error);
1922
+ const isExpectedTimeout = isHttp && (!msg || msg === "undefined" || msg.includes("SSE") || msg.includes("timeout"));
1923
+ if (!isExpectedTimeout) {
1924
+ logger7.error({ error, serverName: name }, `Transport error: ${name}`);
1990
1925
  connection.server.status = "disconnected";
1991
- this.appendErrorMessage(connection, error.message);
1926
+ this.appendErrorMessage(connection, msg);
1992
1927
  }
1993
- if (!isHttpTransport) {
1928
+ if (!isHttp)
1994
1929
  this.handleDisconnection(name, error);
1995
- }
1996
1930
  };
1997
1931
  connection.transport.onclose = async () => {
1998
- if (isHttpTransport) {
1999
- logger7.debug({ serverName: name }, `SSE connection closed for "${name}" (stateless, will reconnect on demand)`);
2000
- } else {
2001
- logger7.warn({ serverName: name }, `Transport closed for "${name}"`);
1932
+ if (!isHttp) {
1933
+ logger7.warn({ serverName: name }, `Transport closed: ${name}`);
2002
1934
  connection.server.status = "disconnected";
2003
1935
  this.handleDisconnection(name, new Error("Transport closed"));
2004
1936
  }
@@ -2009,11 +1941,8 @@ class McpService extends Service {
2009
1941
  if (!connection)
2010
1942
  return;
2011
1943
  const config = JSON.parse(connection.server.config);
2012
- const isHttpTransport = config.type !== "stdio";
2013
- if (isHttpTransport) {
2014
- logger7.debug(`[McpService] Skipping ping monitoring for HTTP server: ${name}`);
1944
+ if (config.type !== "stdio")
2015
1945
  return;
2016
- }
2017
1946
  const state = this.connectionStates.get(name);
2018
1947
  if (!state || !this.pingConfig.enabled)
2019
1948
  return;
@@ -2021,7 +1950,7 @@ class McpService extends Service {
2021
1950
  clearInterval(state.pingInterval);
2022
1951
  state.pingInterval = setInterval(() => {
2023
1952
  this.sendPing(name).catch((err) => {
2024
- logger7.warn({ error: err instanceof Error ? err.message : String(err), serverName: name }, `Ping failed for ${name}`);
1953
+ logger7.warn({ error: errMsg(err), serverName: name }, `Ping failed: ${name}`);
2025
1954
  this.handlePingFailure(name, err);
2026
1955
  });
2027
1956
  }, this.pingConfig.intervalMs);
@@ -2029,7 +1958,7 @@ class McpService extends Service {
2029
1958
  async sendPing(name) {
2030
1959
  const connection = this.connections.get(name);
2031
1960
  if (!connection)
2032
- throw new Error(`No connection for ping: ${name}`);
1961
+ throw new Error(`No connection: ${name}`);
2033
1962
  await Promise.race([
2034
1963
  connection.client.listTools(),
2035
1964
  new Promise((_, reject) => setTimeout(() => reject(new Error("Ping timeout")), this.pingConfig.timeoutMs))
@@ -2071,7 +2000,7 @@ class McpService extends Service {
2071
2000
  try {
2072
2001
  await this.initializeConnection(name, JSON.parse(config));
2073
2002
  } catch (err) {
2074
- logger7.error({ error: err instanceof Error ? err.message : String(err), serverName: name }, `Reconnect attempt failed for ${name}`);
2003
+ logger7.error({ error: errMsg(err), serverName: name }, `Reconnect attempt failed for ${name}`);
2075
2004
  this.handleDisconnection(name, err);
2076
2005
  }
2077
2006
  }
@@ -2084,7 +2013,7 @@ class McpService extends Service {
2084
2013
  await connection.transport.close();
2085
2014
  await connection.client.close();
2086
2015
  } catch (error) {
2087
- logger7.error({ error: error instanceof Error ? error.message : String(error), serverName: name }, `Failed to close transport for ${name}`);
2016
+ logger7.error({ error: errMsg(error), serverName: name }, `Failed to close transport for ${name}`);
2088
2017
  }
2089
2018
  this.connections.delete(name);
2090
2019
  }
@@ -2097,9 +2026,6 @@ class McpService extends Service {
2097
2026
  this.connectionStates.delete(name);
2098
2027
  }
2099
2028
  }
2100
- getServerConnection(serverName) {
2101
- return this.connections.get(serverName);
2102
- }
2103
2029
  async buildStdioClientTransport(name, config) {
2104
2030
  if (!config.command) {
2105
2031
  throw new Error(`Missing command for stdio MCP server ${name}`);
@@ -2116,74 +2042,61 @@ class McpService extends Service {
2116
2042
  });
2117
2043
  }
2118
2044
  async buildHttpClientTransport(name, config) {
2119
- if (!config.url) {
2120
- throw new Error(`Missing URL for HTTP MCP server ${name}`);
2121
- }
2045
+ if (!config.url)
2046
+ throw new Error(`Missing URL for MCP server ${name}`);
2047
+ const url = new URL(config.url);
2048
+ const opts = config.headers ? { requestInit: { headers: config.headers } } : undefined;
2122
2049
  if (config.type === "sse") {
2123
- logger7.warn(`Server "${name}": "sse" transport type is deprecated. Use "streamable-http" or "http" instead for the modern Streamable HTTP transport.`);
2050
+ logger7.warn(`[MCP] "${name}": SSE requires Redis. Use "streamable-http" instead.`);
2051
+ return new SSEClientTransport(url, opts);
2124
2052
  }
2125
- return new SSEClientTransport(new URL(config.url));
2053
+ return new StreamableHTTPClientTransport(url, opts);
2126
2054
  }
2127
2055
  appendErrorMessage(connection, error) {
2128
- const newError = connection.server.error ? `${connection.server.error}
2056
+ connection.server.error = connection.server.error ? `${connection.server.error}
2129
2057
  ${error}` : error;
2130
- connection.server.error = newError;
2131
2058
  }
2132
2059
  async fetchToolsList(serverName) {
2060
+ const connection = this.connections.get(serverName);
2061
+ if (!connection)
2062
+ return [];
2133
2063
  try {
2134
- const connection = this.getServerConnection(serverName);
2135
- if (!connection) {
2136
- return [];
2137
- }
2138
2064
  const response = await connection.client.listTools();
2139
- const tools = (response?.tools || []).map((tool) => {
2140
- let processedTool = { ...tool };
2141
- if (tool.inputSchema) {
2142
- try {
2143
- if (!this.compatibilityInitialized) {
2144
- this.initializeToolCompatibility();
2145
- }
2146
- processedTool.inputSchema = this.applyToolCompatibility(tool.inputSchema);
2147
- logger7.debug(`Applied tool compatibility for: ${tool.name} on server: ${serverName}`);
2148
- } catch (error) {
2149
- logger7.warn({ error, toolName: tool.name, serverName }, `Tool compatibility failed for ${tool.name} on ${serverName}`);
2150
- }
2065
+ return (response?.tools || []).map((tool) => {
2066
+ if (!tool.inputSchema)
2067
+ return tool;
2068
+ if (!this.compatibilityInitialized)
2069
+ this.initializeToolCompatibility();
2070
+ try {
2071
+ return { ...tool, inputSchema: this.applyToolCompatibility(tool.inputSchema) };
2072
+ } catch {
2073
+ return tool;
2151
2074
  }
2152
- return processedTool;
2153
2075
  });
2154
- logger7.info(`Fetched ${tools.length} tools for ${serverName}`);
2155
- for (const tool of tools) {
2156
- logger7.info(`[${serverName}] ${tool.name}: ${tool.description}`);
2157
- }
2158
- return tools;
2159
2076
  } catch (error) {
2160
- logger7.error({ error: error instanceof Error ? error.message : String(error), serverName }, `Failed to fetch tools for ${serverName}`);
2077
+ logger7.error({ error: errMsg(error), serverName }, `Failed to fetch tools: ${serverName}`);
2161
2078
  return [];
2162
2079
  }
2163
2080
  }
2164
- async fetchResourcesList(serverName) {
2081
+ async fetchResourcesList(name) {
2082
+ const conn = this.connections.get(name);
2083
+ if (!conn)
2084
+ return [];
2165
2085
  try {
2166
- const connection = this.getServerConnection(serverName);
2167
- if (!connection) {
2168
- return [];
2169
- }
2170
- const response = await connection.client.listResources();
2171
- return response?.resources || [];
2086
+ return (await conn.client.listResources())?.resources || [];
2172
2087
  } catch (error) {
2173
- logger7.warn({ error: error instanceof Error ? error.message : String(error), serverName }, `No resources found for ${serverName}`);
2088
+ logger7.debug({ error: errMsg(error), serverName: name }, `No resources for ${name}`);
2174
2089
  return [];
2175
2090
  }
2176
2091
  }
2177
- async fetchResourceTemplatesList(serverName) {
2092
+ async fetchResourceTemplatesList(name) {
2093
+ const conn = this.connections.get(name);
2094
+ if (!conn)
2095
+ return [];
2178
2096
  try {
2179
- const connection = this.getServerConnection(serverName);
2180
- if (!connection) {
2181
- return [];
2182
- }
2183
- const response = await connection.client.listResourceTemplates();
2184
- return response?.resourceTemplates || [];
2097
+ return (await conn.client.listResourceTemplates())?.resourceTemplates || [];
2185
2098
  } catch (error) {
2186
- logger7.warn({ error: error instanceof Error ? error.message : String(error), serverName }, `No resource templates found for ${serverName}`);
2099
+ logger7.debug({ error: errMsg(error), serverName: name }, `No resource templates for ${name}`);
2187
2100
  return [];
2188
2101
  }
2189
2102
  }
@@ -2193,76 +2106,53 @@ ${error}` : error;
2193
2106
  getProviderData() {
2194
2107
  return this.mcpProvider;
2195
2108
  }
2196
- async callTool(serverName, toolName, toolArguments) {
2197
- const connection = this.connections.get(serverName);
2198
- if (!connection) {
2199
- throw new Error(`No connection found for server: ${serverName}`);
2200
- }
2201
- if (connection.server.disabled) {
2202
- throw new Error(`Server "${serverName}" is disabled`);
2203
- }
2204
- let timeout = DEFAULT_MCP_TIMEOUT_SECONDS;
2205
- try {
2206
- const config = JSON.parse(connection.server.config);
2207
- timeout = config.timeoutInMillis || DEFAULT_MCP_TIMEOUT_SECONDS;
2208
- } catch (error) {
2209
- logger7.error({ error: error instanceof Error ? error.message : String(error), serverName }, `Failed to parse timeout configuration for server ${serverName}`);
2210
- }
2211
- const result = await connection.client.callTool({ name: toolName, arguments: toolArguments }, undefined, { timeout });
2212
- if (!result.content) {
2213
- throw new Error("Invalid tool result: missing content array");
2214
- }
2109
+ async callTool(serverName, toolName, args) {
2110
+ const conn = this.connections.get(serverName);
2111
+ if (!conn)
2112
+ throw new Error(`No connection: ${serverName}`);
2113
+ if (conn.server.disabled)
2114
+ throw new Error(`Server disabled: ${serverName}`);
2115
+ const config = JSON.parse(conn.server.config);
2116
+ const timeout = (config.type === "stdio" ? config.timeoutInMillis : config.timeout) ?? DEFAULT_MCP_TIMEOUT_SECONDS;
2117
+ const result = await conn.client.callTool({ name: toolName, arguments: args }, undefined, {
2118
+ timeout
2119
+ });
2120
+ if (!result.content)
2121
+ throw new Error("Invalid tool result: missing content");
2215
2122
  return result;
2216
2123
  }
2217
2124
  async readResource(serverName, uri) {
2218
- const connection = this.connections.get(serverName);
2219
- if (!connection) {
2220
- throw new Error(`No connection found for server: ${serverName}`);
2221
- }
2222
- if (connection.server.disabled) {
2223
- throw new Error(`Server "${serverName}" is disabled`);
2224
- }
2225
- return await connection.client.readResource({ uri });
2125
+ const conn = this.connections.get(serverName);
2126
+ if (!conn)
2127
+ throw new Error(`No connection: ${serverName}`);
2128
+ if (conn.server.disabled)
2129
+ throw new Error(`Server disabled: ${serverName}`);
2130
+ return conn.client.readResource({ uri });
2226
2131
  }
2227
2132
  async restartConnection(serverName) {
2228
- const connection = this.connections.get(serverName);
2229
- const config = connection?.server.config;
2230
- if (config) {
2231
- logger7.info(`Restarting ${serverName} MCP server...`);
2232
- connection.server.status = "connecting";
2233
- connection.server.error = "";
2234
- try {
2235
- await this.deleteConnection(serverName);
2236
- await this.initializeConnection(serverName, JSON.parse(config));
2237
- logger7.info(`${serverName} MCP server connected`);
2238
- } catch (error) {
2239
- logger7.error({ error: error instanceof Error ? error.message : String(error), serverName }, `Failed to restart connection for ${serverName}`);
2240
- throw new Error(`Failed to connect to ${serverName} MCP server`);
2241
- }
2242
- }
2133
+ const conn = this.connections.get(serverName);
2134
+ if (!conn)
2135
+ throw new Error(`No connection: ${serverName}`);
2136
+ const config = conn.server.config;
2137
+ conn.server.status = "connecting";
2138
+ conn.server.error = "";
2139
+ await this.deleteConnection(serverName);
2140
+ await this.initializeConnection(serverName, JSON.parse(config));
2243
2141
  }
2244
2142
  initializeToolCompatibility() {
2245
2143
  if (this.compatibilityInitialized)
2246
2144
  return;
2247
2145
  this.toolCompatibility = createMcpToolCompatibilitySync(this.runtime);
2248
2146
  this.compatibilityInitialized = true;
2249
- if (this.toolCompatibility) {
2250
- logger7.info(`Tool compatibility enabled`);
2251
- } else {
2252
- logger7.info(`No tool compatibility needed`);
2253
- }
2254
2147
  }
2255
2148
  applyToolCompatibility(toolSchema) {
2256
- if (!this.compatibilityInitialized) {
2149
+ if (!this.compatibilityInitialized)
2257
2150
  this.initializeToolCompatibility();
2258
- }
2259
- if (!this.toolCompatibility || !toolSchema) {
2151
+ if (!this.toolCompatibility || !toolSchema)
2260
2152
  return toolSchema;
2261
- }
2262
2153
  try {
2263
2154
  return this.toolCompatibility.transformToolSchema(toolSchema);
2264
- } catch (error) {
2265
- logger7.warn({ error }, `Tool compatibility transformation failed`);
2155
+ } catch {
2266
2156
  return toolSchema;
2267
2157
  }
2268
2158
  }
@@ -2299,4 +2189,4 @@ export {
2299
2189
  BACKOFF_MULTIPLIER
2300
2190
  };
2301
2191
 
2302
- //# debugId=73694D75D6553EC464756E2164756E21
2192
+ //# debugId=D6293B10B9AC06C464756E2164756E21