MCP server
Skoup exposes an MCP (Model Context Protocol) server: an AI assistant can read your brands’ AI visibility, alerts, tasks, queries, catalogue and attributed revenue, and act on some of them, without writing code.
https://api.skoup.ai/mcpStreamable HTTP transport, stateless. The server is open on every plan, like the API.
Connecting
Claude, ChatGPT: OAuth connector
Add a custom connector with the address above. The assistant sends you to Skoup:
- sign in if needed (every sign-in method works);
- the consent screen shows the assistant, your account and the workspaces covered;
- tick Allow changes or not, then Allow.
The connection is personal: the assistant sees all your workspaces, with your rights in each. A client-viewer can never write. Connections are managed and cut in My profile → Connected apps.
Claude Code, Cursor, n8n: API key
A local client can use an API key instead of OAuth:
claude mcp add --transport http skoup https://api.skoup.ai/mcp \
--header "Authorization: Bearer skoup_live_…"{
"mcpServers": {
"skoup": {
"url": "https://api.skoup.ai/mcp",
"headers": { "Authorization": "Bearer skoup_live_…" }
}
}
}The assistant then has exactly the key’s scopes and brands. A skoup_test_ key works on the
demo workspace and never saves a write (Test mode).
Tools
Every tool is a public API route: same filters, same objects, same ids, same errors. Start with list_brands, or with search to find an object across all your brands: search and fetch follow ChatGPT’s deep-research format.
| Tool | Route | Scope |
|---|---|---|
list_brands | brands you can reach (all your workspaces with OAuth) | brands:read |
search | free text across the alerts, tasks, queries and products of all your brands | read scope of each type |
fetch | one object by the id search returned (same JSON as the API + a link to Skoup) | read scope of the type |
list_markets | GET /v1/brands/{brand}/markets | brands:read |
get_metrics | GET /v1/brands/{brand}/metrics | metrics:read |
list_samplings | GET /v1/brands/{brand}/samplings | metrics:read |
list_competitors | GET /v1/brands/{brand}/competitors | metrics:read |
get_readiness | GET /v1/brands/{brand}/readiness | metrics:read |
get_product_perception | GET /v1/brands/{brand}/products/{product}/perception | metrics:read |
list_alerts, get_alert | GET /v1/brands/{brand}/alerts[/{alert}] | alerts:read |
treat_alert, dismiss_alert | POST …/alerts/{alert}/treat | dismiss | alerts:write |
list_tasks, get_task | GET /v1/brands/{brand}/tasks[/{task}] | tasks:read |
create_task, update_task | POST …/tasks, PATCH …/tasks/{task} | tasks:write |
list_queries, get_query | GET /v1/brands/{brand}/queries[/{query}] | queries:read |
add_query, update_query | POST …/queries, PATCH …/queries/{query} | queries:write |
list_products, get_product | GET /v1/brands/{brand}/products[/{product}] | products:read |
get_ai_revenue | GET /v1/brands/{brand}/attribution | revenue:read |
get_ai_traffic | GET /v1/brands/{brand}/traffic (Growth and up) | revenue:read |
get_visibility_revenue_correlation | GET /v1/brands/{brand}/correlation (Growth and up) | revenue:read |
Two prompts are provided: weekly_brief (a brand’s weekly summary) and explain_alert.
With OAuth, read tools need no scope; write tools need Allow changes and a role that can edit the brand.
No tool spends credits or deletes anything: verifying an alert (which re-runs a sampling) stays in the app and the API.
Errors, limits, logs
- An error comes back as an
isErrortool result, in the API format (quota_exceeded,plan_feature_unavailable,insufficient_scope…). Missing authentication answers401with aWWW-Authenticateheader that points the client to OAuth. - The API rate limits apply, per key or per connected assistant.
- Every call shows up in Settings → Developers → Logs, tagged MCP, with the
/v1route actually called.
Pitfalls
- Prefixed ids: pass the
br_…,alrt_…,task_…a tool returns as they are to the next one. - A
nullblock was never measured: it is not 0 %. - Log out other sessions (profile) does not cut assistants: use Connected apps.