@mastra/mcp 0.4.1-alpha.2 → 0.4.1-alpha.4

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.
@@ -5,13 +5,20 @@ import type { Protocol } from '@modelcontextprotocol/sdk/shared/protocol.js';
5
5
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
6
6
  import type { SSEClientTransportOptions } from '@modelcontextprotocol/sdk/client/sse.js';
7
7
  import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
8
- import type { StdioServerParameters } from '@modelcontextprotocol/sdk/client/stdio.js';
9
8
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
9
+ import type { StreamableHTTPClientTransportOptions } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
10
10
  import { Tool } from '@mastra/core/tools';
11
11
  import { ToolExecutionContext } from '@mastra/core';
12
12
  import type { ToolsInput } from '@mastra/core/agent';
13
13
  import { z } from 'zod';
14
14
 
15
+ declare type BaseServerOptions = {
16
+ logger?: LogHandler;
17
+ timeout?: number;
18
+ capabilities?: ClientCapabilities;
19
+ enableServerLogs?: boolean;
20
+ };
21
+
15
22
  declare type ConvertedTool = {
16
23
  name: string;
17
24
  description?: string;
@@ -22,39 +29,26 @@ declare type ConvertedTool = {
22
29
 
23
30
  export declare function createLogger(server?: Server): Logger;
24
31
 
25
- export declare interface Logger {
26
- info: (message: string, data?: any) => Promise<void>;
27
- warning: (message: string, data?: any) => Promise<void>;
28
- error: (message: string, error?: any) => Promise<void>;
29
- debug: (message: string, data?: any) => Promise<void>;
30
- }
31
-
32
- export declare const logger: Logger;
33
-
34
- export { LoggingLevel }
35
- export { LoggingLevel as LoggingLevel_alias_1 }
36
-
37
- declare type LogHandler = (logMessage: LogMessage) => void;
38
- export { LogHandler }
39
- export { LogHandler as LogHandler_alias_1 }
40
-
41
- declare interface LogMessage {
42
- level: LoggingLevel;
43
- message: string;
44
- timestamp: Date;
45
- serverName: string;
46
- details?: Record<string, any>;
47
- }
48
- export { LogMessage }
49
- export { LogMessage as LogMessage_alias_1 }
32
+ declare type HttpServerDefinition = BaseServerOptions & {
33
+ url: URL;
34
+ command?: never;
35
+ args?: never;
36
+ env?: never;
37
+ requestInit?: StreamableHTTPClientTransportOptions['requestInit'];
38
+ eventSourceInit?: SSEClientTransportOptions['eventSourceInit'];
39
+ reconnectionOptions?: StreamableHTTPClientTransportOptions['reconnectionOptions'];
40
+ sessionId?: StreamableHTTPClientTransportOptions['sessionId'];
41
+ };
50
42
 
51
- declare class MastraMCPClient extends MastraBase {
43
+ export declare class InternalMastraMCPClient extends MastraBase {
52
44
  name: string;
53
- private transport;
54
45
  private client;
55
46
  private readonly timeout;
56
47
  private logHandler?;
57
48
  private enableServerLogs?;
49
+ private static hasWarned;
50
+ private serverConfig;
51
+ private transport?;
58
52
  constructor({ name, version, server, capabilities, timeout, }: {
59
53
  name: string;
60
54
  server: MastraMCPServerDefinition;
@@ -70,41 +64,100 @@ declare class MastraMCPClient extends MastraBase {
70
64
  */
71
65
  private log;
72
66
  private setupLogging;
67
+ private connectStdio;
68
+ private connectHttp;
73
69
  private isConnected;
74
70
  connect(): Promise<void>;
71
+ /**
72
+ * Get the current session ID if using the Streamable HTTP transport.
73
+ * Returns undefined if not connected or not using Streamable HTTP.
74
+ */
75
+ get sessionId(): string | undefined;
75
76
  disconnect(): Promise<void>;
76
77
  resources(): Promise<ReturnType<Protocol<any, any, any>['request']>>;
77
78
  tools(): Promise<Record<string, any>>;
78
79
  }
80
+
81
+ export declare interface Logger {
82
+ info: (message: string, data?: any) => Promise<void>;
83
+ warning: (message: string, data?: any) => Promise<void>;
84
+ error: (message: string, error?: any) => Promise<void>;
85
+ debug: (message: string, data?: any) => Promise<void>;
86
+ }
87
+
88
+ export declare const logger: Logger;
89
+
90
+ export { LoggingLevel }
91
+ export { LoggingLevel as LoggingLevel_alias_1 }
92
+
93
+ declare type LogHandler = (logMessage: LogMessage) => void;
94
+ export { LogHandler }
95
+ export { LogHandler as LogHandler_alias_1 }
96
+
97
+ declare interface LogMessage {
98
+ level: LoggingLevel;
99
+ message: string;
100
+ timestamp: Date;
101
+ serverName: string;
102
+ details?: Record<string, any>;
103
+ }
104
+ export { LogMessage }
105
+ export { LogMessage as LogMessage_alias_1 }
106
+
107
+ /**
108
+ * @deprecated MastraMCPClient is deprecated and will be removed in a future release. Please use MCPClient instead.
109
+ */
110
+ declare const MastraMCPClient: typeof InternalMastraMCPClient;
79
111
  export { MastraMCPClient }
80
112
  export { MastraMCPClient as MastraMCPClient_alias_1 }
81
113
 
82
- declare type MastraMCPServerDefinition = (StdioServerParameters | SSEClientParameters) & {
83
- logger?: LogHandler;
84
- timeout?: number;
85
- capabilities?: ClientCapabilities;
86
- enableServerLogs?: boolean;
87
- };
114
+ declare type MastraMCPServerDefinition = StdioServerDefinition | HttpServerDefinition;
88
115
  export { MastraMCPServerDefinition }
89
116
  export { MastraMCPServerDefinition as MastraMCPServerDefinition_alias_1 }
90
117
 
91
- declare class MCPConfiguration extends MastraBase {
118
+ declare class MCPClient extends MastraBase {
92
119
  private serverConfigs;
93
120
  private id;
94
121
  private defaultTimeout;
95
- constructor(args: MCPConfigurationOptions);
122
+ private mcpClientsById;
123
+ private disconnectPromise;
124
+ constructor(args: MCPClientOptions);
96
125
  private addToInstanceCache;
97
126
  private makeId;
98
127
  disconnect(): Promise<void>;
99
128
  getTools(): Promise<Record<string, any>>;
100
129
  getToolsets(): Promise<Record<string, Record<string, any>>>;
101
- private mcpClientsById;
130
+ /**
131
+ * Get the current session IDs for all connected MCP clients using the Streamable HTTP transport.
132
+ * Returns an object mapping server names to their session IDs.
133
+ */
134
+ get sessionIds(): Record<string, string>;
102
135
  private getConnectedClient;
103
136
  private eachClientTools;
104
137
  }
138
+ export { MCPClient }
139
+ export { MCPClient as MCPClient_alias_1 }
140
+
141
+ declare interface MCPClientOptions {
142
+ id?: string;
143
+ servers: Record<string, MastraMCPServerDefinition>;
144
+ timeout?: number;
145
+ }
146
+ export { MCPClientOptions }
147
+ export { MCPClientOptions as MCPClientOptions_alias_1 }
148
+
149
+ /**
150
+ * @deprecated MCPConfiguration is deprecated and will be removed in a future release. Use MCPClient instead.
151
+ */
152
+ declare class MCPConfiguration extends MCPClient {
153
+ constructor(args: MCPClientOptions);
154
+ }
105
155
  export { MCPConfiguration }
106
156
  export { MCPConfiguration as MCPConfiguration_alias_1 }
107
157
 
158
+ /**
159
+ * @deprecated MCPConfigurationOptions is deprecated and will be removed in a future release. Use MCPClientOptions instead.
160
+ */
108
161
  declare interface MCPConfigurationOptions {
109
162
  id?: string;
110
163
  servers: Record<string, MastraMCPServerDefinition>;
@@ -228,9 +281,16 @@ export declare const server_alias_1: Server<{
228
281
  } | undefined;
229
282
  }>;
230
283
 
231
- declare type SSEClientParameters = {
232
- url: URL;
233
- } & SSEClientTransportOptions;
284
+ declare type StdioServerDefinition = BaseServerOptions & {
285
+ command: string;
286
+ args?: string[];
287
+ env?: Record<string, string>;
288
+ url?: never;
289
+ requestInit?: never;
290
+ eventSourceInit?: never;
291
+ reconnectionOptions?: never;
292
+ sessionId?: never;
293
+ };
234
294
 
235
295
  export declare const weatherTool: Tool<z.ZodObject<{
236
296
  location: z.ZodString;
package/dist/index.cjs CHANGED
@@ -6,9 +6,11 @@ var utils = require('@mastra/core/utils');
6
6
  var index_js = require('@modelcontextprotocol/sdk/client/index.js');
7
7
  var sse_js = require('@modelcontextprotocol/sdk/client/sse.js');
8
8
  var stdio_js = require('@modelcontextprotocol/sdk/client/stdio.js');
9
+ var streamableHttp_js = require('@modelcontextprotocol/sdk/client/streamableHttp.js');
9
10
  var protocol_js = require('@modelcontextprotocol/sdk/shared/protocol.js');
10
11
  var types_js = require('@modelcontextprotocol/sdk/types.js');
11
12
  var exitHook = require('exit-hook');
13
+ var equal = require('fast-deep-equal');
12
14
  var uuid = require('uuid');
13
15
  var core = require('@mastra/core');
14
16
  var index_js$1 = require('@modelcontextprotocol/sdk/server/index.js');
@@ -18,6 +20,8 @@ var fs = require('fs');
18
20
  var os = require('os');
19
21
  var path = require('path');
20
22
 
23
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
24
+
21
25
  function _interopNamespace(e) {
22
26
  if (e && e.__esModule) return e;
23
27
  var n = Object.create(null);
@@ -36,6 +40,7 @@ function _interopNamespace(e) {
36
40
  return Object.freeze(n);
37
41
  }
38
42
 
43
+ var equal__default = /*#__PURE__*/_interopDefault(equal);
39
44
  var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
40
45
  var os__namespace = /*#__PURE__*/_interopNamespace(os);
41
46
  var path__namespace = /*#__PURE__*/_interopNamespace(path);
@@ -4117,13 +4122,15 @@ function convertLogLevelToLoggerMethod(level) {
4117
4122
  return "info";
4118
4123
  }
4119
4124
  }
4120
- var MastraMCPClient = class extends base.MastraBase {
4125
+ var InternalMastraMCPClient = class _InternalMastraMCPClient extends base.MastraBase {
4121
4126
  name;
4122
- transport;
4123
4127
  client;
4124
4128
  timeout;
4125
4129
  logHandler;
4126
4130
  enableServerLogs;
4131
+ static hasWarned = false;
4132
+ serverConfig;
4133
+ transport;
4127
4134
  constructor({
4128
4135
  name,
4129
4136
  version = "1.0.0",
@@ -4132,23 +4139,17 @@ var MastraMCPClient = class extends base.MastraBase {
4132
4139
  timeout = protocol_js.DEFAULT_REQUEST_TIMEOUT_MSEC
4133
4140
  }) {
4134
4141
  super({ name: "MastraMCPClient" });
4142
+ if (!_InternalMastraMCPClient.hasWarned) {
4143
+ console.warn(
4144
+ "[DEPRECATION] MastraMCPClient is deprecated and will be removed in a future release. Please use MCPClient instead."
4145
+ );
4146
+ _InternalMastraMCPClient.hasWarned = true;
4147
+ }
4135
4148
  this.name = name;
4136
4149
  this.timeout = timeout;
4137
4150
  this.logHandler = server.logger;
4138
4151
  this.enableServerLogs = server.enableServerLogs ?? true;
4139
- const { logger: logger3, enableServerLogs, ...serverConfig } = server;
4140
- if (`url` in serverConfig) {
4141
- this.transport = new sse_js.SSEClientTransport(serverConfig.url, {
4142
- requestInit: serverConfig.requestInit,
4143
- eventSourceInit: serverConfig.eventSourceInit
4144
- });
4145
- } else {
4146
- this.transport = new stdio_js.StdioClientTransport({
4147
- ...serverConfig,
4148
- // without ...getDefaultEnvironment() commands like npx will fail because there will be no PATH env var
4149
- env: { ...stdio_js.getDefaultEnvironment(), ...serverConfig.env || {} }
4150
- });
4151
- }
4152
+ this.serverConfig = server;
4152
4153
  this.client = new index_js.Client(
4153
4154
  {
4154
4155
  name,
@@ -4168,11 +4169,12 @@ var MastraMCPClient = class extends base.MastraBase {
4168
4169
  */
4169
4170
  log(level, message, details) {
4170
4171
  const loggerMethod = convertLogLevelToLoggerMethod(level);
4171
- this.logger[loggerMethod](message, details);
4172
+ const msg = `[${this.name}] ${message}`;
4173
+ this.logger[loggerMethod](msg, details);
4172
4174
  if (this.logHandler) {
4173
4175
  this.logHandler({
4174
4176
  level,
4175
- message,
4177
+ message: msg,
4176
4178
  timestamp: /* @__PURE__ */ new Date(),
4177
4179
  serverName: this.name,
4178
4180
  details
@@ -4195,44 +4197,121 @@ var MastraMCPClient = class extends base.MastraBase {
4195
4197
  );
4196
4198
  }
4197
4199
  }
4200
+ async connectStdio(command) {
4201
+ this.log("debug", `Using Stdio transport for command: ${command}`);
4202
+ try {
4203
+ this.transport = new stdio_js.StdioClientTransport({
4204
+ command,
4205
+ args: this.serverConfig.args,
4206
+ env: { ...stdio_js.getDefaultEnvironment(), ...this.serverConfig.env || {} }
4207
+ });
4208
+ await this.client.connect(this.transport, { timeout: this.serverConfig.timeout ?? this.timeout });
4209
+ this.log("debug", `Successfully connected to MCP server via Stdio`);
4210
+ } catch (e) {
4211
+ this.log("error", e instanceof Error ? e.stack || e.message : JSON.stringify(e));
4212
+ throw e;
4213
+ }
4214
+ }
4215
+ async connectHttp(url) {
4216
+ const { requestInit, eventSourceInit } = this.serverConfig;
4217
+ this.log("debug", `Attempting to connect to URL: ${url}`);
4218
+ let shouldTrySSE = url.pathname.endsWith(`/sse`);
4219
+ if (!shouldTrySSE) {
4220
+ try {
4221
+ this.log("debug", "Trying Streamable HTTP transport...");
4222
+ const streamableTransport = new streamableHttp_js.StreamableHTTPClientTransport(url, {
4223
+ requestInit,
4224
+ reconnectionOptions: this.serverConfig.reconnectionOptions,
4225
+ sessionId: this.serverConfig.sessionId
4226
+ });
4227
+ await this.client.connect(streamableTransport, {
4228
+ timeout: (
4229
+ // this is hardcoded to 3s because the long default timeout would be extremely slow for sse backwards compat (60s)
4230
+ 3e3
4231
+ )
4232
+ });
4233
+ this.transport = streamableTransport;
4234
+ this.log("debug", "Successfully connected using Streamable HTTP transport.");
4235
+ } catch (error) {
4236
+ this.log("debug", `Streamable HTTP transport failed: ${error}`);
4237
+ shouldTrySSE = true;
4238
+ }
4239
+ }
4240
+ if (shouldTrySSE) {
4241
+ this.log("debug", "Falling back to deprecated HTTP+SSE transport...");
4242
+ try {
4243
+ const sseTransport = new sse_js.SSEClientTransport(url, { requestInit, eventSourceInit });
4244
+ await this.client.connect(sseTransport, { timeout: this.serverConfig.timeout ?? this.timeout });
4245
+ this.transport = sseTransport;
4246
+ this.log("debug", "Successfully connected using deprecated HTTP+SSE transport.");
4247
+ } catch (sseError) {
4248
+ this.log(
4249
+ "error",
4250
+ `Failed to connect with SSE transport after failing to connect to Streamable HTTP transport first. SSE error: ${sseError}`
4251
+ );
4252
+ throw new Error("Could not connect to server with any available HTTP transport");
4253
+ }
4254
+ }
4255
+ }
4198
4256
  isConnected = false;
4199
4257
  async connect() {
4200
4258
  if (this.isConnected) return;
4259
+ const { command, url } = this.serverConfig;
4260
+ if (command) {
4261
+ await this.connectStdio(command);
4262
+ } else if (url) {
4263
+ await this.connectHttp(url);
4264
+ } else {
4265
+ throw new Error("Server configuration must include either a command or a url.");
4266
+ }
4267
+ this.isConnected = true;
4268
+ const originalOnClose = this.client.onclose;
4269
+ this.client.onclose = () => {
4270
+ this.log("debug", `MCP server connection closed`);
4271
+ this.isConnected = false;
4272
+ if (typeof originalOnClose === `function`) {
4273
+ originalOnClose();
4274
+ }
4275
+ };
4276
+ exitHook.asyncExitHook(
4277
+ async () => {
4278
+ this.log("debug", `Disconnecting MCP server during exit`);
4279
+ await this.disconnect();
4280
+ },
4281
+ { wait: 5e3 }
4282
+ );
4283
+ process.on("SIGTERM", () => exitHook.gracefulExit());
4284
+ this.log("debug", `Successfully connected to MCP server`);
4285
+ }
4286
+ /**
4287
+ * Get the current session ID if using the Streamable HTTP transport.
4288
+ * Returns undefined if not connected or not using Streamable HTTP.
4289
+ */
4290
+ get sessionId() {
4291
+ if (this.transport instanceof streamableHttp_js.StreamableHTTPClientTransport) {
4292
+ return this.transport.sessionId;
4293
+ }
4294
+ return void 0;
4295
+ }
4296
+ async disconnect() {
4297
+ if (!this.transport) {
4298
+ this.log("debug", "Disconnect called but no transport was connected.");
4299
+ return;
4300
+ }
4301
+ this.log("debug", `Disconnecting from MCP server`);
4201
4302
  try {
4202
- this.log("debug", `Connecting to MCP server`);
4203
- await this.client.connect(this.transport, {
4204
- timeout: this.timeout
4205
- });
4206
- this.isConnected = true;
4207
- const originalOnClose = this.client.onclose;
4208
- this.client.onclose = () => {
4209
- this.log("debug", `MCP server connection closed`);
4210
- this.isConnected = false;
4211
- if (typeof originalOnClose === `function`) {
4212
- originalOnClose();
4213
- }
4214
- };
4215
- exitHook.asyncExitHook(
4216
- async () => {
4217
- this.log("debug", `Disconnecting MCP server during exit`);
4218
- await this.disconnect();
4219
- },
4220
- { wait: 5e3 }
4221
- );
4222
- process.on("SIGTERM", () => exitHook.gracefulExit());
4223
- this.log("info", `Successfully connected to MCP server`);
4303
+ await this.transport.close();
4304
+ this.log("debug", "Successfully disconnected from MCP server");
4224
4305
  } catch (e) {
4225
- this.log("error", `Failed connecting to MCP server`, {
4306
+ this.log("error", "Error during MCP server disconnect", {
4226
4307
  error: e instanceof Error ? e.stack : JSON.stringify(e, null, 2)
4227
4308
  });
4228
- this.isConnected = false;
4229
4309
  throw e;
4310
+ } finally {
4311
+ this.transport = void 0;
4312
+ this.isConnected = false;
4230
4313
  }
4231
4314
  }
4232
- async disconnect() {
4233
- this.log("debug", `Disconnecting from MCP server`);
4234
- return await this.client.close();
4235
- }
4236
4315
  // TODO: do the type magic to return the right method type. Right now we get infinitely deep infered type errors from Zod without using "any"
4237
4316
  async resources() {
4238
4317
  this.log("debug", `Requesting resources from MCP server`);
@@ -4282,48 +4361,74 @@ var MastraMCPClient = class extends base.MastraBase {
4282
4361
  return toolsRes;
4283
4362
  }
4284
4363
  };
4285
- var mastraMCPConfigurationInstances = /* @__PURE__ */ new Map();
4286
- var MCPConfiguration = class extends base.MastraBase {
4364
+ var MastraMCPClient = InternalMastraMCPClient;
4365
+ var mcpClientInstances = /* @__PURE__ */ new Map();
4366
+ var MCPClient = class extends base.MastraBase {
4287
4367
  serverConfigs = {};
4288
4368
  id;
4289
4369
  defaultTimeout;
4370
+ mcpClientsById = /* @__PURE__ */ new Map();
4371
+ disconnectPromise = null;
4290
4372
  constructor(args) {
4291
- super({ name: "MCPConfiguration" });
4373
+ super({ name: "MCPClient" });
4292
4374
  this.defaultTimeout = args.timeout ?? protocol_js.DEFAULT_REQUEST_TIMEOUT_MSEC;
4293
4375
  this.serverConfigs = args.servers;
4294
4376
  this.id = args.id ?? this.makeId();
4295
- const existingInstance = mastraMCPConfigurationInstances.get(this.id);
4377
+ if (args.id) {
4378
+ this.id = args.id;
4379
+ const cached = mcpClientInstances.get(this.id);
4380
+ if (cached && !equal__default.default(cached.serverConfigs, args.servers)) {
4381
+ const existingInstance2 = mcpClientInstances.get(this.id);
4382
+ if (existingInstance2) {
4383
+ void existingInstance2.disconnect();
4384
+ }
4385
+ }
4386
+ } else {
4387
+ this.id = this.makeId();
4388
+ }
4389
+ const existingInstance = mcpClientInstances.get(this.id);
4296
4390
  if (existingInstance) {
4297
4391
  if (!args.id) {
4298
- throw new Error(`MCPConfiguration was initialized multiple times with the same configuration options.
4392
+ throw new Error(`MCPClient was initialized multiple times with the same configuration options.
4299
4393
 
4300
4394
  This error is intended to prevent memory leaks.
4301
4395
 
4302
4396
  To fix this you have three different options:
4303
- 1. If you need multiple MCPConfiguration class instances with identical server configurations, set an id when configuring: new MCPConfiguration({ id: "my-unique-id" })
4304
- 2. Call "await configuration.disconnect()" after you're done using the configuration and before you recreate another instance with the same options. If the identical MCPConfiguration instance is already closed at the time of re-creating it, you will not see this error.
4305
- 3. If you only need one instance of MCPConfiguration in your app, refactor your code so it's only created one time (ex. move it out of a loop into a higher scope code block)
4397
+ 1. If you need multiple MCPClient class instances with identical server configurations, set an id when configuring: new MCPClient({ id: "my-unique-id" })
4398
+ 2. Call "await client.disconnect()" after you're done using the client and before you recreate another instance with the same options. If the identical MCPClient instance is already closed at the time of re-creating it, you will not see this error.
4399
+ 3. If you only need one instance of MCPClient in your app, refactor your code so it's only created one time (ex. move it out of a loop into a higher scope code block)
4306
4400
  `);
4307
4401
  }
4308
4402
  return existingInstance;
4309
4403
  }
4404
+ mcpClientInstances.set(this.id, this);
4310
4405
  this.addToInstanceCache();
4311
4406
  return this;
4312
4407
  }
4313
4408
  addToInstanceCache() {
4314
- if (!mastraMCPConfigurationInstances.has(this.id)) {
4315
- mastraMCPConfigurationInstances.set(this.id, this);
4409
+ if (!mcpClientInstances.has(this.id)) {
4410
+ mcpClientInstances.set(this.id, this);
4316
4411
  }
4317
4412
  }
4318
4413
  makeId() {
4319
4414
  const text = JSON.stringify(this.serverConfigs).normalize("NFKC");
4320
- const idNamespace = uuid.v5(`MCPConfiguration`, uuid.v5.DNS);
4415
+ const idNamespace = uuid.v5(`MCPClient`, uuid.v5.DNS);
4321
4416
  return uuid.v5(text, idNamespace);
4322
4417
  }
4323
4418
  async disconnect() {
4324
- mastraMCPConfigurationInstances.delete(this.id);
4325
- await Promise.all(Array.from(this.mcpClientsById.values()).map((client) => client.disconnect()));
4326
- this.mcpClientsById.clear();
4419
+ if (this.disconnectPromise) {
4420
+ return this.disconnectPromise;
4421
+ }
4422
+ this.disconnectPromise = (async () => {
4423
+ try {
4424
+ mcpClientInstances.delete(this.id);
4425
+ await Promise.all(Array.from(this.mcpClientsById.values()).map((client) => client.disconnect()));
4426
+ this.mcpClientsById.clear();
4427
+ } finally {
4428
+ this.disconnectPromise = null;
4429
+ }
4430
+ })();
4431
+ return this.disconnectPromise;
4327
4432
  }
4328
4433
  async getTools() {
4329
4434
  this.addToInstanceCache();
@@ -4345,16 +4450,34 @@ To fix this you have three different options:
4345
4450
  });
4346
4451
  return connectedToolsets;
4347
4452
  }
4348
- mcpClientsById = /* @__PURE__ */ new Map();
4453
+ /**
4454
+ * Get the current session IDs for all connected MCP clients using the Streamable HTTP transport.
4455
+ * Returns an object mapping server names to their session IDs.
4456
+ */
4457
+ get sessionIds() {
4458
+ const sessionIds = {};
4459
+ for (const [serverName, client] of this.mcpClientsById.entries()) {
4460
+ if (client.sessionId) {
4461
+ sessionIds[serverName] = client.sessionId;
4462
+ }
4463
+ }
4464
+ return sessionIds;
4465
+ }
4349
4466
  async getConnectedClient(name, config) {
4467
+ if (this.disconnectPromise) {
4468
+ await this.disconnectPromise;
4469
+ }
4350
4470
  const exists = this.mcpClientsById.has(name);
4471
+ const existingClient = this.mcpClientsById.get(name);
4351
4472
  if (exists) {
4352
- const mcpClient2 = this.mcpClientsById.get(name);
4353
- await mcpClient2.connect();
4354
- return mcpClient2;
4473
+ if (!existingClient) {
4474
+ throw new Error(`Client ${name} exists but is undefined`);
4475
+ }
4476
+ await existingClient.connect();
4477
+ return existingClient;
4355
4478
  }
4356
4479
  this.logger.debug(`Connecting to ${name} MCP server`);
4357
- const mcpClient = new MastraMCPClient({
4480
+ const mcpClient = new InternalMastraMCPClient({
4358
4481
  name,
4359
4482
  server: config,
4360
4483
  timeout: config.timeout ?? this.defaultTimeout
@@ -4364,10 +4487,12 @@ To fix this you have three different options:
4364
4487
  await mcpClient.connect();
4365
4488
  } catch (e) {
4366
4489
  this.mcpClientsById.delete(name);
4367
- this.logger.error(`MCPConfiguration errored connecting to MCP server ${name}`, {
4490
+ this.logger.error(`MCPClient errored connecting to MCP server ${name}`, {
4368
4491
  error: e instanceof Error ? e.message : String(e)
4369
4492
  });
4370
- throw new Error(`Failed to connect to MCP server ${name}: ${e instanceof Error ? e.message : String(e)}`);
4493
+ throw new Error(
4494
+ `Failed to connect to MCP server ${name}: ${e instanceof Error ? e.stack || e.message : String(e)}`
4495
+ );
4371
4496
  }
4372
4497
  this.logger.debug(`Connected to ${name} MCP server`);
4373
4498
  return mcpClient;
@@ -4382,6 +4507,14 @@ To fix this you have three different options:
4382
4507
  );
4383
4508
  }
4384
4509
  };
4510
+ var MCPConfiguration = class extends MCPClient {
4511
+ constructor(args) {
4512
+ super(args);
4513
+ this.logger.warn(
4514
+ `MCPConfiguration has been renamed to MCPClient and MCPConfiguration is deprecated. The API is identical but the MCPConfiguration export will be removed in the future. Update your imports now to prevent future errors.`
4515
+ );
4516
+ }
4517
+ };
4385
4518
 
4386
4519
  // ../../node_modules/.pnpm/json-schema-to-zod@2.6.0/node_modules/json-schema-to-zod/dist/esm/parsers/parseAnyOf.js
4387
4520
  var parseAnyOf = (schema, refs) => {
@@ -6502,6 +6635,7 @@ var MCPServer = class {
6502
6635
  }
6503
6636
  };
6504
6637
 
6638
+ exports.MCPClient = MCPClient;
6505
6639
  exports.MCPConfiguration = MCPConfiguration;
6506
6640
  exports.MCPServer = MCPServer;
6507
6641
  exports.MastraMCPClient = MastraMCPClient;
package/dist/index.d.cts CHANGED
@@ -3,6 +3,8 @@ export { LogMessage_alias_1 as LogMessage } from './_tsup-dts-rollup.cjs';
3
3
  export { LogHandler_alias_1 as LogHandler } from './_tsup-dts-rollup.cjs';
4
4
  export { MastraMCPServerDefinition_alias_1 as MastraMCPServerDefinition } from './_tsup-dts-rollup.cjs';
5
5
  export { MastraMCPClient_alias_1 as MastraMCPClient } from './_tsup-dts-rollup.cjs';
6
+ export { MCPClientOptions_alias_1 as MCPClientOptions } from './_tsup-dts-rollup.cjs';
7
+ export { MCPClient_alias_1 as MCPClient } from './_tsup-dts-rollup.cjs';
6
8
  export { MCPConfigurationOptions_alias_1 as MCPConfigurationOptions } from './_tsup-dts-rollup.cjs';
7
9
  export { MCPConfiguration_alias_1 as MCPConfiguration } from './_tsup-dts-rollup.cjs';
8
10
  export { MCPServer } from './_tsup-dts-rollup.cjs';
package/dist/index.d.ts CHANGED
@@ -3,6 +3,8 @@ export { LogMessage_alias_1 as LogMessage } from './_tsup-dts-rollup.js';
3
3
  export { LogHandler_alias_1 as LogHandler } from './_tsup-dts-rollup.js';
4
4
  export { MastraMCPServerDefinition_alias_1 as MastraMCPServerDefinition } from './_tsup-dts-rollup.js';
5
5
  export { MastraMCPClient_alias_1 as MastraMCPClient } from './_tsup-dts-rollup.js';
6
+ export { MCPClientOptions_alias_1 as MCPClientOptions } from './_tsup-dts-rollup.js';
7
+ export { MCPClient_alias_1 as MCPClient } from './_tsup-dts-rollup.js';
6
8
  export { MCPConfigurationOptions_alias_1 as MCPConfigurationOptions } from './_tsup-dts-rollup.js';
7
9
  export { MCPConfiguration_alias_1 as MCPConfiguration } from './_tsup-dts-rollup.js';
8
10
  export { MCPServer } from './_tsup-dts-rollup.js';