MCP Data API¶
General overview¶
The FraudScore MCP server lets language models (LLMs) and MCP-compatible clients retrieve traffic quality analytics from the FraudScore Data API. The user states a task ("show me the top affiliates by fraud score for September"), the LLM calls the appropriate tool with correct parameters, the server queries the Data API and returns ready-to-use data.
Capabilities:
- install and custom event data for a period (raw rows or aggregated);
- grouping, filtering, sorting, pagination;
- aggregated reports on install ↔ custom event joins;
- sensible defaults — a channel and a date range are enough to start;
- listing the account's channels (
list_channels) — the recommended starting point; - access control: an account only sees its own channels;
- all tools carry the read-only annotation (rendered by clients such as Claude Desktop and Cursor).
Connecting¶
| Parameter | Value |
|---|---|
| URL | https://mcp-data.fraudscore.ai/mcp |
| Transport | Streamable HTTP (stateless: no session, every request is independent) |
| Method | POST |
| Headers | Authorization: Bearer <MCP_TOKEN>, Content-Type: application/json, Accept: application/json, text/event-stream |
| Health check | GET /healthz → {"status":"ok"} |
The token (mcp_*) is issued by FraudScore and sent in the Authorization header with every request. The server uses the token to identify the account and its available channels. The token is personal — treat it as a secret.
Configuration for a typical MCP client (Claude Desktop, Cursor, etc.) — note the "type": "http" entry: without it the client tries to launch a local stdio process:
{
"mcpServers": {
"fraudscore-data-api": {
"type": "http",
"url": "[https://mcp-data.fraudscore.ai/mcp](https://mcp-data.fraudscore.ai/mcp)",
"headers": {
"Authorization": "Bearer mcp_your_token"
}
}
}
}
Node.js client example:
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
const transport = new StreamableHTTPClientTransport(new URL('[https://mcp-data.fraudscore.ai/mcp](https://mcp-data.fraudscore.ai/mcp)'), {
requestInit: { headers: { Authorization: `Bearer ${MCP_TOKEN}` } }
})
const client = new Client({ name: 'my-app', version: '1.0.0' })
await client.connect(transport)
const result = await client.callTool({
name: 'get_installs',
arguments: { channelId: 'my-channel', date_from: '2026-09-01', date_to: '2026-09-15' }
})
Or plain JSON-RPC over HTTP:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_installs",
"arguments": { "channelId": "my-channel", "date_from": "2026-09-01", "date_to": "2026-09-15" }
}
}
Tools¶
list_channels¶
Returns the channel identifiers (channelId) available to the account. Takes no parameters.
Recommended starting point: fetch your channelId values first, then use them with the data tools (get_installs, get_custom_events, get_install_custom_groups, get_custom_install_groups).
The channel list is identical on every endpoint. An individual channel may still be served by a different endpoint: if a data tool returns a zone error, connect to the endpoint named in that error.
Common request parameters
The table applies to the data tools; list_channels takes no parameters.
| Parameter | Type | Required | Description |
|---|---|---|---|
channelId |
string / number | yes | a channel of the account |
date_from |
string | yes | period start, YYYY-MM-DD |
date_to |
string | yes | period end, YYYY-MM-DD |
group |
string[] | see below | grouping fields (plain field keys: offer_id, affiliate_id, date). Provided = aggregated report, omitted = raw event list |
fields |
string[] | — | response fields (by name or API key; valid names — see the list_available_fields tool). Defaults if omitted |
filters |
object | — | equality filters: {"affiliate_id": "136"} or a value list {"offer_id": ["1","2"]} |
sort_field |
string | — | defaults to score (score_avg in groups). API rule: sorting is only allowed by a field present in the response — the server adds it to fields automatically |
sort_direction |
"asc" | "desc" |
— | defaults to desc |
page |
number | — | page number. Omitted = full result (page=all) |
page_size |
number | — | rows per page when page is set (default 100, max 1000) |
get_installs¶
Install data for a period. Without group — a raw event list; with group — an aggregated report (fraud scores, counts, payouts, cost). For questions about installs, install fraud, and anything grouped by install dimensions.
get_custom_events¶
Custom event data for a period (your app's in-app events: registration, purchase, level-up, etc.). Same modes; the default field set is adapted for custom events (includes the event name and value). Default custom aggregates: score_avg and count.
get_install_custom_groups¶
Installs with a custom event breakdown: groups installs by the given key; each row shows the install count plus a per-custom-event breakdown (custom_count/custom_users arrays aligned with the events header by index). For questions like "installs by affiliate with their custom events". group is required; filters applies to installs, custom_filters — to custom events. Do not confuse with get_custom_install_groups.
get_custom_install_groups¶
Custom events with install counts: groups custom events by the given key, with counts joined to installs (custom_count/custom_users arrays aligned with events by index). For questions like "custom events by country". group is required; default aggregates are score_avg and count (payout aggregates are not accepted). The grouping key is present in rows but may be empty when custom events have no such field. Do not confuse with get_install_custom_groups.
list_available_fields¶
Reference of available fields: keys, modes (list/group), group keys, filterability. Optional parameter mode: "list" | "group". Recommended before using unfamiliar field names.
Defaults¶
When parameters are omitted, the server applies verified defaults:
- List fields: the standard field set of the method (custom has its own set without install-only fields, plus
nameandvalue). - Group fields:
score_avg,count,affiliate_payout_sum,cost_sum,score_ok/low/mid/highfor install-based methods; for custom-based methods — onlyscore_avgandcount(payout aggregates are unavailable). scoreis added to every request automatically (score_avgin groups).- The sort field, if not present in the response, is added to
fieldsautomatically (API rule: sorting only by fields present in the response). - Sorting:
score_desc(score_avg_descin groups). - Pagination: full result without paging (
page=all).
Field aliases: in group mode offer_name → any_offer_name, affiliate_payout → affiliate_payout_sum, etc. — either name can be passed. The group parameter always takes plain field keys (offer_id), never any_*.
Response format¶
A tool returns compact JSON. The examples below are illustrative; the set of events and the values depend on your application:
{"url":"[https://api.fraudscore.ai/{channel}/install?key=***&](https://api.fraudscore.ai/{channel}/install?key=***&)...","mode":"list","period":{"from":"2026-09-01","to":"2026-09-15"},"page":"all","events":null,"row_count":2,"truncated":false,"rows":[{"datetime":"2026-09-01T10:00:00","offer_id":"...","score":87}]}
Aggregation methods add an events header (custom event names), separated from the data rows:
{"url":"...","mode":"group","page":"all","events":["registration","first_purchase"],"row_count":54,"truncated":false,"rows":[{"affiliate_id":"123","count":"1050","score_avg":15,"custom_count":["600","350"],"custom_users":["590","340"]}]}
url— the Data API request with a masked key (for transparency and debugging);events— the aggregation methods header: custom event names; thecustom_count/custom_usersarrays in rows are aligned with it by index;rows— array of result rows;truncated—truewhen a paged request returned a full page; accompanied bynext_page— the number of the next page.
Errors¶
HTTP level (authorization and request body):
| Code | Reason |
|---|---|
| 400 | invalid request body: malformed JSON or forbidden properties (e.g. __proto__) |
| 401 | missing Authorization header or token does not match the mcp_* format |
| 403 | token not found or account does not exist |
| 502 | authorization service unavailable, retry later |
Tool level (JSON-RPC): on execution errors the result has isError: true with a human-readable reason in English: channel access denied, integration not available in the current zone (with the appropriate endpoint), unknown field (with the list of allowed values), inverted date range, Data API error. The LLM can use the error text to self-correct the request.
Limitations¶
- At most 60 requests per minute and at most one request per second to the Data API (enforced automatically by the server).
- An account only has access to its own channels; a foreign
channelIdis rejected. - The
page=allresponse is not size-limited: for chat scenarios (Claude Desktop, Cursor) keep in mind that the entire result goes into the model context. - The endpoint serves integrations of its own zone only: requesting an integration from another zone returns an error pointing to the appropriate endpoint. The channel list (
list_channels) is always complete, regardless of the endpoint.
Security¶
- The token is a personal secret: send it only in the
Authorizationheader, keep it in secure storage and have it reissued if you suspect compromise. - All connections use HTTPS.
- An account has access only to its own channels' data.
- The server keeps no state between requests.
oct 7, 2026