@mastra/mcp 0.11.3-alpha.1 → 0.11.3-alpha.2

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.
Files changed (40) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/package.json +16 -3
  3. package/.turbo/turbo-build.log +0 -4
  4. package/eslint.config.js +0 -11
  5. package/integration-tests/node_modules/.bin/tsc +0 -21
  6. package/integration-tests/node_modules/.bin/tsserver +0 -21
  7. package/integration-tests/node_modules/.bin/vitest +0 -21
  8. package/integration-tests/package.json +0 -29
  9. package/integration-tests/src/mastra/agents/weather.ts +0 -34
  10. package/integration-tests/src/mastra/index.ts +0 -15
  11. package/integration-tests/src/mastra/mcp/index.ts +0 -46
  12. package/integration-tests/src/mastra/tools/weather.ts +0 -13
  13. package/integration-tests/src/server.test.ts +0 -238
  14. package/integration-tests/tsconfig.json +0 -13
  15. package/integration-tests/vitest.config.ts +0 -14
  16. package/src/__fixtures__/fire-crawl-complex-schema.ts +0 -1013
  17. package/src/__fixtures__/server-weather.ts +0 -16
  18. package/src/__fixtures__/stock-price.ts +0 -128
  19. package/src/__fixtures__/tools.ts +0 -94
  20. package/src/__fixtures__/weather.ts +0 -269
  21. package/src/client/client.test.ts +0 -585
  22. package/src/client/client.ts +0 -628
  23. package/src/client/configuration.test.ts +0 -856
  24. package/src/client/configuration.ts +0 -468
  25. package/src/client/elicitationActions.ts +0 -26
  26. package/src/client/index.ts +0 -3
  27. package/src/client/promptActions.ts +0 -70
  28. package/src/client/resourceActions.ts +0 -119
  29. package/src/index.ts +0 -2
  30. package/src/server/index.ts +0 -2
  31. package/src/server/promptActions.ts +0 -48
  32. package/src/server/resourceActions.ts +0 -90
  33. package/src/server/server-logging.test.ts +0 -181
  34. package/src/server/server.test.ts +0 -2142
  35. package/src/server/server.ts +0 -1445
  36. package/src/server/types.ts +0 -59
  37. package/tsconfig.build.json +0 -9
  38. package/tsconfig.json +0 -5
  39. package/tsup.config.ts +0 -17
  40. package/vitest.config.ts +0 -8
@@ -1,468 +0,0 @@
1
- import { MastraBase } from '@mastra/core/base';
2
- import { ErrorCategory, ErrorDomain, MastraError } from '@mastra/core/error';
3
- import { DEFAULT_REQUEST_TIMEOUT_MSEC } from '@modelcontextprotocol/sdk/shared/protocol.js';
4
- import type { ElicitRequest, ElicitResult, Prompt, Resource, ResourceTemplate } from '@modelcontextprotocol/sdk/types.js';
5
- import equal from 'fast-deep-equal';
6
- import { v5 as uuidv5 } from 'uuid';
7
- import { InternalMastraMCPClient } from './client';
8
- import type { MastraMCPServerDefinition } from './client';
9
-
10
- const mcpClientInstances = new Map<string, InstanceType<typeof MCPClient>>();
11
-
12
- export interface MCPClientOptions {
13
- id?: string;
14
- servers: Record<string, MastraMCPServerDefinition>;
15
- timeout?: number; // Optional global timeout
16
- }
17
-
18
- export class MCPClient extends MastraBase {
19
- private serverConfigs: Record<string, MastraMCPServerDefinition> = {};
20
- private id: string;
21
- private defaultTimeout: number;
22
- private mcpClientsById = new Map<string, InternalMastraMCPClient>();
23
- private disconnectPromise: Promise<void> | null = null;
24
-
25
- constructor(args: MCPClientOptions) {
26
- super({ name: 'MCPClient' });
27
- this.defaultTimeout = args.timeout ?? DEFAULT_REQUEST_TIMEOUT_MSEC;
28
- this.serverConfigs = args.servers;
29
- this.id = args.id ?? this.makeId();
30
-
31
- if (args.id) {
32
- this.id = args.id;
33
- const cached = mcpClientInstances.get(this.id);
34
-
35
- if (cached && !equal(cached.serverConfigs, args.servers)) {
36
- const existingInstance = mcpClientInstances.get(this.id);
37
- if (existingInstance) {
38
- void existingInstance.disconnect();
39
- mcpClientInstances.delete(this.id);
40
- }
41
- }
42
- } else {
43
- this.id = this.makeId();
44
- }
45
-
46
- // to prevent memory leaks return the same MCP server instance when configured the same way multiple times
47
- const existingInstance = mcpClientInstances.get(this.id);
48
- if (existingInstance) {
49
- if (!args.id) {
50
- throw new Error(`MCPClient was initialized multiple times with the same configuration options.
51
-
52
- This error is intended to prevent memory leaks.
53
-
54
- To fix this you have three different options:
55
- 1. If you need multiple MCPClient class instances with identical server configurations, set an id when configuring: new MCPClient({ id: "my-unique-id" })
56
- 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.
57
- 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)
58
- `);
59
- }
60
- return existingInstance;
61
- }
62
-
63
- mcpClientInstances.set(this.id, this);
64
- this.addToInstanceCache();
65
- return this;
66
- }
67
- public get elicitation() {
68
- this.addToInstanceCache();
69
- return {
70
- onRequest: async (serverName: string, handler: (request: ElicitRequest['params']) => Promise<ElicitResult>) => {
71
- try {
72
- const internalClient = await this.getConnectedClientForServer(serverName);
73
- return internalClient.elicitation.onRequest(handler);
74
- } catch (err) {
75
- throw new MastraError({
76
- id: 'MCP_CLIENT_ON_REQUEST_ELICITATION_FAILED',
77
- domain: ErrorDomain.MCP,
78
- category: ErrorCategory.THIRD_PARTY,
79
- details: {
80
- serverName,
81
- }
82
- }, err);
83
- }
84
- }
85
- }
86
- }
87
-
88
- public get resources() {
89
- this.addToInstanceCache();
90
- return {
91
- list: async (): Promise<Record<string, Resource[]>> => {
92
- const allResources: Record<string, Resource[]> = {};
93
- for (const serverName of Object.keys(this.serverConfigs)) {
94
- try {
95
- const internalClient = await this.getConnectedClientForServer(serverName);
96
- allResources[serverName] = await internalClient.resources.list();
97
- } catch (error) {
98
- const mastraError = new MastraError({
99
- id: 'MCP_CLIENT_LIST_RESOURCES_FAILED',
100
- domain: ErrorDomain.MCP,
101
- category: ErrorCategory.THIRD_PARTY,
102
- details: {
103
- serverName,
104
- }
105
- }, error);
106
- this.logger.trackException(mastraError);
107
- this.logger.error('Failed to list resources from server:', { error: mastraError.toString() });
108
- }
109
- }
110
- return allResources;
111
- },
112
- templates: async (): Promise<Record<string, ResourceTemplate[]>> => {
113
- const allTemplates: Record<string, ResourceTemplate[]> = {};
114
- for (const serverName of Object.keys(this.serverConfigs)) {
115
- try {
116
- const internalClient = await this.getConnectedClientForServer(serverName);
117
- allTemplates[serverName] = await internalClient.resources.templates();
118
- } catch (error) {
119
- const mastraError = new MastraError({
120
- id: 'MCP_CLIENT_LIST_RESOURCE_TEMPLATES_FAILED',
121
- domain: ErrorDomain.MCP,
122
- category: ErrorCategory.THIRD_PARTY,
123
- details: {
124
- serverName,
125
- }
126
- }, error);
127
- this.logger.trackException(mastraError);
128
- this.logger.error('Failed to list resource templates from server:', { error: mastraError.toString() });
129
- }
130
- }
131
- return allTemplates;
132
- },
133
- read: async (serverName: string, uri: string) => {
134
- try {
135
- const internalClient = await this.getConnectedClientForServer(serverName);
136
- return internalClient.resources.read(uri);
137
- } catch (error) {
138
- throw new MastraError({
139
- id: 'MCP_CLIENT_READ_RESOURCE_FAILED',
140
- domain: ErrorDomain.MCP,
141
- category: ErrorCategory.THIRD_PARTY,
142
- details: {
143
- serverName,
144
- uri,
145
- }
146
- }, error);
147
- }
148
- },
149
- subscribe: async (serverName: string, uri: string) => {
150
- try {
151
- const internalClient = await this.getConnectedClientForServer(serverName);
152
- return internalClient.resources.subscribe(uri);
153
- } catch (error) {
154
- throw new MastraError({
155
- id: 'MCP_CLIENT_SUBSCRIBE_RESOURCE_FAILED',
156
- domain: ErrorDomain.MCP,
157
- category: ErrorCategory.THIRD_PARTY,
158
- details: {
159
- serverName,
160
- uri,
161
- }
162
- }, error);
163
- }
164
- },
165
- unsubscribe: async (serverName: string, uri: string) => {
166
- try {
167
- const internalClient = await this.getConnectedClientForServer(serverName);
168
- return internalClient.resources.unsubscribe(uri);
169
- } catch (err) {
170
- throw new MastraError({
171
- id: 'MCP_CLIENT_UNSUBSCRIBE_RESOURCE_FAILED',
172
- domain: ErrorDomain.MCP,
173
- category: ErrorCategory.THIRD_PARTY,
174
- details: {
175
- serverName,
176
- uri,
177
- }
178
- }, err);
179
- }
180
- },
181
- onUpdated: async (serverName: string, handler: (params: { uri: string }) => void) => {
182
- try {
183
- const internalClient = await this.getConnectedClientForServer(serverName);
184
- return internalClient.resources.onUpdated(handler);
185
- } catch (err) {
186
- throw new MastraError({
187
- id: 'MCP_CLIENT_ON_UPDATED_RESOURCE_FAILED',
188
- domain: ErrorDomain.MCP,
189
- category: ErrorCategory.THIRD_PARTY,
190
- details: {
191
- serverName,
192
- }
193
- }, err);
194
- }
195
- },
196
- onListChanged: async (serverName: string, handler: () => void) => {
197
- try {
198
- const internalClient = await this.getConnectedClientForServer(serverName);
199
- return internalClient.resources.onListChanged(handler);
200
- } catch (err) {
201
- throw new MastraError({
202
- id: 'MCP_CLIENT_ON_LIST_CHANGED_RESOURCE_FAILED',
203
- domain: ErrorDomain.MCP,
204
- category: ErrorCategory.THIRD_PARTY,
205
- details: {
206
- serverName,
207
- }
208
- }, err);
209
- }
210
- },
211
- };
212
- }
213
-
214
- public get prompts() {
215
- this.addToInstanceCache();
216
- return {
217
- list: async (): Promise<Record<string, Prompt[]>> => {
218
- const allPrompts: Record<string, Prompt[]> = {};
219
- for (const serverName of Object.keys(this.serverConfigs)) {
220
- try {
221
- const internalClient = await this.getConnectedClientForServer(serverName);
222
- allPrompts[serverName] = await internalClient.prompts.list();
223
- } catch (error) {
224
- const mastraError = new MastraError({
225
- id: 'MCP_CLIENT_LIST_PROMPTS_FAILED',
226
- domain: ErrorDomain.MCP,
227
- category: ErrorCategory.THIRD_PARTY,
228
- details: {
229
- serverName,
230
- }
231
- }, error);
232
- this.logger.trackException(mastraError);
233
- this.logger.error('Failed to list prompts from server:', { error: mastraError.toString() });
234
- }
235
- }
236
- return allPrompts;
237
- },
238
- get: async ({ serverName, name, args, version }: { serverName: string, name: string, args?: Record<string, any>, version?: string }) => {
239
- try {
240
- const internalClient = await this.getConnectedClientForServer(serverName);
241
- return internalClient.prompts.get({ name, args, version });
242
- } catch (error) {
243
- throw new MastraError({
244
- id: 'MCP_CLIENT_GET_PROMPT_FAILED',
245
- domain: ErrorDomain.MCP,
246
- category: ErrorCategory.THIRD_PARTY,
247
- details: {
248
- serverName,
249
- name,
250
- }
251
- }, error);
252
- }
253
- },
254
- onListChanged: async (serverName: string, handler: () => void) => {
255
- try {
256
- const internalClient = await this.getConnectedClientForServer(serverName);
257
- return internalClient.prompts.onListChanged(handler);
258
- } catch (error) {
259
- throw new MastraError({
260
- id: 'MCP_CLIENT_ON_LIST_CHANGED_PROMPT_FAILED',
261
- domain: ErrorDomain.MCP,
262
- category: ErrorCategory.THIRD_PARTY,
263
- details: {
264
- serverName,
265
- }
266
- }, error);
267
- }
268
- },
269
- };
270
- }
271
-
272
- private addToInstanceCache() {
273
- if (!mcpClientInstances.has(this.id)) {
274
- mcpClientInstances.set(this.id, this);
275
- }
276
- }
277
-
278
- private makeId() {
279
- const text = JSON.stringify(this.serverConfigs).normalize('NFKC');
280
- const idNamespace = uuidv5(`MCPClient`, uuidv5.DNS);
281
-
282
- return uuidv5(text, idNamespace);
283
- }
284
-
285
- public async disconnect() {
286
- // Helps to prevent race condition
287
- // If there is already a disconnect ongoing, return the existing promise.
288
- if (this.disconnectPromise) {
289
- return this.disconnectPromise;
290
- }
291
-
292
- this.disconnectPromise = (async () => {
293
- try {
294
- mcpClientInstances.delete(this.id);
295
-
296
- // Disconnect all clients in the cache
297
- await Promise.all(Array.from(this.mcpClientsById.values()).map(client => client.disconnect()));
298
- this.mcpClientsById.clear();
299
- } finally {
300
- this.disconnectPromise = null;
301
- }
302
- })();
303
-
304
- return this.disconnectPromise;
305
- }
306
-
307
- public async getTools() {
308
- this.addToInstanceCache();
309
- const connectedTools: Record<string, any> = {}; // <- any because we don't have proper tool schemas
310
-
311
- try {
312
- await this.eachClientTools(async ({ serverName, tools }) => {
313
- for (const [toolName, toolConfig] of Object.entries(tools)) {
314
- connectedTools[`${serverName}_${toolName}`] = toolConfig; // namespace tool to prevent tool name conflicts between servers
315
- }
316
- });
317
- } catch (error) {
318
- throw new MastraError({
319
- id: 'MCP_CLIENT_GET_TOOLS_FAILED',
320
- domain: ErrorDomain.MCP,
321
- category: ErrorCategory.THIRD_PARTY,
322
- }, error);
323
- }
324
-
325
- return connectedTools;
326
- }
327
-
328
- public async getToolsets() {
329
- this.addToInstanceCache();
330
- const connectedToolsets: Record<string, Record<string, any>> = {}; // <- any because we don't have proper tool schemas
331
-
332
- try {
333
- await this.eachClientTools(async ({ serverName, tools }) => {
334
- if (tools) {
335
- connectedToolsets[serverName] = tools;
336
- }
337
- });
338
- } catch (error) {
339
- throw new MastraError({
340
- id: 'MCP_CLIENT_GET_TOOLSETS_FAILED',
341
- domain: ErrorDomain.MCP,
342
- category: ErrorCategory.THIRD_PARTY,
343
- }, error);
344
- }
345
-
346
- return connectedToolsets;
347
- }
348
-
349
- /**
350
- * @deprecated all resource actions have been moved to the this.resources object. Use this.resources.list() instead.
351
- */
352
- public async getResources() {
353
- return this.resources.list();
354
- }
355
-
356
- /**
357
- * Get the current session IDs for all connected MCP clients using the Streamable HTTP transport.
358
- * Returns an object mapping server names to their session IDs.
359
- */
360
- get sessionIds(): Record<string, string> {
361
- const sessionIds: Record<string, string> = {};
362
- for (const [serverName, client] of this.mcpClientsById.entries()) {
363
- if (client.sessionId) {
364
- sessionIds[serverName] = client.sessionId;
365
- }
366
- }
367
- return sessionIds;
368
- }
369
-
370
- private async getConnectedClient(name: string, config: MastraMCPServerDefinition): Promise<InternalMastraMCPClient> {
371
- if (this.disconnectPromise) {
372
- await this.disconnectPromise;
373
- }
374
-
375
- const exists = this.mcpClientsById.has(name);
376
- const existingClient = this.mcpClientsById.get(name);
377
-
378
- this.logger.debug(`getConnectedClient ${name} exists: ${exists}`);
379
-
380
- if (exists) {
381
- // This is just to satisfy Typescript since technically you could have this.mcpClientsById.set('someKey', undefined);
382
- // Should never reach this point basically we always create a new MastraMCPClient instance when we add to the Map.
383
- if (!existingClient) {
384
- throw new Error(`Client ${name} exists but is undefined`);
385
- }
386
- await existingClient.connect();
387
- return existingClient;
388
- }
389
-
390
- this.logger.debug(`Connecting to ${name} MCP server`);
391
-
392
- // Create client with server configuration including log handler
393
- const mcpClient = new InternalMastraMCPClient({
394
- name,
395
- server: config,
396
- timeout: config.timeout ?? this.defaultTimeout,
397
- });
398
-
399
- mcpClient.__setLogger(this.logger);
400
-
401
- this.mcpClientsById.set(name, mcpClient);
402
-
403
- try {
404
- await mcpClient.connect();
405
- } catch (e) {
406
- const mastraError = new MastraError({
407
- id: 'MCP_CLIENT_CONNECT_FAILED',
408
- domain: ErrorDomain.MCP,
409
- category: ErrorCategory.THIRD_PARTY,
410
- text: `Failed to connect to MCP server ${name}: ${e instanceof Error ? e.stack || e.message : String(e)}`,
411
- details: {
412
- name,
413
- }
414
- }, e);
415
- this.logger.trackException(mastraError);
416
- this.logger.error('MCPClient errored connecting to MCP server:', { error: mastraError.toString() });
417
- this.mcpClientsById.delete(name);
418
- throw mastraError;
419
- }
420
- this.logger.debug(`Connected to ${name} MCP server`);
421
- return mcpClient;
422
- }
423
-
424
- private async getConnectedClientForServer(serverName: string): Promise<InternalMastraMCPClient> {
425
- const serverConfig = this.serverConfigs[serverName];
426
- if (!serverConfig) {
427
- throw new Error(`Server configuration not found for name: ${serverName}`);
428
- }
429
- return this.getConnectedClient(serverName, serverConfig);
430
- }
431
-
432
- private async eachClientTools(
433
- cb: (args: {
434
- serverName: string;
435
- tools: Record<string, any>; // <- any because we don't have proper tool schemas
436
- client: InstanceType<typeof InternalMastraMCPClient>;
437
- }) => Promise<void>,
438
- ) {
439
- await Promise.all(
440
- Object.entries(this.serverConfigs).map(async ([serverName, serverConfig]) => {
441
- const client = await this.getConnectedClient(serverName, serverConfig);
442
- const tools = await client.tools();
443
- await cb({ serverName, tools, client });
444
- }),
445
- );
446
- }
447
- }
448
-
449
- /**
450
- * @deprecated MCPConfigurationOptions is deprecated and will be removed in a future release. Use MCPClientOptions instead.
451
- */
452
- export interface MCPConfigurationOptions {
453
- id?: string;
454
- servers: Record<string, MastraMCPServerDefinition>;
455
- timeout?: number; // Optional global timeout
456
- }
457
-
458
- /**
459
- * @deprecated MCPConfiguration is deprecated and will be removed in a future release. Use MCPClient instead.
460
- */
461
- export class MCPConfiguration extends MCPClient {
462
- constructor(args: MCPClientOptions) {
463
- super(args);
464
- this.logger.warn(
465
- `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.`,
466
- );
467
- }
468
- }
@@ -1,26 +0,0 @@
1
- import type { IMastraLogger } from "@mastra/core/logger";
2
- import type { ElicitRequest, ElicitResult } from "@modelcontextprotocol/sdk/types.js";
3
- import type { InternalMastraMCPClient } from "./client";
4
-
5
- interface ElicitationClientActionsConfig {
6
- client: InternalMastraMCPClient;
7
- logger: IMastraLogger;
8
- }
9
-
10
- export class ElicitationClientActions {
11
- private readonly client: InternalMastraMCPClient;
12
- private readonly logger: IMastraLogger;
13
-
14
- constructor({ client, logger }: ElicitationClientActionsConfig) {
15
- this.client = client;
16
- this.logger = logger;
17
- }
18
-
19
- /**
20
- * Set a handler for elicitation requests.
21
- * @param handler The callback function to handle the elicitation request.
22
- */
23
- public onRequest(handler: (request: ElicitRequest['params']) => Promise<ElicitResult>): void {
24
- this.client.setElicitationRequestHandler(handler);
25
- }
26
- }
@@ -1,3 +0,0 @@
1
- export type { LoggingLevel, LogMessage, LogHandler, MastraMCPServerDefinition, ElicitationHandler } from './client';
2
- export { MastraMCPClient } from './client';
3
- export * from './configuration';
@@ -1,70 +0,0 @@
1
- import type { IMastraLogger } from "@mastra/core/logger";
2
- import { ErrorCode } from "@modelcontextprotocol/sdk/types.js";
3
- import type { GetPromptResult, Prompt } from "@modelcontextprotocol/sdk/types.js";
4
- import type { InternalMastraMCPClient } from "./client";
5
-
6
- interface PromptClientActionsConfig {
7
- client: InternalMastraMCPClient;
8
- logger: IMastraLogger;
9
- }
10
-
11
- /**
12
- * Client-side prompt actions for listing, getting, and subscribing to prompt changes.
13
- */
14
- export class PromptClientActions {
15
- private readonly client: InternalMastraMCPClient;
16
- private readonly logger: IMastraLogger;
17
-
18
- constructor({ client, logger }: PromptClientActionsConfig) {
19
- this.client = client;
20
- this.logger = logger;
21
- }
22
-
23
- /**
24
- * Get all prompts from the connected MCP server.
25
- * @returns A list of prompts with their versions.
26
- */
27
- public async list(): Promise<Prompt[]> {
28
- try {
29
- const response = await this.client.listPrompts();
30
- if (response && response.prompts && Array.isArray(response.prompts)) {
31
- return response.prompts.map((prompt) => ({ ...prompt, version: prompt.version || '' }));
32
- } else {
33
- this.logger.warn(`Prompts response from server ${this.client.name} did not have expected structure.`, {
34
- response,
35
- });
36
- return [];
37
- }
38
- } catch (e: any) {
39
- // MCP Server might not support prompts, so we return an empty array
40
- if (e.code === ErrorCode.MethodNotFound) {
41
- return []
42
- }
43
- this.logger.error(`Error getting prompts from server ${this.client.name}`, {
44
- error: e instanceof Error ? e.message : String(e),
45
- });
46
- throw new Error(
47
- `Failed to fetch prompts from server ${this.client.name}: ${e instanceof Error ? e.stack || e.message : String(e)}`,
48
- );
49
- }
50
- }
51
-
52
- /**
53
- * Get a specific prompt.
54
- * @param name The name of the prompt to get.
55
- * @param args Optional arguments for the prompt.
56
- * @param version Optional version of the prompt to get.
57
- * @returns The prompt content.
58
- */
59
- public async get({name, args, version}: {name: string, args?: Record<string, any>, version?: string}): Promise<GetPromptResult> {
60
- return this.client.getPrompt({name, args, version});
61
- }
62
-
63
- /**
64
- * Set a notification handler for when the list of available prompts changes.
65
- * @param handler The callback function to handle the notification.
66
- */
67
- public async onListChanged(handler: () => void): Promise<void> {
68
- this.client.setPromptListChangedNotificationHandler(handler);
69
- }
70
- }
@@ -1,119 +0,0 @@
1
- import type { IMastraLogger } from "@mastra/core/logger";
2
- import { ErrorCode } from "@modelcontextprotocol/sdk/types.js";
3
- import type { Resource, ResourceTemplate } from "@modelcontextprotocol/sdk/types.js";
4
- import type { InternalMastraMCPClient } from "./client";
5
-
6
- interface ResourceClientActionsConfig {
7
- client: InternalMastraMCPClient;
8
- logger: IMastraLogger;
9
- }
10
-
11
- export class ResourceClientActions {
12
- private readonly client: InternalMastraMCPClient;
13
- private readonly logger: IMastraLogger;
14
-
15
- constructor({ client, logger }: ResourceClientActionsConfig) {
16
- this.client = client;
17
- this.logger = logger;
18
- }
19
-
20
- /**
21
- * Get all resources from the connected MCP server.
22
- * @returns A list of resources.
23
- */
24
- public async list(): Promise<Resource[]> {
25
- try {
26
- const response = await this.client.listResources();
27
- if (response && response.resources && Array.isArray(response.resources)) {
28
- return response.resources;
29
- } else {
30
- this.logger.warn(`Resources response from server ${this.client.name} did not have expected structure.`, {
31
- response,
32
- });
33
- return [];
34
- }
35
- } catch (e: any) {
36
- // MCP Server might not support resources, so we return an empty array
37
- if (e.code === ErrorCode.MethodNotFound) {
38
- return []
39
- }
40
- this.logger.error(`Error getting resources from server ${this.client.name}`, {
41
- error: e instanceof Error ? e.message : String(e),
42
- });
43
- throw new Error(
44
- `Failed to fetch resources from server ${this.client.name}: ${e instanceof Error ? e.stack || e.message : String(e)}`,
45
- );
46
- }
47
- }
48
-
49
- /**
50
- * Get all resource templates from the connected MCP server.
51
- * @returns A list of resource templates.
52
- */
53
- public async templates(): Promise<ResourceTemplate[]> {
54
- try {
55
- const response = await this.client.listResourceTemplates();
56
- if (response && response.resourceTemplates && Array.isArray(response.resourceTemplates)) {
57
- return response.resourceTemplates;
58
- } else {
59
- this.logger.warn(
60
- `Resource templates response from server ${this.client.name} did not have expected structure.`,
61
- { response },
62
- );
63
- return [];
64
- }
65
- } catch (e: any) {
66
- // MCP Server might not support resources, so we return an empty array
67
- if (e.code === ErrorCode.MethodNotFound) {
68
- return []
69
- }
70
- this.logger.error(`Error getting resource templates from server ${this.client.name}`, {
71
- error: e instanceof Error ? e.message : String(e),
72
- });
73
- throw new Error(
74
- `Failed to fetch resource templates from server ${this.client.name}: ${e instanceof Error ? e.stack || e.message : String(e)}`,
75
- );
76
- }
77
- }
78
-
79
- /**
80
- * Read a specific resource.
81
- * @param uri The URI of the resource to read.
82
- * @returns The resource content.
83
- */
84
- public async read(uri: string) {
85
- return this.client.readResource(uri);
86
- }
87
-
88
- /**
89
- * Subscribe to a specific resource.
90
- * @param uri The URI of the resource to subscribe to.
91
- */
92
- public async subscribe(uri: string) {
93
- return this.client.subscribeResource(uri);
94
- }
95
-
96
- /**
97
- * Unsubscribe from a specific resource.
98
- * @param uri The URI of the resource to unsubscribe from.
99
- */
100
- public async unsubscribe(uri: string) {
101
- return this.client.unsubscribeResource(uri);
102
- }
103
-
104
- /**
105
- * Set a notification handler for when a specific resource is updated.
106
- * @param handler The callback function to handle the notification.
107
- */
108
- public async onUpdated(handler: (params: { uri: string }) => void): Promise<void> {
109
- this.client.setResourceUpdatedNotificationHandler(handler);
110
- }
111
-
112
- /**
113
- * Set a notification handler for when the list of available resources changes.
114
- * @param handler The callback function to handle the notification.
115
- */
116
- public async onListChanged(handler: () => void): Promise<void> {
117
- this.client.setResourceListChangedNotificationHandler(handler);
118
- }
119
- }
package/src/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from './client';
2
- export * from './server';
@@ -1,2 +0,0 @@
1
- export * from './server';
2
- export * from './types';