Conversation
b7738b6 to
6268658
Compare
6268658 to
f8a0257
Compare
f8a0257 to
71faa9b
Compare
71faa9b to
e96a3af
Compare
e96a3af to
4f38fbb
Compare
4f38fbb to
7fb7dbc
Compare
7fb7dbc to
6ce8e7b
Compare
6ce8e7b to
ab44722
Compare
ab44722 to
59d36ee
Compare
59d36ee to
1c99b15
Compare
1c99b15 to
7a66678
Compare
7a66678 to
a25fce9
Compare
5f489a3 to
349550c
Compare
ccfd25e to
a365c74
Compare
a365c74 to
ac85c6d
Compare
ac85c6d to
f94ea8c
Compare
f94ea8c to
430cbe5
Compare
430cbe5 to
eb5a3c3
Compare
eb5a3c3 to
92c96ed
Compare
92c96ed to
1daa134
Compare
c00f24a to
e26485d
Compare
e26485d to
fb396c2
Compare
fb396c2 to
ca14510
Compare
ca14510 to
e2dbb4b
Compare
4 tasks
Adds a one-line curated lead-in above the auto-generated ### Patch Changes section pointing at release-notes.mdx for the narrative. Matches the 3.0.0 convention where CHANGELOG.md is the per-PR detail and release-notes.mdx is the curated story. Side effect: pushing this from a human identity fires the required CI checks on the Version Packages PR. The bot's GITHUB_TOKEN-based push doesn't trigger workflows (GitHub blocks recursive workflow runs from GITHUB_TOKEN), which is why CI was stuck pending. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
adcontextprotocol@3.0.1
Patch Changes
10aa2b3: Cut 3.0.1 to ship
skills/in the protocol tarball and fix path drift inskills/call-adcp-agent/SKILL.md. Closes release: re-cut 3.0.0 tarball with skills/ + manifest.contents.skills #3116, skills: call-adcp-agent references dist/schemas/ paths that don't exist for SDK consumers #3117.Why a patch bump (not a re-cut at 3.0.0): the protocol tarball is the SDK distribution surface.
3.0.0.tgzwas published 2026-04-22, before feat(skills): hoist call-adcp-agent + bundle skills/ into protocol tarball #3097 hoistedskills/. Re-cutting at the same version would mean a new SHA-256 at the same stable URL — incompatible with content-addressed pipelines, supply-chain attestations, and the cosign signature bound to the original content. Pre-merge expert review (protocol + security) recommended bumping to preserve immutability and produce a fresh signed release through the normalrelease.ymlpath.What's in 3.0.1:
skills/bundled in/protocol/3.0.1.tgz(the seven protocol-managed skills:call-adcp-agent+ the per-protocoladcp-{brand,creative,governance,media-buy,si,signals})manifest.contents.skillsenumerated for SDK sync scripts to detectskills/call-adcp-agent/SKILL.md— replace four hardcodeddist/schemas/<version>/bundled/...references with discovery-first phrasing that doesn't assume an SDK layoutdocs/protocol/calling-an-agent.mdx— sister content fixWhat does NOT change: every schema, every task definition, every wire-format detail in 3.0.0 carries over identically to 3.0.1. The bump is for the bundle/skill axis, not the protocol-spec axis.
SDK action: bump
ADCP_VERSIONfrom3.0.0to3.0.1to receive the canonical skills via your existing sync flow. JS-side wiring is in adcontextprotocol/adcp-client#965; Python and Go follow-ups tracked in adcp-client-python#274 and adcp-go#91.a7dbe65: docs(brand): specify normative request-validation clauses for
acquire_rights(closes acquire_rights: CPM governance projection is unspecified — implementers will disagree on cost estimate #2680, acquire_rights: expired-campaign-dates rejection is sensible but unspecified #2681)Two campaign-field validations on
acquire_rightswere sensible-but-unspecified in 3.0, leaving implementers to disagree on identical requests:Expired campaign window. Brand agents MUST reject with
INVALID_REQUESTandfield: "campaign.end_date"whencampaign.end_dateis in the past at the time of the request. Issuing a zero-duration grant is almost always a buyer-side bug; deterministic rejection is more useful than silent expiry. Unlikecreate_media_buy(whereany_ofsupports time-shifting a flight forward), rights grants attach to the requested period and cannot be retroactively shifted, so reject-only is the correct contract.CPM-priced rights under a governed plan. When the request carries an intent-phase
governance_contexttoken (the buyer's plan is governed) and the selected pricing option hasmodel: "cpm", brand agents MUST reject withINVALID_REQUESTandfield: "campaign.estimated_impressions"when that field is omitted or0. When provided, projected commitment is(pricing_option.price / 1000) × campaign.estimated_impressionsevaluated inpricing_option.currency. Ifpricing_option.currencydiffers from the plan's budget currency, the agent MUST reject withfield: "pricing_option_id"— currency conversion is not specified. If the projected commitment exceeds remaining plan budget, the agent MUST reject withfield: "campaign.estimated_impressions". Non-CPM pricing options commit the flat amount regardless of volume; agents MUST NOT requireestimated_impressionsfor governance projection on those.Added a new "Request validation" section to
docs/brand-protocol/tasks/acquire_rights.mdxand tightened the field descriptions onstatic/schemas/source/brand/acquire-rights-request.jsonforcampaign.end_dateandcampaign.estimated_impressionsso the validation contract is discoverable from both the task reference and the schema.Patch-eligible: docs-only clarification of behavior the spec already implied. No schema shape changes (only description text); no new error codes (
INVALID_REQUESTis already standard). Thegovernance_contextanchor and the(price / 1000) × impressionsprojection formula reference fields that exist on the published 3.0 schemas — this PR does not introduce new wire surface, only normative interpretation.926b079: feat(compliance): add seed_creative_format scenario and list_creative_formats pagination
Adds
seed_creative_formattocomply_test_controllerso the compliance harness can pre-populate a deterministic, size-controlled set of creative formats for pagination-integrity storyboards.comply_test_controlleris a conformance-harness surface, not a core-protocol task — additive enum extensions on it bump at patch level under AdCP semver.Schema changes (comply-test-controller-request.json, comply-test-controller-response.json):
seed_creative_formatadded to thescenarioenum in both files. The request schema gains aparams.format_idstring field (required whenscenario = seed_creative_format) and the response schema'slist_scenariosenum is extended to match.Training-agent implementation:
seed_creative_formatis handled inhandleComplyTestControllerbefore the SDK dispatcher. Seeded formats are stored in a newsession.complyExtensions.seededCreativeFormatsmap and replace the static catalog when non-empty forlist_creative_formatsresponses.Pagination:
handleListCreativeFormatsnow applies cursor-based pagination (matching thelist_creativespattern) and is session-aware to read seeded formats. Non-compliance callers continue to see the full static catalog with pagination applied.Storyboard:
pagination-integrity-creative-formats.yamlexercises the cursor↔has_more invariant onlist_creative_formatsby seeding two formats and walking pages atmax_results=1.Non-breaking: adds a new enum value and optional param. Sellers that don't implement
seed_creative_formatwill returnUNKNOWN_SCENARIO; the storyboard'scontroller_seeding: truesignals that support is required for this storyboard to pass. Existing callers oflist_creative_formatsare unaffected — pagination fields are additive to the response.Closes Pagination integrity for list_creative_formats blocked on agent-portable filter #3108.
ae7eae2: Add optional
modefield toget_plan_audit_logsaudit entries, recording the governance mode (enforce/advisory/audit) active at check time. Surfaces the enforcement posture that produced each decision, closing a gap where audit and enforce modes produced identical-looking trails.46439c4: Apply the AdCP URL canonicalization rule to brand.json agent URLs.
Follow-up to docs(reference): add URL canonicalization reference page #3067 — the canonicalization reference page now exists,
and
seller-agent-ref,adagents.jsonauthorized_agents[].url,format-id, andprovider-registrationall link to it.brand.jsondeclares additional agent URLs that fall in the same identifier-
comparison class but weren't covered:
brand_agent_entry.url— the brand-declared agent endpoint (MCP orA2A) used by callers resolving "is this the agent that signed this
artifact?" or matching against a discovery cache.
brand_agent.url— the brand agent MCP endpoint reference.rights_agent.url— the rights agent MCP endpoint reference.All three now reference the AdCP URL canonicalization rules at
docs/reference/url-canonicalizationso two URLs differing only incase, default port, or percent-encoded unreserved characters compare
equal during agent resolution.
logo.url,data_subject_contestation.url, asset-libraryurl, andthe brand's primary
urlare not identifier-comparison keys (theypoint at human-facing pages or asset CDN endpoints), so they were
left unchanged.
jwks_uri(line 627) is a fetch target for JWKS download, not anidentifier-comparison key — receivers HTTP-GET the URL as declared
without comparing it to anything. Not in scope for this rule.
No schema shape changes. Descriptions only.
1cd99c2: Make the
task_status/response_statusprohibition from docs(spec): prohibit dual-emission of legacy status fields alongside v3 status #3021 machine-enforceable at the schema level. Adds anot: { anyOf: [{ required: [task_status] }, { required: [response_status] }] }constraint onprotocol-envelope.json(matching the existing idiom incatchment.json) so any JSON Schema validator rejects envelopes that dual-emit legacy status fields — no runner-specific primitive required. The prose MUST NOT in the envelopestatusdescription remains for human readers; the constraint is what validators act on. Closes Conformance check: envelope properties matching /^(task|response)_status$/ #3041 at the spec layer. Runtime conformance (storyboardfield_absentprimitive +@adcp/clientimplementation) is tracked separately.ea8e282: Add
titleto alloneOfbranches informat.json'sassets[]array so codegen tools (json-schema-to-typescript, datamodel-code-generator, oapi-codegen) produce named, discriminated per-asset-type interfaces instead of collapsing them to an untyped union. Adds titlesIndividualImageAsset…IndividualCatalogAssetandRepeatableGroupAssetat the top level, plusGroupImageAsset…GroupWebhookAssetfor the nested branches insiderepeatable_group.assets[]. Purely annotation-level; no validation or wire-format change.cecca44: Deprecates top-level
max_resultsonget_signalsand pinspagination.max_resultsprecedence.get-signals-request.jsoncarried two independent pagination fields — a legacy top-levelmax_results(no cap, no default, predates the pagination envelope) and the standardpaginationenvelope (pagination.max_results, max: 100, default: 50). The schema was silent on which wins when both are present.This change adds a MUST-level precedence rule: when both fields are present, agents MUST honor
pagination.max_results. It also deprecates the top-level field with guidance for sellers receiving it without a pagination envelope. The top-levelmax_resultswill be removed in AdCP 4.0.All other paginated read endpoints (
get_products,list_creatives,list_creative_formats,get-collection-list,get-property-list,get-media-buy-artifacts,tasks-list) carry onlypagination— this bringsget_signalsinto alignment.Non-breaking: adds description-level deprecation and normative prose. No type, structure, or required-field changes. Existing callers unaffected; sellers adding the conflict check gain new conformance grounding.
00c1574: Add
modetocheck_governanceresponse schema and fixbinding→check_typedrift in training agent audit entries.check-governance-response.jsonnow declares the optionalmodefield (enforce/advisory/audit) that the training agent was already emitting, letting counterparties and regulators distinguishapproved-with-finding decisions made underenforcefrom those made underaudit. The training agent audit log handler no longer emits the non-canonicalbindingfield (which caused schema-validation failures on the strictentries[]schema); it now emitscheck_type: "intent"|"execution"per the existing schema contract. The schema carriesx-status: experimental. Audit-entrymodeis added separately by feat(schema): add mode to get_plan_audit_logs audit entries #3160.ff95642: Clarify
policies_evaluateddescription incheck-governance-response.jsonandget-plan-audit-logs-response.json. The previous wording ("Registry policy IDs...") was incomplete and misleading: governance agents also record inlinepolicy_ids fromcustom_policiesin this field, and a consumer reading the description literally could write a parser that filters them out. The new wording names both sources. Both schemas carryx-status: experimental. Description-only clarification; no type, enum, or wire change.20a8310: Mark
governance-mode.jsonenum asx-status: experimentaland clarify the per-check semantics of the audit-entrymodefield.The enum is referenced exclusively from experimental schemas (
check-governance-response.json,get-plan-audit-logs-response.jsonentries[]); annotating it explicitly prevents the enum from being treated as stable while its consumers are still experimental. Theentries[].modedescription is tightened to clarify that the field reflects the mode active for that specific check, distinct from a futuregoverned_actions[].mode(which would describe the action's current mode and may differ if the plan has been re-synced since).3027c39: feat(schema): hoist 4 duplicate inline enum literal sets into shared
enums/definitions (closes Hoist duplicate inline-union literal sets into shared definitions #3144)Several inline string-literal unions in the AdCP source schemas had byte-identical value sets across multiple parent schemas but no shared
$ref, causing the TypeScript SDK to emit per-parent duplicate exports (Account_PaymentTermsValues,GetAccountFinancialsSuccess_PaymentTermsValues, etc.) when a single canonicalPaymentTermsValuesis what consumers expect.New shared enum files added (4 new
$id-bearing schemas instatic/schemas/source/enums/):payment-terms.json—["net_15","net_30","net_45","net_60","net_90","prepay"]audio-channel-layout.json—["mono","stereo","5.1","7.1"]media-buy-valid-action.json—["pause","resume","cancel","update_budget","update_dates","update_packages","add_packages","sync_creatives"]rights-billing-period.json—["daily","weekly","monthly","quarterly","annual","one_time"]Schemas updated to use
$ref(10 files; wire format unchanged in all cases):core/account.json,account/sync-accounts-request.json,account/sync-accounts-response.json,account/get-account-financials-response.json→payment_termsnow refsenums/payment-terms.jsoncore/assets/audio-asset.json,core/assets/video-asset.json→channels/audio_channelsnow refenums/audio-channel-layout.jsonmedia-buy/create-media-buy-response.json,media-buy/update-media-buy-response.json→valid_actionsitems now refenums/media-buy-valid-action.jsonbrand/rights-terms.json,brand/rights-pricing-option.json→periodnow refsenums/rights-billing-period.jsonNot changed:
core/insertion-order.jsonpayment_terms(["net_30","net_60","net_90","prepaid","due_on_receipt"]— different set, kept inline).Non-breaking: replacing inline
{"type":"string","enum":[...]}with a$refto an equivalent standalone schema produces an identical JSON Schema subgraph; all existing validators behave identically. Source-schema refactor only; bundled wire format is unchanged — patch-eligible.After a
npm run sync-schemasinadcp-client, the SDK will emit single canonical exports (PaymentTermsValues,AudioChannelLayoutValues, etc.) and should ship deprecated re-export aliases for any per-parent names that were in a published release.feed616: Hoist 13 duplicate inline enum sets into shared
enums/definitions (follow-up to feat(schema): hoist 4 duplicate inline enum sets into shared enums/ definitions #3148).Adds
match-type,collection-kind,frame-rate-type,scan-type,gop-type,moov-atom-position,binary-verdict,account-scope,governance-decision,billing-party,feature-check-status,snapshot-unavailable-reason, andtravel-time-unitas standalone$id-bearing enum files. Updates 21 source schemas to$refthese files instead of repeating the inline definitions. Source-schema refactor only; bundled wire format is unchanged in all cases.4614f4d: Clarify that v3 agents MUST NOT emit legacy status fields (
task_status,response_status, or any alias) alongside the v3statusfield. Adds a migration checklist row, a conformance warning in the task-lifecycle reference, and extends the protocol envelope schema'sstatusdescription with the prohibition. Closes Task status: prohibit dual-emission of legacy status fields alongside v3 status #2987.90ad0dd: Add
x-status: experimentalto all 9 TMP schemas andcore/seller-agent-ref.json(exclusively referenced by TMP), completing the experimental-status contract already declared fortrusted_match.coreinget_adcp_capabilitiesandexperimental-status.mdx. Mirrors the existing pattern on all 11 sponsored-intelligence schemas. Enables validators, doc generators, and tooling to identify TMP as an experimental surface. No wire-format or field changes.f1e8340: TMP: explicit seller-agent attribution on AvailablePackage.
Add
seller_agent: { agent_url, id? }to the Trusted Match ProtocolAvailablePackage schema, making seller identity explicit on every
package cached by a TMP provider. The canonical identifier is the
seller's agent URL as declared in the property publisher's
adagents.jsonauthorized_agents[].url; the reservedidslot isforward-compatible with a future registry-assigned opaque identifier.
/schemas/core/seller-agent-ref.json— new shared schemamirroring the
{agent_url, id?}shape used byformat-idandProviderEntry./schemas/tmp/available-package.json—seller_agentadded asa required field. Lands as a patch under the experimental-surface
contract (
experimental_features: trusted_match.core, which allowsbreaking changes between 3.x releases with advance notice); sellers
syncing
AvailablePackagepayloads need to populate it goingforward.
/schemas/tmp/offer.json— optionalseller_agentecho sopublisher-side log pipelines can attribute offers to sellers
without round-tripping to the media-buy store. Non-authoritative:
the cached package binding remains source of truth; routers MAY
stamp the field on merge when providers omit it.
/schemas/tmp/error.json— addsseller_not_authorizederrorcode for sync-time rejection when
seller_agent.agent_urlis notpresent in the property publisher's adagents.json
authorized_agents[].urllist.docs/trusted-match/specification.mdx— new "Package Sync"section defines the sync contract, the SHOULD-level adagents.json
validation flow, explicit per-actor responsibilities (seller
agent, publisher, router, provider), and the "what this is not"
boundary (not a request-time filter, not a sellers.json bridge,
not a cryptographic attestation). Offer and Error tables updated
accordingly; definitions table gains a Seller agent entry.
Seller identity lives on the cached
AvailablePackage, not oncontext_match_requestoridentity_match_request. Providers —which have no access to a media-buy store — need provenance on the
wire they actually receive; putting it on the request would either
duplicate the sync-time binding or open a path for request-time
seller filtering that re-introduces the identity- and
allocation-leakage failure modes that package-set decorrelation
exists to prevent. Publishers and routers can derive seller identity
from
media_buy_idagainst their own stores; providers cannot.TMP remains experimental under AdCP 3.x — schema additions here
follow the experimental-surface contract and do not bump the stable
AdCP major. The
SellerAgentRef.idslot and optionalextnamespaceleave room to layer signed seller claims or an AAO-assigned opaque
identifier without a rename later.
aa71ebc: URL canonicalization: one authoritative reference for every URL-as-identifier comparison in AdCP.
The canonicalization algorithm previously lived only under the request-signing profile in
docs/building/implementation/security.mdx, but AdCP compares URLs as identifiers in many other places — TMP seller authorization (seller_agent.agent_urlvsauthorized_agents[].url), TMP provider resolution (ProviderEntry.agent_url),format-id.agent_urlequivalence, and signal/feature agent lookups inadagents.json. Schemas today said "exactly as declared," which reads as byte-equality; two URLs that differ only in case, default port, or percent-encoded unreserved characters would silently miss the match.This change moves the algorithm to a first-class reference page and links every consuming surface to it, so the same canonicalization binds everywhere.
docs/reference/url-canonicalization.mdx— the authoritative home of the 8-step algorithm (RFC 3986 §6.2.2 + §6.2.3, UTS-46 Nontransitional IDN pin, IPv6 zone-identifier rejection, enumerated malformed-authority cases), a "where it applies" table covering signing / TMP seller authorization / TMP provider resolution /adagents.jsonlookups /format-id/authoritative_locationindirection, a "signing profile extensions" note for the transport-only bits, and a common-pitfalls list.docs/building/implementation/security.mdx—@target-urisection now cites the reference page instead of restating the eight steps. Keeps only the signing-specific extensions (HTTP/2:authorityderivation, dual-header rejection,request_target_uri_malformederror, cross-vhost replay gate). Removes the drift risk between two copies.static/schemas/source/core/seller-agent-ref.json—agent_urldescription replaces "exactly as declared" with canonicalization-based comparison. Also drops the "in production" weasel on HTTPS — the scheme requirement is now unconditional.static/schemas/source/adagents.json— all sixurldescriptions updated: the fourauthorized_agents[].urlvariants, plus the two signals-authorization variants (signal_ids,signal_tags) and the property-features variant.static/schemas/source/core/format-id.json—agent_urldescription updated to require canonicalization.static/schemas/source/tmp/provider-registration.json—endpointdescription extends the existing SSRF/DNS-rebinding language with a canonicalization rule for provider-registry de-duplication.docs/trusted-match/specification.mdx— TMP Sync-Time Validation step 2 links canonicalization rules explicitly and adds an explicithttps://-only rejection (non-HTTPS seller URLs getseller_not_authorized, closing the scheme-mismatch bypass). ProviderEntry table row links the canonicalization rules for provider comparison.docs.json— reference page added to both primary and legacy sidebars adjacent toversioning(other interop-rules references).No schema shape changes. Descriptions only. Schema link style follows the repo convention (
See docs/<path>bare, no backticks or leading slash).9ff83de: feat(compliance): v3 envelope integrity universal storyboard
Adds
static/compliance/source/universal/v3-envelope-integrity.yaml— a universal storyboard (applies to all agent interaction models) that asserts the v3statusfield is present on the response envelope and that the legacy v2task_status/response_statusfield names are absent.Schema-level enforcement of the prohibition is provided separately by
envelope-forbid-legacy-status-fields.md(top-levelnot: { anyOf: [{ required: [task_status] }, { required: [response_status] }] }onprotocol-envelope.json). This changeset is the runtime/storyboard counterpart.The explicit envelope-root field-absence assertions are wired as TODO
field_absentchecks pending runner support in@adcp/client; the immediate enforcement path remains the schema-level constraint, which any schema-aware validator detects without runner-specific primitives. Closes Conformance check: envelope properties matching /^(task|response)_status$/ #3041 at the storyboard layer.