Skip to content

Commit cbac1b4

Browse files
bokelleyclaude
andcommitted
Merge branch 'main' into fix-mcp-cleanup-errors
Pull in batch preview API changes from #18 before merging cleanup improvements. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2 parents 14708de + 813df8a commit cbac1b4

17 files changed

+2202
-218
lines changed

examples/README.md

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# ADCP Python Client Examples
2+
3+
This directory contains examples demonstrating how to use the ADCP Python client's preview URL generation feature.
4+
5+
## Preview URL Generation Demo
6+
7+
This demo shows how to fetch creative format previews from the ADCP creative agent and display them in a web browser using the `<rendered-creative>` web component.
8+
9+
### Quick Start
10+
11+
1. **Install the package** (if not already installed):
12+
```bash
13+
pip install -e .
14+
```
15+
16+
2. **Fetch preview URLs from the creative agent**:
17+
```bash
18+
python examples/fetch_previews.py
19+
```
20+
21+
This will:
22+
- Connect to the reference creative agent at `https://creative.adcontextprotocol.org`
23+
- Call `list_creative_formats()` with `fetch_previews=True`
24+
- Generate preview URLs for available formats
25+
- Save the results to `examples/preview_urls.json`
26+
27+
3. **Start a local web server** (required for the web component to work):
28+
```bash
29+
cd /path/to/adcp-client-python
30+
python -m http.server 8000
31+
```
32+
33+
4. **Open the demo in your browser**:
34+
```
35+
http://localhost:8000/examples/web_component_demo.html
36+
```
37+
38+
### What You'll See
39+
40+
The demo page displays a grid of creative format previews, each showing:
41+
- Format name
42+
- Format ID
43+
- Live preview rendered in the `<rendered-creative>` web component
44+
45+
Features demonstrated:
46+
- **Shadow DOM isolation** - No CSS conflicts between previews
47+
- **Lazy loading** - Previews load only when visible
48+
- **Responsive grid** - Adapts to different screen sizes
49+
- **Interactive previews** - Full creative rendering with animations
50+
51+
### Files
52+
53+
- **`fetch_previews.py`** - Python script to fetch preview URLs from the creative agent
54+
- **`web_component_demo.html`** - HTML page demonstrating the `<rendered-creative>` web component
55+
- **`preview_urls.json`** - Generated file containing preview URLs (created by fetch script)
56+
57+
### How It Works
58+
59+
The Python script uses the new `fetch_previews` parameter:
60+
61+
```python
62+
from adcp import ADCPClient
63+
from adcp.types import AgentConfig, Protocol
64+
from adcp.types.generated import ListCreativeFormatsRequest
65+
66+
creative_agent = ADCPClient(
67+
AgentConfig(
68+
id="creative_agent",
69+
agent_uri="https://creative.adcontextprotocol.org",
70+
protocol=Protocol.MCP,
71+
)
72+
)
73+
74+
# Fetch formats with preview URLs
75+
result = await creative_agent.list_creative_formats(
76+
ListCreativeFormatsRequest(),
77+
fetch_previews=True # ← New parameter!
78+
)
79+
80+
# Access preview data
81+
formats_with_previews = result.metadata["formats_with_previews"]
82+
for fmt in formats_with_previews:
83+
preview_data = fmt["preview_data"]
84+
print(f"Preview URL: {preview_data['preview_url']}")
85+
print(f"Expires: {preview_data['expires_at']}")
86+
```
87+
88+
The HTML page then uses the official ADCP web component to render the previews:
89+
90+
```html
91+
<!-- Include the web component -->
92+
<script src="https://creative.adcontextprotocol.org/static/rendered-creative.js"></script>
93+
94+
<!-- Render previews -->
95+
<rendered-creative
96+
src="{{preview_url}}"
97+
width="300"
98+
height="400"
99+
lazy="true">
100+
</rendered-creative>
101+
```
102+
103+
### Troubleshooting
104+
105+
**"Preview URLs file not found" error:**
106+
- Run `python examples/fetch_previews.py` first
107+
108+
**Web component not loading:**
109+
- Make sure you're using a web server (not `file://` URLs)
110+
- Check that you have internet access (web component loads from CDN)
111+
112+
**No previews showing:**
113+
- Check browser console for errors
114+
- Verify the creative agent is accessible: `https://creative.adcontextprotocol.org`
115+
116+
### Using with Products
117+
118+
You can also fetch preview URLs for products:
119+
120+
```python
121+
from adcp.types.generated import GetProductsRequest
122+
123+
# Setup publisher and creative agents
124+
publisher_agent = ADCPClient(publisher_config)
125+
creative_agent = ADCPClient(creative_config)
126+
127+
# Get products with preview URLs
128+
result = await publisher_agent.get_products(
129+
GetProductsRequest(brief="video campaign"),
130+
fetch_previews=True,
131+
creative_agent_client=creative_agent
132+
)
133+
134+
# Access product previews
135+
products_with_previews = result.metadata["products_with_previews"]
136+
for product in products_with_previews:
137+
print(f"Product: {product['name']}")
138+
for format_id, preview_data in product["format_previews"].items():
139+
print(f" Format {format_id}: {preview_data['preview_url']}")
140+
```
141+
142+
## More Examples
143+
144+
For more examples, see the [documentation](https://docs.adcontextprotocol.org) and [integration tests](../tests/integration/).

examples/fetch_preview_urls.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
"""
2+
Example script to fetch preview URLs from the ADCP creative agent.
3+
4+
This demonstrates the new preview URL generation feature by:
5+
1. Connecting to the reference creative agent
6+
2. Listing available formats
7+
3. Generating preview URLs for each format
8+
4. Saving the results to use in the web component demo
9+
"""
10+
11+
import asyncio
12+
import json
13+
from pathlib import Path
14+
15+
from adcp import ADCPClient
16+
from adcp.types import AgentConfig, Protocol
17+
from adcp.types.generated import ListCreativeFormatsRequest
18+
19+
20+
async def main():
21+
"""Fetch preview URLs from the creative agent."""
22+
23+
# Connect to the reference creative agent
24+
creative_agent = ADCPClient(
25+
AgentConfig(
26+
id="creative_agent",
27+
agent_uri="https://creative.adcontextprotocol.org",
28+
protocol=Protocol.MCP,
29+
)
30+
)
31+
32+
print("Fetching creative formats with preview URLs...")
33+
print("=" * 60)
34+
35+
try:
36+
# List formats with preview URL generation
37+
result = await creative_agent.list_creative_formats(
38+
ListCreativeFormatsRequest(), fetch_previews=True
39+
)
40+
41+
if not result.success:
42+
print(f"❌ Failed to fetch formats: {result.error}")
43+
return
44+
45+
# Get formats with previews from metadata
46+
formats_with_previews = result.metadata.get("formats_with_previews", [])
47+
48+
print(f"\n✅ Successfully fetched {len(formats_with_previews)} formats with previews\n")
49+
50+
# Display preview URLs
51+
preview_data = []
52+
for fmt in formats_with_previews[:5]: # Show first 5
53+
format_id = fmt.get("format_id")
54+
name = fmt.get("name", "Unknown")
55+
preview = fmt.get("preview_data", {})
56+
preview_url = preview.get("preview_url")
57+
58+
if preview_url:
59+
print(f"📋 {name}")
60+
print(f" Format ID: {format_id}")
61+
print(f" Preview URL: {preview_url}")
62+
print(f" Expires: {preview.get('expires_at', 'N/A')}")
63+
print()
64+
65+
preview_data.append({
66+
"format_id": format_id,
67+
"name": name,
68+
"preview_url": preview_url,
69+
"width": 300,
70+
"height": 400,
71+
})
72+
73+
# Save to JSON for the web component demo
74+
output_file = Path(__file__).parent / "preview_urls.json"
75+
with open(output_file, "w") as f:
76+
json.dump(preview_data, f, indent=2)
77+
78+
print(f"💾 Saved preview URLs to: {output_file}")
79+
print(f"\n🌐 Open examples/web_component_demo.html in a browser to see the previews!")
80+
81+
except Exception as e:
82+
print(f"❌ Error: {e}")
83+
raise
84+
finally:
85+
await creative_agent.close()
86+
87+
88+
if __name__ == "__main__":
89+
asyncio.run(main())

examples/generate_mock_previews.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""
2+
Generate mock preview data for demonstration purposes.
3+
4+
Note: This uses mock data because the reference creative agent at
5+
https://creative.adcontextprotocol.org doesn't currently return
6+
structured format data via MCP (it returns a text message instead).
7+
8+
This demonstrates what the preview URL feature would look like
9+
when connected to a properly implemented ADCP creative agent.
10+
"""
11+
12+
import json
13+
from pathlib import Path
14+
15+
16+
def main():
17+
"""Generate mock preview URLs."""
18+
19+
# Mock preview data that demonstrates the feature
20+
mock_previews = [
21+
{
22+
"format_id": "display_300x250",
23+
"name": "Display 300x250",
24+
"preview_url": "https://creative.adcontextprotocol.org/preview/sample-banner/desktop.html",
25+
"width": 300,
26+
"height": 250,
27+
},
28+
{
29+
"format_id": "display_728x90",
30+
"name": "Display 728x90 Leaderboard",
31+
"preview_url": "https://creative.adcontextprotocol.org/preview/sample-leaderboard/desktop.html",
32+
"width": 728,
33+
"height": 90,
34+
},
35+
{
36+
"format_id": "display_160x600",
37+
"name": "Display 160x600 Skyscraper",
38+
"preview_url": "https://creative.adcontextprotocol.org/preview/sample-skyscraper/desktop.html",
39+
"width": 160,
40+
"height": 600,
41+
},
42+
]
43+
44+
# Save to JSON
45+
output_file = Path(__file__).parent / "preview_urls.json"
46+
with open(output_file, "w") as f:
47+
json.dump(mock_previews, f, indent=2)
48+
49+
print("✅ Generated mock preview URLs")
50+
print(f"💾 Saved to: {output_file}")
51+
print()
52+
print("Mock previews:")
53+
for preview in mock_previews:
54+
print(f" - {preview['name']}: {preview['preview_url']}")
55+
print()
56+
print("🌐 Open examples/web_component_demo.html in a browser to see them!")
57+
print()
58+
print("Note: These are mock URLs for demonstration. In a real implementation,")
59+
print("the preview URLs would be generated by calling preview_creative on the")
60+
print("creative agent for each format.")
61+
62+
63+
if __name__ == "__main__":
64+
main()

examples/preview_urls.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[
2+
{
3+
"format_id": "display_300x250",
4+
"name": "Display 300x250",
5+
"preview_url": "https://creative.adcontextprotocol.org/preview/sample-banner/desktop.html",
6+
"width": 300,
7+
"height": 250
8+
},
9+
{
10+
"format_id": "display_728x90",
11+
"name": "Display 728x90 Leaderboard",
12+
"preview_url": "https://creative.adcontextprotocol.org/preview/sample-leaderboard/desktop.html",
13+
"width": 728,
14+
"height": 90
15+
},
16+
{
17+
"format_id": "display_160x600",
18+
"name": "Display 160x600 Skyscraper",
19+
"preview_url": "https://creative.adcontextprotocol.org/preview/sample-skyscraper/desktop.html",
20+
"width": 160,
21+
"height": 600
22+
}
23+
]

0 commit comments

Comments
 (0)