MCP Blacklist¶
Introduction¶
The FraudScore channel blacklist service exposes a single interface that can be used in two ways:
- as an MCP server — connected to any LLM client with Model Context Protocol support (Claude Desktop, Cursor, etc.);
- as a plain JSON-RPC 2.0 API — by sending requests directly from your code, with no LLM involved.
Both modes use the same protocol and the same set of tools: the MCP transport is built on top of JSON-RPC 2.0, so any request an MCP client sends can be reproduced with a plain HTTP POST /mcp call.
Note: tool names, tool descriptions and all API-returned texts (success messages and errors) are always in English, regardless of the language of this documentation. This ensures unambiguous interpretation by both LLMs and integrations.
General overview¶
| Parameter | Value |
|---|---|
| Base URL | https://mcp.fraudscore.ai |
| API endpoint | POST /mcp |
| Health check | GET /healthz — returns {"status":"ok"} |
| Protocol | JSON-RPC 2.0 (Streamable HTTP, sessionless) |
| Response format | application/json (single JSON response, no streaming) |
| Maximum request size | 256 KB |
The service is sessionless: every HTTP request is processed independently. There is no session ID to keep, no handshake to perform, and no re-initialization — you simply send standalone JSON-RPC requests.
Authentication¶
Every request to POST /mcp requires an API token in the Authorization header:
Token requirements:
- the
mcp_prefix; - followed by 8 to 128 characters: Latin letters, digits,
_,-and..
The token determines your account and the list of channels you are allowed to manage. Any attempt to access a channel not linked to your account will be rejected. Use the list_channels tool to see the channels available to you.
The token is a secret. Only send it over HTTPS and never publish it.
Tools¶
The service provides three tools. Tool names and the descriptions shown to the LLM in tools/list are in English. Standard MCP annotations (readOnlyHint, destructiveHint, idempotentHint) are declared for read and write tools — MCP clients may use them to confirm dangerous actions.
list_channels¶
Returns the list of channel identifiers available to your account. Takes no parameters.
Result: {"channels": ["my_channel_1", "my_channel_2"]} — identifiers only, with no additional channel information.
Typical workflow: call list_channels to discover valid IDs first, then use get_install_filter / update_install_filter to read and modify.
get_install_filter¶
Retrieves the current blacklist settings of a channel.
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
channelId |
string | number | yes | Channel identifier |
channelId format: a string of 1 to 200 characters, allowing Latin letters, digits, _ and -. Numeric identifiers are accepted as well.
Result: the install_filter object with the channel's current filter configuration (see the format below).
update_install_filter¶
Updates the blacklist settings of a channel.
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
channelId |
string | number | yes | Channel identifier |
install_filter |
object | yes | New filter configuration |
Important: the operation replaces the filter configuration as a whole — the submitted lists are not merged with the existing ones. To preserve current values, first fetch them via get_install_filter, apply your changes, and submit the full object.
Result: a confirmation that the update succeeded, along with the applied filter configuration.
install_filter format¶
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | yes | Always "block" — no other value is accepted |
affiliate |
string[] | no | List of affiliate identifiers the filter applies to |
offer |
string[] | no | List of offer identifiers the filter applies to |
Constraints on the affiliate and offer lists:
- up to 100 items per list;
- each item is a string of 1 to 648 characters (surrounding whitespace is trimmed);
- passing an empty array [] or omitting the field entirely clears the list;
- no fields other than the ones listed above are allowed — the object is validated strictly, and unknown fields cause an error.
The type field is required in every update request, including updates that only modify the lists.
Direct API¶
Every tool is invoked via the JSON-RPC method tools/call. To retrieve the list of available tools, use tools/list.
Request headers¶
POST https://mcp.fraudscore.ai/mcp
Authorization: Bearer mcp_XXXXXXXXXXXXXXXX
Content-Type: application/json
Accept: application/json, text/event-stream
Listing tools¶
Calling list_channels¶
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "list_channels",
"arguments": {}
}
}
Example response:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "{\"channels\":[\"my_channel_1\",\"my_channel_2\"]}"
}
],
"isError": false
}
}
Calling get_install_filter¶
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "get_install_filter",
"arguments": {
"channelId": "my_channel_1"
}
}
}
Example response:
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "{\"install_filter\":{\"type\":\"block\",\"affiliate\":[\"affiliate_1\"]}}"
}
],
"isError": false
}
}
A tool's payload is always returned in result.content[0].text as a compact JSON string (no whitespace) — parse it on your side (e.g., JSON.parse in JavaScript).
Calling update_install_filter¶
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "update_install_filter",
"arguments": {
"channelId": "my_channel_1",
"install_filter": {
"type": "block",
"affiliate": ["affiliate_1", "affiliate_2"],
"offer": ["offer_1"]
}
}
}
}
Example success response:
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"content": [
{
"type": "text",
"text": "{\"success\":true,\"message\":\"Filter updated successfully\",\"install_filter\":{\"type\":\"block\",\"affiliate\":[\"affiliate_1\",\"affiliate_2\"],\"offer\":[\"offer_1\"]}}"
}
],
"isError": false
}
}
JavaScript example (no SDK)¶
const response = await fetch('https://mcp.fraudscore.ai/mcp', {
method: 'POST',
headers: {
'Authorization': 'Bearer mcp_XXXXXXXXXXXXXXXX',
'Content-Type': 'application/json',
'Accept': 'application/json, text/event-stream'
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'tools/call',
params: {
name: 'get_install_filter',
arguments: { channelId: 'my_channel_1' }
}
})
})
const rpc = await response.json()
const payload = JSON.parse(rpc.result.content[0].text)
console.log(payload.install_filter)
MCP server¶
Connect the service to your MCP client. Example configuration:
{
"mcpServers": {
"fraudscore": {
"type": "http",
"url": "https://mcp.fraudscore.ai/mcp",
"headers": {
"Authorization": "Bearer mcp_XXXXXXXXXXXXXXXX"
}
}
}
}
Once connected, you can give the model instructions in natural language, for example:
- "Show the available channels";
- "Show the current blacklist of channel my_channel_1";
- "Add affiliate affiliate_3 to the blacklist of channel my_channel_1" — with such a request the model performs the chain on its own:
list_channels→get_install_filter→update_install_filterwith the complete object.
The client and the server exchange exactly the same JSON-RPC messages as in direct mode — the MCP client and the LLM simply take care of composing them. You can talk to the model in any language; only the API's service texts (tool descriptions, success messages and errors) are in English.
Error handling¶
Errors are returned on two levels. All API error texts are in English.
HTTP level¶
| Code | Response body | Reason | What to do |
|---|---|---|---|
401 |
{"error": "Unauthorized. Valid mcp_* token required"} |
Missing token or invalid format | Check the Authorization header and the mcp_* token format |
403 |
{"error": "Forbidden or account not found"} |
Token not found or account unavailable | Contact support to verify your token |
502 |
{"error": "Authorization service unavailable"} |
Temporary unavailability of the authorization service | Retry the request later |
Tool level¶
If the HTTP request succeeds but the tool itself fails, the response comes back with isError: true and a textual error description in English.
Example — no access to the channel:
{
"jsonrpc": "2.0",
"id": 5,
"result": {
"content": [
{
"type": "text",
"text": "Access to channel my_channel_2 denied"
}
],
"isError": true
}
}
Example — filter validation error (the specific reason is included):
{
"jsonrpc": "2.0",
"id": 6,
"result": {
"content": [
{
"type": "text",
"text": "Invalid install_filter: \"type\" must be strictly \"block\""
}
],
"isError": true
}
}
Typical causes and message formats:
- no access to the channel — the channel is not linked to your token's account:
Access to channel ... denied; install_filtervalidation error — unknown fields, wrongtype, values too long, etc.:Invalid install_filter: <specific reason>;- internal failure — a neutral message with no internal details:
Failed to retrieve filteron reads,Failed to update filteron writes.
This message format lets integrations (and LLMs) immediately understand the cause of an error and fix the request, without exposing the service's internal details.
Constraints and notes¶
- One request, one operation: the service keeps no state between requests.
- The update operation replaces the filter configuration as a whole: to preserve the current lists, first fetch them via
get_install_filter, apply your changes, and submit the full object. - Retrying the same update request is safe: it brings the filter to the same state.
- All requests and responses use UTF-8 encoding.
oct 7, 2026