From 4be5ebb9cb19365eaeb581d2f927387f94828ab3 Mon Sep 17 00:00:00 2001 From: garvitkaushik-123 Date: Sun, 23 Aug 2026 23:47:53 +0530 Subject: [PATCH] fix(schemas): restore adcp_major_version in compact beta.0 request schemas The 3.2.0-beta.0 snapshot for buy-products, accept-proposal, and control-media-buy was cut before the source schemas gained the deprecated adcp_major_version field (#6647). Combined with additionalProperties: false, conforming SDK buyers that emit both version fields (required through 3.x per the spec) fail MCP input validation before the seller handler runs. Patches the 18 affected dist files across all beta.0 output paths (bundled, MCP, profiles, model-context) to include adcp_major_version with the same definition used in the version envelope and in all subsequent beta snapshots. Also fixes compact-version-envelope.test.cjs which encoded the bug as expected behavior, and adds two regression guards to lint-version-envelope.test.cjs: - source lint: every request schema with adcp_version must also declare adcp_major_version - dist lint: every versioned bundled dist schema must preserve both version fields Refs #6649 --- .changeset/fix-compact-version-envelope.md | 18 +++++++ .../media-buy/accept-proposal-request.json | 9 +++- .../media-buy/buy-products-request.json | 9 +++- .../media-buy/control-media-buy-request.json | 9 +++- .../media-buy/accept-proposal-request.json | 3 ++ .../media-buy/buy-products-request.json | 3 ++ .../media-buy/control-media-buy-request.json | 3 ++ .../media-buy/accept-proposal-request.json | 3 ++ .../media-buy/buy-products-request.json | 3 ++ .../media-buy/control-media-buy-request.json | 3 ++ .../media-buy/accept-proposal-request.json | 3 ++ .../media-buy/buy-products-request.json | 3 ++ .../media-buy/control-media-buy-request.json | 3 ++ .../media-buy/accept-proposal-request.json | 3 ++ .../media-buy/buy-products-request.json | 3 ++ .../media-buy/control-media-buy-request.json | 3 ++ .../media-buy/accept-proposal-request.json | 3 ++ .../media-buy/buy-products-request.json | 3 ++ .../media-buy/control-media-buy-request.json | 3 ++ tests/compact-version-envelope.test.cjs | 7 +-- tests/lint-version-envelope.test.cjs | 48 +++++++++++++++++++ 21 files changed, 136 insertions(+), 9 deletions(-) create mode 100644 .changeset/fix-compact-version-envelope.md diff --git a/.changeset/fix-compact-version-envelope.md b/.changeset/fix-compact-version-envelope.md new file mode 100644 index 0000000000..4c545a14ef --- /dev/null +++ b/.changeset/fix-compact-version-envelope.md @@ -0,0 +1,18 @@ +--- +"adcontextprotocol": patch +--- + +Restore `adcp_major_version` in compact MCP request schemas. + +The 3.2.0-beta.0 frozen snapshots for `buy-products`, `accept-proposal`, +and `control-media-buy` request schemas were published before the source +schemas gained the deprecated `adcp_major_version` field. Combined with +`additionalProperties: false`, this caused conforming SDK buyers to fail +MCP input validation when emitting both version fields (as the spec +requires through 3.x). + +Patches the 18 affected dist schema files across all beta.0 output +paths (bundled, MCP, profiles, model-context) and adds lint coverage to +prevent the same drift in future version snapshots. + +Refs #6649 diff --git a/dist/schemas/3.2.0-beta.0/bundled/media-buy/accept-proposal-request.json b/dist/schemas/3.2.0-beta.0/bundled/media-buy/accept-proposal-request.json index bc92814936..69dd3b4be4 100644 --- a/dist/schemas/3.2.0-beta.0/bundled/media-buy/accept-proposal-request.json +++ b/dist/schemas/3.2.0-beta.0/bundled/media-buy/accept-proposal-request.json @@ -39,6 +39,13 @@ "3.1-rc.1" ] }, + "adcp_major_version": { + "type": "integer", + "deprecated": true, + "description": "DEPRECATED in favor of adcp_version (release-precision string). Servers MUST continue to honor this field through 3.x. Removed in 4.0. Original semantics: the AdCP major version the buyer's payloads conform to. Sellers validate against their supported major_versions and return VERSION_UNSUPPORTED if unsupported. When omitted, the seller assumes its highest supported version.", + "minimum": 1, + "maximum": 99 + }, "idempotency_key": { "type": "string", "minLength": 16, @@ -669,4 +676,4 @@ "generatedAt": "2026-08-17T20:29:51.925Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } -} \ No newline at end of file +} diff --git a/dist/schemas/3.2.0-beta.0/bundled/media-buy/buy-products-request.json b/dist/schemas/3.2.0-beta.0/bundled/media-buy/buy-products-request.json index a260999c0e..9ab52a0abf 100644 --- a/dist/schemas/3.2.0-beta.0/bundled/media-buy/buy-products-request.json +++ b/dist/schemas/3.2.0-beta.0/bundled/media-buy/buy-products-request.json @@ -27,6 +27,13 @@ "3.1-rc.1" ] }, + "adcp_major_version": { + "type": "integer", + "deprecated": true, + "description": "DEPRECATED in favor of adcp_version (release-precision string). Servers MUST continue to honor this field through 3.x. Removed in 4.0. Original semantics: the AdCP major version the buyer's payloads conform to. Sellers validate against their supported major_versions and return VERSION_UNSUPPORTED if unsupported. When omitted, the seller assumes its highest supported version.", + "minimum": 1, + "maximum": 99 + }, "idempotency_key": { "type": "string", "minLength": 16, @@ -6899,4 +6906,4 @@ "generatedAt": "2026-08-17T20:29:52.149Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } -} \ No newline at end of file +} diff --git a/dist/schemas/3.2.0-beta.0/bundled/media-buy/control-media-buy-request.json b/dist/schemas/3.2.0-beta.0/bundled/media-buy/control-media-buy-request.json index 4e368b983d..ae07cd01b3 100644 --- a/dist/schemas/3.2.0-beta.0/bundled/media-buy/control-media-buy-request.json +++ b/dist/schemas/3.2.0-beta.0/bundled/media-buy/control-media-buy-request.json @@ -38,6 +38,13 @@ "3.1-rc.1" ] }, + "adcp_major_version": { + "type": "integer", + "deprecated": true, + "description": "DEPRECATED in favor of adcp_version (release-precision string). Servers MUST continue to honor this field through 3.x. Removed in 4.0. Original semantics: the AdCP major version the buyer's payloads conform to. Sellers validate against their supported major_versions and return VERSION_UNSUPPORTED if unsupported. When omitted, the seller assumes its highest supported version.", + "minimum": 1, + "maximum": 99 + }, "idempotency_key": { "type": "string", "minLength": 16, @@ -5708,4 +5715,4 @@ "generatedAt": "2026-08-17T20:29:52.168Z", "note": "This is a bundled schema with all $ref resolved inline. For the modular version with references, use the parent directory." } -} \ No newline at end of file +} diff --git a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/media-buy/accept-proposal-request.json b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/media-buy/accept-proposal-request.json index 9bcd0b4faa..4e6cd7f759 100644 --- a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/media-buy/accept-proposal-request.json +++ b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/media-buy/accept-proposal-request.json @@ -31,6 +31,9 @@ "adcp_version": { "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_version" }, + "adcp_major_version": { + "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_major_version" + }, "idempotency_key": { "type": "string", "minLength": 16, diff --git a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/media-buy/buy-products-request.json b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/media-buy/buy-products-request.json index 8afde7da2a..8320eff563 100644 --- a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/media-buy/buy-products-request.json +++ b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/media-buy/buy-products-request.json @@ -19,6 +19,9 @@ "adcp_version": { "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_version" }, + "adcp_major_version": { + "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_major_version" + }, "idempotency_key": { "type": "string", "minLength": 16, diff --git a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/media-buy/control-media-buy-request.json b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/media-buy/control-media-buy-request.json index 938dd40fd5..fbb667d52a 100644 --- a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/media-buy/control-media-buy-request.json +++ b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/media-buy/control-media-buy-request.json @@ -30,6 +30,9 @@ "adcp_version": { "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_version" }, + "adcp_major_version": { + "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_major_version" + }, "idempotency_key": { "type": "string", "minLength": 16, diff --git a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/media-buy/accept-proposal-request.json b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/media-buy/accept-proposal-request.json index afcc2e5264..f8d90b914b 100644 --- a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/media-buy/accept-proposal-request.json +++ b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/media-buy/accept-proposal-request.json @@ -28,6 +28,9 @@ "adcp_version": { "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_version" }, + "adcp_major_version": { + "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_major_version" + }, "idempotency_key": { "type": "string", "minLength": 16, diff --git a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/media-buy/buy-products-request.json b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/media-buy/buy-products-request.json index 83de3d009c..a7ffd9261a 100644 --- a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/media-buy/buy-products-request.json +++ b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/media-buy/buy-products-request.json @@ -16,6 +16,9 @@ "adcp_version": { "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_version" }, + "adcp_major_version": { + "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_major_version" + }, "idempotency_key": { "type": "string", "minLength": 16, diff --git a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/media-buy/control-media-buy-request.json b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/media-buy/control-media-buy-request.json index 9ecffe5328..6eac9df1b9 100644 --- a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/media-buy/control-media-buy-request.json +++ b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/media-buy/control-media-buy-request.json @@ -27,6 +27,9 @@ "adcp_version": { "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_version" }, + "adcp_major_version": { + "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_major_version" + }, "idempotency_key": { "type": "string", "minLength": 16, diff --git a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/model-context/media-buy/accept-proposal-request.json b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/model-context/media-buy/accept-proposal-request.json index 61a34ff7fe..730b61cad5 100644 --- a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/model-context/media-buy/accept-proposal-request.json +++ b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/model-context/media-buy/accept-proposal-request.json @@ -4,6 +4,9 @@ "adcp_version": { "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_version" }, + "adcp_major_version": { + "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_major_version" + }, "idempotency_key": { "type": "string" }, diff --git a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/model-context/media-buy/buy-products-request.json b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/model-context/media-buy/buy-products-request.json index 0ba94b43ed..e56719c5ef 100644 --- a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/model-context/media-buy/buy-products-request.json +++ b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/model-context/media-buy/buy-products-request.json @@ -4,6 +4,9 @@ "adcp_version": { "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_version" }, + "adcp_major_version": { + "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_major_version" + }, "idempotency_key": { "type": "string" }, diff --git a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/model-context/media-buy/control-media-buy-request.json b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/model-context/media-buy/control-media-buy-request.json index 87cf9d22ed..a1aff60fdf 100644 --- a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/model-context/media-buy/control-media-buy-request.json +++ b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/media-buy/model-context/media-buy/control-media-buy-request.json @@ -4,6 +4,9 @@ "adcp_version": { "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_version" }, + "adcp_major_version": { + "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_major_version" + }, "idempotency_key": { "type": "string" }, diff --git a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/production/media-buy/accept-proposal-request.json b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/production/media-buy/accept-proposal-request.json index b847c1a944..d09f7a14a9 100644 --- a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/production/media-buy/accept-proposal-request.json +++ b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/production/media-buy/accept-proposal-request.json @@ -28,6 +28,9 @@ "adcp_version": { "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_version" }, + "adcp_major_version": { + "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_major_version" + }, "idempotency_key": { "type": "string", "minLength": 16, diff --git a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/production/media-buy/buy-products-request.json b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/production/media-buy/buy-products-request.json index ac42673b2f..74a50be684 100644 --- a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/production/media-buy/buy-products-request.json +++ b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/production/media-buy/buy-products-request.json @@ -16,6 +16,9 @@ "adcp_version": { "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_version" }, + "adcp_major_version": { + "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_major_version" + }, "idempotency_key": { "type": "string", "minLength": 16, diff --git a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/production/media-buy/control-media-buy-request.json b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/production/media-buy/control-media-buy-request.json index 3268163f02..d8fce03881 100644 --- a/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/production/media-buy/control-media-buy-request.json +++ b/dist/schemas/3.2.0-beta.0/mcp/2026-07-28/profiles/production/media-buy/control-media-buy-request.json @@ -27,6 +27,9 @@ "adcp_version": { "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_version" }, + "adcp_major_version": { + "$ref": "#/$defs/external:core~1version-envelope.json/properties/adcp_major_version" + }, "idempotency_key": { "type": "string", "minLength": 16, diff --git a/dist/schemas/3.2.0-beta.0/media-buy/accept-proposal-request.json b/dist/schemas/3.2.0-beta.0/media-buy/accept-proposal-request.json index 3a2a367931..227d6d8746 100644 --- a/dist/schemas/3.2.0-beta.0/media-buy/accept-proposal-request.json +++ b/dist/schemas/3.2.0-beta.0/media-buy/accept-proposal-request.json @@ -31,6 +31,9 @@ "adcp_version": { "$ref": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/version-envelope.json#/properties/adcp_version" }, + "adcp_major_version": { + "$ref": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/version-envelope.json#/properties/adcp_major_version" + }, "idempotency_key": { "type": "string", "minLength": 16, diff --git a/dist/schemas/3.2.0-beta.0/media-buy/buy-products-request.json b/dist/schemas/3.2.0-beta.0/media-buy/buy-products-request.json index f6c782455f..79a284980f 100644 --- a/dist/schemas/3.2.0-beta.0/media-buy/buy-products-request.json +++ b/dist/schemas/3.2.0-beta.0/media-buy/buy-products-request.json @@ -19,6 +19,9 @@ "adcp_version": { "$ref": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/version-envelope.json#/properties/adcp_version" }, + "adcp_major_version": { + "$ref": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/version-envelope.json#/properties/adcp_major_version" + }, "idempotency_key": { "type": "string", "minLength": 16, diff --git a/dist/schemas/3.2.0-beta.0/media-buy/control-media-buy-request.json b/dist/schemas/3.2.0-beta.0/media-buy/control-media-buy-request.json index 0b7e4e1d6f..797896112c 100644 --- a/dist/schemas/3.2.0-beta.0/media-buy/control-media-buy-request.json +++ b/dist/schemas/3.2.0-beta.0/media-buy/control-media-buy-request.json @@ -30,6 +30,9 @@ "adcp_version": { "$ref": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/version-envelope.json#/properties/adcp_version" }, + "adcp_major_version": { + "$ref": "https://adcontextprotocol.org/schemas/3.2.0-beta.0/core/version-envelope.json#/properties/adcp_major_version" + }, "idempotency_key": { "type": "string", "minLength": 16, diff --git a/tests/compact-version-envelope.test.cjs b/tests/compact-version-envelope.test.cjs index 7fbee552bd..955f3bdd4a 100644 --- a/tests/compact-version-envelope.test.cjs +++ b/tests/compact-version-envelope.test.cjs @@ -10,11 +10,6 @@ const { ProtocolClient } = require('@adcp/sdk'); const SOURCE_DIR = path.resolve(__dirname, '..', 'static', 'schemas', 'source'); const ADCP_VERSION = '3.2.0-beta.0'; -const COMPACT_SCHEMAS_WITHOUT_MAJOR = new Set([ - 'buy_products', - 'accept_proposal', - 'control_media_buy', -]); function readSchema(uri) { if (!uri.startsWith('/schemas/')) { @@ -108,7 +103,7 @@ test('SDK auto version envelope passes every strict compact lifecycle request sc for (const [tool, request] of Object.entries(compactRequests)) { await ProtocolClient.callTool(agent, tool, request, { adcpVersion: ADCP_VERSION }); const expectedEnvelope = { - adcp_major_version: COMPACT_SCHEMAS_WITHOUT_MAJOR.has(tool) ? undefined : 3, + adcp_major_version: 3, adcp_version: '3.2-beta.0', }; assert.deepEqual({ diff --git a/tests/lint-version-envelope.test.cjs b/tests/lint-version-envelope.test.cjs index aa592bdf17..cf48a9b5f3 100644 --- a/tests/lint-version-envelope.test.cjs +++ b/tests/lint-version-envelope.test.cjs @@ -117,3 +117,51 @@ test('release-precision version grammar stays aligned across inlined negotiation ); assert.equal(versionPatternCheck?.pattern, canonicalPattern); }); + +test('every source request schema with adcp_version also has adcp_major_version', () => { + const violations = []; + for (const file of listJsonFiles(SOURCE_DIR)) { + if (!file.endsWith('-request.json')) continue; + let schema; + try { schema = JSON.parse(fs.readFileSync(file, 'utf8')); } catch { continue; } + if (!schema.properties) continue; + const hasVersion = 'adcp_version' in schema.properties; + const hasMajor = 'adcp_major_version' in schema.properties; + if (hasVersion && !hasMajor) { + violations.push(path.relative(path.resolve(__dirname, '..'), file)); + } + } + assert.deepEqual( + violations, + [], + 'Request schemas that declare adcp_version MUST also declare ' + + 'adcp_major_version (deprecated but required through 3.x). ' + + 'Missing in:\n' + violations.map((v) => ` ${v}`).join('\n'), + ); +}); + +const DIST_DIR = path.resolve(__dirname, '..', 'dist', 'schemas'); + +test('every versioned dist request schema with adcp_version also has adcp_major_version', () => { + if (!fs.existsSync(DIST_DIR)) return; + const violations = []; + for (const ver of fs.readdirSync(DIST_DIR).filter((d) => d.match(/^\d/))) { + const bundled = path.join(DIST_DIR, ver, 'bundled'); + if (!fs.existsSync(bundled)) continue; + for (const file of listJsonFiles(bundled)) { + if (!file.endsWith('-request.json')) continue; + let schema; + try { schema = JSON.parse(fs.readFileSync(file, 'utf8')); } catch { continue; } + if (!schema.properties) continue; + if ('adcp_version' in schema.properties && !('adcp_major_version' in schema.properties)) { + violations.push(path.relative(path.resolve(__dirname, '..'), file)); + } + } + } + assert.deepEqual( + violations, + [], + 'Versioned bundled dist schemas must preserve adcp_major_version alongside ' + + 'adcp_version. Missing in:\n' + violations.map((v) => ` ${v}`).join('\n'), + ); +});