@mastra/mcp 0.10.2 → 0.10.3

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.
@@ -0,0 +1,70 @@
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
+ }
@@ -40,7 +40,6 @@ export class ResourceClientActions {
40
40
  this.logger.error(`Error getting resources from server ${this.client.name}`, {
41
41
  error: e instanceof Error ? e.message : String(e),
42
42
  });
43
- console.log('errorheere', e)
44
43
  throw new Error(
45
44
  `Failed to fetch resources from server ${this.client.name}: ${e instanceof Error ? e.stack || e.message : String(e)}`,
46
45
  );
@@ -65,7 +64,6 @@ export class ResourceClientActions {
65
64
  }
66
65
  } catch (e: any) {
67
66
  // MCP Server might not support resources, so we return an empty array
68
- console.log({ errorcooode: e.code })
69
67
  if (e.code === ErrorCode.MethodNotFound) {
70
68
  return []
71
69
  }
package/src/index.ts CHANGED
@@ -1,4 +1,2 @@
1
- export type { LoggingLevel, LogMessage, LogHandler, MastraMCPServerDefinition } from './client/client';
2
- export { MastraMCPClient } from './client/client';
3
- export * from './client/configuration';
4
- export * from './server/server';
1
+ export * from './client';
2
+ export * from './server';
@@ -0,0 +1,2 @@
1
+ export * from './server';
2
+ export * from './types';
@@ -0,0 +1,37 @@
1
+ import type { IMastraLogger } from '@mastra/core/logger';
2
+ import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+
4
+ interface ServerPromptActionsDependencies {
5
+ getLogger: () => IMastraLogger;
6
+ getSdkServer: () => Server;
7
+ clearDefinedPrompts: () => void;
8
+ }
9
+
10
+ export class ServerPromptActions {
11
+ private readonly getLogger: () => IMastraLogger;
12
+ private readonly getSdkServer: () => Server;
13
+ private readonly clearDefinedPrompts: () => void;
14
+
15
+ constructor(dependencies: ServerPromptActionsDependencies) {
16
+ this.getLogger = dependencies.getLogger;
17
+ this.getSdkServer = dependencies.getSdkServer;
18
+ this.clearDefinedPrompts = dependencies.clearDefinedPrompts;
19
+ }
20
+
21
+ /**
22
+ * Notifies the server that the overall list of available prompts has changed.
23
+ * This will clear the internal cache of defined prompts and send a list_changed notification to clients.
24
+ */
25
+ public async notifyListChanged(): Promise<void> {
26
+ this.getLogger().info('Prompt list change externally notified. Clearing definedPrompts and sending notification.');
27
+ this.clearDefinedPrompts();
28
+ try {
29
+ await this.getSdkServer().sendPromptListChanged();
30
+ } catch (error) {
31
+ this.getLogger().error('Failed to send prompt list changed notification:', {
32
+ error: error instanceof Error ? error.message : String(error),
33
+ });
34
+ throw error;
35
+ }
36
+ }
37
+ }
@@ -13,6 +13,8 @@ import type {
13
13
  ListResourcesResult,
14
14
  ReadResourceResult,
15
15
  ListResourceTemplatesResult,
16
+ GetPromptResult,
17
+ Prompt,
16
18
  } from '@modelcontextprotocol/sdk/types.js';
17
19
  import { MockLanguageModelV1 } from 'ai/test';
18
20
  import { Hono } from 'hono';
@@ -22,7 +24,7 @@ import { weatherTool } from '../__fixtures__/tools';
22
24
  import { InternalMastraMCPClient } from '../client/client';
23
25
  import { MCPClient } from '../client/configuration';
24
26
  import { MCPServer } from './server';
25
- import type { MCPServerResources, MCPServerResourceContent } from './server';
27
+ import type { MCPServerResources, MCPServerResourceContent } from './types';
26
28
 
27
29
  const PORT = 9100 + Math.floor(Math.random() * 1000);
28
30
  let server: MCPServer;
@@ -607,6 +609,227 @@ describe('MCPServer', () => {
607
609
  });
608
610
  });
609
611
 
612
+ describe('Prompts', () => {
613
+ let promptServer: MCPServer;
614
+ let promptInternalClient: InternalMastraMCPClient;
615
+ let promptHttpServer: http.Server;
616
+ const PROMPT_PORT = 9500 + Math.floor(Math.random() * 1000);
617
+
618
+ let currentPrompts: Prompt[] = [
619
+ {
620
+ name: 'explain-code',
621
+ version: 'v1',
622
+ description: 'Explain code v1',
623
+ arguments: [{ name: 'code', required: true }],
624
+ getMessages: async (args: any) => [
625
+ { role: 'user', content: { type: 'text', text: `Explain this code (v1):\n${args.code}` } },
626
+ ],
627
+ },
628
+ {
629
+ name: 'explain-code',
630
+ version: 'v2',
631
+ description: 'Explain code v2',
632
+ arguments: [{ name: 'code', required: true }],
633
+ getMessages: async (args: any) => [
634
+ { role: 'user', content: { type: 'text', text: `Explain this code (v2):\n${args.code}` } },
635
+ ],
636
+ },
637
+ {
638
+ name: 'summarize',
639
+ version: 'v1',
640
+ description: 'Summarize text',
641
+ arguments: [{ name: 'text', required: true }],
642
+ getMessages: async (args: any) => [
643
+ { role: 'user', content: { type: 'text', text: `Summarize this:\n${args.text}` } },
644
+ ],
645
+ },
646
+ ];
647
+
648
+ beforeAll(async () => {
649
+ // Register multiple versions of the same prompt
650
+
651
+ promptServer = new MCPServer({
652
+ name: 'PromptTestServer',
653
+ version: '1.0.0',
654
+ tools: {},
655
+ prompts: {
656
+ listPrompts: async () => currentPrompts,
657
+ getPromptMessages: async (params: { name: string; version?: string; args?: any }) => {
658
+ let prompt;
659
+ if (params.version) {
660
+ prompt = currentPrompts.find(p => p.name === params.name && p.version === params.version);
661
+ } else {
662
+ // Select the first matching name if no version is provided.
663
+ prompt = currentPrompts.find(p => p.name === params.name);
664
+ }
665
+ if (!prompt)
666
+ throw new Error(
667
+ `Prompt "${params.name}"${params.version ? ` (version ${params.version})` : ''} not found`,
668
+ );
669
+ return (prompt as any).getMessages(params.args);
670
+ },
671
+ },
672
+ });
673
+
674
+ promptHttpServer = http.createServer(async (req: http.IncomingMessage, res: http.ServerResponse) => {
675
+ const url = new URL(req.url || '', `http://localhost:${PROMPT_PORT}`);
676
+ await promptServer.startSSE({
677
+ url,
678
+ ssePath: '/sse',
679
+ messagePath: '/messages',
680
+ req,
681
+ res,
682
+ });
683
+ });
684
+ await new Promise<void>(resolve => promptHttpServer.listen(PROMPT_PORT, () => resolve()));
685
+ promptInternalClient = new InternalMastraMCPClient({
686
+ name: 'prompt-test-internal-client',
687
+ server: { url: new URL(`http://localhost:${PROMPT_PORT}/sse`) },
688
+ });
689
+ await promptInternalClient.connect();
690
+ });
691
+
692
+ afterAll(async () => {
693
+ await promptInternalClient.disconnect();
694
+ if (promptHttpServer) {
695
+ promptHttpServer.closeAllConnections?.();
696
+ await new Promise<void>((resolve, reject) => {
697
+ promptHttpServer.close(err => {
698
+ if (err) return reject(err);
699
+ resolve();
700
+ });
701
+ });
702
+ }
703
+ if (promptServer) {
704
+ await promptServer.close();
705
+ }
706
+ });
707
+
708
+ it('should send prompt list changed notification when prompts change', async () => {
709
+ const listChangedPromise = new Promise<void>(resolve => {
710
+ promptInternalClient.setPromptListChangedNotificationHandler(() => {
711
+ resolve();
712
+ });
713
+ });
714
+ await promptServer.prompts.notifyListChanged();
715
+
716
+ await expect(listChangedPromise).resolves.toBeUndefined(); // Wait for the notification
717
+ });
718
+
719
+ it('should list all prompts with version field', async () => {
720
+ const result = await promptInternalClient.listPrompts();
721
+ expect(result).toBeDefined();
722
+ expect(result.prompts).toBeInstanceOf(Array);
723
+ // Should contain both explain-code v1 and v2 and summarize v1
724
+ const explainV1 = result.prompts.find((p: Prompt) => p.name === 'explain-code' && p.version === 'v1');
725
+ const explainV2 = result.prompts.find((p: Prompt) => p.name === 'explain-code' && p.version === 'v2');
726
+ const summarizeV1 = result.prompts.find((p: Prompt) => p.name === 'summarize' && p.version === 'v1');
727
+ expect(explainV1).toBeDefined();
728
+ expect(explainV2).toBeDefined();
729
+ expect(summarizeV1).toBeDefined();
730
+ });
731
+
732
+ it('should retrieve prompt by name and version', async () => {
733
+ const result = await promptInternalClient.getPrompt({
734
+ name: 'explain-code',
735
+ args: { code: 'let x = 1;' },
736
+ version: 'v2',
737
+ });
738
+ const prompt = result.prompt as GetPromptResult;
739
+ expect(prompt).toBeDefined();
740
+ expect(prompt.name).toBe('explain-code');
741
+ expect(prompt.version).toBe('v2');
742
+
743
+ const messages = result.messages;
744
+ expect(messages).toBeDefined();
745
+ expect(messages.length).toBeGreaterThan(0);
746
+ expect(messages[0].content.text).toContain('(v2)');
747
+ });
748
+
749
+ it('should retrieve prompt by name and default to first version if not specified', async () => {
750
+ const result = await promptInternalClient.getPrompt({ name: 'explain-code', args: { code: 'let y = 2;' } });
751
+ expect(result.prompt).toBeDefined();
752
+ const prompt = result.prompt as GetPromptResult;
753
+ expect(prompt.name).toBe('explain-code');
754
+ // Should default to first version (v1)
755
+ expect(prompt.version).toBe('v1');
756
+
757
+ const messages = result.messages;
758
+ expect(messages).toBeDefined();
759
+ expect(messages.length).toBeGreaterThan(0);
760
+ expect(messages[0].content.text).toContain('(v1)');
761
+ });
762
+
763
+ it('should return error if prompt name/version does not exist', async () => {
764
+ await expect(
765
+ promptInternalClient.getPrompt({ name: 'explain-code', args: { code: 'foo' }, version: 'v999' }),
766
+ ).rejects.toThrow();
767
+ });
768
+ it('should throw error if required argument is missing', async () => {
769
+ await expect(
770
+ promptInternalClient.getPrompt({ name: 'explain-code', args: {} }), // missing 'code'
771
+ ).rejects.toThrow(/Missing required argument/);
772
+ });
773
+
774
+ it('should succeed if all required arguments are provided', async () => {
775
+ const result = await promptInternalClient.getPrompt({ name: 'explain-code', args: { code: 'let z = 3;' } });
776
+ expect(result.prompt).toBeDefined();
777
+ expect(result.messages[0].content.text).toContain('let z = 3;');
778
+ });
779
+ it('should allow prompts with optional arguments', async () => {
780
+ // Register a prompt with an optional argument
781
+ currentPrompts = [
782
+ {
783
+ name: 'optional-arg-prompt',
784
+ version: 'v1',
785
+ description: 'Prompt with optional argument',
786
+ arguments: [{ name: 'foo', required: false }],
787
+ getMessages: async (args: any) => [
788
+ { role: 'user', content: { type: 'text', text: `foo is: ${args.foo ?? 'none'}` } },
789
+ ],
790
+ },
791
+ ];
792
+ await promptServer.prompts.notifyListChanged();
793
+ const result = await promptInternalClient.getPrompt({ name: 'optional-arg-prompt', args: {} });
794
+ expect(result.prompt).toBeDefined();
795
+ expect(result.messages[0].content.text).toContain('foo is: none');
796
+ });
797
+ it('should retrieve prompt with no version field by name only', async () => {
798
+ currentPrompts = [
799
+ {
800
+ name: 'no-version',
801
+ description: 'Prompt without version',
802
+ arguments: [],
803
+ getMessages: async () => [{ role: 'user', content: { type: 'text', text: 'no version' } }],
804
+ },
805
+ ];
806
+ await promptServer.prompts.notifyListChanged();
807
+ const result = await promptInternalClient.getPrompt({ name: 'no-version', args: {} });
808
+ const prompt = result.prompt as GetPromptResult;
809
+ expect(prompt).toBeDefined();
810
+ expect(prompt.version).toBeUndefined();
811
+ const messages = result.messages;
812
+ expect(messages).toBeDefined();
813
+ expect(messages.length).toBeGreaterThan(0);
814
+ expect(messages[0].content.text).toContain('no version');
815
+ });
816
+ it('should list prompts with required fields', async () => {
817
+ const result = await promptInternalClient.listPrompts();
818
+ result.prompts.forEach((p: Prompt) => {
819
+ expect(p.name).toBeDefined();
820
+ expect(p.description).toBeDefined();
821
+ expect(p.arguments).toBeDefined();
822
+ });
823
+ });
824
+ it('should return empty list if no prompts are registered', async () => {
825
+ currentPrompts = [];
826
+ await promptServer.prompts.notifyListChanged();
827
+ const result = await promptInternalClient.listPrompts();
828
+ expect(result.prompts).toBeInstanceOf(Array);
829
+ expect(result.prompts.length).toBe(0);
830
+ });
831
+ });
832
+
610
833
  describe('MCPServer SSE transport', () => {
611
834
  let sseRes: Response | undefined;
612
835
  let reader: ReadableStreamDefaultReader<Uint8Array> | undefined;
@@ -29,32 +29,30 @@ import {
29
29
  ListResourceTemplatesRequestSchema,
30
30
  SubscribeRequestSchema,
31
31
  UnsubscribeRequestSchema,
32
+ ListPromptsRequestSchema,
33
+ GetPromptRequestSchema,
34
+ PromptSchema,
32
35
  } from '@modelcontextprotocol/sdk/types.js';
33
36
  import type {
34
37
  ResourceContents,
35
38
  Resource,
36
39
  ResourceTemplate,
37
40
  ServerCapabilities,
41
+ Prompt,
38
42
  } from '@modelcontextprotocol/sdk/types.js';
39
43
  import type { SSEStreamingApi } from 'hono/streaming';
40
44
  import { streamSSE } from 'hono/streaming';
41
45
  import { SSETransport } from 'hono-mcp-server-sse-transport';
42
46
  import { z } from 'zod';
47
+ import { ServerPromptActions } from './promptActions';
43
48
  import { ServerResourceActions } from './resourceActions';
49
+ import type {
50
+ MCPServerPromptMessagesCallback,
51
+ MCPServerPrompts,
52
+ MCPServerResourceContentCallback,
53
+ MCPServerResources,
54
+ } from './types';
44
55
 
45
- export type MCPServerResourceContentCallback = ({
46
- uri,
47
- }: {
48
- uri: string;
49
- }) => Promise<MCPServerResourceContent | MCPServerResourceContent[]>;
50
- export type MCPServerResourceContent = { text?: string } | { blob?: string };
51
- export type MCPServerResources = {
52
- listResources: () => Promise<Resource[]>;
53
- getResourceContent: MCPServerResourceContentCallback;
54
- resourceTemplates?: () => Promise<ResourceTemplate[]>;
55
- };
56
-
57
- export type { Resource, ResourceTemplate };
58
56
  export class MCPServer extends MCPServerBase {
59
57
  private server: Server;
60
58
  private stdioTransport?: StdioServerTransport;
@@ -69,11 +67,17 @@ export class MCPServer extends MCPServerBase {
69
67
  private subscribeResourceHandlerIsRegistered: boolean = false;
70
68
  private unsubscribeResourceHandlerIsRegistered: boolean = false;
71
69
 
70
+ private listPromptsHandlerIsRegistered: boolean = false;
71
+ private getPromptHandlerIsRegistered: boolean = false;
72
+
72
73
  private definedResources?: Resource[];
73
74
  private definedResourceTemplates?: ResourceTemplate[];
74
75
  private resourceOptions?: MCPServerResources;
76
+ private definedPrompts?: Prompt[];
77
+ private promptOptions?: MCPServerPrompts;
75
78
  private subscriptions: Set<string> = new Set();
76
79
  public readonly resources: ServerResourceActions;
80
+ public readonly prompts: ServerPromptActions;
77
81
 
78
82
  /**
79
83
  * Get the current stdio transport.
@@ -114,9 +118,10 @@ export class MCPServer extends MCPServerBase {
114
118
  * Construct a new MCPServer instance.
115
119
  * @param opts - Configuration options for the server, including registry metadata.
116
120
  */
117
- constructor(opts: MCPServerConfig & { resources?: MCPServerResources }) {
121
+ constructor(opts: MCPServerConfig & { resources?: MCPServerResources; prompts?: MCPServerPrompts }) {
118
122
  super(opts);
119
123
  this.resourceOptions = opts.resources;
124
+ this.promptOptions = opts.prompts;
120
125
 
121
126
  const capabilities: ServerCapabilities = {
122
127
  tools: {},
@@ -127,6 +132,10 @@ export class MCPServer extends MCPServerBase {
127
132
  capabilities.resources = { subscribe: true, listChanged: true };
128
133
  }
129
134
 
135
+ if (opts.prompts) {
136
+ capabilities.prompts = { listChanged: true };
137
+ }
138
+
130
139
  this.server = new Server({ name: this.name, version: this.version }, { capabilities });
131
140
 
132
141
  this.logger.info(
@@ -146,6 +155,13 @@ export class MCPServer extends MCPServerBase {
146
155
  this.registerListResourceTemplatesHandler();
147
156
  }
148
157
  }
158
+ if (opts.prompts) {
159
+ this.registerListPromptsHandler();
160
+ this.registerGetPromptHandler({
161
+ getPromptMessagesCallback: opts.prompts.getPromptMessages,
162
+ });
163
+ }
164
+
149
165
  this.resources = new ServerResourceActions({
150
166
  getSubscriptions: () => this.subscriptions,
151
167
  getLogger: () => this.logger,
@@ -157,6 +173,14 @@ export class MCPServer extends MCPServerBase {
157
173
  this.definedResourceTemplates = undefined;
158
174
  },
159
175
  });
176
+
177
+ this.prompts = new ServerPromptActions({
178
+ getLogger: () => this.logger,
179
+ getSdkServer: () => this.server,
180
+ clearDefinedPrompts: () => {
181
+ this.definedPrompts = undefined;
182
+ },
183
+ });
160
184
  }
161
185
 
162
186
  private convertAgentsToTools(
@@ -654,6 +678,107 @@ export class MCPServer extends MCPServerBase {
654
678
  });
655
679
  }
656
680
 
681
+ /**
682
+ * Register the ListPrompts handler.
683
+ */
684
+ private registerListPromptsHandler() {
685
+ if (this.listPromptsHandlerIsRegistered) {
686
+ return;
687
+ }
688
+ this.listPromptsHandlerIsRegistered = true;
689
+ const capturedPromptOptions = this.promptOptions;
690
+
691
+ if (!capturedPromptOptions?.listPrompts) {
692
+ this.logger.warn('ListPrompts capability not supported by server configuration.');
693
+ return;
694
+ }
695
+
696
+ this.server.setRequestHandler(ListPromptsRequestSchema, async () => {
697
+ this.logger.debug('Handling ListPrompts request');
698
+ if (this.definedPrompts) {
699
+ return {
700
+ prompts: this.definedPrompts?.map(p => ({ ...p, version: p.version ?? undefined })),
701
+ };
702
+ } else {
703
+ try {
704
+ const prompts = await capturedPromptOptions.listPrompts();
705
+ // Parse and cache the prompts
706
+ for (const prompt of prompts) {
707
+ PromptSchema.parse(prompt);
708
+ }
709
+ this.definedPrompts = prompts;
710
+ this.logger.debug(`Fetched and cached ${this.definedPrompts.length} prompts.`);
711
+ return {
712
+ prompts: this.definedPrompts?.map(p => ({ ...p, version: p.version ?? undefined })),
713
+ };
714
+ } catch (error) {
715
+ this.logger.error('Error fetching prompts via listPrompts():', {
716
+ error: error instanceof Error ? error.message : String(error),
717
+ });
718
+ // Re-throw to let the MCP Server SDK handle formatting the error response
719
+ throw error;
720
+ }
721
+ }
722
+ });
723
+ }
724
+
725
+ /**
726
+ * Register the GetPrompt handler.
727
+ */
728
+ private registerGetPromptHandler({
729
+ getPromptMessagesCallback,
730
+ }: {
731
+ getPromptMessagesCallback?: MCPServerPromptMessagesCallback;
732
+ }) {
733
+ if (this.getPromptHandlerIsRegistered) return;
734
+ this.getPromptHandlerIsRegistered = true;
735
+ // Accept optional version parameter in prompts/get
736
+ this.server.setRequestHandler(
737
+ GetPromptRequestSchema,
738
+ async (request: { params: { name: string; version?: string; arguments?: any } }) => {
739
+ const startTime = Date.now();
740
+ const { name, version, arguments: args } = request.params;
741
+ if (!this.definedPrompts) {
742
+ const prompts = await this.promptOptions?.listPrompts?.();
743
+ if (!prompts) throw new Error('Failed to load prompts');
744
+ this.definedPrompts = prompts;
745
+ }
746
+ // Select prompt by name and version (if provided)
747
+ let prompt;
748
+ if (version) {
749
+ prompt = this.definedPrompts?.find(p => p.name === name && p.version === version);
750
+ } else {
751
+ // Select the first matching name if no version is provided.
752
+ prompt = this.definedPrompts?.find(p => p.name === name);
753
+ }
754
+ if (!prompt) throw new Error(`Prompt "${name}"${version ? ` (version ${version})` : ''} not found`);
755
+ // Validate required arguments
756
+ if (prompt.arguments) {
757
+ for (const arg of prompt.arguments) {
758
+ if (arg.required && (args?.[arg.name] === undefined || args?.[arg.name] === null)) {
759
+ throw new Error(`Missing required argument: ${arg.name}`);
760
+ }
761
+ }
762
+ }
763
+ try {
764
+ let messages: any[] = [];
765
+ if (getPromptMessagesCallback) {
766
+ messages = await getPromptMessagesCallback({ name, version, args });
767
+ }
768
+ const duration = Date.now() - startTime;
769
+ this.logger.info(
770
+ `Prompt '${name}'${version ? ` (version ${version})` : ''} retrieved successfully in ${duration}ms.`,
771
+ );
772
+ return { prompt, messages };
773
+ } catch (error) {
774
+ const duration = Date.now() - startTime;
775
+ this.logger.error(`Failed to get content for prompt '${name}' in ${duration}ms`, { error });
776
+ throw error;
777
+ }
778
+ },
779
+ );
780
+ }
781
+
657
782
  /**
658
783
  * Start the MCP server using stdio transport (for Windsurf integration).
659
784
  */
@@ -0,0 +1,30 @@
1
+ import type { Prompt, PromptMessage, Resource, ResourceTemplate } from '@modelcontextprotocol/sdk/types.js';
2
+
3
+ export type MCPServerResourceContentCallback = ({
4
+ uri,
5
+ }: {
6
+ uri: string;
7
+ }) => Promise<MCPServerResourceContent | MCPServerResourceContent[]>;
8
+ export type MCPServerResourceContent = { text?: string } | { blob?: string };
9
+ export type MCPServerResources = {
10
+ listResources: () => Promise<Resource[]>;
11
+ getResourceContent: MCPServerResourceContentCallback;
12
+ resourceTemplates?: () => Promise<ResourceTemplate[]>;
13
+ };
14
+
15
+ export type MCPServerPromptMessagesCallback = ({
16
+ name,
17
+ version,
18
+ args,
19
+ }: {
20
+ name: string;
21
+ version?: string;
22
+ args?: any;
23
+ }) => Promise<PromptMessage[]>;
24
+
25
+ export type MCPServerPrompts = {
26
+ listPrompts: () => Promise<Prompt[]>;
27
+ getPromptMessages?: MCPServerPromptMessagesCallback;
28
+ };
29
+
30
+ export type { Resource, ResourceTemplate };