adcp 0.1.2__tar.gz
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.
- adcp-0.1.2/LICENSE +17 -0
- adcp-0.1.2/PKG-INFO +276 -0
- adcp-0.1.2/README.md +239 -0
- adcp-0.1.2/pyproject.toml +82 -0
- adcp-0.1.2/setup.cfg +4 -0
- adcp-0.1.2/src/adcp/__init__.py +18 -0
- adcp-0.1.2/src/adcp/client.py +493 -0
- adcp-0.1.2/src/adcp/protocols/__init__.py +7 -0
- adcp-0.1.2/src/adcp/protocols/a2a.py +159 -0
- adcp-0.1.2/src/adcp/protocols/base.py +38 -0
- adcp-0.1.2/src/adcp/protocols/mcp.py +101 -0
- adcp-0.1.2/src/adcp/types/__init__.py +21 -0
- adcp-0.1.2/src/adcp/types/core.py +99 -0
- adcp-0.1.2/src/adcp/utils/__init__.py +5 -0
- adcp-0.1.2/src/adcp/utils/operation_id.py +13 -0
- adcp-0.1.2/src/adcp.egg-info/PKG-INFO +276 -0
- adcp-0.1.2/src/adcp.egg-info/SOURCES.txt +20 -0
- adcp-0.1.2/src/adcp.egg-info/dependency_links.txt +1 -0
- adcp-0.1.2/src/adcp.egg-info/requires.txt +13 -0
- adcp-0.1.2/src/adcp.egg-info/top_level.txt +1 -0
- adcp-0.1.2/tests/test_client.py +163 -0
- adcp-0.1.2/tests/test_protocols.py +189 -0
adcp-0.1.2/LICENSE
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
Copyright 2025 AdCP Community
|
|
6
|
+
|
|
7
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
you may not use this file except in compliance with the License.
|
|
9
|
+
You may obtain a copy of the License at
|
|
10
|
+
|
|
11
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
|
|
13
|
+
Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
See the License for the specific language governing permissions and
|
|
17
|
+
limitations under the License.
|
adcp-0.1.2/PKG-INFO
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: adcp
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Official Python client for the Ad Context Protocol (AdCP)
|
|
5
|
+
Author-email: AdCP Community <maintainers@adcontextprotocol.org>
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/adcontextprotocol/adcp-client-python
|
|
8
|
+
Project-URL: Documentation, https://docs.adcontextprotocol.org
|
|
9
|
+
Project-URL: Repository, https://github.com/adcontextprotocol/adcp-client-python
|
|
10
|
+
Project-URL: Issues, https://github.com/adcontextprotocol/adcp-client-python/issues
|
|
11
|
+
Keywords: adcp,mcp,a2a,protocol,advertising
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: httpx>=0.24.0
|
|
25
|
+
Requires-Dist: pydantic>=2.0.0
|
|
26
|
+
Requires-Dist: typing-extensions>=4.5.0
|
|
27
|
+
Requires-Dist: a2a-sdk>=0.3.0
|
|
28
|
+
Requires-Dist: mcp>=0.9.0
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
33
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
35
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# adcp - Python Client for Ad Context Protocol
|
|
39
|
+
|
|
40
|
+
[](https://badge.fury.io/py/adcp)
|
|
41
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
42
|
+
[](https://www.python.org/downloads/)
|
|
43
|
+
|
|
44
|
+
Official Python client for the **Ad Context Protocol (AdCP)**. Build distributed advertising operations that work synchronously OR asynchronously with the same code.
|
|
45
|
+
|
|
46
|
+
## The Core Concept
|
|
47
|
+
|
|
48
|
+
AdCP operations are **distributed and asynchronous by default**. An agent might:
|
|
49
|
+
- Complete your request **immediately** (synchronous)
|
|
50
|
+
- Need time to process and **send results via webhook** (asynchronous)
|
|
51
|
+
- Ask for **clarifications** before proceeding
|
|
52
|
+
- Send periodic **status updates** as work progresses
|
|
53
|
+
|
|
54
|
+
**Your code stays the same.** You write handlers once, and they work for both sync completions and webhook deliveries.
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install adcp
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Quick Start: Distributed Operations
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from adcp import ADCPMultiAgentClient
|
|
66
|
+
from adcp.types import AgentConfig
|
|
67
|
+
|
|
68
|
+
# Configure agents and handlers
|
|
69
|
+
client = ADCPMultiAgentClient(
|
|
70
|
+
agents=[
|
|
71
|
+
AgentConfig(
|
|
72
|
+
id="agent_x",
|
|
73
|
+
agent_uri="https://agent-x.com",
|
|
74
|
+
protocol="a2a"
|
|
75
|
+
),
|
|
76
|
+
AgentConfig(
|
|
77
|
+
id="agent_y",
|
|
78
|
+
agent_uri="https://agent-y.com/mcp/",
|
|
79
|
+
protocol="mcp"
|
|
80
|
+
)
|
|
81
|
+
],
|
|
82
|
+
# Webhook URL template (macros: {agent_id}, {task_type}, {operation_id})
|
|
83
|
+
webhook_url_template="https://myapp.com/webhook/{task_type}/{agent_id}/{operation_id}",
|
|
84
|
+
|
|
85
|
+
# Activity callback - fires for ALL events
|
|
86
|
+
on_activity=lambda activity: print(f"[{activity.type}] {activity.task_type}"),
|
|
87
|
+
|
|
88
|
+
# Status change handlers
|
|
89
|
+
handlers={
|
|
90
|
+
"on_get_products_status_change": lambda response, metadata: (
|
|
91
|
+
db.save_products(metadata.operation_id, response.products)
|
|
92
|
+
if metadata.status == "completed" else None
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# Execute operation - library handles operation IDs, webhook URLs, context management
|
|
98
|
+
agent = client.agent("agent_x")
|
|
99
|
+
result = await agent.get_products(brief="Coffee brands")
|
|
100
|
+
|
|
101
|
+
# Check result
|
|
102
|
+
if result.status == "completed":
|
|
103
|
+
# Agent completed synchronously!
|
|
104
|
+
print(f"✅ Sync completion: {len(result.data.products)} products")
|
|
105
|
+
|
|
106
|
+
if result.status == "submitted":
|
|
107
|
+
# Agent will send webhook when complete
|
|
108
|
+
print(f"⏳ Async - webhook registered at: {result.submitted.webhook_url}")
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Features
|
|
112
|
+
|
|
113
|
+
### Full Protocol Support
|
|
114
|
+
- **A2A Protocol**: Native support for Agent-to-Agent protocol
|
|
115
|
+
- **MCP Protocol**: Native support for Model Context Protocol
|
|
116
|
+
- **Auto-detection**: Automatically detect which protocol an agent uses
|
|
117
|
+
|
|
118
|
+
### Type Safety
|
|
119
|
+
Full type hints with Pydantic validation:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
result = await agent.get_products(brief="Coffee brands")
|
|
123
|
+
# result: TaskResult[GetProductsResponse]
|
|
124
|
+
|
|
125
|
+
if result.success:
|
|
126
|
+
for product in result.data.products:
|
|
127
|
+
print(product.name, product.price) # Full IDE autocomplete!
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Multi-Agent Operations
|
|
131
|
+
Execute across multiple agents simultaneously:
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
# Parallel execution across all agents
|
|
135
|
+
results = await client.get_products(brief="Coffee brands")
|
|
136
|
+
|
|
137
|
+
for result in results:
|
|
138
|
+
if result.status == "completed":
|
|
139
|
+
print(f"Sync: {len(result.data.products)} products")
|
|
140
|
+
elif result.status == "submitted":
|
|
141
|
+
print(f"Async: webhook to {result.submitted.webhook_url}")
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Webhook Handling
|
|
145
|
+
Single endpoint handles all webhooks:
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
from fastapi import FastAPI, Request
|
|
149
|
+
|
|
150
|
+
app = FastAPI()
|
|
151
|
+
|
|
152
|
+
@app.post("/webhook/{task_type}/{agent_id}/{operation_id}")
|
|
153
|
+
async def webhook(task_type: str, agent_id: str, operation_id: str, request: Request):
|
|
154
|
+
payload = await request.json()
|
|
155
|
+
payload["task_type"] = task_type
|
|
156
|
+
payload["operation_id"] = operation_id
|
|
157
|
+
|
|
158
|
+
# Route to agent client - handlers fire automatically
|
|
159
|
+
agent = client.agent(agent_id)
|
|
160
|
+
await agent.handle_webhook(
|
|
161
|
+
payload,
|
|
162
|
+
request.headers.get("x-adcp-signature")
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
return {"received": True}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Security
|
|
169
|
+
Webhook signature verification built-in:
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
client = ADCPMultiAgentClient(
|
|
173
|
+
agents=agents,
|
|
174
|
+
webhook_secret=os.getenv("WEBHOOK_SECRET")
|
|
175
|
+
)
|
|
176
|
+
# Signatures verified automatically on handle_webhook()
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Available Tools
|
|
180
|
+
|
|
181
|
+
All AdCP tools with full type safety:
|
|
182
|
+
|
|
183
|
+
**Media Buy Lifecycle:**
|
|
184
|
+
- `get_products()` - Discover advertising products
|
|
185
|
+
- `list_creative_formats()` - Get supported creative formats
|
|
186
|
+
- `create_media_buy()` - Create new media buy
|
|
187
|
+
- `update_media_buy()` - Update existing media buy
|
|
188
|
+
- `sync_creatives()` - Upload/sync creative assets
|
|
189
|
+
- `list_creatives()` - List creative assets
|
|
190
|
+
- `get_media_buy_delivery()` - Get delivery performance
|
|
191
|
+
|
|
192
|
+
**Audience & Targeting:**
|
|
193
|
+
- `list_authorized_properties()` - Get authorized properties
|
|
194
|
+
- `get_signals()` - Get audience signals
|
|
195
|
+
- `activate_signal()` - Activate audience signals
|
|
196
|
+
- `provide_performance_feedback()` - Send performance feedback
|
|
197
|
+
|
|
198
|
+
## Property Discovery (AdCP v2.2.0)
|
|
199
|
+
|
|
200
|
+
Build agent registries by discovering properties agents can sell:
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
from adcp.discovery import PropertyCrawler, get_property_index
|
|
204
|
+
|
|
205
|
+
# Crawl agents to discover properties
|
|
206
|
+
crawler = PropertyCrawler()
|
|
207
|
+
await crawler.crawl_agents([
|
|
208
|
+
{"agent_url": "https://agent-x.com", "protocol": "a2a"},
|
|
209
|
+
{"agent_url": "https://agent-y.com/mcp/", "protocol": "mcp"}
|
|
210
|
+
])
|
|
211
|
+
|
|
212
|
+
index = get_property_index()
|
|
213
|
+
|
|
214
|
+
# Query 1: Who can sell this property?
|
|
215
|
+
matches = index.find_agents_for_property("domain", "cnn.com")
|
|
216
|
+
|
|
217
|
+
# Query 2: What can this agent sell?
|
|
218
|
+
auth = index.get_agent_authorizations("https://agent-x.com")
|
|
219
|
+
|
|
220
|
+
# Query 3: Find by tags
|
|
221
|
+
premium = index.find_agents_by_property_tags(["premium", "ctv"])
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Environment Configuration
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
# .env
|
|
228
|
+
WEBHOOK_URL_TEMPLATE="https://myapp.com/webhook/{task_type}/{agent_id}/{operation_id}"
|
|
229
|
+
WEBHOOK_SECRET="your-webhook-secret"
|
|
230
|
+
|
|
231
|
+
ADCP_AGENTS='[
|
|
232
|
+
{
|
|
233
|
+
"id": "agent_x",
|
|
234
|
+
"agent_uri": "https://agent-x.com",
|
|
235
|
+
"protocol": "a2a",
|
|
236
|
+
"auth_token_env": "AGENT_X_TOKEN"
|
|
237
|
+
}
|
|
238
|
+
]'
|
|
239
|
+
AGENT_X_TOKEN="actual-token-here"
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
# Auto-discover from environment
|
|
244
|
+
client = ADCPMultiAgentClient.from_env()
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Development
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# Install with dev dependencies
|
|
251
|
+
pip install -e ".[dev]"
|
|
252
|
+
|
|
253
|
+
# Run tests
|
|
254
|
+
pytest
|
|
255
|
+
|
|
256
|
+
# Type checking
|
|
257
|
+
mypy src/
|
|
258
|
+
|
|
259
|
+
# Format code
|
|
260
|
+
black src/ tests/
|
|
261
|
+
ruff check src/ tests/
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Contributing
|
|
265
|
+
|
|
266
|
+
Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
267
|
+
|
|
268
|
+
## License
|
|
269
|
+
|
|
270
|
+
Apache 2.0 License - see [LICENSE](LICENSE) file for details.
|
|
271
|
+
|
|
272
|
+
## Support
|
|
273
|
+
|
|
274
|
+
- **Documentation**: [docs.adcontextprotocol.org](https://docs.adcontextprotocol.org)
|
|
275
|
+
- **Issues**: [GitHub Issues](https://github.com/adcontextprotocol/adcp-client-python/issues)
|
|
276
|
+
- **Protocol Spec**: [AdCP Specification](https://github.com/adcontextprotocol/adcp)
|
adcp-0.1.2/README.md
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# adcp - Python Client for Ad Context Protocol
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/py/adcp)
|
|
4
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
5
|
+
[](https://www.python.org/downloads/)
|
|
6
|
+
|
|
7
|
+
Official Python client for the **Ad Context Protocol (AdCP)**. Build distributed advertising operations that work synchronously OR asynchronously with the same code.
|
|
8
|
+
|
|
9
|
+
## The Core Concept
|
|
10
|
+
|
|
11
|
+
AdCP operations are **distributed and asynchronous by default**. An agent might:
|
|
12
|
+
- Complete your request **immediately** (synchronous)
|
|
13
|
+
- Need time to process and **send results via webhook** (asynchronous)
|
|
14
|
+
- Ask for **clarifications** before proceeding
|
|
15
|
+
- Send periodic **status updates** as work progresses
|
|
16
|
+
|
|
17
|
+
**Your code stays the same.** You write handlers once, and they work for both sync completions and webhook deliveries.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install adcp
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start: Distributed Operations
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from adcp import ADCPMultiAgentClient
|
|
29
|
+
from adcp.types import AgentConfig
|
|
30
|
+
|
|
31
|
+
# Configure agents and handlers
|
|
32
|
+
client = ADCPMultiAgentClient(
|
|
33
|
+
agents=[
|
|
34
|
+
AgentConfig(
|
|
35
|
+
id="agent_x",
|
|
36
|
+
agent_uri="https://agent-x.com",
|
|
37
|
+
protocol="a2a"
|
|
38
|
+
),
|
|
39
|
+
AgentConfig(
|
|
40
|
+
id="agent_y",
|
|
41
|
+
agent_uri="https://agent-y.com/mcp/",
|
|
42
|
+
protocol="mcp"
|
|
43
|
+
)
|
|
44
|
+
],
|
|
45
|
+
# Webhook URL template (macros: {agent_id}, {task_type}, {operation_id})
|
|
46
|
+
webhook_url_template="https://myapp.com/webhook/{task_type}/{agent_id}/{operation_id}",
|
|
47
|
+
|
|
48
|
+
# Activity callback - fires for ALL events
|
|
49
|
+
on_activity=lambda activity: print(f"[{activity.type}] {activity.task_type}"),
|
|
50
|
+
|
|
51
|
+
# Status change handlers
|
|
52
|
+
handlers={
|
|
53
|
+
"on_get_products_status_change": lambda response, metadata: (
|
|
54
|
+
db.save_products(metadata.operation_id, response.products)
|
|
55
|
+
if metadata.status == "completed" else None
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Execute operation - library handles operation IDs, webhook URLs, context management
|
|
61
|
+
agent = client.agent("agent_x")
|
|
62
|
+
result = await agent.get_products(brief="Coffee brands")
|
|
63
|
+
|
|
64
|
+
# Check result
|
|
65
|
+
if result.status == "completed":
|
|
66
|
+
# Agent completed synchronously!
|
|
67
|
+
print(f"✅ Sync completion: {len(result.data.products)} products")
|
|
68
|
+
|
|
69
|
+
if result.status == "submitted":
|
|
70
|
+
# Agent will send webhook when complete
|
|
71
|
+
print(f"⏳ Async - webhook registered at: {result.submitted.webhook_url}")
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Features
|
|
75
|
+
|
|
76
|
+
### Full Protocol Support
|
|
77
|
+
- **A2A Protocol**: Native support for Agent-to-Agent protocol
|
|
78
|
+
- **MCP Protocol**: Native support for Model Context Protocol
|
|
79
|
+
- **Auto-detection**: Automatically detect which protocol an agent uses
|
|
80
|
+
|
|
81
|
+
### Type Safety
|
|
82
|
+
Full type hints with Pydantic validation:
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
result = await agent.get_products(brief="Coffee brands")
|
|
86
|
+
# result: TaskResult[GetProductsResponse]
|
|
87
|
+
|
|
88
|
+
if result.success:
|
|
89
|
+
for product in result.data.products:
|
|
90
|
+
print(product.name, product.price) # Full IDE autocomplete!
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Multi-Agent Operations
|
|
94
|
+
Execute across multiple agents simultaneously:
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
# Parallel execution across all agents
|
|
98
|
+
results = await client.get_products(brief="Coffee brands")
|
|
99
|
+
|
|
100
|
+
for result in results:
|
|
101
|
+
if result.status == "completed":
|
|
102
|
+
print(f"Sync: {len(result.data.products)} products")
|
|
103
|
+
elif result.status == "submitted":
|
|
104
|
+
print(f"Async: webhook to {result.submitted.webhook_url}")
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Webhook Handling
|
|
108
|
+
Single endpoint handles all webhooks:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from fastapi import FastAPI, Request
|
|
112
|
+
|
|
113
|
+
app = FastAPI()
|
|
114
|
+
|
|
115
|
+
@app.post("/webhook/{task_type}/{agent_id}/{operation_id}")
|
|
116
|
+
async def webhook(task_type: str, agent_id: str, operation_id: str, request: Request):
|
|
117
|
+
payload = await request.json()
|
|
118
|
+
payload["task_type"] = task_type
|
|
119
|
+
payload["operation_id"] = operation_id
|
|
120
|
+
|
|
121
|
+
# Route to agent client - handlers fire automatically
|
|
122
|
+
agent = client.agent(agent_id)
|
|
123
|
+
await agent.handle_webhook(
|
|
124
|
+
payload,
|
|
125
|
+
request.headers.get("x-adcp-signature")
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
return {"received": True}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Security
|
|
132
|
+
Webhook signature verification built-in:
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
client = ADCPMultiAgentClient(
|
|
136
|
+
agents=agents,
|
|
137
|
+
webhook_secret=os.getenv("WEBHOOK_SECRET")
|
|
138
|
+
)
|
|
139
|
+
# Signatures verified automatically on handle_webhook()
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Available Tools
|
|
143
|
+
|
|
144
|
+
All AdCP tools with full type safety:
|
|
145
|
+
|
|
146
|
+
**Media Buy Lifecycle:**
|
|
147
|
+
- `get_products()` - Discover advertising products
|
|
148
|
+
- `list_creative_formats()` - Get supported creative formats
|
|
149
|
+
- `create_media_buy()` - Create new media buy
|
|
150
|
+
- `update_media_buy()` - Update existing media buy
|
|
151
|
+
- `sync_creatives()` - Upload/sync creative assets
|
|
152
|
+
- `list_creatives()` - List creative assets
|
|
153
|
+
- `get_media_buy_delivery()` - Get delivery performance
|
|
154
|
+
|
|
155
|
+
**Audience & Targeting:**
|
|
156
|
+
- `list_authorized_properties()` - Get authorized properties
|
|
157
|
+
- `get_signals()` - Get audience signals
|
|
158
|
+
- `activate_signal()` - Activate audience signals
|
|
159
|
+
- `provide_performance_feedback()` - Send performance feedback
|
|
160
|
+
|
|
161
|
+
## Property Discovery (AdCP v2.2.0)
|
|
162
|
+
|
|
163
|
+
Build agent registries by discovering properties agents can sell:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from adcp.discovery import PropertyCrawler, get_property_index
|
|
167
|
+
|
|
168
|
+
# Crawl agents to discover properties
|
|
169
|
+
crawler = PropertyCrawler()
|
|
170
|
+
await crawler.crawl_agents([
|
|
171
|
+
{"agent_url": "https://agent-x.com", "protocol": "a2a"},
|
|
172
|
+
{"agent_url": "https://agent-y.com/mcp/", "protocol": "mcp"}
|
|
173
|
+
])
|
|
174
|
+
|
|
175
|
+
index = get_property_index()
|
|
176
|
+
|
|
177
|
+
# Query 1: Who can sell this property?
|
|
178
|
+
matches = index.find_agents_for_property("domain", "cnn.com")
|
|
179
|
+
|
|
180
|
+
# Query 2: What can this agent sell?
|
|
181
|
+
auth = index.get_agent_authorizations("https://agent-x.com")
|
|
182
|
+
|
|
183
|
+
# Query 3: Find by tags
|
|
184
|
+
premium = index.find_agents_by_property_tags(["premium", "ctv"])
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Environment Configuration
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
# .env
|
|
191
|
+
WEBHOOK_URL_TEMPLATE="https://myapp.com/webhook/{task_type}/{agent_id}/{operation_id}"
|
|
192
|
+
WEBHOOK_SECRET="your-webhook-secret"
|
|
193
|
+
|
|
194
|
+
ADCP_AGENTS='[
|
|
195
|
+
{
|
|
196
|
+
"id": "agent_x",
|
|
197
|
+
"agent_uri": "https://agent-x.com",
|
|
198
|
+
"protocol": "a2a",
|
|
199
|
+
"auth_token_env": "AGENT_X_TOKEN"
|
|
200
|
+
}
|
|
201
|
+
]'
|
|
202
|
+
AGENT_X_TOKEN="actual-token-here"
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
# Auto-discover from environment
|
|
207
|
+
client = ADCPMultiAgentClient.from_env()
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Development
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
# Install with dev dependencies
|
|
214
|
+
pip install -e ".[dev]"
|
|
215
|
+
|
|
216
|
+
# Run tests
|
|
217
|
+
pytest
|
|
218
|
+
|
|
219
|
+
# Type checking
|
|
220
|
+
mypy src/
|
|
221
|
+
|
|
222
|
+
# Format code
|
|
223
|
+
black src/ tests/
|
|
224
|
+
ruff check src/ tests/
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Contributing
|
|
228
|
+
|
|
229
|
+
Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
230
|
+
|
|
231
|
+
## License
|
|
232
|
+
|
|
233
|
+
Apache 2.0 License - see [LICENSE](LICENSE) file for details.
|
|
234
|
+
|
|
235
|
+
## Support
|
|
236
|
+
|
|
237
|
+
- **Documentation**: [docs.adcontextprotocol.org](https://docs.adcontextprotocol.org)
|
|
238
|
+
- **Issues**: [GitHub Issues](https://github.com/adcontextprotocol/adcp-client-python/issues)
|
|
239
|
+
- **Protocol Spec**: [AdCP Specification](https://github.com/adcontextprotocol/adcp)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "adcp"
|
|
7
|
+
version = "0.1.2"
|
|
8
|
+
description = "Official Python client for the Ad Context Protocol (AdCP)"
|
|
9
|
+
authors = [
|
|
10
|
+
{name = "AdCP Community", email = "maintainers@adcontextprotocol.org"}
|
|
11
|
+
]
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
requires-python = ">=3.10"
|
|
14
|
+
license = {text = "Apache-2.0"}
|
|
15
|
+
keywords = ["adcp", "mcp", "a2a", "protocol", "advertising"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: Apache Software License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
dependencies = [
|
|
29
|
+
"httpx>=0.24.0",
|
|
30
|
+
"pydantic>=2.0.0",
|
|
31
|
+
"typing-extensions>=4.5.0",
|
|
32
|
+
"a2a-sdk>=0.3.0",
|
|
33
|
+
"mcp>=0.9.0",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
dev = [
|
|
38
|
+
"pytest>=7.0.0",
|
|
39
|
+
"pytest-asyncio>=0.21.0",
|
|
40
|
+
"pytest-cov>=4.0.0",
|
|
41
|
+
"mypy>=1.0.0",
|
|
42
|
+
"black>=23.0.0",
|
|
43
|
+
"ruff>=0.1.0",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
[project.urls]
|
|
47
|
+
Homepage = "https://github.com/adcontextprotocol/adcp-client-python"
|
|
48
|
+
Documentation = "https://docs.adcontextprotocol.org"
|
|
49
|
+
Repository = "https://github.com/adcontextprotocol/adcp-client-python"
|
|
50
|
+
Issues = "https://github.com/adcontextprotocol/adcp-client-python/issues"
|
|
51
|
+
|
|
52
|
+
[tool.setuptools.packages.find]
|
|
53
|
+
where = ["src"]
|
|
54
|
+
|
|
55
|
+
[tool.black]
|
|
56
|
+
line-length = 100
|
|
57
|
+
target-version = ["py310", "py311", "py312"]
|
|
58
|
+
|
|
59
|
+
[tool.ruff]
|
|
60
|
+
line-length = 100
|
|
61
|
+
target-version = "py310"
|
|
62
|
+
|
|
63
|
+
[tool.ruff.lint]
|
|
64
|
+
select = ["E", "F", "I", "N", "W", "UP"]
|
|
65
|
+
|
|
66
|
+
[tool.mypy]
|
|
67
|
+
python_version = "3.10"
|
|
68
|
+
strict = true
|
|
69
|
+
warn_return_any = true
|
|
70
|
+
warn_unused_configs = true
|
|
71
|
+
|
|
72
|
+
[[tool.mypy.overrides]]
|
|
73
|
+
module = "tests.*"
|
|
74
|
+
disable_error_code = ["import-not-found", "no-untyped-def", "var-annotated", "operator"]
|
|
75
|
+
|
|
76
|
+
[[tool.mypy.overrides]]
|
|
77
|
+
module = "tests.integration.*"
|
|
78
|
+
ignore_errors = true
|
|
79
|
+
|
|
80
|
+
[tool.pytest.ini_options]
|
|
81
|
+
testpaths = ["tests"]
|
|
82
|
+
asyncio_mode = "auto"
|
adcp-0.1.2/setup.cfg
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AdCP Python Client Library
|
|
3
|
+
|
|
4
|
+
Official Python client for the Ad Context Protocol (AdCP).
|
|
5
|
+
Supports both A2A and MCP protocols with full type safety.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from adcp.client import ADCPClient, ADCPMultiAgentClient
|
|
9
|
+
from adcp.types.core import AgentConfig, TaskResult, WebhookMetadata
|
|
10
|
+
|
|
11
|
+
__version__ = "0.1.2"
|
|
12
|
+
__all__ = [
|
|
13
|
+
"ADCPClient",
|
|
14
|
+
"ADCPMultiAgentClient",
|
|
15
|
+
"AgentConfig",
|
|
16
|
+
"TaskResult",
|
|
17
|
+
"WebhookMetadata",
|
|
18
|
+
]
|