Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 29 additions & 10 deletions docs/protocols/a2a-guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -711,32 +711,51 @@ console.log('Examples:', getProductsSkill.examples);
]
}
],
"extensions": {
"adcp": {
"adcp_version": "2.4.0",
"protocols_supported": ["media_buy"]
"extensions": [
{
"uri": "https://adcontextprotocol.org/extensions/adcp",
"description": "AdCP media buying protocol support",
"required": false,
"params": {
"adcp_version": "2.6.0",
"protocols_supported": ["media_buy"],
"extensions_supported": ["sustainability"]
}
}
}
]
}
```

### AdCP Extension

**Recommended**: Include the `extensions.adcp` field in your agent card to declare AdCP support programmatically.
**Recommended**: Include the AdCP extension in your agent card's `extensions` array to declare AdCP support programmatically.

The A2A protocol uses an `extensions` array where each extension has:
- **`uri`**: Extension identifier (use `https://adcontextprotocol.org/extensions/adcp`)
- **`description`**: Human-readable description of how you use AdCP
- **`required`**: Whether clients must support this extension (typically `false` for AdCP)
- **`params`**: AdCP-specific configuration (see schema below)

```javascript
// Check if agent supports AdCP
const agentCard = await fetch('https://sales.example.com/.well-known/agent.json')
.then(r => r.json());

if (agentCard.extensions?.adcp) {
console.log('AdCP Version:', agentCard.extensions.adcp.adcp_version);
console.log('Supported domains:', agentCard.extensions.adcp.protocols_supported);
// Find the AdCP extension in the extensions array
const adcpExt = agentCard.extensions?.find(
ext => ext.uri === 'https://adcontextprotocol.org/extensions/adcp'
);

if (adcpExt) {
console.log('AdCP Version:', adcpExt.params.adcp_version);
console.log('Supported domains:', adcpExt.params.protocols_supported);
// ["media_buy", "creative", "signals"]
console.log('Typed extensions:', adcpExt.params.extensions_supported);
// ["sustainability"]
}
```

**Extension Structure**: See the [AdCP extension schema](https://adcontextprotocol.org/schemas/v2/protocols/adcp-extension.json) for complete specification.
**Extension Params Schema**: See the [AdCP extension schema](https://adcontextprotocol.org/schemas/v2/protocols/adcp-extension.json) for the complete `params` specification.

**Benefits**:
- Clients can discover AdCP capabilities without making test calls
Expand Down
52 changes: 45 additions & 7 deletions docs/protocols/mcp-guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -632,22 +632,60 @@ const adcpTools = tools.filter(t => t.name.startsWith('adcp_') ||
['get_products', 'create_media_buy'].includes(t.name));
```

### AdCP Extension (Future)
### AdCP Extension via MCP Server Card

**Status**: MCP server cards are expected in a future MCP release. When available, AdCP servers will include the AdCP extension.
MCP servers can declare AdCP support via a server card at `/.well-known/mcp.json` (or `/.well-known/server.json`). AdCP-specific metadata goes in the `_meta` field using the `adcontextprotocol.org` namespace.

```json
{
"extensions": {
"adcp": {
"adcp_version": "2.4.0",
"protocols_supported": ["media_buy", "creative", "signals"]
"name": "io.adcontextprotocol/media-buy-agent",
"version": "1.0.0",
"title": "AdCP Media Buy Agent",
"description": "AI-powered media buying agent implementing AdCP",
"tools": [
{ "name": "get_products" },
{ "name": "create_media_buy" },
{ "name": "list_creative_formats" }
],
"_meta": {
"adcontextprotocol.org": {
"adcp_version": "2.6.0",
"protocols_supported": ["media_buy"],
"extensions_supported": ["sustainability"]
}
}
}
```

This will allow clients to programmatically discover which AdCP version and protocol domains an MCP server implements. See the [AdCP extension schema](https://adcontextprotocol.org/schemas/v2/protocols/adcp-extension.json) for specification details.
**Discovering AdCP support:**

```javascript
// Check both possible locations for MCP server card
const serverCard = await fetch('https://sales.example.com/.well-known/mcp.json')
.then(r => r.ok ? r.json() : null)
.catch(() => null)
|| await fetch('https://sales.example.com/.well-known/server.json')
.then(r => r.json());

// Check for AdCP metadata
const adcpMeta = serverCard?._meta?.['adcontextprotocol.org'];

if (adcpMeta) {
console.log('AdCP Version:', adcpMeta.adcp_version);
console.log('Supported domains:', adcpMeta.protocols_supported);
// ["media_buy", "creative", "signals"]
console.log('Typed extensions:', adcpMeta.extensions_supported);
// ["sustainability"]
}
```

**Benefits:**
- Clients can discover AdCP capabilities without making test calls
- Declare which protocol domains you implement (media_buy, creative, signals)
- Declare which [typed extensions](/docs/reference/extensions-and-context#typed-extensions) you support
- Enable compatibility checks based on version

**Note:** The `_meta` field uses reverse DNS namespacing per the [MCP server.json spec](https://github.com/modelcontextprotocol/registry/blob/main/docs/reference/server-json/generic-server-json.md). AdCP servers should support both `/.well-known/mcp.json` and `/.well-known/server.json` locations.

### Parameter Validation
```javascript
Expand Down
207 changes: 207 additions & 0 deletions docs/reference/extensions-and-context.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,213 @@ Without namespacing:
- Impossible to support multiple platforms simultaneously
- Harder to deprecate platform-specific features

## Typed Extensions

AdCP supports formal JSON schemas for extensions, enabling type safety and validation. Typed extensions are published in the `/schemas/extensions/` directory and can be declared in agent cards.

### How Typed Extensions Work

Typed extensions provide a middle ground between untyped vendor extensions and core AdCP fields:

- **Untyped extensions** (`ext.vendor.*`) - Any JSON, no validation, vendor-specific
- **Typed extensions** (`ext.sustainability.*`) - Formal schema, validated, cross-vendor
- **Core fields** - Part of AdCP specification, required for interoperability

Typed extensions enable SDK code generation, schema validation, and cross-vendor interoperability while remaining optional.

### Extension Schema Registry

The registry of available typed extensions is auto-generated from extension files:
- **Registry**: `/schemas/v1/extensions/index.json`
- **Extension schemas**: `/schemas/v1/extensions/{namespace}.json`
- **Meta schema**: `/schemas/v1/extensions/extension-meta.json`

Each versioned schema path (`/schemas/v2.5/`, `/schemas/v2.6/`) includes only extensions valid for that version, based on the `valid_from` and `valid_until` fields in each extension.

### Extension Versioning

Extensions are versioned independently of the AdCP specification:

```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "/schemas/extensions/sustainability.json",
"title": "Sustainability Extension",
"description": "Carbon footprint and green certification data",
"valid_from": "2.5",
"valid_until": "4.0",
"docs_url": "https://adcontextprotocol.org/docs/extensions/sustainability",
"type": "object",
"properties": {
"carbon_kg_per_impression": { "type": "number" },
"certified_green": { "type": "boolean" }
}
}
```

- **`valid_from`** (required): Minimum AdCP version this extension works with (e.g., `"2.5"`)
- **`valid_until`** (optional): Last AdCP version this extension works with. Omit if still valid.

This allows extensions to be backported to earlier AdCP versions and deprecated gracefully.

### Declaring Extension Support

Agents declare which typed extensions they support in their discovery metadata. The location depends on the protocol:

#### A2A Agent Cards

A2A agents declare AdCP support in the `extensions` array at `/.well-known/agent.json`:

```json
{
"name": "AdCP Media Buy Agent",
"skills": [{ "name": "get_products" }, { "name": "create_media_buy" }],
"extensions": [
{
"uri": "https://adcontextprotocol.org/extensions/adcp",
"description": "AdCP media buying protocol support",
"required": false,
"params": {
"adcp_version": "2.6.0",
"protocols_supported": ["media_buy"],
"extensions_supported": ["sustainability"]
}
}
]
}
```

See the [A2A Guide](/docs/protocols/a2a-guide#adcp-extension) for complete details.

#### MCP Server Cards

MCP servers declare AdCP support via the `_meta` field at `/.well-known/mcp.json` or `/.well-known/server.json`:

```json
{
"name": "io.adcontextprotocol/media-buy-agent",
"tools": [{ "name": "get_products" }, { "name": "create_media_buy" }],
"_meta": {
"adcontextprotocol.org": {
"adcp_version": "2.6.0",
"protocols_supported": ["media_buy"],
"extensions_supported": ["sustainability"]
}
}
}
```

See the [MCP Guide](/docs/protocols/mcp-guide#adcp-extension-via-mcp-server-card) for complete details.

#### Extension Params Schema

Both protocols use the same params structure, defined in the [AdCP extension schema](https://adcontextprotocol.org/schemas/v2/protocols/adcp-extension.json):
- **`adcp_version`** (required): Semantic version of AdCP implemented (e.g., "2.6.0")
- **`protocols_supported`** (required): Array of protocol domains (media_buy, creative, signals)
- **`extensions_supported`** (optional): Array of typed extension namespaces

When an agent declares support for an extension, clients can expect:
- The agent will accept and populate `ext.{namespace}` fields conforming to that extension's schema
- Data in `ext.{namespace}` is strongly typed and can be validated
- SDK code generation can produce type-safe interfaces for the extension

### Using Typed Extensions

When an agent supports a typed extension, you can include and expect data in the corresponding namespace:

```json
{
"product_id": "premium_ctv",
"name": "Premium CTV Package",
"ext": {
"sustainability": {
"carbon_kg_per_impression": 0.0012,
"certified_green": true
}
}
}
```

### Creating a Typed Extension

To create a typed extension:

1. **Create the extension file** at `/schemas/extensions/{namespace}.json`
2. **Follow the meta schema** defined in `/schemas/extensions/extension-meta.json`
3. **Set `valid_from`** to the minimum AdCP version your extension requires
4. **Add documentation** via the `docs_url` field

Example extension file:

```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "/schemas/extensions/sustainability.json",
"title": "Sustainability Extension",
"description": "Carbon footprint and green certification data for ad products",
"valid_from": "2.5",
"docs_url": "https://adcontextprotocol.org/docs/extensions/sustainability",
"type": "object",
"properties": {
"carbon_kg_per_impression": {
"type": "number",
"description": "Estimated CO2 emissions per impression in kilograms"
},
"certified_green": {
"type": "boolean",
"description": "Whether the inventory is certified by a green advertising program"
},
"certification_provider": {
"type": "string",
"description": "Name of the green certification provider"
}
}
}
```

The build process auto-discovers extension files and includes them in the appropriate versioned schema builds.

### Proposing Typed Extensions

To propose a typed extension for inclusion in AdCP:

1. **Validate in production first** - Use vendor-namespaced extensions (`ext.yourcompany.*`) to prove value
2. **Document the schema** - Define clear property names, types, and descriptions
3. **Gather adoption evidence** - Show multiple implementations or strong demand
4. **Submit an RFC** - Propose the extension with schema and use cases
5. **If accepted** - Extension is added to `/schemas/extensions/` with appropriate `valid_from`

### Reserved Namespaces

The following namespaces are reserved and cannot be used for typed extensions:
- `adcp`, `core`, `protocol`, `schema`, `meta`, `ext`, `context`

These are reserved to prevent confusion with core AdCP concepts.

### Extension Deprecation Policy

#### When Extensions May Be Deprecated

1. **Superseded** - A better extension exists with a documented migration path
2. **Promoted to core** - The extension becomes a core AdCP field
3. **Low adoption** - Insufficient usage across implementations
4. **Incompatible** - Breaking changes in AdCP require removal

#### Deprecation Process

1. Set `valid_until` to current version + 1 minor release (minimum grace period)
2. Announce deprecation in CHANGELOG
3. Publish migration guide if replacement exists
4. Add deprecation warning to extension docs
5. Extension removed from builds after `valid_until` version

#### Emergency Deprecation

Security issues may require immediate deprecation:
- `valid_until` set to current version
- Security advisory published
- Patch release issued

## Proposing Spec Additions

If your extension field represents **common ad tech functionality** that would benefit all AdCP implementations:
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"test:schemas": "node tests/schema-validation.test.cjs",
"test:examples": "node tests/example-validation-simple.test.cjs",
"test:extensions": "node tests/extension-fields.test.cjs",
"test:extension-schemas": "node tests/extension-schemas.test.cjs",
"test:snippets": "node tests/snippet-validation.test.cjs",
"test:json-schema": "node tests/json-schema-validation.test.cjs",
"test:error-handling": "node tests/check-error-handling.cjs",
Expand All @@ -27,7 +28,7 @@
"test:registry": "vitest run server/tests",
"test:docker": "docker compose -f docker-compose.test.yml up --build --abort-on-container-exit",
"generate-openapi": "node scripts/generate-openapi.cjs",
"test": "npm run test:schemas && npm run test:examples && npm run test:extensions && npm run test:error-handling && npm run test:json-schema && npm run test:composed && npm run test:migrations && npm run test:unit && npm run typecheck",
"test": "npm run test:schemas && npm run test:examples && npm run test:extensions && npm run test:extension-schemas && npm run test:error-handling && npm run test:json-schema && npm run test:composed && npm run test:migrations && npm run test:unit && npm run typecheck",
"test:all": "npm run test:schemas && npm run test:examples && npm run test:extensions && npm run test:error-handling && npm run test:snippets && npm run typecheck",
"precommit": "npm test",
"prepare": "husky",
Expand Down
Loading