Skip to content

Conversation

@ochafik
Copy link
Contributor

@ochafik ochafik commented Dec 12, 2025

Summary

Add auto-generated Zod schemas and types from spec.types.ts using ts-to-zod, with pre-processing to match SDK type hierarchy.

Pipeline

spec.types.ts (from spec repo)
    ↓ preProcessTypes()
sdk.types.ts (SDK-compatible types)
    ↓ ts-to-zod
sdk.schemas.ts (generated Zod schemas)
    ↓
generated/index.ts (public API)
    ↓
types.ts (re-exports + SDK extras)

Pre-Processing (NEW)

Instead of post-processing generated schemas, we now pre-process the types:

content = content.replace(/extends JSONRPCRequest/g, 'extends Request');
content = content.replace(/extends JSONRPCNotification/g, 'extends Notification');

This transforms the type hierarchy so generated types/schemas match SDK conventions, where jsonrpc/id fields are handled at the transport layer.

Generated Files

  • sdk.types.ts - Pre-processed types (SDK hierarchy)
  • sdk.schemas.ts - Zod schemas from sdk.types.ts
  • sdk.schemas.zod.test.ts - Integration tests
  • index.ts - Public API with explicit exports

Post-Processing

Step Transformation
1 Zod v4 import: "zod""zod/v4"
2 Index signatures: z.record().and(z.object())z.looseObject()
3 typeof expressions: jsonrpc: z.any()z.literal("2.0")
4 Integer refinements: ProgressTokenSchema, RequestIdSchema use .int()

Usage

import { ProgressTokenSchema, ProgressToken } from '@modelcontextprotocol/sdk/generated';

What's Next

With sdk.types.ts now generated, types.ts can become a thin re-export layer:

// types.ts
export * from './generated/sdk.schemas.js';
export type * from './generated/sdk.types.js';
// + SDK-specific extras (ErrorCode, McpError, etc.)

Test plan

  • npm run generate:schemas produces sdk.types.ts + sdk.schemas.ts
  • npm run build succeeds
  • 97 comparison tests pass (generated vs manual schemas)
  • 1586 total tests pass (same pre-existing failures on main)

🤖 Generated with Claude Code

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 12, 2025

Open in StackBlitz

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/sdk@1292

commit: 4d2ab8c

@ochafik ochafik force-pushed the ochafik/ts2zod-library-approach branch from 4a263d3 to b093040 Compare December 12, 2025 16:56
Add auto-generated Zod schemas from spec.types.ts using ts-to-zod as a library,
with post-processing for SDK compatibility.

## What's New

- `src/generated/spec.schemas.ts` - 145 auto-generated Zod schemas
- `src/generated/index.ts` - Public API with explicit exports by name
- `test/generated/spec.schemas.compare.test.ts` - 97 tests verifying equivalence
- `scripts/generate-schemas.ts` - Library-based generator with post-processing

## Post-Processing

The generator applies several transformations for SDK compatibility:

1. **Zod v4 import** - `"zod"` → `"zod/v4"`
2. **Index signatures** - `z.record().and(z.object())` → `z.looseObject()`
3. **typeof expressions** - `jsonrpc: z.any()` → `z.literal("2.0")`
4. **SDK hierarchy** - Notifications/Requests extend `NotificationSchema`/`RequestSchema`
5. **Integer refinements** - `ProgressTokenSchema`, `RequestIdSchema` use `.int()`

## Usage

```typescript
import { ProgressTokenSchema } from '@modelcontextprotocol/sdk/generated';
```

## Design

- **types.ts unchanged** - Full refactor to thin re-export layer deferred
- **Explicit exports** - Each schema/type listed by name for legibility
- **No description duplication** - spec.types.ts kept clean (no @description injection)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@ochafik ochafik force-pushed the ochafik/ts2zod-library-approach branch from b093040 to 400cfa6 Compare December 12, 2025 16:59
ochafik and others added 2 commits December 12, 2025 17:03
Move the SDK hierarchy transformation from post-processing (on generated
schemas) to pre-processing (on source types). This is cleaner because:

1. Types are transformed ONCE, before schema generation
2. Generated schemas directly reflect SDK hierarchy
3. No need to maintain a list of request/notification names

Transform applied:
- `extends JSONRPCRequest` → `extends Request`
- `extends JSONRPCNotification` → `extends Notification`

Added ts-morph alternative in comments for future reference if regex
becomes fragile.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Write pre-processed types to sdk.types.ts so types.ts can re-export them:

1. spec.types.ts → preProcessTypes() → sdk.types.ts
2. sdk.types.ts → ts-to-zod → sdk.schemas.ts
3. types.ts can now re-export from sdk.types.ts + sdk.schemas.ts

Generated files:
- sdk.types.ts: Types with `extends Request`/`Notification` (not JSONRPC*)
- sdk.schemas.ts: Zod schemas matching SDK hierarchy
- sdk.schemas.zod.test.ts: Integration tests

This enables types.ts to become a thin re-export layer in a follow-up.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants