Monitly MCP Documentation

MCP Overview

The Monitly MCP server gives AI agents direct access to official statistics and economic indicators (Eurostat, World Bank, OECD, IMF, national statistical offices) through the Model Context Protocol. Clients such as Claude Desktop, Cursor, Windsurf, VS Code or your own agents call structured tools to find datasets, read time series and manage the Monitly account — watchlist, alerts, keys and plan — without leaving the chat.

Endpointhttps://monit.ly/api/mcp
ProtocolMCP Streamable HTTP · JSON-RPC 2.0 · protocol version 2024-11-05 · server name monitly
Methodsinitialize, tools/list, tools/call, ping, notifications/initialized
Tools5 data tools · 16 account tools

Quickstart

  1. Create a key in Settings → Integrations → MCP. It starts with mcpk_ and is shown only once.
  2. Add the server to your client configuration (below).
  3. Restart the client if it does not reload MCP configuration, then ask in natural language — the model maps your prompt to tool calls.
Cursor
~/.cursor/mcp.json (or .cursor/mcp.json in the project)
{
  "mcpServers": {
    "monitly": {
      "url": "https://monit.ly/api/mcp",
      "headers": {
        "Authorization": "Bearer mcpk_YOUR_KEY"
      }
    }
  }
}
Claude Desktop / Windsurf / VS Code
Client MCP settings → add a remote (HTTP) server
{
  "mcpServers": {
    "monitly": {
      "url": "https://monit.ly/api/mcp",
      "headers": {
        "Authorization": "Bearer mcpk_YOUR_KEY"
      }
    }
  }
}
Test with curl
curl -s https://monit.ly/api/mcp \
  -H "Authorization: Bearer mcpk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Authentication

Every request must carry an MCP key. Keys belong to your account, are stored only as SHA-256 hashes and can be revoked at any time. MCP keys (mcpk_…) are separate from REST API keys (mon_…).

Preferred headerAuthorization: Bearer mcpk_…
Alternative headerX-API-Key: mcpk_…
Manage keysIn Settings → Integrations → MCP, or from the agent with list_mcp_keys, create_mcp_key, delete_mcp_key.

A missing or revoked key returns HTTP 401 with a JSON-RPC error body.

Quota

Data tools — each successful tools/call uses one unit of the monthly mcp_queries meter. Account tools are free. initialize, tools/list and ping are never metered. The meter resets with your billing period; check it any time with get_usage.

PlanMCP queries / monthWatchlist datasetsREST API / day
Essential (free)105100
Pro5001005,000

When the limit is reached, data tools return a JSON-RPC error with the used / limit counts. Upgrade from the agent with upgrade_plan or on the pricing page.

Data tools

DATAsearch_catalog

Hybrid search over the catalog (name/code + embeddings). Returns compact dataset cards with id, code, source, period range and available geographies — not the values. Start every analysis here.

Arguments
NameTypeDescription
query*stringWhat to find, e.g. 'unemployment rate monthly'.
countrystringPrefer datasets that include this country, e.g. 'Germany'.
source_namestringFilter by source: 'Eurostat', 'World Bank', 'OECD', 'IMF'…
limitinteger1–16, default 8.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "search_catalog",
    "arguments": {
      "query": "HICP inflation rate",
      "country": "Poland",
      "limit": 2
    }
  }
}
Result (content[0].text)
{
  "datasets": [
    {
      "id": 4179,
      "dataset_code": "tec00118",
      "dataset_name": "HICP - inflation rate",
      "source_name": "Eurostat",
      "oldest_period": "2013",
      "latest_period": "2024",
      "observation_count": 476,
      "dim_labels": ["Time frequency", "Unit of measure", "Classification of individual consumption by purpose (COICOP)"],
      "default_view": {
        "dim1": ["Annual"],
        "dim2": ["Annual average rate of change"],
        "dim3": ["All-items HICP"],
        "country": ["Poland"]
      },
      "has_country": true,
      "geo_count": 38,
      "match": "lexical"
    }
  ],
  "returned_count": 1
}
DATAsearch_datasets

Same as search_catalog — kept for clients that expect this name.

Arguments
NameTypeDescription
query*stringWhat to find.
countrystringOptional country.
source_namestringOptional source filter.
limitinteger1–16, default 8.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "search_datasets",
    "arguments": {
      "query": "GDP per capita PPS"
    }
  }
}
Result (content[0].text)
{ "datasets": [ … ], "returned_count": 8 }
DATAinspect_dataset

Look into one dataset: default slice, dimension values, whether a country is present, the data id to query and the latest observations. Use it before execute_sql.

Arguments
NameTypeDescription
id*integerDataset id (main.id) from search_catalog.
countrystringCountry to resolve in the series, e.g. 'Poland'.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "inspect_dataset",
    "arguments": {
      "id": 4179,
      "country": "Poland"
    }
  }
}
Result (content[0].text)
{
  "dataset": {
    "id": 4179,
    "dataset_code": "tec00118",
    "dataset_name": "HICP - inflation rate",
    "default_view": { "dim1": ["Annual"], "dim2": ["Annual average rate of change"], "dim3": ["All-items HICP"], "country": ["Poland"] }
  },
  "series": {
    "dataId": 7229553,
    "dim_values": { "dim1": "Annual", "dim2": "Annual average rate of change", "dim3": "All-items HICP" },
    "country_header": "Poland",
    "country_in_format": true,
    "recent": [
      { "period": "2023", "value": "10.9" },
      { "period": "2024", "value": "3.7" },
      { "period": "2025", "value": "3.3" }
    ]
  }
}
DATAget_dataset

Full metadata row for one dataset: description, source and metadata URLs, dimension labels, default view, period range and geographies.

Arguments
NameTypeDescription
id*integerDataset id (main.id).
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_dataset",
    "arguments": {
      "id": 4179
    }
  }
}
Result (content[0].text)
{
  "dataset": {
    "id": "4179",
    "dataset_code": "tec00118",
    "dataset_name": "HICP - inflation rate",
    "description": "Harmonised Indices of Consumer Prices (HICPs) are designed for international comparisons…",
    "source_name": "Eurostat",
    "last_update": "2026-07-17T11:00:00+0200",
    "oldest_period": "2013",
    "latest_period": "2024",
    "observation_count": 476,
    "available_geo": { "AT": "Austria", "DE": "Germany", "PL": "Poland", "…": "…" }
  }
}
DATAexecute_sql

Run one read-only SELECT (or WITH … SELECT) against the tables main and data to pull exact time series for a known dataset. Each data row is one series (dim1_value…dim8_value, unit); format holds the column headers (countries) and values the semicolon-separated rows. Use after search_catalog + inspect_dataset (which gives the dataId); always add LIMIT.

Arguments
NameTypeDescription
query*stringSELECT statement on main / data only.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "execute_sql",
    "arguments": {
      "query": "SELECT id, dim1_value, dim2_value, dim3_value, unit, format, values FROM data WHERE id = 7229553"
    }
  }
}
Result (content[0].text)
{
  "rows": [
    {
      "id": "7229553",
      "dim1_value": "Annual",
      "dim2_value": "Annual average rate of change",
      "dim3_value": "All-items HICP",
      "unit": "",
      "format": "Data;European Union - 27 countries (from 2020);…;Poland;…",
      "values": "2014;0.4;0.4;…"
    }
  ],
  "returned_count": 1
}

Account tools

ACCOUNTlist_plans

Monitly plans (Essential, Pro, Enterprise) with prices and limits.

Arguments
None.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_plans",
    "arguments": {}
  }
}
Result (content[0].text)
{
  "plans": [
    { "id": "essential", "name": "Essential", "price": "$0", "limits": { "mcp": "10", "charts": "5", "api": "100" } },
    { "id": "pro", "name": "Pro", "price": "$49", "period": "per month", "limits": { "mcp": "500", "charts": "100", "api": "5,000" } },
    { "id": "enterprise", "name": "Enterprise", "price": "Custom", "limits": "custom" }
  ]
}
ACCOUNTget_plan

Plan of the key owner: name, status, renewal date and limits. Members of an organization inherit the owner's plan.

Arguments
None.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_plan",
    "arguments": {}
  }
}
Result (content[0].text)
{
  "plan": {
    "id": "pro",
    "name": "Pro",
    "status": "active",
    "current_period_end": "2026-11-02T10:14:00Z",
    "limits": { "api_requests_per_day": 5000, "mcp_queries_per_month": 500, "watchlist_datasets": 100, "api_keys": 10 }
  }
}
ACCOUNTget_usage

MCP queries in the current billing period, REST API requests today and watchlist slots — used, limit and remaining.

Arguments
None.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_usage",
    "arguments": {}
  }
}
Result (content[0].text)
{
  "usage": {
    "plan": "Pro",
    "mcp_queries": { "used": 42, "limit": 500, "remaining": 458, "period": "2026-10" },
    "api_requests_today": { "used": 130, "limit": 5000, "remaining": 4870 },
    "watchlist_datasets": { "used": 12, "limit": 100, "remaining": 88 }
  }
}
ACCOUNTupgrade_plan

Creates a Stripe Checkout session for Pro and returns checkout_url. Open it in the browser to pay; the plan switches automatically after payment.

Arguments
NameTypeDescription
plan_idstring'pro' (default).
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "upgrade_plan",
    "arguments": {
      "plan_id": "pro"
    }
  }
}
Result (content[0].text)
{
  "current_plan": "Essential",
  "target_plan": "Pro",
  "checkout_url": "https://checkout.stripe.com/c/pay/cs_live_…"
}
ACCOUNTlist_watchlist

Datasets the user follows, with source, latest period and whether update alerts are on. Organization members see the organization's watchlist.

Arguments
NameTypeDescription
limitinteger1–100, default 20.
offsetintegerPagination offset, default 0.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_watchlist",
    "arguments": {
      "limit": 10
    }
  }
}
Result (content[0].text)
{
  "watchlist": [
    {
      "dataset_id": 4179,
      "dataset_name": "HICP - inflation rate",
      "source_name": "Eurostat",
      "latest_period": "2024",
      "notifications": true,
      "url": "https://monit.ly/app/chart?id=4179"
    }
  ],
  "total": 12,
  "limit": 100
}
ACCOUNTadd_to_watchlist

Adds a dataset to the watchlist with e-mail alerts on update. Returns limit_reached when the plan's watchlist is full.

Arguments
NameTypeDescription
dataset_id*integerDataset id from search_catalog.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "add_to_watchlist",
    "arguments": {
      "dataset_id": 4179
    }
  }
}
Result (content[0].text)
{
  "status": "added",
  "dataset": { "dataset_id": 4179, "dataset_name": "HICP - inflation rate", "source_name": "Eurostat" }
}
ACCOUNTadd_watchlist_batch

Follows up to 100 datasets in one call. Duplicates are skipped; ids beyond the plan limit are returned in skipped_limit.

Arguments
NameTypeDescription
dataset_ids*integer[]Dataset ids.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "add_watchlist_batch",
    "arguments": {
      "dataset_ids": [
        4179,
        2973,
        168
      ]
    }
  }
}
Result (content[0].text)
{
  "added": 2,
  "total": 3,
  "added_ids": [2973, 168],
  "already_watched": [4179],
  "not_found": [],
  "skipped_limit": []
}
ACCOUNTremove_from_watchlist

Removes a dataset from the watchlist.

Arguments
NameTypeDescription
dataset_id*integerDataset id.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "remove_from_watchlist",
    "arguments": {
      "dataset_id": 168
    }
  }
}
Result (content[0].text)
{ "status": "removed", "dataset_id": 168 }
ACCOUNTset_notification_preferences

action='get' returns alert settings. action='set' changes e-mail or Slack alerts for all followed datasets, or switches alerts for one dataset (dataset_id + dataset_notifications). The Slack webhook itself is configured in Settings.

Arguments
NameTypeDescription
action*'get' | 'set'Read or change.
email_notificationsbooleanE-mail alerts on/off.
slack_notificationsbooleanSlack alerts on/off.
dataset_idintegerFollowed dataset to change.
dataset_notificationsbooleanAlerts for that dataset on/off.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "set_notification_preferences",
    "arguments": {
      "action": "set",
      "email_notifications": true
    }
  }
}
Result (content[0].text)
{
  "status": "updated",
  "preferences": { "email_notifications": true, "slack_notifications": false, "slack_webhook_configured": false }
}
ACCOUNTlist_api_keys

Active REST API keys (mon_…): id, name, prefix, created and last used.

Arguments
None.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_api_keys",
    "arguments": {}
  }
}
Result (content[0].text)
{ "api_keys": [ { "id": "8c1e…", "name": "Dashboard", "key_prefix": "mon_3f9a", "is_primary": true } ] }
ACCOUNTcreate_api_key

Creates a REST API key for the /api endpoints (send it as x-api-key). The raw key is returned once. Limit: 3 keys on Essential, 10 on Pro.

Arguments
NameTypeDescription
namestringLabel, max 100 characters.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_api_key",
    "arguments": {
      "name": "Power BI"
    }
  }
}
Result (content[0].text)
{
  "id": "1b7d…",
  "name": "Power BI",
  "key_prefix": "mon_a1b2",
  "api_key": "mon_a1b2c3…",
  "daily_limit": 5000
}
ACCOUNTdelete_api_key

Revokes a REST API key by id. The last remaining key cannot be deleted.

Arguments
NameTypeDescription
key_id*stringKey id from list_api_keys.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "delete_api_key",
    "arguments": {
      "key_id": "1b7d…"
    }
  }
}
Result (content[0].text)
{ "status": "deleted", "key_id": "1b7d…" }
ACCOUNTlist_mcp_keys

Active MCP keys. The key used for the current session is marked current: true.

Arguments
None.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_mcp_keys",
    "arguments": {}
  }
}
Result (content[0].text)
{ "mcp_keys": [ { "id": "f20a…", "name": "Cursor", "key_prefix": "mcpk_9d1c", "current": true } ] }
ACCOUNTcreate_mcp_key

Creates another MCP key, e.g. for a second client. The raw key is returned once.

Arguments
NameTypeDescription
namestringLabel, max 100 characters.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_mcp_key",
    "arguments": {
      "name": "Claude Desktop"
    }
  }
}
Result (content[0].text)
{ "id": "77c3…", "name": "Claude Desktop", "key_prefix": "mcpk_4e5f", "mcp_key": "mcpk_4e5f…" }
ACCOUNTdelete_mcp_key

Revokes an MCP key by id. The key used for the current session cannot be revoked from the agent.

Arguments
NameTypeDescription
key_id*stringKey id from list_mcp_keys.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "delete_mcp_key",
    "arguments": {
      "key_id": "77c3…"
    }
  }
}
Result (content[0].text)
{ "status": "revoked", "key_id": "77c3…" }
ACCOUNTexport_dataset

Returns a CSV download link for a dataset, optionally filtered by countries and dimension values (dim1…dim8 from inspect_dataset). The link is a plain GET and needs no key.

Arguments
NameTypeDescription
dataset_id*integerDataset id.
countriesstring[]Country names, e.g. ['Poland','Germany'].
dimensionsobjecte.g. {"dim1": ["Monthly"]}.
Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "export_dataset",
    "arguments": {
      "dataset_id": 4179,
      "countries": [
        "Poland",
        "Germany"
      ]
    }
  }
}
Result (content[0].text)
{
  "dataset": { "dataset_id": 4179, "dataset_name": "HICP - inflation rate" },
  "csv_url": "https://monit.ly/api/datasets/4179/export.csv?country=Poland&country=Germany"
}

Errors

401Unauthorized

The request has no MCP key, or the key was revoked. Returned with HTTP status 401.

Response
{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32603,
    "message": "Unauthorized",
    "data": { "message": "Invalid or revoked MCP key." }
  }
}
-32700Parse error

The request body could not be parsed as JSON. Returned with HTTP status 400.

Response
{
  "jsonrpc": "2.0",
  "id": null,
  "error": { "code": -32700, "message": "Parse error: invalid JSON body" }
}
-32600Invalid Request

The body is JSON but not a JSON-RPC 2.0 request (jsonrpc: "2.0" is missing).

Response
{
  "jsonrpc": "2.0",
  "id": null,
  "error": { "code": -32600, "message": "Invalid Request: missing jsonrpc field" }
}
-32602Invalid params

tools/call was sent without params.name.

Response
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": { "code": -32602, "message": "Missing tool name." }
}
-32601Not found

The JSON-RPC method or the tool name does not exist. Call tools/list for the current set.

Response
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": { "code": -32601, "message": "Unknown tool: get_datasets" }
}
-32603Limit reached

The monthly mcp_queries limit of the plan is used up. Data tools are blocked until the billing period resets; account tools keep working.

Response
{
  "jsonrpc": "2.0",
  "id": 7,
  "error": {
    "code": -32603,
    "message": "MCP query limit reached (10/month on Essential).",
    "data": { "used": 10, "limit": 10, "remaining": 0, "canUse": false, "planType": "free", "periodYm": "2026-10" }
  }
}
isErrorTool error

For example an unknown dataset id, a full watchlist or the last API key. The result is a normal response with isError: true and the reason in content[0].text.

Response
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [{ "type": "text", "text": "Error: Dataset 99999999 not found." }],
    "isError": true
  }
}

Example prompts

Compare countries
Compare HICP inflation in Poland, Germany and Czechia over the last ten years.
Rank EU countries by the latest unemployment rate.
Which EU country had the fastest real GDP growth last year?
Show government debt as % of GDP for the Baltic states since 2010.
Country deep-dive
Give me a macro snapshot of Poland: GDP, inflation, unemployment and interest rates.
How has the Polish current account balance changed quarter by quarter?
What are the latest house price index values for Spain?
Find the right dataset
Find datasets about renewable energy share in electricity consumption.
Is there monthly retail trade data for Germany? Which source is the freshest?
What does the World Bank have on youth unemployment in Africa?
Monitoring & alerts
Add Eurostat HICP for Poland to my watchlist and turn on e-mail alerts.
Follow unemployment, inflation and GDP datasets for the Visegrád countries.
What is on my watchlist and which datasets were updated this month?
Turn off alerts for the house price index dataset.
Exports & integrations
Give me a CSV link with GDP per capita (PPS) for Poland, Czechia, Slovakia and Hungary.
Create a REST API key called 'Power BI'.
List my API and MCP keys and revoke the ones I don't use.
Plan & usage
How many MCP queries do I have left this month?
What are the limits of my plan?
Upgrade me to Pro.