Skip to content

feat(core): add specTypeSchema() for runtime validation of any spec type#1887

Draft
felixweinberger wants to merge 4 commits intomainfrom
fweinberger/spec-type-predicates
Draft

feat(core): add specTypeSchema() for runtime validation of any spec type#1887
felixweinberger wants to merge 4 commits intomainfrom
fweinberger/spec-type-predicates

Conversation

@felixweinberger
Copy link
Copy Markdown
Contributor

@felixweinberger felixweinberger commented Apr 13, 2026

Adds specTypeSchema(name) and isSpecType(name, value) for runtime validation of any MCP spec type by name. SpecTypeName and SpecTypes are derived from the internal schema map, so every spec type is covered with no per-type curation.

Motivation and Context

Extension authors who embed spec types inside custom-method payloads need a runtime validator. A single keyed function avoids exporting one symbol per type.

How Has This Been Tested?

Unit tests (specTypeSchema.test.ts, valid/invalid/null cases for 5 representative types + JSON-RPC envelope, type-level checks). Reachable from both @modelcontextprotocol/client and @modelcontextprotocol/server dist.

Breaking Changes

None — additive.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Also moves guards.test.ts to test/ (it was previously not picked up by vitest) and corrects the CLAUDE.md test-location guidance.

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 13, 2026

🦋 Changeset detected

Latest commit: a08445c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@modelcontextprotocol/client Patch
@modelcontextprotocol/server Patch
@modelcontextprotocol/express Patch
@modelcontextprotocol/fastify Patch
@modelcontextprotocol/hono Patch
@modelcontextprotocol/node Patch

Not sure what this means? Click here to learn what changesets are.

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

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 13, 2026

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/@modelcontextprotocol/client@1887

@modelcontextprotocol/server

npm i https://pkg.pr.new/@modelcontextprotocol/server@1887

@modelcontextprotocol/express

npm i https://pkg.pr.new/@modelcontextprotocol/express@1887

@modelcontextprotocol/fastify

npm i https://pkg.pr.new/@modelcontextprotocol/fastify@1887

@modelcontextprotocol/hono

npm i https://pkg.pr.new/@modelcontextprotocol/hono@1887

@modelcontextprotocol/node

npm i https://pkg.pr.new/@modelcontextprotocol/node@1887

commit: a08445c

@felixweinberger
Copy link
Copy Markdown
Contributor Author

@claude review

Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — clean, additive, follows established patterns.

Extended reasoning...

Overview

This PR adds five new type-guard functions (, , , , ) to packages/core/src/types/guards.ts, exports them via the public API barrel, and adds 29 unit tests. It also corrects a pre-existing issue where guards.test.ts lived under src/types/ and was never executed by vitest (which only scans test/**).

Security risks

None. These are pure read-only type predicates that delegate to Zod's safeParse — no side effects, no I/O, no auth-sensitive paths.

Level of scrutiny

Low. Each new guard is a single-line lambda following the exact same pattern as the existing isCallToolResult and other guards already present in the file. The public-index export list is alphabetized correctly. The test coverage is thorough (valid inputs, missing required fields, non-object primitives).

Other factors

The only reported issue is a nit: CLAUDE.md's co-location guideline contradicts the vitest include pattern. This is a pre-existing doc inconsistency and is already flagged as an inline comment on the PR — it does not affect the correctness of the code changes. No outstanding human-reviewer comments exist. The changeset correctly marks downstream packages as patch releases.

@felixweinberger felixweinberger changed the title feat(core): export type predicates for spec data-model types feat(core): add specTypeSchema() for runtime validation of any spec type Apr 13, 2026
@felixweinberger felixweinberger force-pushed the fweinberger/spec-type-predicates branch from 5408732 to 1219736 Compare April 13, 2026 16:57
Adds specTypeSchema(name) returning a StandardSchemaV1 validator for any
named MCP spec type, and isSpecType(name, value) as a boolean predicate.
The SpecTypeName union and SpecTypes map are derived from the internal
Zod schemas, so they cover every spec type with no curation.

Replaces the earlier curated-5-predicates approach with a single keyed
entrypoint that does not require a new export each time an extension
embeds a different spec type.

Also: moves guards.test.ts to test/ (vitest include is test/**/*.test.ts;
the file was previously dead) and corrects CLAUDE.md test-location guidance.
@felixweinberger felixweinberger force-pushed the fweinberger/spec-type-predicates branch from 1219736 to 06882c8 Compare April 13, 2026 17:01
felixweinberger and others added 3 commits April 13, 2026 18:21
specTypeSchema()/isSpecType() now also cover the OAuth/OpenID types from
shared/auth.ts (OAuthTokens, OAuthMetadata, OAuthClientMetadata, etc.),
addressing the standalone-validation use noted in #1680 for auth
implementers.
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