@mcpdesc/validator 0.9.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -1
- package/README.md +21 -26
- package/index.d.ts +9 -28
- package/package.json +3 -2
- package/src/index.js +15 -20
- package/src/snapshots/0.8.0-rc.2/semantic.js +21 -9
- package/src/snapshots/{0.8.0-draft.4 → 0.8.0-rc.3}/base.js +28 -8
- package/src/snapshots/{0.8.0-rc.1 → 0.8.0-rc.3}/index.js +3 -3
- package/src/snapshots/{0.8.0-rc.1 → 0.8.0-rc.3}/schema.json +2213 -2213
- package/src/snapshots/{0.8.0-rc.1 → 0.8.0-rc.3}/semantic.js +16 -5
- package/standalone.js +1 -1
- package/src/snapshots/0.8.0-draft.1/index.js +0 -69
- package/src/snapshots/0.8.0-draft.1/schema.json +0 -1648
- package/src/snapshots/0.8.0-draft.1/semantic.js +0 -1397
- package/src/snapshots/0.8.0-draft.2/base.js +0 -1397
- package/src/snapshots/0.8.0-draft.2/index.js +0 -17
- package/src/snapshots/0.8.0-draft.2/schema.json +0 -2161
- package/src/snapshots/0.8.0-draft.2/semantic.js +0 -446
- package/src/snapshots/0.8.0-draft.3/base.js +0 -1397
- package/src/snapshots/0.8.0-draft.3/index.js +0 -17
- package/src/snapshots/0.8.0-draft.3/schema.json +0 -2031
- package/src/snapshots/0.8.0-draft.3/semantic.js +0 -401
- package/src/snapshots/0.8.0-draft.4/index.js +0 -17
- package/src/snapshots/0.8.0-draft.4/schema.json +0 -2820
- package/src/snapshots/0.8.0-draft.4/semantic.js +0 -960
- package/src/snapshots/0.8.0-rc.1/base.js +0 -1397
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,34 @@ Dates for published releases are the UTC publication dates recorded by npm.
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [0.10.1] - 2026-09-07
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Narrowed active runtime support to RC.2 and RC.3 and marked RC.2 deprecated.
|
|
16
|
+
- Excluded retired runtime snapshots from generated bundles and package
|
|
17
|
+
contents while retaining their source and frozen fixtures in Git.
|
|
18
|
+
- Removed the retained snapshot-intake manifest; intake bundles are disposable
|
|
19
|
+
inputs and imported bytes remain protected by the snapshot integrity manifest.
|
|
20
|
+
|
|
21
|
+
## [0.10.0] - 2026-09-07
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- Added the immutable `0.8.0-rc.3` selector with behavior equivalent to RC.2,
|
|
26
|
+
its RC.3 schema identity, and frozen fixtures.
|
|
27
|
+
- Added component reference resolution for RC.2 and RC.3 with deterministic
|
|
28
|
+
terminal-target provenance.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- Validator integrity now relies on package-owned schema, runtime, fixture, and
|
|
33
|
+
package bytes. Specification repository tags and commits are retained only as
|
|
34
|
+
informational provenance.
|
|
35
|
+
- Recorded maintainer-approved additive provenance corrections to the RC.2 and
|
|
36
|
+
RC.3 snapshot implementations. Their schemas, conformance results,
|
|
37
|
+
diagnostics, and frozen fixtures remain unchanged.
|
|
38
|
+
|
|
11
39
|
## [0.9.0] - 2026-09-04
|
|
12
40
|
|
|
13
41
|
### Added
|
|
@@ -111,7 +139,9 @@ Dates for published releases are the UTC publication dates recorded by npm.
|
|
|
111
139
|
- Added synchronous structural and semantic validation for parsed JavaScript values with deterministic diagnostics and exact selector dispatch.
|
|
112
140
|
- Added ESM browser support, TypeScript declarations, embedded schema provenance, frozen fixtures, and package-content checks.
|
|
113
141
|
|
|
114
|
-
[Unreleased]: https://github.com/mcpdesc/core/compare/validator-v0.
|
|
142
|
+
[Unreleased]: https://github.com/mcpdesc/core/compare/validator-v0.10.1...HEAD
|
|
143
|
+
[0.10.1]: https://github.com/mcpdesc/core/compare/validator-v0.10.0...validator-v0.10.1
|
|
144
|
+
[0.10.0]: https://github.com/mcpdesc/core/compare/validator-v0.9.0...validator-v0.10.0
|
|
115
145
|
[0.9.0]: https://github.com/mcpdesc/core/compare/validator-v0.8.0...validator-v0.9.0
|
|
116
146
|
[0.8.0]: https://github.com/mcpdesc/core/compare/validator-v0.7.1...validator-v0.8.0
|
|
117
147
|
[0.7.1]: https://github.com/mcpdesc/core/compare/validator-v0.7.0...validator-v0.7.1
|
package/README.md
CHANGED
|
@@ -44,16 +44,18 @@ a later draft is published.
|
|
|
44
44
|
|
|
45
45
|
## Supported snapshots
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
The package supports these immutable selectors, newest first:
|
|
48
48
|
|
|
49
|
-
| Selector |
|
|
49
|
+
| Selector | First validator release | Embedded schema SHA-256 |
|
|
50
50
|
|---|---|---|
|
|
51
|
-
| `0.8.0-rc.
|
|
52
|
-
| `0.8.0-rc.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
| `0.8.0-rc.3` | `0.10.0` | `a9c3ff77ba37c72362909f538f6e957d055e6fdb372f8b3d529e3651af3fecf4` |
|
|
52
|
+
| `0.8.0-rc.2` (deprecated) | `0.9.0` | `40f6775dde052224114e91d6aa484d826eecf56b77f7ac87b4cf707ffbcb6ce8` |
|
|
53
|
+
|
|
54
|
+
The validator package embeds the schema and executable behavior for each
|
|
55
|
+
selector. RC.2 remains available for migration compatibility; new integrations
|
|
56
|
+
should select RC.3. Earlier selectors remain available by pinning an older
|
|
57
|
+
immutable validator release. npm integrity and trusted-publishing provenance identify released
|
|
58
|
+
package bytes; specification repository tags and commits are informational.
|
|
57
59
|
|
|
58
60
|
## Usage
|
|
59
61
|
|
|
@@ -95,17 +97,10 @@ if (resolution.status === 'resolved') {
|
|
|
95
97
|
|
|
96
98
|
Resolution is pure and performs no network retrieval. It does not validate the
|
|
97
99
|
document and never infers a draft snapshot from `mcpdesc: "0.8.0"` alone.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
ambiguous unless the caller supplies a consistent exact selector:
|
|
101
|
-
|
|
102
|
-
```js
|
|
103
|
-
const resolution = resolveMcpDescriptionSpecification(parsedDocument, {
|
|
104
|
-
specification: '0.8.0-draft.3'
|
|
105
|
-
});
|
|
106
|
-
```
|
|
100
|
+
Retired schema identities are reported as unknown by current releases. Pin an
|
|
101
|
+
older package release to resolve or validate a retired selector.
|
|
107
102
|
|
|
108
|
-
Unresolved results distinguish missing, invalid, unknown,
|
|
103
|
+
Unresolved results distinguish missing, invalid, unknown, and
|
|
109
104
|
contradictory identity, as well as unsupported caller selectors. A supplied
|
|
110
105
|
selector can resolve a document with no `$schema`; when `$schema` is present it
|
|
111
106
|
must match the selected snapshot's recorded schema URI.
|
|
@@ -132,9 +127,9 @@ Structural paths start with AJV's instance path. A `required` error appends its
|
|
|
132
127
|
|
|
133
128
|
## Support metadata
|
|
134
129
|
|
|
135
|
-
The package exports frozen `supportedSpecifications`, `supportedProtocolVersions`, and `specificationProvenance` values. Provenance records include the snapshot tag, recorded schema URI, and embedded schema SHA-256 digest. Public validation dispatches through a registry keyed by exact specification selectors. The
|
|
130
|
+
The package exports frozen `supportedSpecifications`, `deprecatedSpecifications`, `supportedProtocolVersions`, and `specificationProvenance` values. Provenance records include the snapshot tag, recorded schema URI, and embedded schema SHA-256 digest. Public validation dispatches through a registry keyed by exact specification selectors. The active selector set is `0.8.0-rc.2` and `0.8.0-rc.3`; `deprecatedSpecifications` contains RC.2. The protocol-version export is the deduplicated union supported by active snapshots.
|
|
136
131
|
|
|
137
|
-
RC.2 also
|
|
132
|
+
RC.2 and RC.3 also export the frozen `mcpExtensionCatalogue` and
|
|
138
133
|
`mcpExtensionMaturity` classifier. The catalogue pins its authoritative source,
|
|
139
134
|
effective date, and official or experimental identifier assignments. Catalogue
|
|
140
135
|
recognition establishes authority and maturity only; it does not validate
|
|
@@ -142,10 +137,10 @@ extension-specific settings.
|
|
|
142
137
|
|
|
143
138
|
npm package SemVer tracks implementation releases independently from specification snapshot identity. Adding a later snapshot is additive: it must use a sibling implementation and selector rather than changing an existing snapshot's schema, semantics, metadata, fixtures, or results.
|
|
144
139
|
|
|
145
|
-
The RC.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
140
|
+
The RC.2 and RC.3 component resolvers report authored and terminal target
|
|
141
|
+
paths for successful substitutions. The additive tooling corrections do not
|
|
142
|
+
change snapshot schemas, validation results, diagnostics, or fixtures and are
|
|
143
|
+
recorded in the integrity manifest.
|
|
149
144
|
|
|
150
145
|
The runtime bundles its schema, performs no network fetches for external schema references, and imports no Node.js built-ins. Unresolved external Tool-schema references produce incomplete-validation warnings and are preserved. All three ESM entry points support Node.js 20 or later and browser bundlers.
|
|
151
146
|
|
|
@@ -159,7 +154,7 @@ exact specification repository tag or commit and then:
|
|
|
159
154
|
3. Add the exact selector to the runtime registry and update support metadata, TypeScript declarations, tests, the package changelog, and expected package contents. Unqualified versions, aliases, ranges, and not-yet-published selectors remain unsupported.
|
|
160
155
|
4. Run the package and repository validation suites. The schema digest, immutable metadata, fixture behavior, browser bundle, declarations, and tarball contents must all pass.
|
|
161
156
|
|
|
162
|
-
The test snapshots are repository-only development assets and are excluded from the npm tarball.
|
|
157
|
+
The test snapshots are repository-only development assets and are excluded from the npm tarball. Historical runtime sources remain in Git for integrity history. Only active runtime snapshot implementations and embedded schemas ship, so installed packages remain self-contained without accumulating retired selectors.
|
|
163
158
|
|
|
164
159
|
Specification approval and imported supporting code do not authorize package
|
|
165
160
|
publication. During release review, a maintainer explicitly decides the
|
|
@@ -182,4 +177,4 @@ npm run test:browser --workspace @mcpdesc/validator
|
|
|
182
177
|
npm run test:package --workspace @mcpdesc/validator
|
|
183
178
|
```
|
|
184
179
|
|
|
185
|
-
The package test runs each
|
|
180
|
+
The package test runs each active snapshot against its own frozen valid, invalid, and warning fixture corpus and verifies historical artifact integrity separately. YAML source fixtures are decoded by the test harness before validation; the public API continues to accept parsed JavaScript values only. The other checks compile the declarations, bundle the public browser entry with esbuild and Vite, reject runtime AJV compiler inputs and dynamic code generation in those bundles, and inspect `npm pack --dry-run --json` against the intended tarball contents and declared export targets.
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type McpDescriptionSpecification = '0.8.0-
|
|
1
|
+
export type McpDescriptionSpecification = '0.8.0-rc.2' | '0.8.0-rc.3';
|
|
2
2
|
|
|
3
3
|
export type SupportedProtocolVersion =
|
|
4
4
|
| '2024-11-05'
|
|
@@ -38,7 +38,7 @@ export interface McpDescriptionComponentResolutionResult {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export interface ResolveMcpDescriptionComponentReferencesOptions {
|
|
41
|
-
readonly specification: '0.8.0-rc.
|
|
41
|
+
readonly specification: '0.8.0-rc.2' | '0.8.0-rc.3';
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
export type McpExtensionMaturity = 'official' | 'experimental' | 'uncatalogued';
|
|
@@ -56,36 +56,16 @@ export interface McpExtensionCatalogue {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
export interface SpecificationProvenance {
|
|
59
|
-
readonly '0.8.0-draft.1': {
|
|
60
|
-
readonly snapshotTag: 'v0.8.0-draft.1';
|
|
61
|
-
readonly schemaUri: 'https://mcpdesc.org/schema/0.8.0.json';
|
|
62
|
-
readonly schemaSha256: '4ceb6042c3fd31703199cd3db869ec5c35c17d2fe9ab7b2f5b96a2a3af0cebe4';
|
|
63
|
-
};
|
|
64
|
-
readonly '0.8.0-draft.2': {
|
|
65
|
-
readonly snapshotTag: 'v0.8.0-draft.2';
|
|
66
|
-
readonly schemaUri: 'https://mcpdesc.org/schema/0.8.0.json';
|
|
67
|
-
readonly schemaSha256: 'ab692c1a5a0f7e5f29be1940aa8c64a56d4620be0a19d00cf0a64680b7e517fa';
|
|
68
|
-
};
|
|
69
|
-
readonly '0.8.0-draft.3': {
|
|
70
|
-
readonly snapshotTag: 'v0.8.0-draft.3';
|
|
71
|
-
readonly schemaUri: 'https://mcpdesc.org/schema/0.8.0.json';
|
|
72
|
-
readonly schemaSha256: '8823c1f1946360b2a44d00920e2092e5e4acd139a1964befad4eb0bf3ce96002';
|
|
73
|
-
};
|
|
74
|
-
readonly '0.8.0-draft.4': {
|
|
75
|
-
readonly snapshotTag: 'v0.8.0-draft.4';
|
|
76
|
-
readonly schemaUri: 'https://mcpdesc.org/schema/mcp-description/0.8.0-draft.4.json';
|
|
77
|
-
readonly schemaSha256: '93ed03f74059b5b3ce7509a96b59161bdab2c3cf7734397a9bec5a7588d0b03b';
|
|
78
|
-
};
|
|
79
|
-
readonly '0.8.0-rc.1': {
|
|
80
|
-
readonly snapshotTag: 'v0.8.0-rc.1';
|
|
81
|
-
readonly schemaUri: 'https://mcpdesc.org/schema/mcp-description/0.8.0-rc.1.json';
|
|
82
|
-
readonly schemaSha256: '936a0f24ade501fcabf3d6498c0440c445daa672a575573a35954cee49430ac4';
|
|
83
|
-
};
|
|
84
59
|
readonly '0.8.0-rc.2': {
|
|
85
60
|
readonly snapshotTag: 'v0.8.0-rc.2';
|
|
86
61
|
readonly schemaUri: 'https://mcpdesc.org/schema/mcp-description/0.8.0-rc.2.json';
|
|
87
62
|
readonly schemaSha256: '40f6775dde052224114e91d6aa484d826eecf56b77f7ac87b4cf707ffbcb6ce8';
|
|
88
63
|
};
|
|
64
|
+
readonly '0.8.0-rc.3': {
|
|
65
|
+
readonly snapshotTag: 'v0.8.0-rc.3';
|
|
66
|
+
readonly schemaUri: 'https://mcpdesc.org/schema/mcp-description/0.8.0-rc.3.json';
|
|
67
|
+
readonly schemaSha256: 'a9c3ff77ba37c72362909f538f6e957d055e6fdb372f8b3d529e3651af3fecf4';
|
|
68
|
+
};
|
|
89
69
|
}
|
|
90
70
|
|
|
91
71
|
export interface ResolveMcpDescriptionSpecificationOptions {
|
|
@@ -109,7 +89,8 @@ export type McpDescriptionSpecificationResolution =
|
|
|
109
89
|
| ResolvedMcpDescriptionSpecification
|
|
110
90
|
| UnresolvedMcpDescriptionSpecification;
|
|
111
91
|
|
|
112
|
-
export declare const supportedSpecifications: readonly ['0.8.0-
|
|
92
|
+
export declare const supportedSpecifications: readonly ['0.8.0-rc.2', '0.8.0-rc.3'];
|
|
93
|
+
export declare const deprecatedSpecifications: readonly ['0.8.0-rc.2'];
|
|
113
94
|
|
|
114
95
|
export declare const supportedProtocolVersions: readonly [
|
|
115
96
|
'2024-11-05',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcpdesc/validator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Structural and semantic validation for MCP Description snapshots",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./index.d.ts",
|
|
@@ -31,7 +31,8 @@
|
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"src/index.js",
|
|
34
|
-
"src/snapshots",
|
|
34
|
+
"src/snapshots/0.8.0-rc.2",
|
|
35
|
+
"src/snapshots/0.8.0-rc.3",
|
|
35
36
|
"standalone.js",
|
|
36
37
|
"index.d.ts",
|
|
37
38
|
"CHANGELOG.md",
|
package/src/index.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import * as draft1 from './snapshots/0.8.0-draft.1/index.js';
|
|
2
|
-
import * as draft2 from './snapshots/0.8.0-draft.2/index.js';
|
|
3
|
-
import * as draft3 from './snapshots/0.8.0-draft.3/index.js';
|
|
4
|
-
import * as draft4 from './snapshots/0.8.0-draft.4/index.js';
|
|
5
|
-
import * as rc1 from './snapshots/0.8.0-rc.1/index.js';
|
|
6
1
|
import * as rc2 from './snapshots/0.8.0-rc.2/index.js';
|
|
7
|
-
import
|
|
2
|
+
import * as rc3 from './snapshots/0.8.0-rc.3/index.js';
|
|
3
|
+
import { resolveComponentReferences as resolveRc2ComponentReferences } from './snapshots/0.8.0-rc.2/semantic.js';
|
|
4
|
+
import { resolveComponentReferences as resolveRc3ComponentReferences } from './snapshots/0.8.0-rc.3/semantic.js';
|
|
8
5
|
import {
|
|
9
6
|
mcpExtensionCatalogue,
|
|
10
7
|
mcpExtensionMaturity
|
|
@@ -13,24 +10,22 @@ import {
|
|
|
13
10
|
export { mcpExtensionCatalogue, mcpExtensionMaturity };
|
|
14
11
|
|
|
15
12
|
const snapshots = Object.freeze({
|
|
16
|
-
[
|
|
17
|
-
[
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
[rc2.specification]: rc2,
|
|
14
|
+
[rc3.specification]: rc3
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const componentResolvers = Object.freeze({
|
|
18
|
+
'0.8.0-rc.2': resolveRc2ComponentReferences,
|
|
19
|
+
'0.8.0-rc.3': resolveRc3ComponentReferences
|
|
22
20
|
});
|
|
23
21
|
|
|
24
22
|
const schemaUris = Object.freeze({
|
|
25
|
-
'0.8.0-
|
|
26
|
-
'0.8.0-
|
|
27
|
-
'0.8.0-draft.3': 'https://mcpdesc.org/schema/0.8.0.json',
|
|
28
|
-
'0.8.0-draft.4': 'https://mcpdesc.org/schema/mcp-description/0.8.0-draft.4.json',
|
|
29
|
-
'0.8.0-rc.1': 'https://mcpdesc.org/schema/mcp-description/0.8.0-rc.1.json',
|
|
30
|
-
'0.8.0-rc.2': 'https://mcpdesc.org/schema/mcp-description/0.8.0-rc.2.json'
|
|
23
|
+
'0.8.0-rc.2': 'https://mcpdesc.org/schema/mcp-description/0.8.0-rc.2.json',
|
|
24
|
+
'0.8.0-rc.3': 'https://mcpdesc.org/schema/mcp-description/0.8.0-rc.3.json'
|
|
31
25
|
});
|
|
32
26
|
|
|
33
27
|
export const supportedSpecifications = Object.freeze(Object.keys(snapshots));
|
|
28
|
+
export const deprecatedSpecifications = Object.freeze(['0.8.0-rc.2']);
|
|
34
29
|
export const supportedProtocolVersions = Object.freeze([
|
|
35
30
|
...new Set(Object.values(snapshots).flatMap((snapshot) => snapshot.supportedProtocolVersions))
|
|
36
31
|
]);
|
|
@@ -158,9 +153,9 @@ export function resolveMcpDescriptionComponentReferences(document, options) {
|
|
|
158
153
|
if (!options || typeof options !== 'object' || Array.isArray(options) || !Object.hasOwn(options, 'specification')) {
|
|
159
154
|
throw new TypeError('options.specification is required');
|
|
160
155
|
}
|
|
161
|
-
if (options.specification
|
|
156
|
+
if (!Object.hasOwn(componentResolvers, options.specification)) {
|
|
162
157
|
throw new RangeError(`Component reference resolution does not support specification: ${String(options.specification)}`);
|
|
163
158
|
}
|
|
164
159
|
|
|
165
|
-
return
|
|
160
|
+
return componentResolvers[options.specification](document);
|
|
166
161
|
}
|
|
@@ -62,6 +62,7 @@ function componentDiagnostic(code, rel, message, path) {
|
|
|
62
62
|
export function resolveComponentReferences(document, rel = 'document') {
|
|
63
63
|
const resolved = structuredClone(document);
|
|
64
64
|
const diagnostics = [];
|
|
65
|
+
const provenance = [];
|
|
65
66
|
let substitutions = 0;
|
|
66
67
|
|
|
67
68
|
function resolve(reference, expectedNamespace, path, stack = []) {
|
|
@@ -75,7 +76,7 @@ export function resolveComponentReferences(document, rel = 'document') {
|
|
|
75
76
|
`must target #/components/${expectedNamespace}, not #/components/${namespace}`,
|
|
76
77
|
path
|
|
77
78
|
));
|
|
78
|
-
return reference;
|
|
79
|
+
return { value: reference };
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
const key = `${namespace}/${name}`;
|
|
@@ -86,7 +87,7 @@ export function resolveComponentReferences(document, rel = 'document') {
|
|
|
86
87
|
`forms a cycle through ${[...stack, key].join(' -> ')}`,
|
|
87
88
|
path
|
|
88
89
|
));
|
|
89
|
-
return reference;
|
|
90
|
+
return { value: reference };
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
const target = document?.components?.[namespace]?.[name];
|
|
@@ -97,18 +98,29 @@ export function resolveComponentReferences(document, rel = 'document') {
|
|
|
97
98
|
`targets missing component ${JSON.stringify(reference.$componentRef)}`,
|
|
98
99
|
path
|
|
99
100
|
));
|
|
100
|
-
return reference;
|
|
101
|
+
return { value: reference };
|
|
101
102
|
}
|
|
102
103
|
substitutions += 1;
|
|
103
104
|
return isReferenceObject(target)
|
|
104
105
|
? resolve(target, expectedNamespace, path, [...stack, key])
|
|
105
|
-
:
|
|
106
|
+
: {
|
|
107
|
+
value: structuredClone(target),
|
|
108
|
+
targetPath: ['components', namespace, name]
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function substitute(reference, expectedNamespace, path, stack = []) {
|
|
113
|
+
const result = resolve(reference, expectedNamespace, path, stack);
|
|
114
|
+
if (result.targetPath) {
|
|
115
|
+
provenance.push({ referencePath: path, targetPath: result.targetPath });
|
|
116
|
+
}
|
|
117
|
+
return result.value;
|
|
106
118
|
}
|
|
107
119
|
|
|
108
120
|
for (const namespace of componentNamespaces) {
|
|
109
121
|
for (const [name, value] of Object.entries(document?.components?.[namespace] ?? {})) {
|
|
110
122
|
if (isReferenceObject(value)) {
|
|
111
|
-
resolved.components[namespace][name] =
|
|
123
|
+
resolved.components[namespace][name] = substitute(value, namespace, ['components', namespace, name], [`${namespace}/${name}`]);
|
|
112
124
|
}
|
|
113
125
|
}
|
|
114
126
|
}
|
|
@@ -124,7 +136,7 @@ export function resolveComponentReferences(document, rel = 'document') {
|
|
|
124
136
|
if (collection === 'tools') {
|
|
125
137
|
for (const field of ['inputSchema', 'outputSchema']) {
|
|
126
138
|
if (isReferenceObject(declaration[field])) {
|
|
127
|
-
resolvedDeclaration[field] =
|
|
139
|
+
resolvedDeclaration[field] = substitute(declaration[field], 'schemas', [collection, declarationIndex, field]);
|
|
128
140
|
}
|
|
129
141
|
}
|
|
130
142
|
}
|
|
@@ -138,7 +150,7 @@ export function resolveComponentReferences(document, rel = 'document') {
|
|
|
138
150
|
: 'promptExamples';
|
|
139
151
|
for (const [name, example] of Object.entries(declaration.examples ?? {})) {
|
|
140
152
|
if (isReferenceObject(example)) {
|
|
141
|
-
resolvedDeclaration.examples[name] =
|
|
153
|
+
resolvedDeclaration.examples[name] = substitute(
|
|
142
154
|
example,
|
|
143
155
|
exampleNamespace,
|
|
144
156
|
[collection, declarationIndex, 'examples', name]
|
|
@@ -152,7 +164,7 @@ export function resolveComponentReferences(document, rel = 'document') {
|
|
|
152
164
|
for (const [declarationIndex, declaration] of (document?.[collection] ?? []).entries()) {
|
|
153
165
|
for (const [elicitationIndex, elicitation] of (declaration.elicitations ?? []).entries()) {
|
|
154
166
|
if (isReferenceObject(elicitation.requestedSchema)) {
|
|
155
|
-
resolved[collection][declarationIndex].elicitations[elicitationIndex].requestedSchema =
|
|
167
|
+
resolved[collection][declarationIndex].elicitations[elicitationIndex].requestedSchema = substitute(
|
|
156
168
|
elicitation.requestedSchema,
|
|
157
169
|
'schemas',
|
|
158
170
|
[collection, declarationIndex, 'elicitations', elicitationIndex, 'requestedSchema']
|
|
@@ -162,7 +174,7 @@ export function resolveComponentReferences(document, rel = 'document') {
|
|
|
162
174
|
}
|
|
163
175
|
}
|
|
164
176
|
|
|
165
|
-
return { document: resolved, diagnostics, substitutions };
|
|
177
|
+
return { document: resolved, diagnostics, substitutions, provenance };
|
|
166
178
|
}
|
|
167
179
|
|
|
168
180
|
function structuralPath(document, error) {
|
|
@@ -23,11 +23,25 @@ export const supportedProtocolVersions = Object.freeze([
|
|
|
23
23
|
const protocolOrder = new Map(supportedProtocolVersions.map((version, index) => [version, index]));
|
|
24
24
|
const toolSchemaDialectVersion = '2025-11-25';
|
|
25
25
|
const completeSemanticConformanceVersion = '2025-06-18';
|
|
26
|
-
const
|
|
27
|
-
'
|
|
28
|
-
|
|
26
|
+
export const mcpExtensionCatalogue = Object.freeze({
|
|
27
|
+
effectiveDate: '2026-09-04',
|
|
28
|
+
source: 'https://modelcontextprotocol.io/extensions/overview',
|
|
29
|
+
officialIdentifiers: Object.freeze([
|
|
30
|
+
'io.modelcontextprotocol/enterprise-managed-authorization',
|
|
31
|
+
'io.modelcontextprotocol/oauth-client-credentials',
|
|
32
|
+
'io.modelcontextprotocol/tasks',
|
|
33
|
+
'io.modelcontextprotocol/ui'
|
|
34
|
+
]),
|
|
35
|
+
experimentalIdentifiers: Object.freeze([])
|
|
36
|
+
});
|
|
29
37
|
const metaKeyPattern = /^(?:(?:[A-Za-z](?:[A-Za-z0-9-]*[A-Za-z0-9])?)(?:\.[A-Za-z](?:[A-Za-z0-9-]*[A-Za-z0-9])?)*\/)?(?:[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?)?$/;
|
|
30
38
|
|
|
39
|
+
export function mcpExtensionMaturity(identifier) {
|
|
40
|
+
if (mcpExtensionCatalogue.officialIdentifiers.includes(identifier)) return 'official';
|
|
41
|
+
if (mcpExtensionCatalogue.experimentalIdentifiers.includes(identifier)) return 'experimental';
|
|
42
|
+
return 'uncatalogued';
|
|
43
|
+
}
|
|
44
|
+
|
|
31
45
|
function createValidatorForDialect(dialect) {
|
|
32
46
|
const Factory = dialect === '2020-12' ? Ajv2020 : Ajv;
|
|
33
47
|
const instance = new Factory({ allErrors: true, strict: false });
|
|
@@ -785,20 +799,26 @@ function validateVersionSpecificSemantics(document, rel, diagnostics) {
|
|
|
785
799
|
diagnostics.push(
|
|
786
800
|
makeDiagnostic(
|
|
787
801
|
'extensions-not-supported-by-version',
|
|
788
|
-
'
|
|
789
|
-
`capabilities[${index}].extensions is not defined
|
|
802
|
+
'warning',
|
|
803
|
+
`capabilities[${index}].extensions is not defined by the MCP ${version} core schema; this description preserves a deployed pre-standard extension negotiation convention. Formal extensions capability negotiation was introduced in MCP 2026-07-28`,
|
|
790
804
|
[...capabilityPath, 'extensions']
|
|
791
805
|
)
|
|
792
806
|
);
|
|
793
807
|
}
|
|
794
808
|
}
|
|
795
809
|
for (const identifier of Object.keys(capability.extensions ?? {})) {
|
|
796
|
-
if (!usesMcpReservedPrefix(identifier)
|
|
810
|
+
if (!usesMcpReservedPrefix(identifier)) continue;
|
|
811
|
+
const maturity = mcpExtensionMaturity(identifier);
|
|
812
|
+
if (maturity === 'official') continue;
|
|
797
813
|
diagnostics.push(
|
|
798
814
|
makeDiagnostic(
|
|
799
|
-
'
|
|
815
|
+
maturity === 'experimental'
|
|
816
|
+
? 'experimental-reserved-extension-identifier'
|
|
817
|
+
: 'unknown-reserved-extension-identifier',
|
|
800
818
|
'warning',
|
|
801
|
-
|
|
819
|
+
maturity === 'experimental'
|
|
820
|
+
? `capabilities[${index}].extensions contains experimental MCP extension ${JSON.stringify(identifier)}; preserve it and review its maturity before relying on it`
|
|
821
|
+
: `capabilities[${index}].extensions contains unrecognized identifier ${JSON.stringify(identifier)} under an MCP-reserved prefix; preserve it and review its authority`,
|
|
802
822
|
[...capabilityPath, 'extensions', identifier]
|
|
803
823
|
)
|
|
804
824
|
);
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
validateMcpdesc08Document
|
|
4
4
|
} from './semantic.js';
|
|
5
5
|
|
|
6
|
-
export const specification = '0.8.0-rc.
|
|
7
|
-
export const snapshotTag = 'v0.8.0-rc.
|
|
8
|
-
export const schemaSha256 = '
|
|
6
|
+
export const specification = '0.8.0-rc.3';
|
|
7
|
+
export const snapshotTag = 'v0.8.0-rc.3';
|
|
8
|
+
export const schemaSha256 = 'a9c3ff77ba37c72362909f538f6e957d055e6fdb372f8b3d529e3651af3fecf4';
|
|
9
9
|
export { supportedProtocolVersions };
|
|
10
10
|
|
|
11
11
|
export function validate(document) {
|