While implementing the server-side Task Store role for io.modelcontextprotocol/tasks, I used schema/draft/schema.json for runtime validation. Two constraints described by the TypeScript source and normative prose are absent from the generated JSON Schema, and both matter to an implementation that is not written in TypeScript.
This report uses ext-tasks commit 2c1425d9a288b9b1f489430fe1e00bb392b47e48: schema.json (blob d6ccaff7e3fb2131b5d752dd8b6f34096e58e976) and schema.ts (blob 2634c47c2b25ac8fafe7fadaa7dd3f3b732c0abc).
1. InputRequest and InputResponse collapse to “anything”
schema.ts declares:
type InputRequest = CreateMessageRequest | ListRootsRequest | ElicitRequest;
type InputResponse = CreateMessageResult | ListRootsResult | ElicitResult;
Those names come from @modelcontextprotocol/sdk/types.js. The current generation does not inline their definitions, so in schema.json both become:
{ "anyOf": [{}, {}, {}] }
Expected: InputRequest and InputResponse contain structural constraints for their three permitted request or response families.
Actual: each exact definition is {"anyOf":[{},{},{}]}. Because an empty JSON Schema accepts every instance, these definitions also accept a value such as { "definitely": "not an MCP request" }.
2. resultType appears nowhere in the generated schema
The extension prose and the JSDoc in schema.ts require CreateTaskResult.resultType to be "task", and require "complete" for GetTaskResult, UpdateTaskResult, and CancelTaskResult.
Expected: CreateTaskResult requires resultType with the constant "task", and the three task-operation results require "complete".
Actual: the string resultType does not occur anywhere in schema.json, so none of the four definitions contains or requires the discriminator.
The normative requirement is present in the extension prose and repeated in schema.ts JSDoc, but the structural result aliases do not encode the literal discriminators. The generated schema contains no corresponding "task" or "complete" constraint, so the requirement is not machine-checkable from that artifact.
Reproduction
The following script prints and asserts the exact generated structures described above. The conclusion that each empty branch accepts every instance follows directly from JSON Schema semantics:
https://github.com/AndresSaa/mcp-durable-tasks/blob/fd0db84500fffa059b24e888c3b1093d50db2adc/examples/conformance-reproductions/schema.mts
From a clone of that commit:
cd examples/conformance-reproductions
node --experimental-strip-types schema.mts
The repository vendors both upstream files with their commit and blob provenance, so this remains a reproducible record of the schemas inspected even after upstream changes.
Question
Should generation inline the six imported request and result member types, or should a resolved bundle be published next to schema.json? And should the structural result types encode the literal resultType constraints so the generated artifact enforces the normative requirement?
Together, those changes would make the generated artifact enforce the constraints described by the source and normative prose. Today, a runtime implementation has to maintain its own mirror of the SDK request/response shapes and result discriminators, which creates an avoidable drift risk.
While implementing the server-side Task Store role for
io.modelcontextprotocol/tasks, I usedschema/draft/schema.jsonfor runtime validation. Two constraints described by the TypeScript source and normative prose are absent from the generated JSON Schema, and both matter to an implementation that is not written in TypeScript.This report uses
ext-taskscommit2c1425d9a288b9b1f489430fe1e00bb392b47e48:schema.json(blobd6ccaff7e3fb2131b5d752dd8b6f34096e58e976) andschema.ts(blob2634c47c2b25ac8fafe7fadaa7dd3f3b732c0abc).1.
InputRequestandInputResponsecollapse to “anything”schema.tsdeclares:Those names come from
@modelcontextprotocol/sdk/types.js. The current generation does not inline their definitions, so inschema.jsonboth become:{ "anyOf": [{}, {}, {}] }Expected:
InputRequestandInputResponsecontain structural constraints for their three permitted request or response families.Actual: each exact definition is
{"anyOf":[{},{},{}]}. Because an empty JSON Schema accepts every instance, these definitions also accept a value such as{ "definitely": "not an MCP request" }.2.
resultTypeappears nowhere in the generated schemaThe extension prose and the JSDoc in
schema.tsrequireCreateTaskResult.resultTypeto be"task", and require"complete"forGetTaskResult,UpdateTaskResult, andCancelTaskResult.Expected:
CreateTaskResultrequiresresultTypewith the constant"task", and the three task-operation results require"complete".Actual: the string
resultTypedoes not occur anywhere inschema.json, so none of the four definitions contains or requires the discriminator.The normative requirement is present in the extension prose and repeated in
schema.tsJSDoc, but the structural result aliases do not encode the literal discriminators. The generated schema contains no corresponding"task"or"complete"constraint, so the requirement is not machine-checkable from that artifact.Reproduction
The following script prints and asserts the exact generated structures described above. The conclusion that each empty branch accepts every instance follows directly from JSON Schema semantics:
https://github.com/AndresSaa/mcp-durable-tasks/blob/fd0db84500fffa059b24e888c3b1093d50db2adc/examples/conformance-reproductions/schema.mts
From a clone of that commit:
cd examples/conformance-reproductions node --experimental-strip-types schema.mtsThe repository vendors both upstream files with their commit and blob provenance, so this remains a reproducible record of the schemas inspected even after upstream changes.
Question
Should generation inline the six imported request and result member types, or should a resolved bundle be published next to
schema.json? And should the structural result types encode the literalresultTypeconstraints so the generated artifact enforces the normative requirement?Together, those changes would make the generated artifact enforce the constraints described by the source and normative prose. Today, a runtime implementation has to maintain its own mirror of the SDK request/response shapes and result discriminators, which creates an avoidable drift risk.