A reference implementation of the Ad Context Protocol (AdCP) sales agent, enabling AI agents to buy advertising inventory through a standardized MCP interface.
The AdCP Sales Agent is a server that:
- Exposes advertising inventory to AI agents via MCP (Model Context Protocol) and A2A (Agent-to-Agent)
- Integrates with ad servers like Google Ad Manager
- Provides an admin interface for managing inventory and campaigns
- Handles the full campaign lifecycle from discovery to reporting
| I want to... | Start here |
|---|---|
| Deploy my own sales agent (publisher) | Quickstart Guide |
| Evaluate or develop locally | Quick Start below |
| Run a multi-tenant platform | Deployment Guide |
Try the sales agent locally with demo data:
# Download and start
curl -O https://raw.githubusercontent.com/adcontextprotocol/salesagent/main/docker-compose.yml
docker compose up -d
# Test the MCP interface
uvx adcp http://localhost:8000/mcp/ --auth test-token list_tools
uvx adcp http://localhost:8000/mcp/ --auth test-token get_products '{"brief":"video"}'Access services at http://localhost:8000:
- Admin UI:
/admin(login:test_super_admin@example.com/test123) - MCP Server:
/mcp/ - A2A Server:
/a2a
This creates a demo tenant with mock data for testing. For production, see the Quickstart Guide.
Publishers deploy their own sales agent. Choose based on your needs:
| Platform | Time | Difficulty | Guide |
|---|---|---|---|
| Docker (local/on-prem) | 2 min | Easy | quickstart-docker.md |
| Fly.io (cloud) | 10-15 min | Medium | quickstart-fly.md |
| Google Cloud Run | 15-20 min | Medium | quickstart-cloud-run.md |
Docker is the fastest - it bundles PostgreSQL and just works. Cloud platforms require separate database setup.
Configure via the Admin UI:
- Configure your ad server (Settings → Adapters)
- Set up products that match your GAM line items
- Add advertisers who will use the MCP API
- Set your custom domain (Settings → General)
For local development with hot-reload:
git clone https://github.com/adcontextprotocol/salesagent.git
cd salesagent
cp .env.template .env
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -dRun tests:
uv run pytest tests/unit/ -x # Unit tests
uv run pytest tests/integration/ # Integration tests (requires PostgreSQL)
uv run pytest tests/e2e/ # E2E tests (uses Docker)See Development Guide for contributing.
For GAM integration, choose your authentication method:
Service Account (Recommended for Production):
- No OAuth credentials needed
- Configure service account JSON in Admin UI
- See GAM Adapter Guide for setup
OAuth (Development/Testing):
- Create OAuth credentials at Google Cloud Console
- Add to .env:
GAM_OAUTH_CLIENT_ID=your-client-id.apps.googleusercontent.com GAM_OAUTH_CLIENT_SECRET=your-client-secret
- Configure in Admin UI: Settings → Adapters → Google Ad Manager
Add to your Claude config (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"adcp": {
"command": "uvx",
"args": ["mcp-remote", "http://localhost:8000/mcp/", "--header", "x-adcp-auth: YOUR_TOKEN"]
}
}
}Get your token from Admin UI → Advertisers → (select advertiser) → API Token.
Container won't start?
docker compose logs adcp-server | head -50GAM OAuth error?
- Verify
GAM_OAUTH_CLIENT_IDandGAM_OAUTH_CLIENT_SECRETin.env - Restart:
docker compose restart
More help: Troubleshooting Guide
- Docker Quickstart - Local/on-prem (2 min)
- Fly.io Quickstart - Cloud deployment (10-15 min)
- Cloud Run Quickstart - GCP deployment (15-20 min)
- Full Deployment Guide - All options (K8s, AWS, Azure, etc.)
- Development Guide - Local development and contributing
- Testing Guide - Running and writing tests
- Architecture - System design and database schema
- Troubleshooting Guide - Monitoring and debugging
- Product Discovery - Natural language search for advertising products
- Campaign Creation - Automated media buying with targeting
- Creative Management - Upload and approval workflows
- Performance Monitoring - Real-time campaign metrics
- Multi-Tenant System - Isolated data per publisher
- Adapter Pattern - Support for multiple ad servers
- Real-time Dashboard - Live activity feed with Server-Sent Events (SSE)
- Workflow Management - Unified system for human-in-the-loop approvals
- Operations Monitoring - Track all media buys, workflows, and system activities
- Admin Interface - Web UI with Google OAuth
- Audit Logging - Complete operational history
- MCP Protocol - Standard interface for AI agents
- A2A Protocol - Agent-to-Agent communication via JSON-RPC 2.0
- REST API - Programmatic tenant management
- Docker Deployment - Easy local and production setup
- Comprehensive Testing - Unit, integration, and E2E tests
The primary interface for AI agents to interact with the AdCP Sales Agent. Uses FastMCP with HTTP/SSE transport.
JSON-RPC 2.0 compliant server for agent-to-agent communication:
- Endpoint:
/a2a(also available at port 8091) - Discovery:
/.well-known/agent.json - Authentication: Bearer tokens via Authorization header
- Library: Built with standard
python-a2alibrary
The mock server provides comprehensive AdCP testing capabilities for developers:
- X-Dry-Run: Test operations without real execution
- X-Mock-Time: Control time for deterministic testing
- X-Jump-To-Event: Skip to specific campaign events
- X-Test-Session-ID: Isolate parallel test sessions
- X-Auto-Advance: Automatic event progression
- X-Force-Error: Simulate error conditions
- X-Next-Event: Next expected campaign event
- X-Next-Event-Time: Timestamp for next event
- X-Simulated-Spend: Current campaign spend simulation
- Campaign Lifecycle Simulation: Complete event progression (creation → completion)
- Error Scenario Testing: Budget exceeded, delivery issues, platform errors
- Time Simulation: Fast-forward campaigns for testing
- Session Isolation: Parallel test execution without conflicts
- Production Safety: Zero real spend during testing
# Example: Test with time simulation
headers = {
"x-adcp-auth": "your_token",
"X-Dry-Run": "true",
"X-Mock-Time": "2025-02-15T12:00:00Z",
"X-Test-Session-ID": "test-123"
}
# Use with any MCP client for safe testingSee examples/mock_server_testing_demo.py for complete testing examples.
from fastmcp.client import Client
from fastmcp.client.transports import StreamableHttpTransport
# Connect to server
headers = {"x-adcp-auth": "your_token"}
transport = StreamableHttpTransport(
url="http://localhost:8000/mcp/",
headers=headers
)
client = Client(transport=transport)
# Discover products
async with client:
products = await client.tools.get_products(
brief="video ads for sports content"
)
# Create media buy
result = await client.tools.create_media_buy(
product_ids=["ctv_sports"],
total_budget=50000,
flight_start_date="2025-02-01",
flight_end_date="2025-02-28"
)salesagent/
├── src/ # Source code
│ ├── core/ # Core MCP server components
│ │ ├── main.py # MCP server implementation
│ │ ├── schemas.py # API schemas and data models
│ │ ├── config_loader.py # Configuration management
│ │ ├── audit_logger.py # Security and audit logging
│ │ └── database/ # Database layer
│ │ ├── models.py # SQLAlchemy models
│ │ ├── database.py # Database initialization
│ │ └── database_session.py # Session management
│ ├── services/ # Business logic services
│ │ ├── ai_product_service.py # AI product management
│ │ ├── targeting_capabilities.py # Targeting system
│ │ └── gam_inventory_service.py # GAM integration
│ ├── adapters/ # Ad server integrations
│ │ ├── base.py # Base adapter interface
│ │ ├── google_ad_manager.py # GAM adapter
│ │ └── mock_ad_server.py # Mock adapter
│ └── admin/ # Admin UI (Flask)
│ ├── app.py # Flask application
│ ├── blueprints/ # Flask blueprints
│ │ ├── tenants.py # Tenant dashboard
│ │ ├── tasks.py # Task management (DEPRECATED - see workflow system)
│ │ └── activity_stream.py # Real-time activity feed
│ └── server.py # Admin server
├── scripts/ # Utility scripts
│ ├── setup/ # Setup and initialization
│ ├── dev/ # Development tools
│ ├── ops/ # Operations scripts
│ └── deploy/ # Deployment scripts
├── tests/ # Test suite
│ ├── unit/ # Unit tests
│ ├── integration/ # Integration tests
│ └── e2e/ # End-to-end tests
├── docs/ # Documentation
├── examples/ # Example code
├── tools/ # Demo and simulation tools
├── alembic/ # Database migrations
├── templates/ # Jinja2 templates
└── config/ # Configuration files
└── nginx/ # Nginx configuration files
- Python 3.12+
- Docker and Docker Compose (for easy deployment)
- PostgreSQL (Docker Compose handles this automatically)
- Google OAuth credentials (for Admin UI)
- Gemini API key (for AI features)
We welcome contributions! Please see our Development Guide for:
- Setting up your development environment
- Running tests
- Code style guidelines
- Creating pull requests
When contributing, please follow our standardized database patterns:
# ✅ CORRECT - Use context manager
from database_session import get_db_session
with get_db_session() as session:
# Your database operations
session.commit()
# ❌ WRONG - Manual management
conn = get_db_connection()
# operations
conn.close() # Prone to leaksSee Database Patterns Guide for details.
Users can belong to multiple tenants with the same email address (like GitHub, Slack, etc.):
- Sign up for multiple publisher accounts with one Google login
- Different roles per tenant (admin in one, viewer in another)
- No "email already exists" errors - users are tenant-scoped
Migration: Database schema updated with composite unique constraint (tenant_id, email). See alembic/versions/aff9ca8baa9c_allow_users_multi_tenant_access.py
Deactivate test or unused tenants without losing data:
How to deactivate:
- Go to Settings → Danger Zone
- Type tenant name exactly to confirm
- Click "Deactivate Sales Agent"
What happens:
- ✅ All data preserved (media buys, creatives, principals)
- ❌ Hidden from login and tenant selection
- ❌ API access blocked
- ℹ️ Can be reactivated by super admin
Reactivation (super admin only):
POST /admin/tenant/{tenant_id}/reactivateNew users can self-provision tenants:
- Google OAuth authentication
- GAM-only for self-signup (other adapters via support)
- Auto-creates tenant, user, and default principal
- Available at
/signupon main domain
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: docs/
Apache 2.0 License - see LICENSE file for details.
- AdCP Specification - Protocol specification
- MCP SDK - Model Context Protocol tools
- FastMCP - MCP server framework