Skip to content
AdCrunch
Esc
↑↓navigate↵open⌘Jpreview
On this page

Auth & scopes

How OAuth works for the MCP server, what each scope grants, what an agent can and cannot change, and how access is revoked.

The AdCrunch MCP server is OAuth-protected. Your AI client (Claude, Cursor, ChatGPT, …) goes through a standard OAuth 2.1 PKCE flow with auth.adcrunch.dev and receives a short-lived bearer token plus a refresh token.

The token is for one resource only, the endpoint https://mcp.adcrunch.dev/mcp. The endpoint accepts no other credential: an API key of the REST API does not work there. Another client gives each step of the flow for a developer.

Which organization your client acts for

Your client acts for one organization: the organization that you choose on the consent screen. The consent screen shows the organization. If you are a member of more than one organization, you choose one there. That choice also changes the active organization of the console.

Your client keeps that organization. A new token, which your client gets about once an hour, carries the same organization. A switch in the console does not move your client to another organization.

To use another organization, connect the client again and choose that organization. If you already allowed the client for that organization, AdCrunch does not show the consent screen again: the client acts for the organization that is active in your AdCrunch session. So switch to that organization in the console first.

If you have no organization yet, AdCrunch asks you to create one before the consent screen. When you create it, you go back to the consent screen.

If you leave the organization, or someone removes you from it, your client cannot get a new token for it. A token that your client already holds works until it expires, at most one hour. Your client then asks you to connect again.

Scopes

OpenID Connect scopes identify you; AdCrunch service scopes gate what the tools can touch. The consent screen lists every scope the client asked for before you approve it.

A scope decides which tools can run. It does not decide which tools your client sees: each token gets the same list of tools. One part of the list depends on your organization: the tools that ask a provider now, such as meta_list_campaigns, show only for a provider that your organization has connected. With Meta, TikTok and Google Ads connected, the list has 70 tools. When the agent calls a tool whose scope the token does not hold, the call fails with the code forbidden. That failure is a normal tool result inside an HTTP 200, so the agent reads it and tells you. Errors gives its shape.

  • openid, profile, email — identifies your account.
  • offline_access — lets your client refresh its token, so you do not authorize it again each hour.
  • observe:read — read your organization’s connected ad-account setup and performance (list_advertisers, the ten tools that read the stored copy, such as list_campaigns and get_campaign, query_insights, meta_list_pages, meta_list_pixels, and the eleven tools that ask a provider now, such as meta_list_campaigns, tiktok_list_adgroups and gads_list_ad_group_ads).
  • skill:read — read your organization’s ad-ops playbooks (skill_list, skill_get).
  • skill:write — create, edit, and delete your playbooks (skill_create, skill_update, skill_delete).
  • brand:read — read your organization’s brand context: identity, voice, guidelines and messaging, plus its personas and its files (brand_list, brand_get, brand_resolve, persona_get, document_list, document_get).
  • brand:write — create, edit, and delete brands and their personas, attach or detach ad accounts, and manage their files (brand_create, brand_update, brand_delete, brand_attach_advertiser, brand_detach_advertiser, persona_create, persona_update, persona_delete, document_create_upload, document_finalize, document_delete).
  • campaign_plan:read — read your organization’s campaign plans: what it intends to run, on which channels, for how much, over what period (campaign_plan_list, campaign_plan_get). A campaign plan is AdCrunch’s own planning document, not a campaign on Meta or Google.
  • campaign_plan:write — write and approve those plans and their line items (campaign_plan_create, campaign_plan_update, campaign_plan_delete, campaign_plan_approve, line_item_create, line_item_update, line_item_delete, line_item_validate, line_item_record_execution). Planning is not buying: approving a plan creates nothing and spends nothing — turning one into live campaigns goes through mutation:write.
  • asset:read — list your organization’s source media and where it’s registered (asset_list, asset_get).
  • asset:write — upload media and register it into an ad account’s library (asset_create_upload, asset_finalize, asset_register).
  • mutation:write — change what is running on your connected ad accounts: create campaigns, ad sets, creatives and ads, move budgets, pause, resume and archive (meta_create_campaign, meta_create_adset, meta_create_creative, meta_create_ad, meta_update_budget, meta_set_status, polled with get_mutation_status). Meta only — what each provider supports says where every other capability stops. This is the only scope that spends money — and nothing is ever created active: everything an agent makes arrives paused.

asset:write covers both uploading and registering, but it is deliberately not mutation:write: an Asset landing in a provider’s library changes no delivery and spends no money, so granting it does not grant pausing a campaign.

What an agent can and cannot change

This is the complete list. There is nothing else behind it.

It can It cannot
Create a campaign, ad set, creative or ad — Meta. Always paused; never starts spending Use media it did not upload for you
Build a creative from media you uploaded — Meta Change targeting on an ad set that already exists
Set a new ad set’s countries, age range and gender — Meta Choose placements, interests, behaviours or audiences
Pause, resume or archive a campaign, ad set or ad — Meta Hard-delete anything, on any network
Change a daily or lifetime budget on a campaign or ad set — Meta Change bids or bid strategy
Upload creative into an ad account’s library — Meta, TikTok Put anything live on its own
Read setup and performance — Meta, TikTok, Google Ads Change a campaign, ad group or ad on any network but Meta
Author playbooks and brand context

Three guardrails, all in the shared mutation layer rather than in the individual tools — so no caller can route around them:

  • A create can never start spend. A campaign is created PAUSED, as a typed literal the layer sets itself. There is no status input on the create tool and there cannot be one, so nothing an agent makes begins spending until a person or a separate, deliberate call activates it.
  • A budget safety cap. Any budget above €1,000,000 or $1,000,000 is refused — on a create as well as an update, checked by the same code so the two cannot drift apart. The cap counts the unit Meta counts, so in a currency Meta counts with no decimals it is 100,000,000, for example ¥100,000,000.
  • A budget level check. On an update, a live read decides whether the budget actually lives on the campaign (Advantage campaign budget) or the ad set, and a change aimed at the wrong one is refused by name rather than silently ignored.

What the model never sees

Your provider credentials are never exposed to the AI model. The agent holds an AdCrunch bearer token — never a Meta, TikTok or Google one. Provider tokens are resolved inside the worker at the moment of the call, are never tool arguments, and are never written into durable workflow state.

Every tool is scoped to your active organization, and re-checks that the organization owns the ad account before it does anything. “No such account” and “not your account” return the same answer, so a client cannot probe for accounts that aren’t yours. Errors says what that answer looks like, and what else you can meet.

Every change is on the record

Each write is recorded in a durable ledger before it runs, and updated with its outcome when it finishes. A row holds who asked (the user, not just “an agent”), which ad account, the exact action — level, target and value — the outcome, and the timestamps for both. It is visible in the console on the Activity page.

The record is written independently of the agent, so an agent cannot act without leaving one, and a failed change is recorded as a failure rather than vanishing.

Token lifecycle

Access tokens are short-lived; clients refresh them with the refresh token issued at consent.

Was this page helpful?