@mastra/mcp 1.16.0 → 1.17.0-alpha.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.cjs CHANGED
@@ -23762,25 +23762,31 @@ onListChanged: async (serverName, handler) => {
23762
23762
  * }
23763
23763
  * ```
23764
23764
  */
23765
- async listToolsWithErrors() {
23765
+ async listToolsWithErrors(options) {
23766
23766
  this.addToInstanceCache();
23767
23767
  const connectedTools = {};
23768
23768
  const errors = {};
23769
+ const durations = {};
23769
23770
  const settled = await this.discoverAcrossServers((serverName) => this.getToolsForServer(serverName), {
23770
23771
  errorId: "MCP_CLIENT_GET_TOOLS_FAILED",
23771
23772
  logMessage: "Failed to list tools from server:"
23772
- });
23773
- for (const { serverName, value, error } of settled) {
23773
+ }, options);
23774
+ for (const { serverName, value, error, duration } of settled) {
23775
+ durations[serverName] = duration;
23774
23776
  if (error !== void 0) {
23775
23777
  errors[serverName] = error;
23776
23778
  continue;
23777
23779
  }
23778
23780
  for (const [toolName, toolConfig] of Object.entries(value)) connectedTools[`${serverName}_${toolName}`] = toolConfig;
23779
23781
  }
23780
- return {
23782
+ const result = {
23781
23783
  tools: connectedTools,
23782
23784
  errors
23783
23785
  };
23786
+ return options ? {
23787
+ ...result,
23788
+ durations
23789
+ } : result;
23784
23790
  }
23785
23791
  /**
23786
23792
  * Returns toolsets organized by server name for dynamic tool injection.
@@ -23825,25 +23831,31 @@ onListChanged: async (serverName, handler) => {
23825
23831
  * }
23826
23832
  * ```
23827
23833
  */
23828
- async listToolsetsWithErrors() {
23834
+ async listToolsetsWithErrors(options) {
23829
23835
  this.addToInstanceCache();
23830
23836
  const connectedToolsets = {};
23831
23837
  const errors = {};
23838
+ const durations = {};
23832
23839
  const settled = await this.discoverAcrossServers((serverName) => this.getToolsForServer(serverName), {
23833
23840
  errorId: "MCP_CLIENT_GET_TOOLSETS_FAILED",
23834
23841
  logMessage: "Failed to list toolsets from server:"
23835
- });
23836
- for (const { serverName, value, error } of settled) {
23842
+ }, options);
23843
+ for (const { serverName, value, error, duration } of settled) {
23844
+ durations[serverName] = duration;
23837
23845
  if (error !== void 0) {
23838
23846
  errors[serverName] = error;
23839
23847
  continue;
23840
23848
  }
23841
23849
  connectedToolsets[serverName] = value;
23842
23850
  }
23843
- return {
23851
+ const result = {
23844
23852
  toolsets: connectedToolsets,
23845
23853
  errors
23846
23854
  };
23855
+ return options ? {
23856
+ ...result,
23857
+ durations
23858
+ } : result;
23847
23859
  }
23848
23860
  /**
23849
23861
  * Discovers every configured server's tools as plain, serializable definitions.
@@ -23877,27 +23889,33 @@ onListChanged: async (serverName, handler) => {
23877
23889
  * Useful when caching a catalog, since it lets you avoid persisting a partial manifest that
23878
23890
  * silently omits a server which happened to be down at discovery time.
23879
23891
  */
23880
- async listToolDefinitionsWithErrors() {
23892
+ async listToolDefinitionsWithErrors(options) {
23881
23893
  this.addToInstanceCache();
23882
23894
  const definitions = {};
23883
23895
  const errors = {};
23896
+ const durations = {};
23884
23897
  const settled = await this.discoverAcrossServers(async (serverName) => {
23885
23898
  return (await this.getConnectedClientForServer(serverName)).toolDefinitions();
23886
23899
  }, {
23887
23900
  errorId: "MCP_CLIENT_GET_TOOL_DEFINITIONS_FAILED",
23888
23901
  logMessage: "Failed to list tool definitions from server:"
23889
- });
23890
- for (const { serverName, value, error } of settled) {
23902
+ }, options);
23903
+ for (const { serverName, value, error, duration } of settled) {
23904
+ durations[serverName] = duration;
23891
23905
  if (error !== void 0) {
23892
23906
  errors[serverName] = error;
23893
23907
  continue;
23894
23908
  }
23895
23909
  definitions[serverName] = value;
23896
23910
  }
23897
- return {
23911
+ const result = {
23898
23912
  definitions,
23899
23913
  errors
23900
23914
  };
23915
+ return options ? {
23916
+ ...result,
23917
+ durations
23918
+ } : result;
23901
23919
  }
23902
23920
  /**
23903
23921
  * Rebuilds an executable Mastra tool from a cached {@link SerializableMCPToolDefinition}.
@@ -23961,14 +23979,21 @@ onListChanged: async (serverName, handler) => {
23961
23979
  * Backs `listTools`/`listToolsets`, `resources.list`/`templates`, and
23962
23980
  * `prompts.list`.
23963
23981
  */
23964
- async discoverAcrossServers(operation, onError) {
23982
+ async discoverAcrossServers(operation, onError, options) {
23965
23983
  const serverNames = Object.keys(this.serverConfigs);
23966
23984
  return Promise.all(serverNames.map(async (serverName) => {
23985
+ const startedAt = performance.now();
23986
+ let timer;
23967
23987
  try {
23988
+ const operationPromise = operation(serverName);
23968
23989
  return {
23969
23990
  serverName,
23970
- value: await operation(serverName),
23971
- error: void 0
23991
+ value: options?.perServerTimeoutMs === void 0 ? await operationPromise : await Promise.race([operationPromise, new Promise((_, reject) => {
23992
+ timer = setTimeout(() => reject(/* @__PURE__ */ new Error(`Discovery timed out after ${options.perServerTimeoutMs}ms`)), options.perServerTimeoutMs);
23993
+ timer.unref?.();
23994
+ })]),
23995
+ error: void 0,
23996
+ duration: performance.now() - startedAt
23972
23997
  };
23973
23998
  } catch (error) {
23974
23999
  const mastraError = new _mastra_core_error.MastraError({
@@ -23982,8 +24007,11 @@ onListChanged: async (serverName, handler) => {
23982
24007
  return {
23983
24008
  serverName,
23984
24009
  value: void 0,
23985
- error: error instanceof Error ? error.message : String(error)
24010
+ error: error instanceof Error ? error.message : String(error),
24011
+ duration: performance.now() - startedAt
23986
24012
  };
24013
+ } finally {
24014
+ clearTimeout(timer);
23987
24015
  }
23988
24016
  }));
23989
24017
  }
@@ -26527,6 +26555,8 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
26527
26555
  stdioTransport;
26528
26556
  sseTransport;
26529
26557
  sseHonoTransports;
26558
+ /** Auth info for the in-flight Hono SSE message POST, keyed by session id. */
26559
+ sseHonoAuthInfo = /* @__PURE__ */ new Map();
26530
26560
  streamableHTTPTransports = /* @__PURE__ */ new Map();
26531
26561
  httpServerInstances = /* @__PURE__ */ new Map();
26532
26562
  resourceOptions;
@@ -27703,7 +27733,7 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
27703
27733
  * export default app;
27704
27734
  * ```
27705
27735
  */
27706
- async startHonoSSE({ url, ssePath, messagePath, context }) {
27736
+ async startHonoSSE({ url, ssePath, messagePath, context, authInfo }) {
27707
27737
  const honoContext = context;
27708
27738
  try {
27709
27739
  if (url.pathname === ssePath) return streamSSE(honoContext, async (stream) => {
@@ -27718,6 +27748,8 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
27718
27748
  this.logger.debug("Received message for sessionId", { sessionId });
27719
27749
  if (!sessionId) return honoContext.text("No sessionId provided", 400);
27720
27750
  if (!this.sseHonoTransports.has(sessionId)) return honoContext.text(`No transport found for sessionId ${sessionId}`, 400);
27751
+ if (authInfo) this.sseHonoAuthInfo.set(sessionId, authInfo);
27752
+ else this.sseHonoAuthInfo.delete(sessionId);
27721
27753
  const message = await this.sseHonoTransports.get(sessionId)?.handlePostMessage(honoContext);
27722
27754
  if (!message) return honoContext.text("Transport not found", 400);
27723
27755
  return message;
@@ -28070,12 +28102,22 @@ var MCPServer = class extends _mastra_core_mcp.MCPServerBase {
28070
28102
  stream.onAbort(() => {
28071
28103
  this.logger.debug("SSE Transport aborted with sessionId:", { sessionId });
28072
28104
  this.sseHonoTransports.delete(sessionId);
28105
+ this.sseHonoAuthInfo.delete(sessionId);
28073
28106
  });
28074
28107
  try {
28075
28108
  await this.server.connect(sseTransport);
28109
+ const onmessage = sseTransport.onmessage?.bind(sseTransport);
28110
+ if (onmessage) sseTransport.onmessage = (message, extra) => {
28111
+ const authInfo = this.sseHonoAuthInfo.get(sessionId);
28112
+ onmessage(message, authInfo ? {
28113
+ ...extra,
28114
+ authInfo
28115
+ } : extra);
28116
+ };
28076
28117
  this.server.onclose = async () => {
28077
28118
  this.logger.debug("SSE Transport closed with sessionId:", { sessionId });
28078
28119
  this.sseHonoTransports.delete(sessionId);
28120
+ this.sseHonoAuthInfo.delete(sessionId);
28079
28121
  await this.server.close();
28080
28122
  };
28081
28123
  while (true) {