This project is a Python-based reference implementation of a Signals Activation Protocol agent using MCP (Model Context Protocol). It demonstrates how to build a signals platform that integrates with AI assistants, supporting various signal types including:
- Audience signals: Demographic and behavioral targeting
- Contextual signals: Content classification and context
- Geographical signals: Location-based targeting
- Temporal signals: Time-based targeting
- Environmental signals: Weather, events, and external conditions
- Bidding signals: Custom bidding data and strategies
Quick Start: Click the green "Code" button above → "Codespaces" → "Create codespace on main"
The demo will automatically set up with real data and AI-powered signal discovery. See DEMO_GUIDE.md for complete instructions.
The Signals Agent provides:
- AI-Powered Discovery: Uses Google Gemini to intelligently rank signals (audiences, bidding data, contextual signals) based on natural language queries
- Smart Match Explanations: Each result includes AI-generated explanations of why the segment matches your targeting goals
- Custom Segment Proposals: AI suggests new custom segments that could be created for better targeting
- Multi-Platform Support: Discover signals across multiple SSPs (Index Exchange, The Trade Desk, LiveRamp, OpenX, etc.)
- Live Platform Integration: Real-time API integration with decisioning platforms (Index Exchange and LiveRamp supported)
- Intelligent Caching: 60-second API response caching for optimal performance
- Real-Time Activation: On-demand signal deployment to decisioning platforms
- Transparent Pricing: CPM and revenue share models with realistic market pricing
- Data Transparency: Shows "Unknown" for coverage/pricing when data is not available (no guessing)
This reference implementation supports all three signal agent types:
- Owned by the principal with exclusive access
- No signal costs (workflow orchestration only)
- Only visible to the owning principal
- Available to any orchestrator without principal registration
- Standard marketplace pricing
- Platform-wide segments only
- Requires principal account with the signal agent
- Account-specific segments plus platform-wide segments
- Mixed pricing: negotiated rates and standard rates
Full MCP support with:
- Tool Discovery:
/mcpendpoint for tool listing - SSE Streaming: Real-time updates via
/mcp/sse - Function Calling: Standard MCP function invocation
The fastest way to try the demo:
- Click "Code" → "Codespaces" → "Create codespace on main"
- Wait for automatic setup (dependencies install automatically)
- Get a free Gemini API key at ai.google.dev
- Configure your API key:
cp config.json.sample config.json # Edit config.json to add your API key - Initialize the database:
uv run python database.py
- Try the interactive demo:
uv run python client.py
For local development:
# Install dependencies
pip install uv
uv sync
# Configure API key
cp config.json.sample config.json
# Edit config.json with your Gemini API key from ai.google.dev
# Initialize database
uv run python database.py
# Start MCP server
uv run python main.pyFor local development, you can run both the MCP server and a web-based search UI:
# Run both MCP server (port 8000) and Search UI (port 8001)
./start_services_dev.sh
# Access the search UI at http://localhost:8001/searchThe Search UI provides:
- Visual search interface with score breakdowns
- RAG (semantic), FTS (keyword), and Hybrid search modes
- AI-powered query expansion toggle
- Real-time search results with explanations
Note: The Search UI is for development only. Production deployments only run the MCP server.
This agent implements the following tasks from the Signals Activation Protocol:
get_signals: Discover signals based on marketing specificationsactivate_signal: Activate signals for specific platforms/accounts (includes status monitoring)
The implementation supports differentiated access levels and pricing based on principal identity:
Access Levels:
- Public: Standard catalog access with base pricing
- Personalized: Access to additional segments with account-specific pricing
- Private: Full catalog access including exclusive segments
Example principals configured:
acme_corp(personalized access) - Custom pricing for luxury segmentspremium_partner(personalized access) - Standard personalized pricingenterprise_client(private access) - Full catalog access
Usage:
# Public access (default)
uv run python client.py --prompt "luxury automotive"
# Principal with custom pricing
uv run python client.py --prompt "luxury automotive" --principal acme_corpThe same segment may show different pricing:
- Public: $2.50 CPM for luxury segments
- ACME Corp: $6.50 CPM (custom negotiated rate)
The system supports real-time integration with decisioning platform APIs:
Supported Platforms:
- Index Exchange: Live API integration with authentication and caching
- LiveRamp: Full catalog sync with 200,000+ segments, offline search capability
- The Trade Desk: Adapter framework ready (implementation pending)
Configuration:
{
"platforms": {
"index-exchange": {
"enabled": true,
"test_mode": false,
"username": "your-ix-username",
"password": "your-ix-password",
"principal_accounts": {
"acme_corp": "1489997"
}
}
}
}Set test_mode: true to use simulated API responses for development/testing.
Security:
- Principal-to-account ID mapping prevents unauthorized access
- API credentials stored securely in config
- 60-second response caching reduces API load
Data Transparency:
- When platform APIs don't provide coverage data, shows "Unknown" instead of estimates
- When segments have no fees configured, shows "Unknown" for pricing
- Clear differentiation between known and unknown data points
The system intelligently determines the best search mode (RAG, FTS, or Hybrid) and whether to use AI query expansion based on query characteristics.
RAG (Vector/Semantic Search)
- Best for: Conceptual, thematic, and behavioral queries
- Uses AI embeddings for semantic similarity
- Examples: "eco-friendly", "luxury lifestyle", "health conscious"
FTS (Full-Text Search)
- Best for: Exact matches and technical queries
- Keyword-based matching
- Examples: Company names, segment IDs, boolean queries
Hybrid Search
- Best for: Natural language descriptions
- Combines RAG and FTS with weighted scoring
- Examples: "parents with young children", "urban professionals"
When using the MCP interface, the system automatically analyzes queries for:
-
Technical Patterns → FTS
- Boolean operators (AND, OR, NOT)
- Quoted phrases, segment IDs
- Company/brand names
-
Behavioral/Intent Indicators → RAG
- Keywords: interested, likely, seeking, lifestyle
- Queries needing semantic understanding
-
Demographic Terms → Hybrid
- Keywords: age, parent, income, education
- Benefits from both approaches
-
Query Length Heuristics
- 1 word → RAG with expansion
- 2 words → Hybrid with expansion
- 3-4 words → Hybrid (conditional expansion)
- 5+ words → Hybrid without expansion
When Applied:
- Short queries (1-2 words)
- Vague/general terms
- Conceptual queries
When Skipped:
- Technical IDs or codes
- Boolean operators present
- Very specific queries (5+ words)
- Exclusion terms (without, except, only)
The AI generates 5 related terms focusing on industry categories, demographics, behaviors, and purchase intent.
- RAG: ~300-400ms (3-7s with expansion)
- FTS: ~20-50ms (fastest)
- Hybrid: ~400-500ms (3-7s with expansion)
Query expansion adds 2-5 seconds due to AI generation and multiple embedding operations.
Quick Start: Click the green "Code" button above → "Codespaces" → "Create codespace on main"
Once in Codespaces (or locally), the demo uses the interactive MCP client:
# Interactive mode - full demo experience
uv run python client.py
# Quick search mode
uv run python client.py --prompt "BMW luxury automotive targeting"
# Limit results (default is 5)
uv run python client.py --prompt "BMW luxury automotive targeting" --limit 10
# Test different principal access levels and pricing
uv run python client.py --prompt "luxury" --principal acme_corpRun the core unit tests:
uv run python -m unittest test_main.pyTest the MCP endpoint:
# Initialize MCP session
curl -X POST http://localhost:8000/mcp/ \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream, application/json" \
-d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}},"id":1}'The system now supports the complete signal lifecycle:
- Discovery: Search for signals with natural language
- AI Proposals: Get custom segment suggestions with unique IDs
- Activation: Activate both existing and custom signals
- Status Tracking: Check deployment progress
Try activating a custom segment:
uv run python client.py
# Use 'discover' to get custom segment IDs
# Use 'activate' with the custom segment ID (supports --principal)
# Use 'status' to check deployment progress (supports --principal)The interactive mode now supports principal identity for all operations:
- Discovery: Different catalogs and pricing based on principal
- Activation: Principal-based access control prevents unauthorized activations
- Status Checking: Only shows status for segments the principal can access
┌─────────────────────┐ ┌──────────────────────┐ ┌─────────────────────┐
│ AI Assistant │ │ Signals Agent │ │ Decisioning │
│ (Orchestrator) │───▶│ (This Project) │───▶│ Platform (DSP) │
└─────────────────────┘ └──────────────────────┘ └─────────────────────┘
│ │ │
│ │ │
└────────────── Direct Integration Model ──────────────────┘
The agent operates within the broader Ad Tech Ecosystem Architecture, enabling direct integration with decisioning platforms while eliminating intermediary reporting complexity.
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.