Skip to main content
Glama
mfontanilla-coder

tiktok-ads-mcp

README.md
# tiktok-ads-mcp

A small, read-only [MCP](https://modelcontextprotocol.io) server that gives Claude Desktop live access to TikTok Ads Manager data through the TikTok Marketing API v1.3 — spend, impressions, clicks, platform conversions and cost per conversion at account, campaign, ad group and ad level, by day if you want it.

Built for agency reporting: one developer app, any number of ad accounts. Each person who installs it authorizes their own TikTok for Business login, so they see exactly the ad accounts they already have access to and nothing else.

Nothing here writes to TikTok.

## Tools

Every tool takes a single `params` object.

| Tool | What it returns |
|---|---|
| `tiktok_debug` | Config check — is the token set, is it valid, how many ad accounts it can see. No secrets in the output. |
| `tiktok_list_advertisers` | The ad accounts the token can read: id, name, currency, timezone. |
| `tiktok_list_campaigns` | Campaigns for an ad account with objective, status, budget. Filter by `status`. |
| `tiktok_get_report` | Performance report for a date range at `advertiser`, `campaign`, `adgroup` or `ad` level; `by_day: true` adds a date column. Pages and long ranges are handled for you. |
| `tiktok_monthly_summary` | One calendar month: account totals, a per-campaign table sorted by spend, rates recomputed from sums, and a reconciliation of campaign sums vs account totals. |

Example prompts once it's connected: *"Run tiktok_debug"* · *"List my TikTok ad accounts"* · *"TikTok monthly summary for advertiser 123 for 2026-08"* · *"TikTok ad-level report by day for last week"*.

## Setup

Three parts: a TikTok developer app (one per agency, made once), a one-time authorization per person, and registering the server with Claude Desktop.

### 1. Developer app — one per agency

If a colleague has already made the app, skip this and get the **App ID** and **Secret** from them.

1. Sign in at <https://business-api.tiktok.com/portal> with a TikTok for Business login.
2. **My Apps → Create an App.** Give it a name and description (e.g. "Agency reporting connector — read only").
3. **Advertiser redirect URL:** any `https://` URL you control, e.g. your agency homepage. After someone approves the app, TikTok sends them to this URL with `?auth_code=...` appended — they copy the code from the address bar. Nothing has to be built on that page.
4. **Scopes** — read-only only: *Ad Account Management → Read*, *Ads Management → Read*, *Reporting → Read*.
5. Submit for review. TikTok typically approves within 1–3 business days and emails you. Until then the app can only see sandbox accounts.
6. On the app page, copy the **App ID** and **Secret**.

### 2. Install and authorize — each person

```bash
git clone https://github.com/mfontanilla-coder/tiktok-ads-mcp.git ~/mcp-servers/tiktok-ads-mcp
cd ~/mcp-servers/tiktok-ads-mcp
bash setup.sh                    # creates .venv, installs mcp + httpx
.venv/bin/python tiktok-auth.py  # one-time authorization
```

`tiktok-auth.py` asks for the App ID, Secret and redirect URL, prints an authorization link, and waits. Open the link, sign in as **yourself** (the TikTok for Business user who has access to the ad accounts you manage), approve, then paste the `auth_code` from the address bar back into the terminal. Do it promptly — the code is short-lived. The script exchanges it for a long-lived access token (Marketing API tokens don't expire unless revoked), lists the ad accounts you authorized, lets you pick a default, and writes everything to `~/.tiktok-mcp/tiktok.env` with `chmod 600`.

If an ad account you expect is missing from the list, your TikTok user doesn't have access to it in Business Center. Fix that there and re-run.

### 3. Register with Claude Desktop

```bash
bash setup.sh --register
```

Adds a `tiktok` entry to `claude_desktop_config.json` pointing at this repo's venv (backs up the config first). Quit and reopen Claude Desktop, then ask Claude to *run tiktok_debug* — you want `token_valid: true`.

## Configuration

Everything lives in `~/.tiktok-mcp/tiktok.env`, outside the repo:

```
TIKTOK_APP_ID=...
TIKTOK_APP_SECRET=...
TIKTOK_ACCESS_TOKEN=...
TIKTOK_ADVERTISER_ID=...   # optional default; tools accept advertiser_id explicitly too
```

The repo's `.gitignore` excludes `*.env`. Never commit this file. To switch default ad accounts, edit the last line; to re-authorize (new login, revoked token), re-run `tiktok-auth.py`.

## Reading the numbers

- `spend` is platform-billed actuals in the ad account's currency.
- `conversion` is TikTok's reported optimization-event count. It is not GA4 key events and not CRM leads — label it "TikTok-reported conversions" when it sits next to either.
- `reach` is only meaningful at account level and is never summed across campaigns.
- Dates are in the ad account's timezone (see `tiktok_list_advertisers`).
- Rates in `totals` and `tiktok_monthly_summary` are recomputed from summed spend/clicks/impressions/conversions, not averaged across rows.
- Ranges longer than a month are fetched in 30-day windows and merged; a single calendar month is always one call so account reach stays whole.

## Troubleshooting

`tiktok_debug` says `token_valid: false` — the token was revoked or the app's approval lapsed. Re-run `tiktok-auth.py`.

*"TikTok API error 40xxx"* — the message from TikTok is passed through verbatim with its `request_id`; the most common cause is asking for an `advertiser_id` your login can't see.

The server doesn't show up in Claude — confirm the entry in `claude_desktop_config.json` points at `<repo>/.venv/bin/python` and `<repo>/server.py`, then fully quit and reopen the app.

## Files

| File | Purpose |
|---|---|
| `server.py` | The MCP server |
| `tiktok-auth.py` | One-time OAuth exchange → writes `~/.tiktok-mcp/tiktok.env` |
| `setup.sh` | venv + dependencies; `--register` adds the server to Claude Desktop |
| `requirements.txt` | `mcp[cli]`, `httpx` |

MIT licensed.