Add _meta support to registerPrompt (#1629)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com>
This commit is contained in:
parent
9bc9abc68b
commit
f73a5af4bc
2 changed files with 105 additions and 4 deletions
|
|
@ -530,7 +530,8 @@ export class McpServer {
|
|||
name,
|
||||
title: prompt.title,
|
||||
description: prompt.description,
|
||||
arguments: prompt.argsSchema ? promptArgumentsFromStandardSchema(prompt.argsSchema) : undefined
|
||||
arguments: prompt.argsSchema ? promptArgumentsFromStandardSchema(prompt.argsSchema) : undefined,
|
||||
_meta: prompt._meta
|
||||
};
|
||||
})
|
||||
})
|
||||
|
|
@ -699,7 +700,8 @@ export class McpServer {
|
|||
title: string | undefined,
|
||||
description: string | undefined,
|
||||
argsSchema: StandardSchemaWithJSON | undefined,
|
||||
callback: PromptCallback<StandardSchemaWithJSON | undefined>
|
||||
callback: PromptCallback<StandardSchemaWithJSON | undefined>,
|
||||
_meta: Record<string, unknown> | undefined
|
||||
): RegisteredPrompt {
|
||||
// Track current schema and callback for handler regeneration
|
||||
let currentArgsSchema = argsSchema;
|
||||
|
|
@ -709,6 +711,7 @@ export class McpServer {
|
|||
title,
|
||||
description,
|
||||
argsSchema,
|
||||
_meta,
|
||||
handler: createPromptHandler(name, argsSchema, callback),
|
||||
enabled: true,
|
||||
disable: () => registeredPrompt.update({ enabled: false }),
|
||||
|
|
@ -721,6 +724,7 @@ export class McpServer {
|
|||
}
|
||||
if (updates.title !== undefined) registeredPrompt.title = updates.title;
|
||||
if (updates.description !== undefined) registeredPrompt.description = updates.description;
|
||||
if (updates._meta !== undefined) registeredPrompt._meta = updates._meta;
|
||||
|
||||
// Track if we need to regenerate the handler
|
||||
let needsHandlerRegen = false;
|
||||
|
|
@ -921,6 +925,7 @@ export class McpServer {
|
|||
title?: string;
|
||||
description?: string;
|
||||
argsSchema?: Args;
|
||||
_meta?: Record<string, unknown>;
|
||||
},
|
||||
cb: PromptCallback<Args>
|
||||
): RegisteredPrompt {
|
||||
|
|
@ -928,14 +933,15 @@ export class McpServer {
|
|||
throw new Error(`Prompt ${name} is already registered`);
|
||||
}
|
||||
|
||||
const { title, description, argsSchema } = config;
|
||||
const { title, description, argsSchema, _meta } = config;
|
||||
|
||||
const registeredPrompt = this._createRegisteredPrompt(
|
||||
name,
|
||||
title,
|
||||
description,
|
||||
argsSchema,
|
||||
cb as PromptCallback<StandardSchemaWithJSON | undefined>
|
||||
cb as PromptCallback<StandardSchemaWithJSON | undefined>,
|
||||
_meta
|
||||
);
|
||||
|
||||
this.setPromptRequestHandlers();
|
||||
|
|
@ -1234,6 +1240,7 @@ export type RegisteredPrompt = {
|
|||
title?: string;
|
||||
description?: string;
|
||||
argsSchema?: StandardSchemaWithJSON;
|
||||
_meta?: Record<string, unknown>;
|
||||
/** @hidden */
|
||||
handler: PromptHandler;
|
||||
enabled: boolean;
|
||||
|
|
@ -1244,6 +1251,7 @@ export type RegisteredPrompt = {
|
|||
title?: string;
|
||||
description?: string;
|
||||
argsSchema?: Args;
|
||||
_meta?: Record<string, unknown>;
|
||||
callback?: PromptCallback<Args>;
|
||||
enabled?: boolean;
|
||||
}): void;
|
||||
|
|
|
|||
|
|
@ -4253,6 +4253,99 @@ describe('Zod v4', () => {
|
|||
}
|
||||
]);
|
||||
});
|
||||
|
||||
/***
|
||||
* Test: Prompt Registration with _meta field
|
||||
*/
|
||||
test('should register prompt with _meta field and include it in list response', async () => {
|
||||
const mcpServer = new McpServer({
|
||||
name: 'test server',
|
||||
version: '1.0'
|
||||
});
|
||||
const client = new Client({
|
||||
name: 'test client',
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
const metaData = {
|
||||
author: 'test-author',
|
||||
version: '1.2.3',
|
||||
category: 'utility',
|
||||
tags: ['test', 'example']
|
||||
};
|
||||
|
||||
mcpServer.registerPrompt(
|
||||
'test-with-meta',
|
||||
{
|
||||
description: 'A prompt with _meta field',
|
||||
_meta: metaData
|
||||
},
|
||||
async () => ({
|
||||
messages: [
|
||||
{
|
||||
role: 'assistant',
|
||||
content: {
|
||||
type: 'text',
|
||||
text: 'Test response'
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
);
|
||||
|
||||
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
||||
|
||||
await Promise.all([client.connect(clientTransport), mcpServer.server.connect(serverTransport)]);
|
||||
|
||||
const result = await client.request({ method: 'prompts/list' });
|
||||
|
||||
expect(result.prompts).toHaveLength(1);
|
||||
expect(result.prompts[0]!.name).toBe('test-with-meta');
|
||||
expect(result.prompts[0]!.description).toBe('A prompt with _meta field');
|
||||
expect(result.prompts[0]!._meta).toEqual(metaData);
|
||||
});
|
||||
|
||||
/***
|
||||
* Test: Prompt Registration without _meta field should have undefined _meta
|
||||
*/
|
||||
test('should register prompt without _meta field and have undefined _meta in response', async () => {
|
||||
const mcpServer = new McpServer({
|
||||
name: 'test server',
|
||||
version: '1.0'
|
||||
});
|
||||
const client = new Client({
|
||||
name: 'test client',
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
mcpServer.registerPrompt(
|
||||
'test-without-meta',
|
||||
{
|
||||
description: 'A prompt without _meta field'
|
||||
},
|
||||
async () => ({
|
||||
messages: [
|
||||
{
|
||||
role: 'assistant',
|
||||
content: {
|
||||
type: 'text',
|
||||
text: 'Test response'
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
);
|
||||
|
||||
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
||||
|
||||
await Promise.all([client.connect(clientTransport), mcpServer.server.connect(serverTransport)]);
|
||||
|
||||
const result = await client.request({ method: 'prompts/list' });
|
||||
|
||||
expect(result.prompts).toHaveLength(1);
|
||||
expect(result.prompts[0]!.name).toBe('test-without-meta');
|
||||
expect(result.prompts[0]!._meta).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Tool title precedence', () => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue