deals-api-mcp Integration¶
The seller agent can distribute deals through deals-api-mcp — an MCP server that implements the IAB Deal Sync API v1.0. The seller agent talks to it over MCP Streamable HTTP.
How It Fits Together¶
seller-agent (Python)
└── DealsAPIMCPClient ← DealSyncClient implementation
└── MCP Transport ← MCP Streamable HTTP transport
└── deals-api-mcp ← MCP server (TypeScript, SQLite)
DealsAPIMCPClient implements the DealSyncClient interface and is registered in the deal-sync registry (a peer of the SSP registry). All operations are exposed through the seller agent's standard REST API — no direct access to the connector is needed.
Prerequisites¶
Start deals-api-mcp in HTTP mode before the seller agent connects:
The server listens at http://localhost:3100/mcp. See deals-api-mcp HTTP Streamable Transport for full env var details.
Configuration¶
Enable the connector via environment variables:
DEAL_SYNC_CONNECTORS=deals_api_mcp
DEALS_API_MCP_URL=http://localhost:3100/mcp
DEALS_API_MCP_SELLER_ORIGIN=publisher.example.com
DEALS_API_MCP_KEY= # omit for NODE_ENV=demo
| Variable | Description |
|---|---|
DEAL_SYNC_CONNECTORS |
Comma-separated list of active deal-sync providers. Include deals_api_mcp to enable. |
DEALS_API_MCP_URL |
Full URL of the deals-api-mcp /mcp endpoint |
DEALS_API_MCP_SELLER_ORIGIN |
Publisher domain stamped on every created deal |
DEALS_API_MCP_KEY |
Auth key. Required when NODE_ENV=production; omit in demo mode |
Operations¶
Distribute (Create) a Deal¶
curl -X POST http://localhost:8000/api/v1/deals/distribute \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{
"deal_id": "your-internal-deal-id",
"ssp_name": "deals_api_mcp",
"name": "Q3 Sports Video",
"advertiser": "Acme Corp",
"cpm": 25.00,
"deal_type": "PMP",
"start_date": "2026-07-01T00:00:00Z",
"end_date": "2026-09-30T00:00:00Z",
"buyer_seat_ids": ["seat-001"]
}'
Response:
{
"deal_id": "8b3f9cfe-7716-48e0-94bf-42fe44595928",
"external_deal_id": "IAB-Q3SPORTS001",
"channel": "deal_sync",
"provider": "deals_api_mcp",
"provider_name": "IAB Deals MCP",
"status": "created",
"deal": { "name": "Q3 Sports Video", "cpm": 25.00, "external_deal_id": "IAB-Q3SPORTS001", ... }
}
deal_id is the internal UUID (e.g. 8b3f9cfe-...) required by MCP tools. external_deal_id is the OpenRTB / IAB deal ID (e.g. "IAB-...") that DSPs need for activation — it is also present on the nested deal object and in DEAL_SYNCED event payloads.
Omit ssp_name to let the seller agent route based on SSP_ROUTING_RULES.
Troubleshoot a Deal¶
curl "http://localhost:8000/api/v1/deals/8b3f9cfe-7716-48e0-94bf-42fe44595928/ssp-troubleshoot?ssp_name=deals_api_mcp" \
-H "Authorization: Bearer <api_key>"
Returns the deal's buyer seat statuses and any rejected seats flagged as primary issues.
Status Mapping¶
deals-api-mcp returns seller status as an integer (sellerStatus). The connector normalizes it:
sellerStatus |
IAB label | Normalized status |
|---|---|---|
0 |
Active | active |
1 |
Paused | paused |
2 |
Pending | created |
4 |
Complete | expired |
5 |
Archived | archived |
Buyer vs seller status codes share the integer space
A buyer-side 0 (Pending) is not the same as a deal-side 0 (Active). They live on different objects — deal.sellerStatus vs buyerSeat.buyerStatus. Always check which field you are reading.
Connection Lifecycle¶
sequenceDiagram
participant SA as seller-agent
participant TR as MCP Transport
participant MCP as deals-api-mcp
SA->>TR: __aenter__ (first request)
TR->>MCP: POST /mcp initialize
MCP-->>TR: 200 OK + Mcp-Session-Id:
TR-->>SA: persistent session ready ✓
SA->>TR: call_tool("deals_create", args)
TR->>MCP: POST /mcp tools/call (Mcp-Session-Id: )
MCP-->>TR: Content-Type: text/event-stream\ndata: {"result":{...}}
TR-->>SA: parsed result dict
SA->>TR: __aenter__ (second request — session reused)
Note over SA,TR: background task still running, no re-initialize
SA->>TR: call_tool("deals_create", args)
TR->>MCP: POST /mcp tools/call (Mcp-Session-Id: )
MCP-->>TR: Content-Type: text/event-stream\ndata: {"result":{...}}
TR-->>SA: parsed result dict
Persistent session
DealsAPIMCPClient keeps a class-level persistent background task so the MCP session is created on first use and reused across subsequent async with blocks without re-initializing.
If the connection drops, the stale session is detected on the next tool call (via a 30 s timeout), the background task is restarted, and the call is retried automatically — no process restart required. The first request after a drop may take up to 30 seconds while reconnection completes; subsequent requests are unaffected.
Related¶
- deals-api-mcp README — server setup, all 10 MCP tools, data models
src/ad_seller/clients/deals_api_mcp_client.py— source forDealsAPIMCPClient