Skip to content

Comments

feat(codemode): support AI SDK jsonSchema wrapper in type generation#960

Draft
mattzcarey wants to merge 15 commits intomainfrom
feat/mcp-tools-zod-schema
Draft

feat(codemode): support AI SDK jsonSchema wrapper in type generation#960
mattzcarey wants to merge 15 commits intomainfrom
feat/mcp-tools-zod-schema

Conversation

@mattzcarey
Copy link
Contributor

@mattzcarey mattzcarey commented Feb 20, 2026

Summary

  • Codemode type generation handles AI SDK jsonSchema wrapper directly (~6µs)
  • MCP client uses fast jsonSchema wrapper (~0.25µs per schema)
  • Direct JSON Schema → TypeScript conversion (no Zod intermediate)

Problem

The codemode generateTypes function only worked with Zod schemas (requiring _zod property). MCP tools use the AI SDK jsonSchema wrapper which doesn't have this property.

Solution

Update codemode converter to detect and handle both schema types:

  1. Zod schemas - use zodToTs (~32µs)
  2. AI SDK jsonSchema wrapper - direct JSON Schema → TypeScript (~6µs)

Performance

Operation Time
MCP getAITools() ~0.25 µs/schema
generateTypes() with jsonSchema ~6 µs
generateTypes() with Zod ~32 µs

Changes

packages/codemode/src/types.ts

  • Add isJsonSchemaWrapper() - detect AI SDK wrapper
  • Add extractJsonSchema() - extract JSON schema from wrapper
  • Add jsonSchemaToTypeString() - direct JSON Schema → TypeScript
  • Support: objects, arrays, enums, unions, intersections, const, nullable

packages/codemode/src/tests/schema-conversion.test.ts

  • 21 focused tests for our code (not zod-to-ts library)
  • sanitizeToolName tests
  • jsonSchema wrapper handling tests
  • Zod schema integration tests

Test plan

  • All 79 codemode tests pass
  • All 652 agents tests pass

MCP tools returned by getAITools() now have the _zod property on their
inputSchema, which is required for codemode type generation.

Previously, getAITools() used the AI SDK's jsonSchema() function to wrap
MCP tool JSON schemas, which created Schema objects without the _zod
property. This change uses Zod v4's fromJSONSchema() function instead,
which converts JSON schemas to actual Zod schemas that include the _zod
property.

- Add static import of fromJSONSchema from zod
- Replace this.jsonSchema() calls with fromJSONSchema() in getAITools()
- Remove the jsonSchema initialization check (no longer needed)
- Update tests to verify _zod property is present on tool inputSchema
@changeset-bot
Copy link

changeset-bot bot commented Feb 20, 2026

⚠️ No Changeset found

Latest commit: b15afa3

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 20, 2026

Open in StackBlitz

npm i https://pkg.pr.new/cloudflare/agents@960
npm i https://pkg.pr.new/cloudflare/agents/@cloudflare/ai-chat@960
npm i https://pkg.pr.new/cloudflare/agents/@cloudflare/codemode@960
npm i https://pkg.pr.new/cloudflare/agents/hono-agents@960

commit: b15afa3

@mattzcarey mattzcarey marked this pull request as draft February 20, 2026 23:12
@mattzcarey mattzcarey force-pushed the feat/mcp-tools-zod-schema branch from 46ca09f to 9f2be18 Compare February 21, 2026 00:16
- Remove unused json-schema-to-typescript dependency from codemode
- Add comprehensive test for MCP tools with input AND output schemas
- Add comprehensive test for AI SDK tool() with input AND output schemas
- Remove redundant mixed tools test (covered by the two focused tests)
- Both tests verify rich output types, not just 'unknown'
@mattzcarey mattzcarey marked this pull request as ready for review February 21, 2026 00:53
- Fix JSONSchema7 type incompatibility with fromJSONSchema parameter type
- Remove unused JSONSchema7 import
- Simplify test to use ToolDescriptors directly instead of AI SDK tool()
- Fix Text component className prop error in codemode example
- Keep jsonSchema property on MCPClientManager (deprecated but functional)
- ensureJsonSchema() still lazy-loads jsonSchema from AI SDK for compat
- No breaking changes - existing code using manager.jsonSchema still works
@mattzcarey
Copy link
Contributor Author

mattzcarey commented Feb 21, 2026

Performance Analysis: jsonSchema() vs fromJSONSchema()

Profiled the performance impact of switching from AI SDK's jsonSchema() to Zod v4's fromJSONSchema():

Metric fromJSONSchema() jsonSchema() Ratio
Simple schema (2 props) 25 µs 0.25 µs ~100x slower
Complex MCP schema 151 µs 0.22 µs ~685x slower
Deeply nested (5 levels) 89 µs 0.26 µs ~342x slower
Memory per schema ~559 KB ~1 KB ~559x more

What this means in practice

For a typical MCP server with 10 tools:

  • fromJSONSchema(): ~1.5ms startup + ~5.5MB memory
  • jsonSchema(): ~0.002ms startup + ~10KB memory

However, this cost is paid once when getAITools() is called, not per-request. After initialization:

  • Validation is fast: ~1 µs per call
  • Schemas are cached in the returned tool definitions

Why we need fromJSONSchema()

  • jsonSchema() creates a thin wrapper without _zod property
  • fromJSONSchema() creates a real Zod schema with _zod property
  • The _zod property is required for zod-to-ts which codemode uses for type generation

Recommendation

keep jsonSchema and build a parser to support it.

@mattzcarey mattzcarey marked this pull request as draft February 21, 2026 01:27
…andling

- Add safeZodToTs() wrapper that returns "unknown" for schemas that can't
  be represented in TypeScript (e.g., transforms) instead of throwing
- Add schema-conversion.test.ts with 165 tests covering all Zod v4 types:
  primitives, literals, enums, objects, arrays, tuples, unions, intersections,
  records, maps, sets, modifiers, readonly, coerce, pipe, transform,
  template literals, lazy/recursive, functions, promises, branded types,
  effects/refinements, string/number validators, fromJSONSchema, and
  sanitizeToolName edge cases
- Test coverage exceeds zod-to-ts package (~25 tests vs 165 tests)
These were used to validate fromJSONSchema() vs jsonSchema() performance:
- fromJSONSchema: ~168µs (creates real Zod schema with _zod property)
- jsonSchema: ~0.25µs (thin wrapper, no _zod property)

The ~680x slower performance is acceptable since schema creation happens
once at startup, not per-request. fromJSONSchema is required for codemode
type generation which needs the _zod property.
Reverts MCP client to use fast jsonSchema wrapper (~0.25µs) instead of
slower fromJSONSchema (~168µs). Type conversion is now handled in the
codemode package's generateTypes function.

Changes to codemode/types.ts:
- Add schema detection: isZodSchema, isJsonSchemaWrapper, isRawJsonSchema
- Add normalizeToZodSchema to convert any schema type to Zod
- Extract JSON schema from AI SDK jsonSchema wrapper via symbol properties
- Use fromJSONSchema internally only during type generation (one-time cost)
- Support: Zod schemas, AI SDK jsonSchema wrapper, raw JSON schemas

Performance:
- MCP getAITools(): ~0.25µs per schema (fast jsonSchema wrapper)
- generateTypes(): ~210µs for complex schemas (acceptable startup cost)

Tests added:
- AI SDK jsonSchema wrapper handling
- Raw JSON Schema object handling
Replace fromJSONSchema-based conversion with direct JSON Schema to
TypeScript string conversion. This avoids creating Zod validators
when we only need type information.

- Add jsonSchemaToTypeString() for direct conversion
- Remove fromJSONSchema import (no longer needed)
- Remove raw JSON Schema handling (only Zod + jsonSchema wrapper)
- Support: objects, arrays, enums, unions, intersections, etc.

Performance:
- jsonSchema wrapper → TypeScript: ~6µs (was ~210µs, 35x faster)
- Zod schema → TypeScript: ~32µs (uses zod-to-ts)
Remove 144 tests that were testing zod-to-ts library behavior.
Keep 21 focused tests for our own code:
- sanitizeToolName (10 tests)
- generateTypes with jsonSchema wrapper (9 tests)  
- generateTypes with Zod schema (2 tests - integration only)
@mattzcarey mattzcarey changed the title fix(mcp): use Zod fromJSONSchema for MCP tool schemas feat(codemode): support AI SDK jsonSchema wrapper in type generation Feb 21, 2026
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.

1 participant