MCP Description 0.9.0 is a community working draft. This guide follows the draft and changes with it; see the changelog for the status of each change and the proposal that introduced it.
Version 0.9.0 measures carried MCP values against each protocol version’s TypeScript schema. Most 0.8.0 documents need only a version change. Documents that put extra properties on closed MCP types must move them.
Version and schema identity
Section titled “Version and schema identity”Set mcpdesc to 0.9.0. When emitting $schema during the draft, use
https://mcpdesc.org/schema/mcp-description/0.9.0-rc.3.json; the stable
identifier is assigned at release.
Union-aware diagnostics in RC.3
Section titled “Union-aware diagnostics in RC.3”The working draft implements review-stage Proposal 0035
(issue #115),
building on RC.2 and Proposal 0034.
Unions with portable selectors use guarded JSON Schema conditionals, so only
the applicable alternative is validated. The remaining inclusive
oauthFlows.anyOf is handled generically. These changes do not intend to alter
which documents are accepted: required members, object closure, extension
eligibility, and reference constraints remain equivalent to RC.2.
Diagnostic paths and rule results can change. A missing-member path now points
to its enclosing object, with the absent name in detail.member. A typo path
points to the unexpected member that exists in the source. Findings reached
through $componentRef use the reference object as their primary path and
provide a component-definition related location. Alternative failures that
do not apply are no longer reported, and rules for those alternatives no
longer fail. Consumers should not rely on raw finding counts or engine schema
paths.
One intentional acceptance narrowing is included: the Elicitation Interaction Response Object in a Tool Interaction Example now rejects unknown members. RC.2’s schema allowed arbitrary additional members on those response objects. The narrowing does not apply to native MCP responses at runtime.
Validation result format 1.4.0 adds factual detail fields and
relatedLocations. Consumers should render recognized detail.kind values
and their fields, falling back to message for unknown kinds or diagnostics
without detail. The document mcpdesc version remains 0.9.0; consumers
should select the exact 0.9.0-rc.3 validator candidate. Published RC.1 and
RC.2 snapshots remain unchanged.
Annotations
Section titled “Annotations”Tool Annotations and Resource Annotations, including annotations on content blocks, accept only the properties MCP defines (Sections 9.6 and 10.3):
| Object | Allowed properties |
|---|---|
Tool annotations |
title, readOnlyHint, destructiveHint, idempotentHint, openWorldHint |
| Resource Annotations | audience, priority, lastModified (from MCP 2025-06-18) |
Remove other properties, including x-* keys. Server-defined metadata belongs
in the declaration’s _meta where the protocol version defines it (from MCP
2025-06-18). MCP Description metadata belongs in x-* properties on the
declaration itself.
{ "name": "inspect", "inputSchema": { "type": "object" }, "annotations": { "readOnlyHint": true }, "_meta": { "com.example/tier": "gold" }}Client capability requirements
Section titled “Client capability requirements”A clientRequirements object names only client capabilities that the
applicable MCP protocol versions define (Section 8.5). Move custom requirements into
experimental or, for MCP 2026-07-28, into extensions:
{ "clientRequirements": { "experimental": { "com.example/replay": {} } } }Server capabilities were already closed in 0.8.0.
Integer numbers
Section titled “Integer numbers”Resource size, the size of resource link content blocks, and Resource
example result ttlMs are integers (Sections 3.6, 10.1.1, and 10.4.4), as in
the JSON Schema MCP generates. Replace a fractional value with the intended
integer; 1024.0 is already an integer.
Resource URIs
Section titled “Resource URIs”A Resource uri must be an RFC 3986 URI with a scheme (Section 10.1.2), as
MCP types it and as Section 15 already required of URI values; 0.8.0 accepted
any string. Custom schemes remain valid. Replace a relative reference or free
text with the absolute URI the server uses, for example file:///docs/readme.md
instead of docs/readme.md. Version conversion reports such a value as
blocked rather than guessing the URI.
Tool schema dialects
Section titled “Tool schema dialects”For MCP 2025-11-25 and later, a Tool inputSchema or outputSchema that
declares $schema must declare JSON Schema 2020-12 or draft-07 (Section 9.2).
In 0.8.0 the accepted set depended on the validator; the reference validator
already accepted only these two, so its results do not change. Replace any
other declared dialect, preferably by removing $schema to use the 2020-12
default.
For MCP 2025-11-25 and later, the dialect also decides the schema’s shape
(Section 9.2). 0.8.0 required a literal "type": "object" at every
inputSchema root; 0.9.0 requires it only before MCP 2025-11-25 and otherwise
rejects only a declared root type that excludes "object". No 0.8.0 document
becomes invalid. A schema that the MCP Tool type of an applicable protocol version
rejects, such as a root in $ref or a boolean properties value for MCP
2025-11-25, stays valid with the new warning tool-schema-mcp-type-mismatch,
because native projection fails for that protocol version. Write {} instead of
true, { "not": {} } instead of false, or "type": "object" beside
$ref or allOf, or narrow the Tool’s protocolVersions.
Example results
Section titled “Example results”Example results and Tool Interaction step responses are checked against each applicable protocol version’s MCP type (Section 3.6):
- A field that an open MCP result type allows but the protocol version does not define
is accepted and preserved with the warning
result-field-not-defined-by-version. For example,resultTypein a result shared by MCP 2025-11-25 and MCP 2026-07-28 no longer requires splitting the declaration. Variants that were split only forresultType,ttlMs, orcacheScopemay be merged; splitting still clears the warning. - The
completionobject of a completion example result accepts onlyvalues,total, andhasMore. Move other fields, for example to result_meta. - For MCP 2026-07-28, sampling, elicitation, and roots step responses are
closed: remove unknown fields, and keep
_metaonly on sampling responses. - Result
_metais accepted in every protocol version. Root_metain roots responses is accepted from MCP 2025-06-18. - Reserved
_metakeys are checked in example results, their content, step responses, and roots.
MCP Description does not support completion examples for MCP 2024-11-05.
Validator output
Section titled “Validator output”Rule catalog consumers
Section titled “Rule catalog consumers”0.9.0 introduces validation rule catalogs and rule-linked diagnostics; these are new to 0.9.0, not formats that 0.8.0 validators emitted. For changes to the catalog and validation result formats in RC.1, see the Release Candidate 1 entry in the 0.9.0 changelog.
Discover catalogs through the publication index, then pin an immutable
manifest. Resolve evidence and description links from its
specificationBaseUrl, not a moving branch. See the
catalog publication contract.
Existing 0.8.0 validators do not gain retroactive rule diagnostics or a catalog.
Document diagnostics
Section titled “Document diagnostics”Every diagnostic carries a rule property naming the validation rule it
reports, next to code, severity, message, and path:
{ "code": "schema-validation", "severity": "error", "message": "does not validate against 0.9.0: /tools/0/annotations must NOT have additional properties", "path": ["tools", 0, "annotations", "audience"], "rule": "mcp.tool-annotations.members"}Tools, CI checks, and snapshot tests that compare whole diagnostic objects, or
reject unknown properties, must accept rule or compare the other four
properties only. @mcpdesc/core updates its frozen diagnostic expectations at
the next validator snapshot intake.
Other output changes:
- Array indices in
schema-validationpaths are numbers, as in semantic diagnostics. Previously they were strings below the document root. - New codes include
result-field-not-defined-by-version(warning). Some conditions that were errors in 0.8.0 are now warnings with that code. invalid-resource-template-uri-templatereplacesresource-template-example-invalid-templateandresource-template-completion-example-invalid-template. It reports a malformeduriTemplateonce, also on Resource Templates without examples, which 0.8.0 accepted.- The
completion-example-version-mismatchmessage for MCP 2024-11-05 says the protocol version is not supported by MCP Description. schema-validationdiagnostics name the rule that owns the failing schema location, for examplemcpdesc.tool.membersormcp.content.members, instead ofmcpdesc.document.schema, which reports only failures of the document root.- A diagnostic whose finding depends on MCP protocol versions lists them in
protocolVersions.rule,severity, andpathare the interoperable contract;codeandmessageare optional producer output (Section 16.5). Compare diagnostics byrule, not bycode. - The exported validator’s
validate()also returnsresults: one status per rule and declared protocol version, in the validation result format. Treatnot-applicableandnot-evaluatedas not confirmed, never as passed. Validity is unchanged.
Recommended algorithm
Section titled “Recommended algorithm”- Validate the 0.8.0 source.
- Set
mcpdescto0.9.0and update$schemawhen emitted. - Remove unknown annotation properties, moving server-defined metadata to
_metaonly where the protocol version defines it. - Move unknown client capability requirements into
experimentalorextensions. - Move extra fields out of completion
completionobjects. - Fix malformed
uriTemplatevalues and fractionalsizeorttlMsvalues. - Validate against the 0.9.0 JSON Schema and semantic rules, and review the new warnings.
A migration tool MUST report unresolved ambiguity instead of guessing, and
MUST NOT move a value into _meta or x-* without author review.
Conversion
Section titled “Conversion”The conversion profile implements this algorithm for tools such as the mcpcontract CLI and the mcpdesc live editor. Steps 1, 2, and 7 are automatic. Steps 3 to 6 are blockers, each reported with a conversion rule and a path:
| Step | Conversion rule | Fixes offered |
|---|---|---|
| 3 | mcpdesc.conversion.0-8-to-0-9.tool-annotations-closed, annotations-closed |
remove-property |
| 4 | mcpdesc.conversion.0-8-to-0-9.client-requirements-closed |
remove-property, move-to-experimental |
| 5 | mcpdesc.conversion.0-8-to-0-9.completion-result-closed |
remove-property |
| 6 | mcpdesc.conversion.0-8-to-0-9.uri-template-checked, integer-numbers |
none |
A fix is applied only when the author requests it. Moving a value into
_meta or x-* is never offered as a fix.