{"_id":"@channel47/tiktok-ads-mcp","name":"@channel47/tiktok-ads-mcp","dist-tags":{"beta":"0.1.0","latest":"0.1.0"},"versions":{"0.1.0":{"name":"@channel47/tiktok-ads-mcp","version":"0.1.0","description":"TikTok Ads MCP Server - Query and mutate TikTok for Business ads data via the Business API","main":"server/index.js","bin":{"tiktok-ads-mcp":"server/index.js"},"type":"module","scripts":{"start":"node server/index.js","test":"node --test *.test.js test/*.test.js","prepublishOnly":"npm test"},"keywords":["mcp","model-context-protocol","tiktok-ads","tiktok-for-business","analytics","advertising","claude"],"author":{"name":"channel47"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/channel47/mcps.git","directory":"tiktok-ads"},"bugs":{"url":"https://github.com/channel47/mcps/issues"},"homepage":"https://github.com/channel47/mcps/tree/main/tiktok-ads#readme","dependencies":{"@modelcontextprotocol/sdk":"^1.29.0"},"engines":{"node":">=18.0.0"},"_id":"@channel47/tiktok-ads-mcp@0.1.0","gitHead":"b40ed5fec586628f184bd1fecd8838760b4e67e9","_nodeVersion":"24.1.0","_npmVersion":"11.3.0","dist":{"integrity":"sha512-jer5ZkkKIAbjzRmTKxLng0DUEMNIDk4Oj1u24GamapQyb7rRnYs0By8fbz6lAABiQfiStTefd+0IwIiz2xK0wQ==","shasum":"231d542fe42948efa3c6a6cbecbba9a922bf77be","tarball":"https://registry.npmjs.org/@channel47/tiktok-ads-mcp/-/tiktok-ads-mcp-0.1.0.tgz","fileCount":19,"unpackedSize":63397,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIASAjI5X09UhhzsB9VG9YTspDxuXk7OhNdus0d36EtONAiEAnAwPVzWNRGGqELUIjEnrfUlfRz8Zif406XjZVLUbyas="}]},"_npmUser":{"name":"ctrlswing","email":"jacksondean.me@gmail.com"},"directories":{},"maintainers":[{"name":"ctrlswing","email":"jacksondean.me@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/tiktok-ads-mcp_0.1.0_1783745133900_0.043447045821428665"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-11T04:45:33.765Z","0.1.0":"2026-07-11T04:45:34.042Z","modified":"2026-07-11T04:45:34.271Z"},"maintainers":[{"name":"ctrlswing","email":"jacksondean.me@gmail.com"}],"description":"TikTok Ads MCP Server - Query and mutate TikTok for Business ads data via the Business API","homepage":"https://github.com/channel47/mcps/tree/main/tiktok-ads#readme","keywords":["mcp","model-context-protocol","tiktok-ads","tiktok-for-business","analytics","advertising","claude"],"repository":{"type":"git","url":"git+https://github.com/channel47/mcps.git","directory":"tiktok-ads"},"author":{"name":"channel47"},"bugs":{"url":"https://github.com/channel47/mcps/issues"},"license":"MIT","readme":"# @channel47/tiktok-ads-mcp\n\nMCP server for TikTok Ads using the TikTok for Business API (`v1.3`).\n\nThis server exposes four tools expected by channel47 TikTok workflows:\n\n- `list_accounts`\n- `query`\n- `report`\n- `mutate`\n\n## Installation\n\n### Standalone\n\n```bash\nnpx @channel47/tiktok-ads-mcp@latest\n```\n\n### Claude Code\n\n```bash\nclaude mcp add tiktok-ads --env TIKTOK_ADS_ACCESS_TOKEN=<token> -- npx @channel47/tiktok-ads-mcp@latest\n```\n\nOr as JSON config:\n\n```json\n{\n  \"mcpServers\": {\n    \"tiktok-ads\": {\n      \"command\": \"npx\",\n      \"args\": [\"@channel47/tiktok-ads-mcp@latest\"],\n      \"env\": {\n        \"TIKTOK_ADS_ACCESS_TOKEN\": \"<token>\",\n        \"TIKTOK_ADS_ADVERTISER_ID\": \"<advertiser id>\"\n      }\n    }\n  }\n}\n```\n\n### Monorepo Development\n\n```bash\ncd mcps\nnpm install\nnpm run test\n```\n\n## Getting Credentials\n\n1. Create a developer app at [TikTok for Business Developers](https://business-api.tiktok.com/portal) (Marketing API).\n2. Authorize the app against your advertiser account(s) via the app's authorization URL.\n3. Exchange the returned `auth_code` for a long-lived access token at `POST /open_api/v1.3/oauth2/access_token/`.\n4. Use that token as `TIKTOK_ADS_ACCESS_TOKEN`. The token is sent as the `Access-Token` request header (not `Authorization: Bearer`).\n\n## Configuration\n\n### Required\n\n| Variable | Description |\n|----------|-------------|\n| `TIKTOK_ADS_ACCESS_TOKEN` | TikTok Business API long-lived access token |\n\n### Optional\n\n| Variable | Description |\n|----------|-------------|\n| `TIKTOK_ADS_ADVERTISER_ID` | Default advertiser ID used when `advertiser_id` is omitted |\n| `TIKTOK_ADS_APP_ID` | Developer app ID — only needed so `list_accounts` can discover authorized advertisers via `/oauth2/advertiser/get/` |\n| `TIKTOK_ADS_APP_SECRET` | Developer app secret (pairs with `TIKTOK_ADS_APP_ID`) |\n| `TIKTOK_ADS_READ_ONLY` | Set to `true` to disable live mutations |\n| `TIKTOK_ADS_REQUEST_TIMEOUT_MS` | HTTP request timeout in milliseconds (default `30000`) |\n\n## Tool Reference\n\n### `list_accounts`\n\nList accessible TikTok ad accounts (advertisers).\n\n**Params:**\n- `advertiser_ids` (optional): explicit advertiser ids to look up\n\n**Notes:**\n- With `TIKTOK_ADS_APP_ID` + `TIKTOK_ADS_APP_SECRET` set, ids are discovered via `GET /oauth2/advertiser/get/`\n- Without app credentials, pass `advertiser_ids` or set `TIKTOK_ADS_ADVERTISER_ID`\n- Details (name, status, currency, timezone, company, country) come from `GET /advertiser/info/` (batched 100 ids per request)\n\n### `query`\n\nStructured query wrapper for TikTok Business API entities:\n\n- `campaigns` — `GET /campaign/get/`\n- `adgroups` — `GET /adgroup/get/`\n- `ads` — `GET /ad/get/`\n\n**Params:**\n- `entity` (required)\n- `advertiser_id` (optional if `TIKTOK_ADS_ADVERTISER_ID` exists)\n- `fields`: array or comma-separated string (entity-specific defaults)\n- `filtering`: TikTok filtering object, e.g. `{ \"campaign_ids\": [\"123\"], \"primary_status\": \"STATUS_DELIVERY_OK\" }`\n- `limit`: max rows (default `100`, max `1000`); pagination via `page`/`page_size` is handled automatically\n\n### `report`\n\nSynchronous integrated reporting via `GET /report/integrated/get/`.\n\n**Params:**\n- `advertiser_id` (optional if `TIKTOK_ADS_ADVERTISER_ID` exists)\n- `report_type`: `BASIC` (default) or `AUDIENCE`\n- `data_level`: `AUCTION_ADVERTISER`, `AUCTION_CAMPAIGN` (default), `AUCTION_ADGROUP`, `AUCTION_AD`\n- `dimensions`: defaults to the data_level id dimension plus `stat_time_day`\n- `metrics`: defaults to `spend, impressions, clicks, ctr, cpc, cpm, conversion, cost_per_conversion, conversion_rate`\n- `start_date` / `end_date` (`YYYY-MM-DD`, default trailing 7 days UTC) or `lifetime: true`\n- `filtering`: array of `{ field_name, filter_type, filter_value }` clauses\n- `order_field` / `order_type` (`ASC` / `DESC`)\n- `limit`: max rows (default `100`, max `1000`)\n\nRows are returned with `dimensions` and `metrics` flattened into a single object per row.\n\n### `mutate`\n\nMutation tool with dry-run safety by default.\n\n**Operation format:**\n\n```json\n{\n  \"entity\": \"campaign\",\n  \"action\": \"update\",\n  \"id\": \"1781234567890\",\n  \"params\": {\n    \"budget\": 500\n  }\n}\n```\n\n**Supported entities:** `campaign`, `adgroup`, `ad`\n\n**Supported actions:**\n- `create` — `POST /<entity>/create/`; campaign and adgroup creates default `operation_status` to `DISABLE` (paused) — pass explicit `operation_status` to override\n- `update` — `POST /<entity>/update/`; `id` maps to `campaign_id`/`adgroup_id`. Ad updates take the full `/ad/update/` body in `params` (ads are identified via `creatives[].ad_id`), so `id` is optional\n- `pause` / `enable` / `delete` — `POST /<entity>/status/update/` with `operation_status` `DISABLE` / `ENABLE` / `DELETE`\n\n**Top-level params:**\n- `operations` (required)\n- `advertiser_id` (optional if `TIKTOK_ADS_ADVERTISER_ID` exists)\n- `dry_run` (default `true`)\n- `partial_failure` (default `true`)\n\n**Safety notes:**\n- TikTok has **no server-side validate-only mode**. `dry_run: true` validates operations locally and returns a preview of the exact requests (method, path, body) without calling the API.\n- `delete` is permanent and unrecoverable — prefer `pause`.\n- Set `TIKTOK_ADS_READ_ONLY=true` to remove the mutate tool entirely.\n\n## Behavior Notes\n\n- Auth is sent via the `Access-Token` request header\n- TikTok returns HTTP `200` with an envelope `{ code, message, request_id, data }`; any non-zero `code` is surfaced as an error including the API code and message\n- Complex GET params (`fields`, `filtering`, `dimensions`, `metrics`, `advertiser_ids`) are JSON-encoded into the query string automatically\n- API retries once on HTTP `429` or envelope error code `40100` (rate limit), honoring `Retry-After` when present (fallback `60s`)\n- Requests are aborted on timeout (default `30000ms`, configurable via `TIKTOK_ADS_REQUEST_TIMEOUT_MS`)\n- List endpoints paginate with `page`/`page_size` (`data.page_info.total_page`)\n\n## Development Commands\n\n```bash\ncd tiktok-ads\nnpm test\nnode server/index.js\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-9d37a08b163463ea0a8049cec222209a"}