Skip to content

Commit a02d1c8

Browse files
pcarletonclaude
andcommitted
Merge main into pcarleton/cimd, resolve conflicts
- Integrate new discovery-metadata.ts from main (replaces basic-dcr/basic-metadata) - Keep CIMD scenario from this branch - Apply .js extension removal to discovery-metadata imports 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2 parents 17cde17 + f087e44 commit a02d1c8

File tree

15 files changed

+714
-346
lines changed

15 files changed

+714
-346
lines changed

.github/workflows/pr-publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ jobs:
2424
- name: Build
2525
run: npm run build
2626
- name: Publish
27-
run: npx pkg-pr-new publish
27+
run: npx pkg-pr-new publish --bin

examples/servers/typescript/everything-server.ts

Lines changed: 140 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ import {
1313
ResourceTemplate
1414
} from '@modelcontextprotocol/sdk/server/mcp.js';
1515
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
16+
import {
17+
ElicitResultSchema,
18+
ListToolsRequestSchema,
19+
type ListToolsResult,
20+
type Tool
21+
} from '@modelcontextprotocol/sdk/types.js';
22+
import { zodToJsonSchema } from 'zod-to-json-schema';
1623
import { z } from 'zod';
1724
import express from 'express';
1825
import cors from 'cors';
@@ -34,6 +41,28 @@ const TEST_IMAGE_BASE64 =
3441
const TEST_AUDIO_BASE64 =
3542
'UklGRiYAAABXQVZFZm10IBAAAAABAAEAQB8AAAB9AAACABAAZGF0YQIAAAA=';
3643

44+
// SEP-1613: Raw JSON Schema 2020-12 definition for conformance testing
45+
// This schema includes $schema, $defs, and additionalProperties to test
46+
// that SDKs correctly preserve these fields
47+
const JSON_SCHEMA_2020_12_INPUT_SCHEMA = {
48+
$schema: 'https://json-schema.org/draft/2020-12/schema',
49+
type: 'object' as const,
50+
$defs: {
51+
address: {
52+
type: 'object',
53+
properties: {
54+
street: { type: 'string' },
55+
city: { type: 'string' }
56+
}
57+
}
58+
},
59+
properties: {
60+
name: { type: 'string' },
61+
address: { $ref: '#/$defs/address' }
62+
},
63+
additionalProperties: false
64+
};
65+
3766
// Function to create a new MCP server instance (one per session)
3867
function createMcpServer() {
3968
const mcpServer = new McpServer(
@@ -369,9 +398,7 @@ function createMcpServer() {
369398
}
370399
}
371400
},
372-
z
373-
.object({ method: z.literal('elicitation/create') })
374-
.passthrough() as any
401+
ElicitResultSchema
375402
);
376403

377404
const elicitResult = result as any;
@@ -445,9 +472,7 @@ function createMcpServer() {
445472
}
446473
}
447474
},
448-
z
449-
.object({ method: z.literal('elicitation/create') })
450-
.passthrough() as any
475+
ElicitResultSchema
451476
);
452477

453478
const elicitResult = result as any;
@@ -544,9 +569,7 @@ function createMcpServer() {
544569
}
545570
}
546571
},
547-
z
548-
.object({ method: z.literal('elicitation/create') })
549-
.passthrough() as any
572+
ElicitResultSchema
550573
);
551574

552575
const elicitResult = result as any;
@@ -571,6 +594,40 @@ function createMcpServer() {
571594
}
572595
);
573596

597+
// SEP-1613: JSON Schema 2020-12 conformance test tool
598+
// This tool is registered with a Zod schema for tools/call validation,
599+
// but the tools/list handler (below) returns the raw JSON Schema 2020-12
600+
// definition to test that SDKs preserve $schema, $defs, additionalProperties
601+
mcpServer.registerTool(
602+
'json_schema_2020_12_tool',
603+
{
604+
description:
605+
'Tool with JSON Schema 2020-12 features for conformance testing (SEP-1613)',
606+
inputSchema: {
607+
name: z.string().optional(),
608+
address: z
609+
.object({
610+
street: z.string().optional(),
611+
city: z.string().optional()
612+
})
613+
.optional()
614+
}
615+
},
616+
async (args: {
617+
name?: string;
618+
address?: { street?: string; city?: string };
619+
}) => {
620+
return {
621+
content: [
622+
{
623+
type: 'text',
624+
text: `JSON Schema 2020-12 tool called with: ${JSON.stringify(args)}`
625+
}
626+
]
627+
};
628+
}
629+
);
630+
574631
// Dynamic tool (registered later via timer)
575632

576633
// ===== RESOURCES =====
@@ -834,6 +891,80 @@ function createMcpServer() {
834891
}
835892
);
836893

894+
// ===== SEP-1613: Override tools/list to return raw JSON Schema 2020-12 =====
895+
// This override is necessary because registerTool converts Zod schemas to
896+
// JSON Schema without preserving $schema, $defs, and additionalProperties.
897+
// We need to return the raw JSON Schema for our test tool while using the
898+
// SDK's conversion for other tools.
899+
mcpServer.server.setRequestHandler(
900+
ListToolsRequestSchema,
901+
(): ListToolsResult => {
902+
// Access internal registered tools (this is internal SDK API but stable)
903+
const registeredTools = (mcpServer as any)._registeredTools as Record<
904+
string,
905+
{
906+
enabled: boolean;
907+
title?: string;
908+
description?: string;
909+
inputSchema?: any;
910+
outputSchema?: any;
911+
annotations?: any;
912+
_meta?: any;
913+
}
914+
>;
915+
916+
return {
917+
tools: Object.entries(registeredTools)
918+
.filter(([, tool]) => tool.enabled)
919+
.map(([name, tool]): Tool => {
920+
// For our SEP-1613 test tool, return raw JSON Schema 2020-12
921+
if (name === 'json_schema_2020_12_tool') {
922+
return {
923+
name,
924+
description: tool.description,
925+
inputSchema: JSON_SCHEMA_2020_12_INPUT_SCHEMA
926+
};
927+
}
928+
929+
// For other tools, convert Zod to JSON Schema
930+
// Handle different inputSchema formats:
931+
// - undefined/null: use empty object schema
932+
// - Zod schema (has _def): convert directly
933+
// - Raw shape (object with Zod values): wrap in z.object first
934+
let inputSchema: Tool['inputSchema'];
935+
if (!tool.inputSchema) {
936+
inputSchema = { type: 'object' as const, properties: {} };
937+
} else if ('_def' in tool.inputSchema) {
938+
// Already a Zod schema
939+
inputSchema = zodToJsonSchema(tool.inputSchema, {
940+
strictUnions: true
941+
}) as Tool['inputSchema'];
942+
} else if (
943+
typeof tool.inputSchema === 'object' &&
944+
Object.keys(tool.inputSchema).length > 0
945+
) {
946+
// Raw shape with Zod values
947+
inputSchema = zodToJsonSchema(z.object(tool.inputSchema), {
948+
strictUnions: true
949+
}) as Tool['inputSchema'];
950+
} else {
951+
// Empty object or unknown format
952+
inputSchema = { type: 'object' as const, properties: {} };
953+
}
954+
955+
return {
956+
name,
957+
title: tool.title,
958+
description: tool.description,
959+
inputSchema,
960+
annotations: tool.annotations,
961+
_meta: tool._meta
962+
};
963+
})
964+
};
965+
}
966+
);
967+
837968
return mcpServer;
838969
}
839970

lefthook.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# lefthook.yml
22
# Configuration reference: https://lefthook.dev/configuration/
33

4-
assert_lefthook_installed: true
4+
assert_lefthook_installed: false
55

66
output:
77
- meta # Print lefthook version

package-lock.json

Lines changed: 14 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@modelcontextprotocol/conformance",
3-
"version": "0.1.5",
3+
"version": "0.1.6",
44
"type": "module",
55
"license": "MIT",
66
"author": "Anthropic, PBC (https://anthropic.com)",
@@ -36,6 +36,7 @@
3636
"cors": "^2.8.5",
3737
"eslint": "^9.8.0",
3838
"eslint-config-prettier": "^10.1.8",
39+
"lefthook": "^2.0.2",
3940
"prettier": "3.6.2",
4041
"tsdown": "^0.15.12",
4142
"tsx": "^4.7.0",
@@ -47,7 +48,6 @@
4748
"@modelcontextprotocol/sdk": "^1.22.0",
4849
"commander": "^14.0.2",
4950
"express": "^5.1.0",
50-
"lefthook": "^2.0.2",
5151
"zod": "^3.25.76"
5252
}
5353
}

0 commit comments

Comments
 (0)