> ## Documentation Index
> Fetch the complete documentation index at: https://docs.useadstudio.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Adstudio MCP

> Connect ChatGPT, Claude, Muse or any MCP client to your ad accounts through Adstudio's read-only MCP server.

Adstudio MCP is a hosted [Model Context Protocol](https://modelcontextprotocol.io) server. It lets an AI assistant you already use read the advertising data connected to your Adstudio workspaces and answer questions like *"why did CPA jump last week?"* with real numbers from your accounts.

|                          |                                                                          |
| ------------------------ | ------------------------------------------------------------------------ |
| **Endpoint**             | `https://useadstudio.com/api/mcp`                                        |
| **Transport**            | Streamable HTTP (MCP 2025-06-18)                                         |
| **Authentication**       | OAuth 2.1 with PKCE, dynamic client registration, refresh token rotation |
| **Platforms live today** | Google Ads, Meta Ads                                                     |
| **Access**               | Read-only. No tool can change anything in an ad account.                 |

## How it works

<Steps>
  <Step title="Connect your ad accounts in Adstudio">
    Google Ads and Meta Ads accounts are connected once, in **Settings → Integrations**, exactly as for the rest of the product. The MCP server never asks for platform credentials itself.
  </Step>

  <Step title="Create your MCP connection">
    In **Settings → MCP** you create one personal connection. It reaches every workspace you belong to, including ones you join later, and shows a per-platform **Read** and **Write** toggle for each workspace. Only what you enable is reachable; write is not exposed by any tool yet, the toggle only records intent for future releases.
  </Step>

  <Step title="Authorize a client">
    Add `https://useadstudio.com/api/mcp` in ChatGPT, Claude, Muse or any MCP client. The client discovers Adstudio's authorization server, you sign in to Adstudio in the browser and approve the connection. See [Connect a client](#connect-a-client).
  </Step>

  <Step title="Ask">
    The assistant first lists your accounts, then names an explicit workspace, platform and account on every call. Nothing is inferred or defaulted. See [Tools](#tools) for what it can retrieve.
  </Step>
</Steps>

## What the assistant can do

* **Discover scope**: the workspaces you belong to, the platforms connected in each, the selected ad account, and whether read is allowed there.
* **Query performance**: spend, impressions, clicks, conversions, conversion value, impression share, reach, frequency, CPM, CTR, CPC and video metrics at account, campaign, ad group, ad set or ad level, with a comparison period and one breakdown (date, device, placement, publisher platform, position, age, gender).
* **Browse structure**: campaigns, ad groups, ad sets and ads with status and type, without metrics.
* **Review creatives**: headlines, body copy, descriptions, media, destination URLs and automation features for any scope.

Every response carries **provenance** (source, retrieval time, currency, period, timezone, attribution model) and an **unresolved** list naming anything that could not be retrieved and why. The assistant never has to guess.

## Permissions and safety

* A connection belongs to a **person**, not a workspace, and can never exceed that person's role. Members read; admins can additionally grant write toggles.
* Scope is **re-read on every request**. Withdrawing a permission in Settings → MCP takes effect on the next call, not at token expiry.
* **Revoke** in Settings → MCP cuts every client's access immediately.
* Text written outside Adstudio (account names, campaign names, ad copy, search terms) is returned marked as untrusted content, so a client can treat it as data rather than instructions.
* Adstudio discloses only the data you ask for, to the client you authorized, and never sends platform OAuth credentials to the client. See the [privacy policy](https://useadstudio.com/privacy-policy).

## Limits

* Google Ads and Meta Ads only. Requests for any other platform are refused with an explicit reason; additional platforms are added as they are verified.
* One selected ad account per platform per workspace, the one selected in Adstudio.
* `query_performance` and `get_entities` return at most 500 rows per call, `get_creatives` at most 100. Responses say when they were truncated and how to widen the query.
* Rate limits apply per workspace and on the registration endpoint. Interactive use does not reach them.

## Connect a client

### Before you start

1. At least one **Google Ads** or **Meta Ads** account is connected in an Adstudio workspace you belong to (**Settings → Integrations**).
2. You created your connection in **Settings → MCP** and enabled **Read** for that platform in that workspace. Authorization is refused until a connection exists, so that no client can silently choose your permissions for you.

The address is always the same and carries no secret:

```
https://useadstudio.com/api/mcp
```

### ChatGPT

<Steps>
  <Step title="Add the app">
    In ChatGPT open **Settings → Apps & Connectors** (or **Plugins**) and search for **Adstudio**. If you are adding it as a custom connector in developer mode, paste the endpoint above.
  </Step>

  <Step title="Sign in and authorize">
    ChatGPT opens Adstudio's sign-in page. Sign in with your Adstudio account and approve the connection.
  </Step>

  <Step title="Ask">
    Start with *"List my ad accounts in Adstudio"*, then ask about performance, structure or creatives of the account you name.
  </Step>
</Steps>

### Claude

<Steps>
  <Step title="Add a custom connector">
    In Claude open **Settings → Connectors → Add custom connector**, name it Adstudio and paste the endpoint above.
  </Step>

  <Step title="Authorize">
    Claude discovers Adstudio's authorization server automatically, registers itself and opens the sign-in page. Approve the connection.
  </Step>

  <Step title="Enable it in a chat">
    Turn the Adstudio connector on in the tools menu of a conversation and ask.
  </Step>
</Steps>

### Muse and other MCP clients

Any client that supports remote MCP servers over Streamable HTTP with OAuth 2.1 works the same way: add the endpoint, complete the browser sign-in, ask. Clients that only support stdio servers need a bridge such as `mcp-remote`:

```json theme={null}
{
  "mcpServers": {
    "adstudio": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://useadstudio.com/api/mcp"]
    }
  }
}
```

### Discovery endpoints

MCP clients find these on their own; they are listed for operators who need to whitelist or debug them.

| Purpose                                  | URL                                                                    |
| ---------------------------------------- | ---------------------------------------------------------------------- |
| Protected resource metadata (RFC 9728)   | `https://useadstudio.com/.well-known/oauth-protected-resource/api/mcp` |
| Authorization server metadata (RFC 8414) | `https://useadstudio.com/.well-known/oauth-authorization-server`       |
| Authorization                            | `https://useadstudio.com/api/mcp/oauth/authorize`                      |
| Token                                    | `https://useadstudio.com/api/mcp/oauth/token`                          |
| Dynamic client registration (RFC 7591)   | `https://useadstudio.com/api/mcp/oauth/register`                       |

Redirect URIs must be exact `https://` URLs or a loopback host. Access tokens are short-lived; refresh tokens rotate on every use.

### Troubleshooting

<AccordionGroup>
  <Accordion title="The client says it cannot find the authorization server">
    The metadata documents above must answer without a session. If your network proxies `useadstudio.com`, make sure `/.well-known/*` and `/api/mcp/*` are reachable unauthenticated.
  </Accordion>

  <Accordion title="Authorization is refused with a message about Settings → MCP">
    You have not created a connection yet. Open **Settings → MCP** in Adstudio, create one, enable Read for the platforms you need, then retry the client.
  </Accordion>

  <Accordion title="list_accounts returns a workspace but read is denied">
    Read is switched off for that platform in that workspace, or your role does not allow it. The response says which. Enable it in Settings → MCP.
  </Accordion>

  <Accordion title="A query returns status error with an unresolved entry">
    The platform API could not answer. Check the integration in **Settings → Integrations** (expired tokens show a reconnect banner) and retry.
  </Accordion>

  <Accordion title="I want to cut access now">
    **Settings → MCP → Revoke**. Every client loses access on its next request. Create a new connection to reconnect.
  </Accordion>
</AccordionGroup>

Still stuck? Use the [support page](https://useadstudio.com/support). Never paste tokens or the challenge value into a support request.

## Tools

All five tools are read-only. Every tool except `list_accounts` requires an explicit `workspaceId`, `platform` (`google_ads` or `meta_ads`) and `accountId`; the server never defaults them. Every response has the same envelope:

```json theme={null}
{
  "data": { "status": "ok", "...": "..." },
  "provenance": { "source": "platform_api", "retrievedAt": "...", "currency": "TRY", "period": { "start": "...", "end": "...", "timezone": "Europe/Istanbul" }, "attribution": "..." },
  "unresolved": [ { "subject": "...", "kind": "could_not_look", "reason": "...", "remedy": "..." } ]
}
```

Values written outside Adstudio (account and campaign names, ad copy, search terms) are wrapped as `{ "untrusted": true, "value": "..." }`.

### list\_accounts

Lists every workspace the connection reaches, the platforms connected in each, the selected account per platform, and whether read and write are allowed there, with the reason when denied. Takes no arguments and makes no platform API call. Always the first call.

### describe\_capabilities

For one account, returns the levels, metrics, breakdowns, filters and limits `query_performance` accepts there, and what `get_entities` and `get_creatives` can return. Call it before the first query against an account.

| Argument                               | Required | Notes                |
| -------------------------------------- | -------- | -------------------- |
| `workspaceId`, `platform`, `accountId` | yes      | From `list_accounts` |

### query\_performance

Attributed performance rows for a date range.

| Argument                               | Required | Notes                                                                                                                                                                                                                                                                                                                                       |
| -------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `workspaceId`, `platform`, `accountId` | yes      |                                                                                                                                                                                                                                                                                                                                             |
| `level`                                | yes      | `account`, `campaign`, `ad_group` (Google), `ad_set` (Meta), `ad`                                                                                                                                                                                                                                                                           |
| `start`, `end`                         | yes      | `YYYY-MM-DD`, in the account's reporting timezone                                                                                                                                                                                                                                                                                           |
| `metrics`                              | yes      | At least one. Google: `impressions`, `clicks`, `spend`, `conversions`, `conversion_value`, plus `search_impression_share`, `search_budget_lost_impression_share`, `search_rank_lost_impression_share` at campaign level. Meta adds `reach`, `frequency`, `cpm`, `ctr`, `cpc`, `video_plays`, `video_thruplays`, `video_p25` … `video_p100`. |
| `comparison`                           | no       | `{ "start", "end" }` for a second period; rows come back with `comparisonMetrics`                                                                                                                                                                                                                                                           |
| `breakdowns`                           | no       | At most one: `date`, `device`, `placement`, `publisher_platform`, `platform_position`, `age`, `gender`                                                                                                                                                                                                                                      |
| `filters`                              | no       | `[{ "field": "entity_id", "value": "<id>" }]`; not allowed at account level                                                                                                                                                                                                                                                                 |
| `sort`                                 | no       | `{ "field", "direction" }`                                                                                                                                                                                                                                                                                                                  |
| `limit`                                | no       | 1–500                                                                                                                                                                                                                                                                                                                                       |

Google Ads returns raw counts only; derive CTR, CPC, CPA and ROAS from them. Meta reports conversions with the account's default attribution windows and names the conversion definition in the response.

### get\_entities

The current hierarchy for one level, without metrics: id, name, status and provider type, plus the parent when `parentId` is given.

| Argument                               | Required | Notes                                                        |
| -------------------------------------- | -------- | ------------------------------------------------------------ |
| `workspaceId`, `platform`, `accountId` | yes      |                                                              |
| `level`                                | yes      | `campaign`, `ad_group`, `ad_set`, `ad`                       |
| `parentId`                             | no       | Immediate parent id, e.g. a campaign id when listing ad sets |
| `limit`                                | no       | 1–500                                                        |

### get\_creatives

Ad-to-creative assignments with normalized copy (headlines, bodies, descriptions, paths, business names, calls to action), media, destination URLs and enabled automation features. No metrics; join with `query_performance` at `ad` level to rank creatives.

| Argument                               | Required             | Notes                                             |
| -------------------------------------- | -------------------- | ------------------------------------------------- |
| `workspaceId`, `platform`, `accountId` | yes                  |                                                   |
| `scopeLevel`                           | yes                  | `account`, `campaign`, `ad_group`, `ad_set`, `ad` |
| `entityId`                             | at non-account scope | The campaign, ad group, ad set or ad id           |
| `limit`                                | no                   | 1–100                                             |

### Example prompts

* "How did my Google Ads campaigns perform last week compared with the week before?"
* "Give me a monthly summary of my Meta Ads account with spend, conversions, CPA and ROAS versus the previous month."
* "Why did the CPA of my Brand Search campaign go up in the last 14 days?"
* "Which ads in my Meta Ads account are showing signs of creative fatigue right now?"
* "Rank the ads in my Summer Sale campaign by ROAS and show me what the top three say."
* "Break down my Meta Ads spend by placement for the last 30 days."

### What the tools will not do

* Change budgets, statuses, bids, targeting or creatives. Requests to do so are answered with the read-only boundary.
* Query TikTok Ads, OpenAI Ads, DV360, Adjust, GA4 or Search Console through MCP yet, even though they are connected in Adstudio.
* Guess a workspace, account, currency or timezone.
