Use SpendDaddy with MCP
SpendDaddy's Model Context Protocol server lets an AI client query your organization's apps, Apple Ads performance, App Store context, subscription outcomes, and tracked organic App Store search ranks. With an owner's permission, the client can also preview and commit a limited set of Apple Ads changes.
The MCP endpoint is:
https://api.spenddaddy.app/mcp
MCP is the recommended way to connect an agent to SpendDaddy. Your client fetches the current tools and their argument schemas each time it connects, so the agent sees changes to a tool without any code changes on your side. Tools can still change while SpendDaddy's agent features are in beta, but hard-coded calls to the HTTP Agent API are more likely to break.
The server uses Streamable HTTP and bearer keys. A read-only key can call every read tool. Committing a change needs a mutation key limited to one app and an execution policy set by the app owner. The MCP tools and the beta Agent API share authorization, rate limits, and the action audit; the Agent API page covers the action and retry workflow.
Before you start
You need:
- A SpendDaddy organization with at least one app.
- An organization-owner account, so you can create an MCP key.
- An MCP client that supports remote Streamable HTTP servers and custom
Authorizationheaders.
An MCP key is not the first-party attribution API key. Use the MCP key only to connect an AI client to SpendDaddy.
Create an MCP key
- Sign in to SpendDaddy.
- Open Settings → Agents for the app.
- Create a key and give it a recognizable name, such as
Claude desktoporTeam analytics. - Copy the secret when it is shown. The full secret is shown only once.
- Store it in your client's secret manager or environment, not in source control.
Keys belong to one organization. Select Limit to this app to restrict a key to the current app. To let a key commit changes, select Permit mutations under owner policy; this also limits the key to the app.
Configure your client
Select Streamable HTTP, HTTP, or Remote MCP server in your client, depending on its terminology. Use the endpoint and header below:
| Setting | Value |
|---|---|
| Server URL | https://api.spenddaddy.app/mcp |
| Authorization | Bearer <your_mcp_key> |
Generic JSON configuration
The exact property names differ between MCP clients. This shows the values to
provide when a client accepts an mcpServers JSON configuration:
{
"mcpServers": {
"spenddaddy": {
"type": "http",
"url": "https://api.spenddaddy.app/mcp",
"headers": {
"Authorization": "Bearer ${SPENDDADDY_MCP_KEY}"
}
}
}
}
${SPENDDADDY_MCP_KEY} is an illustrative environment-variable reference.
Use your client's supported secret substitution, or enter the key in its
secure configuration UI. Do not replace it with a real key in a checked-in
configuration file.
Environment variables
For clients or wrappers that separate connection settings from secrets:
export SPENDDADDY_MCP_URL="https://api.spenddaddy.app/mcp"
export SPENDDADDY_MCP_KEY="<your_mcp_key>"
Configure the client to send:
Authorization: Bearer ${SPENDDADDY_MCP_KEY}
Verify the connection
Send a raw MCP initialization request to check the key. This also helps when a client configuration is not working:
curl "$SPENDDADDY_MCP_URL" \
--request POST \
--header "Authorization: Bearer $SPENDDADDY_MCP_KEY" \
--header "Accept: application/json, text/event-stream" \
--header "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2026-07-28",
"capabilities": {},
"clientInfo": {"name": "curl", "version": "1.0"}
}
}'
A valid key returns a successful MCP initialization response. A missing,
invalid, or revoked key returns 401 Unauthorized.
App IDs are immutable, case-sensitive 12-character random strings, for example
app000000042 (synthetic). Use the id returned by list_apps or
GET /api/v1/apps in every app path, proposal, and MCP argument. Integer
database keys are no longer accepted. Existing app scopes remain valid
internally; clients must refresh IDs and discard old pagination cursors.
Available tools
list_apps
No arguments. Returns the apps visible to the authenticated organization,
including SpendDaddy ID, App Store ID, bundle ID, primary locale, and currency.
Use the SpendDaddy id as app_id in the other tools.
evaluate_keywords
Matches candidate keyword strings to country- and match-type-aware Apple Ads placements and returns joined acquisition economics.
Required arguments:
{
"app_id":"app000000042",
"keyword_texts": ["solar watch", "sunrise alarm"],
"country": "US"
}
Optional arguments:
match_type:EXACTorBROAD.windows: one to three windows from7,30,90,180, or365days.
The response includes placements, external Apple Ads IDs, spend, impressions,
taps, installs, trials, paid conversions, D30 revenue, CAC, D30 ROAS, bid and
impression-share context, and tracked organic rank history. Organic rank is
reported under market_context.organic_rank at app/search-term/country grain:
{
"market_context": {
"organic_rank": [
{
"date": "2026-08-07",
"country_or_region": "US",
"search_term": "solar watch",
"rank": 7,
"result_limit": 200,
"checked_at": "2026-08-07T08:00:00+00:00"
}
]
}
}
A null rank means the app was not found within the tracked result limit. It
does not mean the app has an exact rank beyond that limit.
compare_acquisition
Compares acquisition rows over one to three time windows.
{
"app_id":"app000000042",
"level": "keyword",
"country": "US",
"windows": [30, 90],
"limit": 25
}
level can be country, campaign, ad_group, keyword, or search_term.
Country rows sum single-country campaigns; multi-country and unknown-country campaigns
remain in unallocated_placements without estimating a country split. Search-term
rows contain delivery metrics only; SpendDaddy does not estimate search-term
revenue or organic attribution.
get_funnel
Returns install-cohort funnels at app, campaign, ad-group, or keyword scope.
{
"app_id":"app000000042",
"days": 180,
"granularity": "weekly",
"revenue_window": "d30"
}
granularity can be daily, weekly, or monthly. revenue_window can be
d7, d30, d60, d90, or observed. Use entity_type and entity_id to
scope the funnel to one campaign, ad group, or keyword.
Other tools
| Tool | Purpose |
|---|---|
get_data_health | Data coverage and freshness for an app |
get_economics | D7, D30, D60, and D90 cohort revenue curves with maturity |
get_placement_outlook | Provisional placement forecast and its validation limits |
get_decision_policy | The owner's execution policy and the authority it grants |
list_recommendations, get_recommendation | Recommendations and their evidence |
list_actions, get_action | Action audit, preview evidence, and evaluation revisions |
list_events | Committed events since a cursor, the same records as GET /api/v1/events |
get_delivery_health | Delivery status counts for event webhooks |
propose_outcome_annotation | Record a product, price, or paywall change for the owner to confirm |
preview_action | Preview one bid, keyword status, campaign budget, or campaign status change, or a recommendation that maps to one |
commit_action | Commit a preview. Needs a mutation key, an owner policy, and the organization guardrail |
reconcile_action | Read Apple Ads state for a pending action without repeating the write |
Your client shows each tool's current arguments. The Agent API page explains the action, retry, and event semantics behind these tools.
Data and security notes
- Authentication uses static bearer keys. OAuth sign-in is not available.
- Money and ratios are returned as decimal strings with an explicit currency where applicable.
- App Store metrics remain at app/country grain and are not copied onto keyword rows.
- SpendDaddy does not report or infer search-term revenue or keyword-level organic attribution.
- If a key may have been exposed, select Rotate or Delete next to it in Settings → Agents. Either one stops the old key working immediately.
Troubleshooting
| Symptom | Check |
|---|---|
401 Unauthorized | Confirm the bearer key, endpoint, and that the key has not been rotated or revoked. |
| The client cannot connect | Confirm that it supports remote Streamable HTTP and custom authorization headers. |
list_apps returns no apps | The key may belong to another organization, or the organization may not have an app yet. |
| Organic rank is empty | Rank checks are available only for tracked keyword/country combinations and collected dates. |
For credential handling and rotation guidance, see Secrets and rotation.