feat: pluggable JSON schema validator providers (#1012)
This commit is contained in:
parent
7098bff073
commit
5a8fb39430
1 changed files with 2373 additions and 134 deletions
|
|
@ -1,25 +1,24 @@
|
|||
import { McpServer } from './mcp.js';
|
||||
import { z } from 'zod';
|
||||
import { Client } from '../client/index.js';
|
||||
import { InMemoryTransport } from '../inMemory.js';
|
||||
import { z } from 'zod';
|
||||
import { getDisplayName } from '../shared/metadataUtils.js';
|
||||
import { UriTemplate } from '../shared/uriTemplate.js';
|
||||
import {
|
||||
ListToolsResultSchema,
|
||||
CallToolResultSchema,
|
||||
CompleteResultSchema,
|
||||
ElicitRequestSchema,
|
||||
GetPromptResultSchema,
|
||||
ListPromptsResultSchema,
|
||||
ListResourcesResultSchema,
|
||||
ListResourceTemplatesResultSchema,
|
||||
ReadResourceResultSchema,
|
||||
ListPromptsResultSchema,
|
||||
GetPromptResultSchema,
|
||||
CompleteResultSchema,
|
||||
ListToolsResultSchema,
|
||||
LoggingMessageNotificationSchema,
|
||||
Notification,
|
||||
TextContent,
|
||||
ElicitRequestSchema
|
||||
type Notification,
|
||||
ReadResourceResultSchema,
|
||||
type TextContent
|
||||
} from '../types.js';
|
||||
import { ResourceTemplate } from './mcp.js';
|
||||
import { completable } from './completable.js';
|
||||
import { UriTemplate } from '../shared/uriTemplate.js';
|
||||
import { getDisplayName } from '../shared/metadataUtils.js';
|
||||
import { McpServer, ResourceTemplate } from './mcp.js';
|
||||
|
||||
describe('McpServer', () => {
|
||||
/***
|
||||
|
|
@ -112,11 +111,22 @@ describe('McpServer', () => {
|
|||
}
|
||||
}
|
||||
|
||||
return { content: [{ type: 'text' as const, text: `Operation completed with ${steps} steps` }] };
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Operation completed with ${steps} steps`
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const progressUpdates: Array<{ progress: number; total?: number; message?: string }> = [];
|
||||
const progressUpdates: Array<{
|
||||
progress: number;
|
||||
total?: number;
|
||||
message?: string;
|
||||
}> = [];
|
||||
|
||||
const client = new Client({
|
||||
name: 'test client',
|
||||
|
|
@ -677,9 +687,15 @@ describe('tool()', () => {
|
|||
|
||||
expect(result.tools).toHaveLength(2);
|
||||
expect(result.tools[0].name).toBe('test');
|
||||
expect(result.tools[0].annotations).toEqual({ title: 'Test Tool', readOnlyHint: true });
|
||||
expect(result.tools[0].annotations).toEqual({
|
||||
title: 'Test Tool',
|
||||
readOnlyHint: true
|
||||
});
|
||||
expect(result.tools[1].name).toBe('test (new api)');
|
||||
expect(result.tools[1].annotations).toEqual({ title: 'Test Tool', readOnlyHint: true });
|
||||
expect(result.tools[1].annotations).toEqual({
|
||||
title: 'Test Tool',
|
||||
readOnlyHint: true
|
||||
});
|
||||
});
|
||||
|
||||
/***
|
||||
|
|
@ -722,7 +738,10 @@ describe('tool()', () => {
|
|||
type: 'object',
|
||||
properties: { name: { type: 'string' } }
|
||||
});
|
||||
expect(result.tools[0].annotations).toEqual({ title: 'Test Tool', readOnlyHint: true });
|
||||
expect(result.tools[0].annotations).toEqual({
|
||||
title: 'Test Tool',
|
||||
readOnlyHint: true
|
||||
});
|
||||
expect(result.tools[1].name).toBe('test (new api)');
|
||||
expect(result.tools[1].inputSchema).toEqual(result.tools[0].inputSchema);
|
||||
expect(result.tools[1].annotations).toEqual(result.tools[0].annotations);
|
||||
|
|
@ -756,7 +775,11 @@ describe('tool()', () => {
|
|||
{
|
||||
description: 'A tool with everything',
|
||||
inputSchema: { name: z.string() },
|
||||
annotations: { title: 'Complete Test Tool', readOnlyHint: true, openWorldHint: false }
|
||||
annotations: {
|
||||
title: 'Complete Test Tool',
|
||||
readOnlyHint: true,
|
||||
openWorldHint: false
|
||||
}
|
||||
},
|
||||
async ({ name }) => ({
|
||||
content: [{ type: 'text', text: `Hello, ${name}!` }]
|
||||
|
|
@ -804,7 +827,11 @@ describe('tool()', () => {
|
|||
'test',
|
||||
'A tool with everything but empty params',
|
||||
{},
|
||||
{ title: 'Complete Test Tool with empty params', readOnlyHint: true, openWorldHint: false },
|
||||
{
|
||||
title: 'Complete Test Tool with empty params',
|
||||
readOnlyHint: true,
|
||||
openWorldHint: false
|
||||
},
|
||||
async () => ({
|
||||
content: [{ type: 'text', text: 'Test response' }]
|
||||
})
|
||||
|
|
@ -815,7 +842,11 @@ describe('tool()', () => {
|
|||
{
|
||||
description: 'A tool with everything but empty params',
|
||||
inputSchema: {},
|
||||
annotations: { title: 'Complete Test Tool with empty params', readOnlyHint: true, openWorldHint: false }
|
||||
annotations: {
|
||||
title: 'Complete Test Tool with empty params',
|
||||
readOnlyHint: true,
|
||||
openWorldHint: false
|
||||
}
|
||||
},
|
||||
async () => ({
|
||||
content: [{ type: 'text' as const, text: 'Test response' }]
|
||||
|
|
@ -1342,7 +1373,7 @@ describe('tool()', () => {
|
|||
|
||||
expect(receivedRequestId).toBeDefined();
|
||||
expect(typeof receivedRequestId === 'string' || typeof receivedRequestId === 'number').toBe(true);
|
||||
expect(result.content && result.content[0].text).toContain('Received request ID:');
|
||||
expect(result.content?.[0].text).toContain('Received request ID:');
|
||||
});
|
||||
|
||||
/***
|
||||
|
|
@ -1370,7 +1401,10 @@ describe('tool()', () => {
|
|||
});
|
||||
|
||||
mcpServer.tool('test-tool', async ({ sendNotification }) => {
|
||||
await sendNotification({ method: 'notifications/message', params: { level: 'debug', data: loggingMessage } });
|
||||
await sendNotification({
|
||||
method: 'notifications/message',
|
||||
params: { level: 'debug', data: loggingMessage }
|
||||
});
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue