media_buy and creative.
The server is hosted at sales-agent.dappier.com.
Watch the Video
If you prefer a visual walkthrough, check out the accompanying video below:What is MCP?
If you’ve never seen MCP before, here’s the mental model:- The server advertises tools (name + JSON schema + description).
- The client fetches that list and lets the LLM call any tool by name with arguments that match the schema.
- The server validates, executes, and returns a result the LLM can use to continue the conversation.
What the Sales Agent MCP Server Does
Two AdCP protocols are supported:
What you get as a developer:
- An AI-callable surface for Dappier Sponsored Conversations — the branded prompt suggestions that appear inside publisher AI chat widgets across the Dappier network.
- Campaign lifecycle in a single tool call: create a paused campaign with advertiser details, CTA, targeting, and optional sponsored prompts.
- Creative lifecycle: attach a configurable Dappier Brand Agent (conversational AI creative) to a campaign via
build_creative. - Delivery reporting over a date range.
- It does not quote prices or sell impressions directly — pricing is handled offline by Dappier sales (
[email protected]). - It does not activate campaigns. Every campaign is born
paused; a Dappier reviewer must approve and a sales rep must complete Google Ad Manager (GAM) line-item setup before it serves. - It does not honor standard AdCP targeting (geo, device, language, audience). Dappier targeting is
dappier_network/my_network/individual_agents.
Getting Started
Base URLs and Endpoints
The server is hosted by Dappier. Connect using the standard MCP streamable-HTTP transport.
Health / discovery endpoints (open, no auth):
Use the deployed URL Dappier publishes — for example
https://sales-agent.dappier.com/mcp. Confirm the current host with your Dappier contact.Authentication
Every MCP request (except/ and /.well-known/* discovery endpoints) requires a Dappier API key.
Query parameter
HTTP header
401 with a plain-text body:
Getting an API key
Create Dappier API keys at platform.dappier.com/profile/api-keys. The key is used:- As a Bearer token on every outbound call the server makes to
api.dappier.com. - To authorize the MCP session itself at the edge.
Connecting from Common MCP Clients
Claude Desktop (via mcp-remote)
Claude Desktop speaks MCP over stdio. To reach a remote HTTPS MCP server, proxy through mcp-remote.
Edit your Claude Desktop config (Settings → Developer → Edit Config):
Claude.ai (Connectors / Remote MCP)
On claude.ai, add a custom connector / remote MCP server pointing athttps://sales-agent.dappier.com/mcp. Supply the API key via header (dappier-api-key) where the UI allows custom headers, or via ?apiKey=... in the URL otherwise.
Cursor
Add a remote MCP server in Cursor’s MCP settings pointing at:Cloudflare AI Playground
Go to playground.ai.cloudflare.com and enter this as the server URL:Custom Node.js Client
Any client built on@modelcontextprotocol/sdk can connect over streamable HTTP:
TypeScript
Anthropic SDK (Native MCP Connector)
The Anthropic Messages API can call a remote MCP server directly as a tool-use source — no separate MCP client SDK required:Python
Server Discovery
GET /.well-known/mcp.json (and /.well-known/server.json) returns:
Conventions
ID prefixes
Schemas reject values that don’t match the expected prefix — the server won’t silently accept a mismatched id.
Response envelope
Every tool returns an MCPCallToolResult with two fields:
content[0]— atextblock containing pretty-printed JSON (for LLMs reading the text).structuredContent— the same payload as a machine-readable object (for programmatic clients).
Error shape
Errors follow AdCP conventions:status: "failed" wrapper is used:
Error code reference
Context passthrough
Most tools accept acontext: Record<string, unknown> field. Whatever you send is echoed back unchanged on the response — useful for correlating tool calls with your own session state.
Typical campaign lifecycle
Tools Reference
get_adcp_capabilities
Purpose: The first call a buyer should make. Tells you which AdCP protocols Dappier implements, which features inside those protocols are honored vs. ignored, the auth model, and which creative capabilities are available.
Network behavior: In-memory lookup. No outbound call. Returns instantly.
Inputs (all optional)
Success response
Error response
Targeting dimensions declared
false will return a validation error if sent — they are not silently dropped. media_buy and creative are the only protocols you’ll see.list_creative_formats
Purpose: Discover the creative formats supported by the Dappier sales agent. Call this before build_creative.
Network behavior: In-memory. Instant.
Inputs
All inputs are optional and all are ignored in v1 — accepted for AdCP forward-compat:Success response
Returns a single format descriptor fordappier_brand_agent (the only creative format Dappier exposes). The format_id.agent_url returned here is the exact value you must pass into build_creative.target_format_id.
Call this tool to pick up the exact
agent_url string — don’t hard-code it.build_creative
Purpose: Create a new Dappier Brand Agent (conversational AI creative) and attach it to a campaign, or update an existing one.
A Brand Agent is a configurable chat experience branded for an advertiser: name, description, optional persona, optional single knowledge source (RSS feed or webpage), and optional widget overrides (logo, colors, welcome copy, theme).
Two modes
Inputs
Success response
Example — CREATE
Example — UPDATE (change logo only)
list_creatives
Purpose: Browse the tenant’s Brand Agents, or look up specific ones.
Three filter paths
Mutually exclusive on the primary id filters:If both
creative_ids and media_buy_ids are supplied, creative_ids wins.filters.name_contains (case-insensitive) and filters.statuses (approved / pending_review / archived) narrow any of the three paths.
Inputs
get_products
Purpose: Discover Dappier’s advertising inventory. Always returns the single Sponsored Conversations product (or an empty list if your filters exclude it).
Network behavior: In-memory. No API call.
Inputs
Success response
brief_relevance is present only when brief was supplied.create_media_buy
Purpose: Create a sponsored campaign on the Dappier network. Campaign is born paused. It will not serve until:
- Dappier sales sets up the GAM line item offline.
- A Dappier reviewer approves it.
sponsored_prompts to create the clickable prompt content atomically with the campaign.
Inputs
Success response
Error response
INVALID_REQUEST, 401/403 → POLICY_VIOLATION, 409 → CREATIVE_ID_EXISTS, else → INTERNAL_ERROR.
Example
update_media_buy
Purpose: Modify an existing Dappier campaign. PATCH semantics — omitted fields are preserved. Atomic — either all changes apply or none do.
The handler routes to one of three backend operations based on what you send:
Inputs
All optional exceptmedia_buy_id:
Sponsored-prompts replacement semantics
Pass the full desired set after the update:- Entries with
prompt_id(pm_xxxx) → updated. - Entries without
prompt_id→ newly created. - Existing prompts not present in the array → soft-deleted.
Success response
Resume-pending special case
If you sendpaused: false and the backend rejects with INVALID_STATE, NOT_APPROVED, or PENDING_APPROVAL, the tool returns status: "submitted" (not an error) with the message:
Resume requires Dappier sales to complete GAM setup and a reviewer to approve. The campaign remains paused.
Validation error — empty request
If you send nocanceled, no paused, and no update fields:
Examples
Pause a campaign:get_media_buys
Purpose: Retrieve the current operational state of Dappier campaigns — configuration, sponsored-prompt approval status, and which campaigns are waiting on Dappier sales / GAM setup.
Use this for “what’s the current state of my campaigns?”. For performance over a date range, use get_media_buy_delivery instead.
Inputs (all optional)
Success response
Status derivation rules
is_deleted === true→canceled- else
status === "active"→active - else if creative_ids exist →
paused - else →
pending_creatives
Valid actions by status
Empty-result nudge
If you pass neithermedia_buy_ids nor status_filter, the default filter is ["active"]. If that produces no campaigns, the response includes:
get_media_buy_delivery
Purpose: Retrieve delivery metrics (impressions, clicks, etc.) for Dappier campaigns over a date range or campaign lifetime.
Use this for “how did my campaigns perform over a period?”. For current state, use get_media_buys.
Inputs
Date range rules
- Send both dates or neither.
- Both must match
YYYY-MM-DD. start_date < end_datestrictly.- Violations return
INVALID_DATE_RANGEwithfieldset to the offender — no backend call is made.
Unsupported in v1
- Reporting dimensions (geo, device, audience, placement).
- Spend, ROAS, CPM, conversion value — pricing is handled offline in GAM, not tracked in Dappier.
Success response
Whatever the backend returns for the AdCP delivery shape is passed through verbatim, plus yourcontext echo. Expect at minimum per-campaign impressions/clicks and a reporting_period object.
Error response
code / error_code passed through if provided, else 404 → MEDIA_BUY_NOT_FOUND, 401 → AUTH_REQUIRED, 400 → INVALID_DATE_RANGE, else → INTERNAL_ERROR.
End-to-End Recipes
Launch a campaign (minimum viable flow)
What’s happening with my campaigns right now?
How did last month perform?
Edit the prompts on an existing campaign
Any pre-existing prompts not listed above are soft-deleted.
Attach a different Brand Agent to a campaign
Callbuild_creative in UPDATE mode with the existing creative_id. Only send the asset fields you want to change — the rest are preserved.
Guardrails the Server Enforces
These are quiet-but-strict rules callers often trip over.FAQ
Do I need to call get_adcp_capabilities on every request?
Do I need to call get_adcp_capabilities on every request?
No. Call it once per session to discover the surface, then cache the result.
Why is my new campaign still paused an hour later?
Why is my new campaign still paused an hour later?
Every Dappier campaign is born paused and requires (a) Dappier sales to configure the GAM line item offline and (b) a reviewer to approve. Calling
update_media_buy { paused: false } before those steps complete returns status: "submitted" with an explanatory message, not an error.Can I set a budget?
Can I set a budget?
Pricing is offline. Budget / CPM / ROAS fields are not honored.
pricing_option_id is always "contact_sales".Can I target by geo / device / audience?
Can I target by geo / device / audience?
No. Dappier targeting is
dappier_network (whole network), my_network (your own publishers), or individual_agents (list of am_xxxx ids).What happens if I pass extra fields the server doesn't understand?
What happens if I pass extra fields the server doesn't understand?
Fields defined by AdCP but unused by Dappier (
idempotency_key, budget, include_snapshot, include_history, reporting_dimensions, format-filter arguments, etc.) are accepted for forward compatibility but ignored. Fields that are targeting dimensions Dappier doesn’t support will cause validation errors.How do I correlate a tool call with my own request id?
How do I correlate a tool call with my own request id?
Pass
context: { your_request_id: "..." } on any tool — it’s echoed back unchanged.Is the cursor format stable?
Is the cursor format stable?
get_media_buys currently uses page:<n> cursors. Treat it as opaque — don’t parse or construct it yourself.Can I create multiple creatives on one campaign?
Can I create multiple creatives on one campaign?
No. On CREATE, the target campaign must not already have a creative attached. Use UPDATE mode to modify the existing Brand Agent.
Glossary
Conclusion
The Dappier Sales Agent MCP gives AI agents a complete, AI-callable surface over the Dappier Sponsored Conversations network — campaign creation, Brand Agent creatives, and delivery reporting — while keeping pricing and activation in the hands of Dappier’s sales team. 🔗 Explore further:- Dappier Developers
- Dappier Platform — create your API key
- AdCP Specification
- Model Context Protocol
- Questions on pricing or activation? Contact [email protected]

