adcp 1.2.1__tar.gz → 1.3.0__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-1.2.1/src/adcp.egg-info → adcp-1.3.0}/PKG-INFO +136 -1
- {adcp-1.2.1 → adcp-1.3.0}/README.md +135 -0
- {adcp-1.2.1 → adcp-1.3.0}/pyproject.toml +1 -1
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/__init__.py +24 -1
- adcp-1.3.0/src/adcp/testing/__init__.py +38 -0
- adcp-1.3.0/src/adcp/testing/test_helpers.py +311 -0
- {adcp-1.2.1 → adcp-1.3.0/src/adcp.egg-info}/PKG-INFO +136 -1
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp.egg-info/SOURCES.txt +3 -0
- adcp-1.3.0/tests/test_helpers.py +239 -0
- {adcp-1.2.1 → adcp-1.3.0}/LICENSE +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/setup.cfg +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/__main__.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/client.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/config.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/exceptions.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/protocols/__init__.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/protocols/a2a.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/protocols/base.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/protocols/mcp.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/types/__init__.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/types/core.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/types/generated.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/types/tasks.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/utils/__init__.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/utils/operation_id.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/utils/preview_cache.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp/utils/response_parser.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp.egg-info/dependency_links.txt +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp.egg-info/entry_points.txt +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp.egg-info/requires.txt +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/src/adcp.egg-info/top_level.txt +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/tests/test_cli.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/tests/test_client.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/tests/test_code_generation.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/tests/test_discriminated_unions.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/tests/test_format_id_validation.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/tests/test_preview_html.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/tests/test_protocols.py +0 -0
- {adcp-1.2.1 → adcp-1.3.0}/tests/test_response_parser.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: adcp
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Official Python client for the Ad Context Protocol (AdCP)
|
|
5
5
|
Author-email: AdCP Community <maintainers@adcontextprotocol.org>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -61,8 +61,43 @@ pip install adcp
|
|
|
61
61
|
|
|
62
62
|
> **Note**: This client requires Python 3.10 or later and supports both synchronous and asynchronous workflows.
|
|
63
63
|
|
|
64
|
+
## Quick Start: Test Helpers
|
|
65
|
+
|
|
66
|
+
The fastest way to get started is using the pre-configured test agents:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from adcp.testing import test_agent
|
|
70
|
+
from adcp.types.generated import GetProductsRequest
|
|
71
|
+
|
|
72
|
+
# Zero configuration - just import and use!
|
|
73
|
+
result = await test_agent.get_products(
|
|
74
|
+
GetProductsRequest(
|
|
75
|
+
brief="Coffee subscription service",
|
|
76
|
+
promoted_offering="Premium coffee deliveries"
|
|
77
|
+
)
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if result.success:
|
|
81
|
+
print(f"Found {len(result.data.products)} products")
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Test helpers include:
|
|
85
|
+
- **`test_agent`**: Pre-configured MCP test agent with authentication
|
|
86
|
+
- **`test_agent_a2a`**: Pre-configured A2A test agent with authentication
|
|
87
|
+
- **`test_agent_no_auth`**: Pre-configured MCP test agent WITHOUT authentication
|
|
88
|
+
- **`test_agent_a2a_no_auth`**: Pre-configured A2A test agent WITHOUT authentication
|
|
89
|
+
- **`creative_agent`**: Reference creative agent for preview functionality
|
|
90
|
+
- **`test_agent_client`**: Multi-agent client with both protocols
|
|
91
|
+
- **`create_test_agent()`**: Factory for custom test configurations
|
|
92
|
+
|
|
93
|
+
> **Note**: Test agents are rate-limited and for testing/examples only. DO NOT use in production.
|
|
94
|
+
|
|
95
|
+
See [examples/test_helpers_demo.py](examples/test_helpers_demo.py) for more examples.
|
|
96
|
+
|
|
64
97
|
## Quick Start: Distributed Operations
|
|
65
98
|
|
|
99
|
+
For production use, configure your own agents:
|
|
100
|
+
|
|
66
101
|
```python
|
|
67
102
|
from adcp import ADCPMultiAgentClient, AgentConfig, GetProductsRequest
|
|
68
103
|
|
|
@@ -112,6 +147,66 @@ async with ADCPMultiAgentClient(
|
|
|
112
147
|
|
|
113
148
|
## Features
|
|
114
149
|
|
|
150
|
+
### Test Helpers
|
|
151
|
+
|
|
152
|
+
Pre-configured test agents for instant prototyping and testing:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from adcp.testing import (
|
|
156
|
+
test_agent, test_agent_a2a,
|
|
157
|
+
test_agent_no_auth, test_agent_a2a_no_auth,
|
|
158
|
+
creative_agent, test_agent_client, create_test_agent
|
|
159
|
+
)
|
|
160
|
+
from adcp.types.generated import GetProductsRequest, PreviewCreativeRequest
|
|
161
|
+
|
|
162
|
+
# 1. Single agent with authentication (MCP)
|
|
163
|
+
result = await test_agent.get_products(
|
|
164
|
+
GetProductsRequest(brief="Coffee brands")
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# 2. Single agent with authentication (A2A)
|
|
168
|
+
result = await test_agent_a2a.get_products(
|
|
169
|
+
GetProductsRequest(brief="Coffee brands")
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
# 3. Single agent WITHOUT authentication (MCP)
|
|
173
|
+
# Useful for testing unauthenticated behavior
|
|
174
|
+
result = await test_agent_no_auth.get_products(
|
|
175
|
+
GetProductsRequest(brief="Coffee brands")
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
# 4. Single agent WITHOUT authentication (A2A)
|
|
179
|
+
result = await test_agent_a2a_no_auth.get_products(
|
|
180
|
+
GetProductsRequest(brief="Coffee brands")
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
# 5. Creative agent (preview functionality, no auth required)
|
|
184
|
+
result = await creative_agent.preview_creative(
|
|
185
|
+
PreviewCreativeRequest(
|
|
186
|
+
manifest={"format_id": "banner_300x250", "assets": {...}}
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# 6. Multi-agent (parallel execution with both protocols)
|
|
191
|
+
results = await test_agent_client.get_products(
|
|
192
|
+
GetProductsRequest(brief="Coffee brands")
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
# 7. Custom configuration
|
|
196
|
+
from adcp.client import ADCPClient
|
|
197
|
+
config = create_test_agent(id="my-test", timeout=60.0)
|
|
198
|
+
client = ADCPClient(config)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Use cases:**
|
|
202
|
+
- Quick prototyping and experimentation
|
|
203
|
+
- Example code and documentation
|
|
204
|
+
- Integration testing without mock servers
|
|
205
|
+
- Testing authentication behavior (comparing auth vs no-auth results)
|
|
206
|
+
- Learning AdCP concepts
|
|
207
|
+
|
|
208
|
+
**Important:** Test agents are public, rate-limited, and for testing only. Never use in production.
|
|
209
|
+
|
|
115
210
|
### Full Protocol Support
|
|
116
211
|
- **A2A Protocol**: Native support for Agent-to-Agent protocol
|
|
117
212
|
- **MCP Protocol**: Native support for Model Context Protocol
|
|
@@ -377,6 +472,46 @@ uvx adcp --json myagent get_products '{"brief":"TV ads"}'
|
|
|
377
472
|
uvx adcp --debug myagent get_products '{"brief":"TV ads"}'
|
|
378
473
|
```
|
|
379
474
|
|
|
475
|
+
### Using Test Agents from CLI
|
|
476
|
+
|
|
477
|
+
The CLI provides easy access to public test agents without configuration:
|
|
478
|
+
|
|
479
|
+
```bash
|
|
480
|
+
# Use test agent with authentication (MCP)
|
|
481
|
+
uvx adcp https://test-agent.adcontextprotocol.org/mcp/ \
|
|
482
|
+
--auth 1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ \
|
|
483
|
+
get_products '{"brief":"Coffee brands"}'
|
|
484
|
+
|
|
485
|
+
# Use test agent WITHOUT authentication (MCP)
|
|
486
|
+
uvx adcp https://test-agent.adcontextprotocol.org/mcp/ \
|
|
487
|
+
get_products '{"brief":"Coffee brands"}'
|
|
488
|
+
|
|
489
|
+
# Use test agent with authentication (A2A)
|
|
490
|
+
uvx adcp --protocol a2a \
|
|
491
|
+
--auth 1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ \
|
|
492
|
+
https://test-agent.adcontextprotocol.org \
|
|
493
|
+
get_products '{"brief":"Coffee brands"}'
|
|
494
|
+
|
|
495
|
+
# Save test agent for easier access
|
|
496
|
+
uvx adcp --save-auth test-agent https://test-agent.adcontextprotocol.org/mcp/ mcp
|
|
497
|
+
# Enter token when prompted: 1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ
|
|
498
|
+
|
|
499
|
+
# Now use saved config
|
|
500
|
+
uvx adcp test-agent get_products '{"brief":"Coffee brands"}'
|
|
501
|
+
|
|
502
|
+
# Use creative agent (no auth required)
|
|
503
|
+
uvx adcp https://creative.adcontextprotocol.org/mcp \
|
|
504
|
+
preview_creative @creative_manifest.json
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
**Test Agent Details:**
|
|
508
|
+
- **URL (MCP)**: `https://test-agent.adcontextprotocol.org/mcp/`
|
|
509
|
+
- **URL (A2A)**: `https://test-agent.adcontextprotocol.org`
|
|
510
|
+
- **Auth Token**: `1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ` (optional, public token)
|
|
511
|
+
- **Rate Limited**: For testing only, not for production
|
|
512
|
+
- **No Auth Mode**: Omit `--auth` flag to test unauthenticated behavior
|
|
513
|
+
```
|
|
514
|
+
|
|
380
515
|
### Configuration Management
|
|
381
516
|
|
|
382
517
|
```bash
|
|
@@ -24,8 +24,43 @@ pip install adcp
|
|
|
24
24
|
|
|
25
25
|
> **Note**: This client requires Python 3.10 or later and supports both synchronous and asynchronous workflows.
|
|
26
26
|
|
|
27
|
+
## Quick Start: Test Helpers
|
|
28
|
+
|
|
29
|
+
The fastest way to get started is using the pre-configured test agents:
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
from adcp.testing import test_agent
|
|
33
|
+
from adcp.types.generated import GetProductsRequest
|
|
34
|
+
|
|
35
|
+
# Zero configuration - just import and use!
|
|
36
|
+
result = await test_agent.get_products(
|
|
37
|
+
GetProductsRequest(
|
|
38
|
+
brief="Coffee subscription service",
|
|
39
|
+
promoted_offering="Premium coffee deliveries"
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
if result.success:
|
|
44
|
+
print(f"Found {len(result.data.products)} products")
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Test helpers include:
|
|
48
|
+
- **`test_agent`**: Pre-configured MCP test agent with authentication
|
|
49
|
+
- **`test_agent_a2a`**: Pre-configured A2A test agent with authentication
|
|
50
|
+
- **`test_agent_no_auth`**: Pre-configured MCP test agent WITHOUT authentication
|
|
51
|
+
- **`test_agent_a2a_no_auth`**: Pre-configured A2A test agent WITHOUT authentication
|
|
52
|
+
- **`creative_agent`**: Reference creative agent for preview functionality
|
|
53
|
+
- **`test_agent_client`**: Multi-agent client with both protocols
|
|
54
|
+
- **`create_test_agent()`**: Factory for custom test configurations
|
|
55
|
+
|
|
56
|
+
> **Note**: Test agents are rate-limited and for testing/examples only. DO NOT use in production.
|
|
57
|
+
|
|
58
|
+
See [examples/test_helpers_demo.py](examples/test_helpers_demo.py) for more examples.
|
|
59
|
+
|
|
27
60
|
## Quick Start: Distributed Operations
|
|
28
61
|
|
|
62
|
+
For production use, configure your own agents:
|
|
63
|
+
|
|
29
64
|
```python
|
|
30
65
|
from adcp import ADCPMultiAgentClient, AgentConfig, GetProductsRequest
|
|
31
66
|
|
|
@@ -75,6 +110,66 @@ async with ADCPMultiAgentClient(
|
|
|
75
110
|
|
|
76
111
|
## Features
|
|
77
112
|
|
|
113
|
+
### Test Helpers
|
|
114
|
+
|
|
115
|
+
Pre-configured test agents for instant prototyping and testing:
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
from adcp.testing import (
|
|
119
|
+
test_agent, test_agent_a2a,
|
|
120
|
+
test_agent_no_auth, test_agent_a2a_no_auth,
|
|
121
|
+
creative_agent, test_agent_client, create_test_agent
|
|
122
|
+
)
|
|
123
|
+
from adcp.types.generated import GetProductsRequest, PreviewCreativeRequest
|
|
124
|
+
|
|
125
|
+
# 1. Single agent with authentication (MCP)
|
|
126
|
+
result = await test_agent.get_products(
|
|
127
|
+
GetProductsRequest(brief="Coffee brands")
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# 2. Single agent with authentication (A2A)
|
|
131
|
+
result = await test_agent_a2a.get_products(
|
|
132
|
+
GetProductsRequest(brief="Coffee brands")
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# 3. Single agent WITHOUT authentication (MCP)
|
|
136
|
+
# Useful for testing unauthenticated behavior
|
|
137
|
+
result = await test_agent_no_auth.get_products(
|
|
138
|
+
GetProductsRequest(brief="Coffee brands")
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# 4. Single agent WITHOUT authentication (A2A)
|
|
142
|
+
result = await test_agent_a2a_no_auth.get_products(
|
|
143
|
+
GetProductsRequest(brief="Coffee brands")
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# 5. Creative agent (preview functionality, no auth required)
|
|
147
|
+
result = await creative_agent.preview_creative(
|
|
148
|
+
PreviewCreativeRequest(
|
|
149
|
+
manifest={"format_id": "banner_300x250", "assets": {...}}
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
# 6. Multi-agent (parallel execution with both protocols)
|
|
154
|
+
results = await test_agent_client.get_products(
|
|
155
|
+
GetProductsRequest(brief="Coffee brands")
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# 7. Custom configuration
|
|
159
|
+
from adcp.client import ADCPClient
|
|
160
|
+
config = create_test_agent(id="my-test", timeout=60.0)
|
|
161
|
+
client = ADCPClient(config)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Use cases:**
|
|
165
|
+
- Quick prototyping and experimentation
|
|
166
|
+
- Example code and documentation
|
|
167
|
+
- Integration testing without mock servers
|
|
168
|
+
- Testing authentication behavior (comparing auth vs no-auth results)
|
|
169
|
+
- Learning AdCP concepts
|
|
170
|
+
|
|
171
|
+
**Important:** Test agents are public, rate-limited, and for testing only. Never use in production.
|
|
172
|
+
|
|
78
173
|
### Full Protocol Support
|
|
79
174
|
- **A2A Protocol**: Native support for Agent-to-Agent protocol
|
|
80
175
|
- **MCP Protocol**: Native support for Model Context Protocol
|
|
@@ -340,6 +435,46 @@ uvx adcp --json myagent get_products '{"brief":"TV ads"}'
|
|
|
340
435
|
uvx adcp --debug myagent get_products '{"brief":"TV ads"}'
|
|
341
436
|
```
|
|
342
437
|
|
|
438
|
+
### Using Test Agents from CLI
|
|
439
|
+
|
|
440
|
+
The CLI provides easy access to public test agents without configuration:
|
|
441
|
+
|
|
442
|
+
```bash
|
|
443
|
+
# Use test agent with authentication (MCP)
|
|
444
|
+
uvx adcp https://test-agent.adcontextprotocol.org/mcp/ \
|
|
445
|
+
--auth 1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ \
|
|
446
|
+
get_products '{"brief":"Coffee brands"}'
|
|
447
|
+
|
|
448
|
+
# Use test agent WITHOUT authentication (MCP)
|
|
449
|
+
uvx adcp https://test-agent.adcontextprotocol.org/mcp/ \
|
|
450
|
+
get_products '{"brief":"Coffee brands"}'
|
|
451
|
+
|
|
452
|
+
# Use test agent with authentication (A2A)
|
|
453
|
+
uvx adcp --protocol a2a \
|
|
454
|
+
--auth 1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ \
|
|
455
|
+
https://test-agent.adcontextprotocol.org \
|
|
456
|
+
get_products '{"brief":"Coffee brands"}'
|
|
457
|
+
|
|
458
|
+
# Save test agent for easier access
|
|
459
|
+
uvx adcp --save-auth test-agent https://test-agent.adcontextprotocol.org/mcp/ mcp
|
|
460
|
+
# Enter token when prompted: 1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ
|
|
461
|
+
|
|
462
|
+
# Now use saved config
|
|
463
|
+
uvx adcp test-agent get_products '{"brief":"Coffee brands"}'
|
|
464
|
+
|
|
465
|
+
# Use creative agent (no auth required)
|
|
466
|
+
uvx adcp https://creative.adcontextprotocol.org/mcp \
|
|
467
|
+
preview_creative @creative_manifest.json
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
**Test Agent Details:**
|
|
471
|
+
- **URL (MCP)**: `https://test-agent.adcontextprotocol.org/mcp/`
|
|
472
|
+
- **URL (A2A)**: `https://test-agent.adcontextprotocol.org`
|
|
473
|
+
- **Auth Token**: `1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ` (optional, public token)
|
|
474
|
+
- **Rate Limited**: For testing only, not for production
|
|
475
|
+
- **No Auth Mode**: Omit `--auth` flag to test unauthenticated behavior
|
|
476
|
+
```
|
|
477
|
+
|
|
343
478
|
### Configuration Management
|
|
344
479
|
|
|
345
480
|
```bash
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "adcp"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.3.0"
|
|
8
8
|
description = "Official Python client for the Ad Context Protocol (AdCP)"
|
|
9
9
|
authors = [
|
|
10
10
|
{name = "AdCP Community", email = "maintainers@adcontextprotocol.org"}
|
|
@@ -18,6 +18,19 @@ from adcp.exceptions import (
|
|
|
18
18
|
ADCPWebhookError,
|
|
19
19
|
ADCPWebhookSignatureError,
|
|
20
20
|
)
|
|
21
|
+
|
|
22
|
+
# Test helpers
|
|
23
|
+
from adcp.testing import (
|
|
24
|
+
CREATIVE_AGENT_CONFIG,
|
|
25
|
+
TEST_AGENT_A2A_CONFIG,
|
|
26
|
+
TEST_AGENT_MCP_CONFIG,
|
|
27
|
+
TEST_AGENT_TOKEN,
|
|
28
|
+
create_test_agent,
|
|
29
|
+
creative_agent,
|
|
30
|
+
test_agent,
|
|
31
|
+
test_agent_a2a,
|
|
32
|
+
test_agent_client,
|
|
33
|
+
)
|
|
21
34
|
from adcp.types.core import AgentConfig, Protocol, TaskResult, TaskStatus, WebhookMetadata
|
|
22
35
|
from adcp.types.generated import (
|
|
23
36
|
ActivateSignalError,
|
|
@@ -133,7 +146,7 @@ from adcp.types.generated import (
|
|
|
133
146
|
TaskStatus as GeneratedTaskStatus,
|
|
134
147
|
)
|
|
135
148
|
|
|
136
|
-
__version__ = "1.
|
|
149
|
+
__version__ = "1.3.0"
|
|
137
150
|
|
|
138
151
|
__all__ = [
|
|
139
152
|
# Client classes
|
|
@@ -145,6 +158,16 @@ __all__ = [
|
|
|
145
158
|
"TaskResult",
|
|
146
159
|
"TaskStatus",
|
|
147
160
|
"WebhookMetadata",
|
|
161
|
+
# Test helpers
|
|
162
|
+
"test_agent",
|
|
163
|
+
"test_agent_a2a",
|
|
164
|
+
"creative_agent",
|
|
165
|
+
"test_agent_client",
|
|
166
|
+
"create_test_agent",
|
|
167
|
+
"TEST_AGENT_TOKEN",
|
|
168
|
+
"TEST_AGENT_MCP_CONFIG",
|
|
169
|
+
"TEST_AGENT_A2A_CONFIG",
|
|
170
|
+
"CREATIVE_AGENT_CONFIG",
|
|
148
171
|
# Exceptions
|
|
149
172
|
"ADCPError",
|
|
150
173
|
"ADCPConnectionError",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Test helpers for AdCP client library.
|
|
2
|
+
|
|
3
|
+
Provides pre-configured test agents for examples and quick testing.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from adcp.testing.test_helpers import (
|
|
9
|
+
CREATIVE_AGENT_CONFIG,
|
|
10
|
+
TEST_AGENT_A2A_CONFIG,
|
|
11
|
+
TEST_AGENT_A2A_NO_AUTH_CONFIG,
|
|
12
|
+
TEST_AGENT_MCP_CONFIG,
|
|
13
|
+
TEST_AGENT_MCP_NO_AUTH_CONFIG,
|
|
14
|
+
TEST_AGENT_TOKEN,
|
|
15
|
+
create_test_agent,
|
|
16
|
+
creative_agent,
|
|
17
|
+
test_agent,
|
|
18
|
+
test_agent_a2a,
|
|
19
|
+
test_agent_a2a_no_auth,
|
|
20
|
+
test_agent_client,
|
|
21
|
+
test_agent_no_auth,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
"test_agent",
|
|
26
|
+
"test_agent_a2a",
|
|
27
|
+
"test_agent_no_auth",
|
|
28
|
+
"test_agent_a2a_no_auth",
|
|
29
|
+
"creative_agent",
|
|
30
|
+
"test_agent_client",
|
|
31
|
+
"create_test_agent",
|
|
32
|
+
"TEST_AGENT_TOKEN",
|
|
33
|
+
"TEST_AGENT_MCP_CONFIG",
|
|
34
|
+
"TEST_AGENT_A2A_CONFIG",
|
|
35
|
+
"TEST_AGENT_MCP_NO_AUTH_CONFIG",
|
|
36
|
+
"TEST_AGENT_A2A_NO_AUTH_CONFIG",
|
|
37
|
+
"CREATIVE_AGENT_CONFIG",
|
|
38
|
+
]
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
"""Test agent helpers for easy examples and quick testing.
|
|
2
|
+
|
|
3
|
+
These provide pre-configured access to AdCP's public test agent.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from adcp.client import ADCPClient, ADCPMultiAgentClient
|
|
11
|
+
from adcp.types.core import AgentConfig, Protocol
|
|
12
|
+
|
|
13
|
+
# Public test agent auth token
|
|
14
|
+
# This token is public and rate-limited, for testing/examples only.
|
|
15
|
+
TEST_AGENT_TOKEN = "1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ"
|
|
16
|
+
|
|
17
|
+
# Public test agent configuration - MCP protocol
|
|
18
|
+
TEST_AGENT_MCP_CONFIG = AgentConfig(
|
|
19
|
+
id="test-agent-mcp",
|
|
20
|
+
agent_uri="https://test-agent.adcontextprotocol.org/mcp/",
|
|
21
|
+
protocol=Protocol.MCP,
|
|
22
|
+
auth_token=TEST_AGENT_TOKEN,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# Public test agent configuration - A2A protocol
|
|
26
|
+
TEST_AGENT_A2A_CONFIG = AgentConfig(
|
|
27
|
+
id="test-agent-a2a",
|
|
28
|
+
agent_uri="https://test-agent.adcontextprotocol.org",
|
|
29
|
+
protocol=Protocol.A2A,
|
|
30
|
+
auth_token=TEST_AGENT_TOKEN,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# Public test agent configuration (no auth) - MCP protocol
|
|
34
|
+
TEST_AGENT_MCP_NO_AUTH_CONFIG = AgentConfig(
|
|
35
|
+
id="test-agent-mcp-no-auth",
|
|
36
|
+
agent_uri="https://test-agent.adcontextprotocol.org/mcp/",
|
|
37
|
+
protocol=Protocol.MCP,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# Public test agent configuration (no auth) - A2A protocol
|
|
41
|
+
TEST_AGENT_A2A_NO_AUTH_CONFIG = AgentConfig(
|
|
42
|
+
id="test-agent-a2a-no-auth",
|
|
43
|
+
agent_uri="https://test-agent.adcontextprotocol.org",
|
|
44
|
+
protocol=Protocol.A2A,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Reference creative agent configuration - MCP protocol
|
|
48
|
+
# No authentication required for the reference creative agent
|
|
49
|
+
CREATIVE_AGENT_CONFIG = AgentConfig(
|
|
50
|
+
id="creative-agent",
|
|
51
|
+
agent_uri="https://creative.adcontextprotocol.org/mcp",
|
|
52
|
+
protocol=Protocol.MCP,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _create_test_agent_client() -> ADCPClient:
|
|
57
|
+
"""Create pre-configured test agent client using MCP protocol.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
ADCPClient instance configured for the public test agent
|
|
61
|
+
|
|
62
|
+
Note:
|
|
63
|
+
This agent is rate-limited and intended for testing/examples only.
|
|
64
|
+
The auth token is public and may be rotated without notice.
|
|
65
|
+
DO NOT use in production applications.
|
|
66
|
+
"""
|
|
67
|
+
return ADCPClient(TEST_AGENT_MCP_CONFIG)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _create_test_agent_a2a_client() -> ADCPClient:
|
|
71
|
+
"""Create pre-configured test agent client using A2A protocol.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
ADCPClient instance configured for the public test agent
|
|
75
|
+
|
|
76
|
+
Note:
|
|
77
|
+
This agent is rate-limited and intended for testing/examples only.
|
|
78
|
+
The auth token is public and may be rotated without notice.
|
|
79
|
+
DO NOT use in production applications.
|
|
80
|
+
"""
|
|
81
|
+
return ADCPClient(TEST_AGENT_A2A_CONFIG)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _create_test_agent_no_auth_client() -> ADCPClient:
|
|
85
|
+
"""Create pre-configured test agent client (no auth) using MCP protocol.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
ADCPClient instance configured for the public test agent without authentication
|
|
89
|
+
|
|
90
|
+
Note:
|
|
91
|
+
This agent is rate-limited and intended for testing scenarios where no auth is provided.
|
|
92
|
+
Useful for testing behavior differences between authenticated and unauthenticated requests.
|
|
93
|
+
DO NOT use in production applications.
|
|
94
|
+
"""
|
|
95
|
+
return ADCPClient(TEST_AGENT_MCP_NO_AUTH_CONFIG)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _create_test_agent_a2a_no_auth_client() -> ADCPClient:
|
|
99
|
+
"""Create pre-configured test agent client (no auth) using A2A protocol.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
ADCPClient instance configured for the public test agent without authentication
|
|
103
|
+
|
|
104
|
+
Note:
|
|
105
|
+
This agent is rate-limited and intended for testing scenarios where no auth is provided.
|
|
106
|
+
Useful for testing behavior differences between authenticated and unauthenticated requests.
|
|
107
|
+
DO NOT use in production applications.
|
|
108
|
+
"""
|
|
109
|
+
return ADCPClient(TEST_AGENT_A2A_NO_AUTH_CONFIG)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _create_creative_agent_client() -> ADCPClient:
|
|
113
|
+
"""Create pre-configured creative agent client.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
ADCPClient instance configured for the reference creative agent
|
|
117
|
+
|
|
118
|
+
Note:
|
|
119
|
+
The reference creative agent is public and requires no authentication.
|
|
120
|
+
It provides creative preview functionality for testing and examples.
|
|
121
|
+
"""
|
|
122
|
+
return ADCPClient(CREATIVE_AGENT_CONFIG)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _create_test_multi_agent_client() -> ADCPMultiAgentClient:
|
|
126
|
+
"""Create multi-agent client with both test agents configured.
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
ADCPMultiAgentClient with both MCP and A2A test agents
|
|
130
|
+
|
|
131
|
+
Note:
|
|
132
|
+
This client is rate-limited and intended for testing/examples only.
|
|
133
|
+
DO NOT use in production applications.
|
|
134
|
+
"""
|
|
135
|
+
return ADCPMultiAgentClient([TEST_AGENT_MCP_CONFIG, TEST_AGENT_A2A_CONFIG])
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
# Pre-configured test agent client using MCP protocol.
|
|
139
|
+
# Ready to use for examples, documentation, and quick testing.
|
|
140
|
+
#
|
|
141
|
+
# Example:
|
|
142
|
+
# ```python
|
|
143
|
+
# from adcp.testing import test_agent
|
|
144
|
+
#
|
|
145
|
+
# # Simple get_products call
|
|
146
|
+
# result = await test_agent.get_products(
|
|
147
|
+
# GetProductsRequest(
|
|
148
|
+
# brief="Coffee subscription service for busy professionals",
|
|
149
|
+
# promoted_offering="Premium monthly coffee deliveries"
|
|
150
|
+
# )
|
|
151
|
+
# )
|
|
152
|
+
#
|
|
153
|
+
# if result.success:
|
|
154
|
+
# print(f"Found {len(result.data.products)} products")
|
|
155
|
+
# ```
|
|
156
|
+
#
|
|
157
|
+
# Note:
|
|
158
|
+
# This agent is rate-limited and intended for testing/examples only.
|
|
159
|
+
# The auth token is public and may be rotated without notice.
|
|
160
|
+
# DO NOT use in production applications.
|
|
161
|
+
test_agent: ADCPClient = _create_test_agent_client()
|
|
162
|
+
|
|
163
|
+
# Pre-configured test agent client using A2A protocol.
|
|
164
|
+
# Identical functionality to test_agent but uses A2A instead of MCP.
|
|
165
|
+
#
|
|
166
|
+
# Example:
|
|
167
|
+
# ```python
|
|
168
|
+
# from adcp.testing import test_agent_a2a
|
|
169
|
+
#
|
|
170
|
+
# result = await test_agent_a2a.get_products(
|
|
171
|
+
# GetProductsRequest(
|
|
172
|
+
# brief="Sustainable fashion brands",
|
|
173
|
+
# promoted_offering="Eco-friendly clothing"
|
|
174
|
+
# )
|
|
175
|
+
# )
|
|
176
|
+
# ```
|
|
177
|
+
#
|
|
178
|
+
# Note:
|
|
179
|
+
# This agent is rate-limited and intended for testing/examples only.
|
|
180
|
+
# The auth token is public and may be rotated without notice.
|
|
181
|
+
# DO NOT use in production applications.
|
|
182
|
+
test_agent_a2a: ADCPClient = _create_test_agent_a2a_client()
|
|
183
|
+
|
|
184
|
+
# Pre-configured test agent client (no auth) using MCP protocol.
|
|
185
|
+
# Useful for testing scenarios where authentication is not provided,
|
|
186
|
+
# such as testing how agents handle unauthenticated requests or
|
|
187
|
+
# comparing behavior between authenticated and unauthenticated calls.
|
|
188
|
+
#
|
|
189
|
+
# Example:
|
|
190
|
+
# ```python
|
|
191
|
+
# from adcp.testing import test_agent_no_auth
|
|
192
|
+
#
|
|
193
|
+
# # Test behavior without authentication
|
|
194
|
+
# result = await test_agent_no_auth.get_products(
|
|
195
|
+
# GetProductsRequest(
|
|
196
|
+
# brief="Coffee subscription service",
|
|
197
|
+
# promoted_offering="Premium monthly coffee"
|
|
198
|
+
# )
|
|
199
|
+
# )
|
|
200
|
+
# ```
|
|
201
|
+
#
|
|
202
|
+
# Note:
|
|
203
|
+
# This agent is rate-limited and intended for testing/examples only.
|
|
204
|
+
# DO NOT use in production applications.
|
|
205
|
+
test_agent_no_auth: ADCPClient = _create_test_agent_no_auth_client()
|
|
206
|
+
|
|
207
|
+
# Pre-configured test agent client (no auth) using A2A protocol.
|
|
208
|
+
# Identical functionality to test_agent_no_auth but uses A2A instead of MCP.
|
|
209
|
+
#
|
|
210
|
+
# Example:
|
|
211
|
+
# ```python
|
|
212
|
+
# from adcp.testing import test_agent_a2a_no_auth
|
|
213
|
+
#
|
|
214
|
+
# # Test A2A behavior without authentication
|
|
215
|
+
# result = await test_agent_a2a_no_auth.get_products(
|
|
216
|
+
# GetProductsRequest(
|
|
217
|
+
# brief="Sustainable fashion brands",
|
|
218
|
+
# promoted_offering="Eco-friendly clothing"
|
|
219
|
+
# )
|
|
220
|
+
# )
|
|
221
|
+
# ```
|
|
222
|
+
#
|
|
223
|
+
# Note:
|
|
224
|
+
# This agent is rate-limited and intended for testing/examples only.
|
|
225
|
+
# DO NOT use in production applications.
|
|
226
|
+
test_agent_a2a_no_auth: ADCPClient = _create_test_agent_a2a_no_auth_client()
|
|
227
|
+
|
|
228
|
+
# Pre-configured reference creative agent.
|
|
229
|
+
# Provides creative preview functionality without authentication.
|
|
230
|
+
#
|
|
231
|
+
# Example:
|
|
232
|
+
# ```python
|
|
233
|
+
# from adcp.testing import creative_agent
|
|
234
|
+
# from adcp.types.generated import PreviewCreativeRequest
|
|
235
|
+
#
|
|
236
|
+
# result = await creative_agent.preview_creative(
|
|
237
|
+
# PreviewCreativeRequest(
|
|
238
|
+
# manifest={
|
|
239
|
+
# "format_id": "banner_300x250",
|
|
240
|
+
# "assets": {...}
|
|
241
|
+
# }
|
|
242
|
+
# )
|
|
243
|
+
# )
|
|
244
|
+
# ```
|
|
245
|
+
#
|
|
246
|
+
# Note:
|
|
247
|
+
# The reference creative agent is public and requires no authentication.
|
|
248
|
+
# Perfect for testing creative rendering and preview functionality.
|
|
249
|
+
creative_agent: ADCPClient = _create_creative_agent_client()
|
|
250
|
+
|
|
251
|
+
# Multi-agent client with both test agents configured.
|
|
252
|
+
# Useful for testing multi-agent patterns and protocol comparisons.
|
|
253
|
+
#
|
|
254
|
+
# Example:
|
|
255
|
+
# ```python
|
|
256
|
+
# from adcp.testing import test_agent_client
|
|
257
|
+
#
|
|
258
|
+
# # Access individual agents
|
|
259
|
+
# mcp_agent = test_agent_client.agent("test-agent-mcp")
|
|
260
|
+
# a2a_agent = test_agent_client.agent("test-agent-a2a")
|
|
261
|
+
#
|
|
262
|
+
# # Use for parallel operations
|
|
263
|
+
# results = await test_agent_client.get_products(
|
|
264
|
+
# GetProductsRequest(
|
|
265
|
+
# brief="Premium coffee brands",
|
|
266
|
+
# promoted_offering="Artisan coffee"
|
|
267
|
+
# )
|
|
268
|
+
# )
|
|
269
|
+
# ```
|
|
270
|
+
#
|
|
271
|
+
# Note:
|
|
272
|
+
# This client is rate-limited and intended for testing/examples only.
|
|
273
|
+
# DO NOT use in production applications.
|
|
274
|
+
test_agent_client: ADCPMultiAgentClient = _create_test_multi_agent_client()
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def create_test_agent(**overrides: Any) -> AgentConfig:
|
|
278
|
+
"""Create a custom test agent configuration.
|
|
279
|
+
|
|
280
|
+
Useful when you need to modify the default test agent setup.
|
|
281
|
+
|
|
282
|
+
Args:
|
|
283
|
+
**overrides: Keyword arguments to override default config values
|
|
284
|
+
|
|
285
|
+
Returns:
|
|
286
|
+
Complete agent configuration
|
|
287
|
+
|
|
288
|
+
Example:
|
|
289
|
+
```python
|
|
290
|
+
from adcp.testing import create_test_agent
|
|
291
|
+
from adcp.client import ADCPClient
|
|
292
|
+
|
|
293
|
+
# Use default test agent with custom ID
|
|
294
|
+
config = create_test_agent(id="my-test-agent")
|
|
295
|
+
client = ADCPClient(config)
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Example:
|
|
299
|
+
```python
|
|
300
|
+
# Use A2A protocol instead of MCP
|
|
301
|
+
from adcp.types.core import Protocol
|
|
302
|
+
|
|
303
|
+
config = create_test_agent(
|
|
304
|
+
protocol=Protocol.A2A,
|
|
305
|
+
agent_uri="https://test-agent.adcontextprotocol.org"
|
|
306
|
+
)
|
|
307
|
+
```
|
|
308
|
+
"""
|
|
309
|
+
base_config = TEST_AGENT_MCP_CONFIG.model_dump()
|
|
310
|
+
base_config.update(overrides)
|
|
311
|
+
return AgentConfig(**base_config)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: adcp
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Official Python client for the Ad Context Protocol (AdCP)
|
|
5
5
|
Author-email: AdCP Community <maintainers@adcontextprotocol.org>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -61,8 +61,43 @@ pip install adcp
|
|
|
61
61
|
|
|
62
62
|
> **Note**: This client requires Python 3.10 or later and supports both synchronous and asynchronous workflows.
|
|
63
63
|
|
|
64
|
+
## Quick Start: Test Helpers
|
|
65
|
+
|
|
66
|
+
The fastest way to get started is using the pre-configured test agents:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from adcp.testing import test_agent
|
|
70
|
+
from adcp.types.generated import GetProductsRequest
|
|
71
|
+
|
|
72
|
+
# Zero configuration - just import and use!
|
|
73
|
+
result = await test_agent.get_products(
|
|
74
|
+
GetProductsRequest(
|
|
75
|
+
brief="Coffee subscription service",
|
|
76
|
+
promoted_offering="Premium coffee deliveries"
|
|
77
|
+
)
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if result.success:
|
|
81
|
+
print(f"Found {len(result.data.products)} products")
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Test helpers include:
|
|
85
|
+
- **`test_agent`**: Pre-configured MCP test agent with authentication
|
|
86
|
+
- **`test_agent_a2a`**: Pre-configured A2A test agent with authentication
|
|
87
|
+
- **`test_agent_no_auth`**: Pre-configured MCP test agent WITHOUT authentication
|
|
88
|
+
- **`test_agent_a2a_no_auth`**: Pre-configured A2A test agent WITHOUT authentication
|
|
89
|
+
- **`creative_agent`**: Reference creative agent for preview functionality
|
|
90
|
+
- **`test_agent_client`**: Multi-agent client with both protocols
|
|
91
|
+
- **`create_test_agent()`**: Factory for custom test configurations
|
|
92
|
+
|
|
93
|
+
> **Note**: Test agents are rate-limited and for testing/examples only. DO NOT use in production.
|
|
94
|
+
|
|
95
|
+
See [examples/test_helpers_demo.py](examples/test_helpers_demo.py) for more examples.
|
|
96
|
+
|
|
64
97
|
## Quick Start: Distributed Operations
|
|
65
98
|
|
|
99
|
+
For production use, configure your own agents:
|
|
100
|
+
|
|
66
101
|
```python
|
|
67
102
|
from adcp import ADCPMultiAgentClient, AgentConfig, GetProductsRequest
|
|
68
103
|
|
|
@@ -112,6 +147,66 @@ async with ADCPMultiAgentClient(
|
|
|
112
147
|
|
|
113
148
|
## Features
|
|
114
149
|
|
|
150
|
+
### Test Helpers
|
|
151
|
+
|
|
152
|
+
Pre-configured test agents for instant prototyping and testing:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from adcp.testing import (
|
|
156
|
+
test_agent, test_agent_a2a,
|
|
157
|
+
test_agent_no_auth, test_agent_a2a_no_auth,
|
|
158
|
+
creative_agent, test_agent_client, create_test_agent
|
|
159
|
+
)
|
|
160
|
+
from adcp.types.generated import GetProductsRequest, PreviewCreativeRequest
|
|
161
|
+
|
|
162
|
+
# 1. Single agent with authentication (MCP)
|
|
163
|
+
result = await test_agent.get_products(
|
|
164
|
+
GetProductsRequest(brief="Coffee brands")
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# 2. Single agent with authentication (A2A)
|
|
168
|
+
result = await test_agent_a2a.get_products(
|
|
169
|
+
GetProductsRequest(brief="Coffee brands")
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
# 3. Single agent WITHOUT authentication (MCP)
|
|
173
|
+
# Useful for testing unauthenticated behavior
|
|
174
|
+
result = await test_agent_no_auth.get_products(
|
|
175
|
+
GetProductsRequest(brief="Coffee brands")
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
# 4. Single agent WITHOUT authentication (A2A)
|
|
179
|
+
result = await test_agent_a2a_no_auth.get_products(
|
|
180
|
+
GetProductsRequest(brief="Coffee brands")
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
# 5. Creative agent (preview functionality, no auth required)
|
|
184
|
+
result = await creative_agent.preview_creative(
|
|
185
|
+
PreviewCreativeRequest(
|
|
186
|
+
manifest={"format_id": "banner_300x250", "assets": {...}}
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# 6. Multi-agent (parallel execution with both protocols)
|
|
191
|
+
results = await test_agent_client.get_products(
|
|
192
|
+
GetProductsRequest(brief="Coffee brands")
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
# 7. Custom configuration
|
|
196
|
+
from adcp.client import ADCPClient
|
|
197
|
+
config = create_test_agent(id="my-test", timeout=60.0)
|
|
198
|
+
client = ADCPClient(config)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Use cases:**
|
|
202
|
+
- Quick prototyping and experimentation
|
|
203
|
+
- Example code and documentation
|
|
204
|
+
- Integration testing without mock servers
|
|
205
|
+
- Testing authentication behavior (comparing auth vs no-auth results)
|
|
206
|
+
- Learning AdCP concepts
|
|
207
|
+
|
|
208
|
+
**Important:** Test agents are public, rate-limited, and for testing only. Never use in production.
|
|
209
|
+
|
|
115
210
|
### Full Protocol Support
|
|
116
211
|
- **A2A Protocol**: Native support for Agent-to-Agent protocol
|
|
117
212
|
- **MCP Protocol**: Native support for Model Context Protocol
|
|
@@ -377,6 +472,46 @@ uvx adcp --json myagent get_products '{"brief":"TV ads"}'
|
|
|
377
472
|
uvx adcp --debug myagent get_products '{"brief":"TV ads"}'
|
|
378
473
|
```
|
|
379
474
|
|
|
475
|
+
### Using Test Agents from CLI
|
|
476
|
+
|
|
477
|
+
The CLI provides easy access to public test agents without configuration:
|
|
478
|
+
|
|
479
|
+
```bash
|
|
480
|
+
# Use test agent with authentication (MCP)
|
|
481
|
+
uvx adcp https://test-agent.adcontextprotocol.org/mcp/ \
|
|
482
|
+
--auth 1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ \
|
|
483
|
+
get_products '{"brief":"Coffee brands"}'
|
|
484
|
+
|
|
485
|
+
# Use test agent WITHOUT authentication (MCP)
|
|
486
|
+
uvx adcp https://test-agent.adcontextprotocol.org/mcp/ \
|
|
487
|
+
get_products '{"brief":"Coffee brands"}'
|
|
488
|
+
|
|
489
|
+
# Use test agent with authentication (A2A)
|
|
490
|
+
uvx adcp --protocol a2a \
|
|
491
|
+
--auth 1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ \
|
|
492
|
+
https://test-agent.adcontextprotocol.org \
|
|
493
|
+
get_products '{"brief":"Coffee brands"}'
|
|
494
|
+
|
|
495
|
+
# Save test agent for easier access
|
|
496
|
+
uvx adcp --save-auth test-agent https://test-agent.adcontextprotocol.org/mcp/ mcp
|
|
497
|
+
# Enter token when prompted: 1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ
|
|
498
|
+
|
|
499
|
+
# Now use saved config
|
|
500
|
+
uvx adcp test-agent get_products '{"brief":"Coffee brands"}'
|
|
501
|
+
|
|
502
|
+
# Use creative agent (no auth required)
|
|
503
|
+
uvx adcp https://creative.adcontextprotocol.org/mcp \
|
|
504
|
+
preview_creative @creative_manifest.json
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
**Test Agent Details:**
|
|
508
|
+
- **URL (MCP)**: `https://test-agent.adcontextprotocol.org/mcp/`
|
|
509
|
+
- **URL (A2A)**: `https://test-agent.adcontextprotocol.org`
|
|
510
|
+
- **Auth Token**: `1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ` (optional, public token)
|
|
511
|
+
- **Rate Limited**: For testing only, not for production
|
|
512
|
+
- **No Auth Mode**: Omit `--auth` flag to test unauthenticated behavior
|
|
513
|
+
```
|
|
514
|
+
|
|
380
515
|
### Configuration Management
|
|
381
516
|
|
|
382
517
|
```bash
|
|
@@ -16,6 +16,8 @@ src/adcp/protocols/__init__.py
|
|
|
16
16
|
src/adcp/protocols/a2a.py
|
|
17
17
|
src/adcp/protocols/base.py
|
|
18
18
|
src/adcp/protocols/mcp.py
|
|
19
|
+
src/adcp/testing/__init__.py
|
|
20
|
+
src/adcp/testing/test_helpers.py
|
|
19
21
|
src/adcp/types/__init__.py
|
|
20
22
|
src/adcp/types/core.py
|
|
21
23
|
src/adcp/types/generated.py
|
|
@@ -29,6 +31,7 @@ tests/test_client.py
|
|
|
29
31
|
tests/test_code_generation.py
|
|
30
32
|
tests/test_discriminated_unions.py
|
|
31
33
|
tests/test_format_id_validation.py
|
|
34
|
+
tests/test_helpers.py
|
|
32
35
|
tests/test_preview_html.py
|
|
33
36
|
tests/test_protocols.py
|
|
34
37
|
tests/test_response_parser.py
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"""Tests for the test helpers module."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from adcp.client import ADCPClient, ADCPMultiAgentClient
|
|
6
|
+
from adcp.testing import (
|
|
7
|
+
CREATIVE_AGENT_CONFIG,
|
|
8
|
+
TEST_AGENT_A2A_CONFIG,
|
|
9
|
+
TEST_AGENT_A2A_NO_AUTH_CONFIG,
|
|
10
|
+
TEST_AGENT_MCP_CONFIG,
|
|
11
|
+
TEST_AGENT_MCP_NO_AUTH_CONFIG,
|
|
12
|
+
TEST_AGENT_TOKEN,
|
|
13
|
+
create_test_agent,
|
|
14
|
+
creative_agent,
|
|
15
|
+
test_agent,
|
|
16
|
+
test_agent_a2a,
|
|
17
|
+
test_agent_a2a_no_auth,
|
|
18
|
+
test_agent_client,
|
|
19
|
+
test_agent_no_auth,
|
|
20
|
+
)
|
|
21
|
+
from adcp.types.core import Protocol
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_exports_from_testing_module():
|
|
25
|
+
"""Test that all expected exports are available from testing module."""
|
|
26
|
+
# These imports should work without errors
|
|
27
|
+
from adcp.testing import (
|
|
28
|
+
TEST_AGENT_A2A_CONFIG,
|
|
29
|
+
TEST_AGENT_A2A_NO_AUTH_CONFIG,
|
|
30
|
+
TEST_AGENT_MCP_CONFIG,
|
|
31
|
+
TEST_AGENT_MCP_NO_AUTH_CONFIG,
|
|
32
|
+
TEST_AGENT_TOKEN,
|
|
33
|
+
create_test_agent,
|
|
34
|
+
test_agent,
|
|
35
|
+
test_agent_a2a,
|
|
36
|
+
test_agent_a2a_no_auth,
|
|
37
|
+
test_agent_client,
|
|
38
|
+
test_agent_no_auth,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
assert test_agent is not None
|
|
42
|
+
assert test_agent_a2a is not None
|
|
43
|
+
assert test_agent_no_auth is not None
|
|
44
|
+
assert test_agent_a2a_no_auth is not None
|
|
45
|
+
assert test_agent_client is not None
|
|
46
|
+
assert callable(create_test_agent)
|
|
47
|
+
assert isinstance(TEST_AGENT_TOKEN, str)
|
|
48
|
+
assert TEST_AGENT_MCP_CONFIG is not None
|
|
49
|
+
assert TEST_AGENT_A2A_CONFIG is not None
|
|
50
|
+
assert TEST_AGENT_MCP_NO_AUTH_CONFIG is not None
|
|
51
|
+
assert TEST_AGENT_A2A_NO_AUTH_CONFIG is not None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_test_agent_token():
|
|
55
|
+
"""Test that TEST_AGENT_TOKEN is a valid string."""
|
|
56
|
+
assert isinstance(TEST_AGENT_TOKEN, str)
|
|
57
|
+
assert len(TEST_AGENT_TOKEN) > 0
|
|
58
|
+
assert TEST_AGENT_TOKEN == "1v8tAhASaUYYp4odoQ1PnMpdqNaMiTrCRqYo9OJp6IQ"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_mcp_config_structure():
|
|
62
|
+
"""Test TEST_AGENT_MCP_CONFIG has correct structure."""
|
|
63
|
+
assert TEST_AGENT_MCP_CONFIG.id == "test-agent-mcp"
|
|
64
|
+
assert TEST_AGENT_MCP_CONFIG.protocol == Protocol.MCP
|
|
65
|
+
# AgentConfig validator strips trailing slashes for consistency
|
|
66
|
+
assert TEST_AGENT_MCP_CONFIG.agent_uri == "https://test-agent.adcontextprotocol.org/mcp"
|
|
67
|
+
assert TEST_AGENT_MCP_CONFIG.auth_token is not None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_a2a_config_structure():
|
|
71
|
+
"""Test TEST_AGENT_A2A_CONFIG has correct structure."""
|
|
72
|
+
assert TEST_AGENT_A2A_CONFIG.id == "test-agent-a2a"
|
|
73
|
+
assert TEST_AGENT_A2A_CONFIG.protocol == Protocol.A2A
|
|
74
|
+
assert TEST_AGENT_A2A_CONFIG.agent_uri == "https://test-agent.adcontextprotocol.org"
|
|
75
|
+
assert TEST_AGENT_A2A_CONFIG.auth_token is not None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def test_test_agent_is_adcp_client():
|
|
79
|
+
"""Test that test_agent is an ADCPClient instance."""
|
|
80
|
+
assert isinstance(test_agent, ADCPClient)
|
|
81
|
+
assert hasattr(test_agent, "get_products")
|
|
82
|
+
assert hasattr(test_agent, "list_creative_formats")
|
|
83
|
+
assert callable(test_agent.get_products)
|
|
84
|
+
assert callable(test_agent.list_creative_formats)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_test_agent_a2a_is_adcp_client():
|
|
88
|
+
"""Test that test_agent_a2a is an ADCPClient instance."""
|
|
89
|
+
assert isinstance(test_agent_a2a, ADCPClient)
|
|
90
|
+
assert hasattr(test_agent_a2a, "get_products")
|
|
91
|
+
assert hasattr(test_agent_a2a, "list_creative_formats")
|
|
92
|
+
assert callable(test_agent_a2a.get_products)
|
|
93
|
+
assert callable(test_agent_a2a.list_creative_formats)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def test_test_agent_client_is_multi_agent():
|
|
97
|
+
"""Test that test_agent_client is an ADCPMultiAgentClient instance."""
|
|
98
|
+
assert isinstance(test_agent_client, ADCPMultiAgentClient)
|
|
99
|
+
assert hasattr(test_agent_client, "agent")
|
|
100
|
+
assert hasattr(test_agent_client, "agents")
|
|
101
|
+
assert callable(test_agent_client.agent)
|
|
102
|
+
assert len(test_agent_client.agent_ids) == 2
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def test_test_agent_client_provides_access_to_both_agents():
|
|
106
|
+
"""Test that test_agent_client provides access to both MCP and A2A agents."""
|
|
107
|
+
mcp_agent = test_agent_client.agent("test-agent-mcp")
|
|
108
|
+
a2a_agent = test_agent_client.agent("test-agent-a2a")
|
|
109
|
+
|
|
110
|
+
assert mcp_agent is not None
|
|
111
|
+
assert a2a_agent is not None
|
|
112
|
+
assert isinstance(mcp_agent, ADCPClient)
|
|
113
|
+
assert isinstance(a2a_agent, ADCPClient)
|
|
114
|
+
assert hasattr(mcp_agent, "get_products")
|
|
115
|
+
assert hasattr(a2a_agent, "get_products")
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def test_create_test_agent_default():
|
|
119
|
+
"""Test that create_test_agent creates valid config with defaults."""
|
|
120
|
+
config = create_test_agent()
|
|
121
|
+
|
|
122
|
+
assert config.id == "test-agent-mcp"
|
|
123
|
+
assert config.protocol == Protocol.MCP
|
|
124
|
+
assert config.auth_token is not None
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def test_create_test_agent_with_overrides():
|
|
128
|
+
"""Test that create_test_agent allows overrides."""
|
|
129
|
+
config = create_test_agent(
|
|
130
|
+
id="custom-test-agent",
|
|
131
|
+
timeout=60.0,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
assert config.id == "custom-test-agent"
|
|
135
|
+
assert config.timeout == 60.0
|
|
136
|
+
assert config.protocol == Protocol.MCP # unchanged
|
|
137
|
+
assert config.auth_token is not None # retained
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def test_create_test_agent_protocol_override():
|
|
141
|
+
"""Test that create_test_agent allows protocol override."""
|
|
142
|
+
config = create_test_agent(
|
|
143
|
+
protocol=Protocol.A2A,
|
|
144
|
+
agent_uri="https://test-agent.adcontextprotocol.org",
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
assert config.protocol == Protocol.A2A
|
|
148
|
+
assert config.agent_uri == "https://test-agent.adcontextprotocol.org"
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def test_test_agent_config_match():
|
|
152
|
+
"""Test that test_agent uses TEST_AGENT_MCP_CONFIG."""
|
|
153
|
+
assert test_agent.agent_config.id == TEST_AGENT_MCP_CONFIG.id
|
|
154
|
+
assert test_agent.agent_config.protocol == TEST_AGENT_MCP_CONFIG.protocol
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def test_test_agent_a2a_config_match():
|
|
158
|
+
"""Test that test_agent_a2a uses TEST_AGENT_A2A_CONFIG."""
|
|
159
|
+
assert test_agent_a2a.agent_config.id == TEST_AGENT_A2A_CONFIG.id
|
|
160
|
+
assert test_agent_a2a.agent_config.protocol == TEST_AGENT_A2A_CONFIG.protocol
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def test_agent_ids_in_test_agent_client():
|
|
164
|
+
"""Test that test_agent_client has correct agent IDs."""
|
|
165
|
+
agent_ids = test_agent_client.agent_ids
|
|
166
|
+
assert "test-agent-mcp" in agent_ids
|
|
167
|
+
assert "test-agent-a2a" in agent_ids
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def test_creative_agent_config_structure():
|
|
171
|
+
"""Test CREATIVE_AGENT_CONFIG has correct structure."""
|
|
172
|
+
assert CREATIVE_AGENT_CONFIG.id == "creative-agent"
|
|
173
|
+
assert CREATIVE_AGENT_CONFIG.protocol == Protocol.MCP
|
|
174
|
+
assert CREATIVE_AGENT_CONFIG.agent_uri == "https://creative.adcontextprotocol.org/mcp"
|
|
175
|
+
# Creative agent requires no authentication
|
|
176
|
+
assert CREATIVE_AGENT_CONFIG.auth_token is None
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def test_creative_agent_is_adcp_client():
|
|
180
|
+
"""Test that creative_agent is an ADCPClient instance."""
|
|
181
|
+
assert isinstance(creative_agent, ADCPClient)
|
|
182
|
+
assert hasattr(creative_agent, "preview_creative")
|
|
183
|
+
assert hasattr(creative_agent, "list_creative_formats")
|
|
184
|
+
assert callable(creative_agent.preview_creative)
|
|
185
|
+
assert callable(creative_agent.list_creative_formats)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def test_creative_agent_config_match():
|
|
189
|
+
"""Test that creative_agent uses CREATIVE_AGENT_CONFIG."""
|
|
190
|
+
assert creative_agent.agent_config.id == CREATIVE_AGENT_CONFIG.id
|
|
191
|
+
assert creative_agent.agent_config.protocol == CREATIVE_AGENT_CONFIG.protocol
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def test_mcp_no_auth_config_structure():
|
|
195
|
+
"""Test TEST_AGENT_MCP_NO_AUTH_CONFIG has correct structure."""
|
|
196
|
+
assert TEST_AGENT_MCP_NO_AUTH_CONFIG.id == "test-agent-mcp-no-auth"
|
|
197
|
+
assert TEST_AGENT_MCP_NO_AUTH_CONFIG.protocol == Protocol.MCP
|
|
198
|
+
assert TEST_AGENT_MCP_NO_AUTH_CONFIG.agent_uri == "https://test-agent.adcontextprotocol.org/mcp"
|
|
199
|
+
assert TEST_AGENT_MCP_NO_AUTH_CONFIG.auth_token is None
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def test_a2a_no_auth_config_structure():
|
|
203
|
+
"""Test TEST_AGENT_A2A_NO_AUTH_CONFIG has correct structure."""
|
|
204
|
+
assert TEST_AGENT_A2A_NO_AUTH_CONFIG.id == "test-agent-a2a-no-auth"
|
|
205
|
+
assert TEST_AGENT_A2A_NO_AUTH_CONFIG.protocol == Protocol.A2A
|
|
206
|
+
assert TEST_AGENT_A2A_NO_AUTH_CONFIG.agent_uri == "https://test-agent.adcontextprotocol.org"
|
|
207
|
+
assert TEST_AGENT_A2A_NO_AUTH_CONFIG.auth_token is None
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def test_test_agent_no_auth_is_adcp_client():
|
|
211
|
+
"""Test that test_agent_no_auth is an ADCPClient instance."""
|
|
212
|
+
assert isinstance(test_agent_no_auth, ADCPClient)
|
|
213
|
+
assert hasattr(test_agent_no_auth, "get_products")
|
|
214
|
+
assert hasattr(test_agent_no_auth, "list_creative_formats")
|
|
215
|
+
assert callable(test_agent_no_auth.get_products)
|
|
216
|
+
assert callable(test_agent_no_auth.list_creative_formats)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def test_test_agent_a2a_no_auth_is_adcp_client():
|
|
220
|
+
"""Test that test_agent_a2a_no_auth is an ADCPClient instance."""
|
|
221
|
+
assert isinstance(test_agent_a2a_no_auth, ADCPClient)
|
|
222
|
+
assert hasattr(test_agent_a2a_no_auth, "get_products")
|
|
223
|
+
assert hasattr(test_agent_a2a_no_auth, "list_creative_formats")
|
|
224
|
+
assert callable(test_agent_a2a_no_auth.get_products)
|
|
225
|
+
assert callable(test_agent_a2a_no_auth.list_creative_formats)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def test_test_agent_no_auth_config_match():
|
|
229
|
+
"""Test that test_agent_no_auth uses TEST_AGENT_MCP_NO_AUTH_CONFIG."""
|
|
230
|
+
assert test_agent_no_auth.agent_config.id == TEST_AGENT_MCP_NO_AUTH_CONFIG.id
|
|
231
|
+
assert test_agent_no_auth.agent_config.protocol == TEST_AGENT_MCP_NO_AUTH_CONFIG.protocol
|
|
232
|
+
assert test_agent_no_auth.agent_config.auth_token is None
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def test_test_agent_a2a_no_auth_config_match():
|
|
236
|
+
"""Test that test_agent_a2a_no_auth uses TEST_AGENT_A2A_NO_AUTH_CONFIG."""
|
|
237
|
+
assert test_agent_a2a_no_auth.agent_config.id == TEST_AGENT_A2A_NO_AUTH_CONFIG.id
|
|
238
|
+
assert test_agent_a2a_no_auth.agent_config.protocol == TEST_AGENT_A2A_NO_AUTH_CONFIG.protocol
|
|
239
|
+
assert test_agent_a2a_no_auth.agent_config.auth_token is None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|