Pro and API tiers can both connect via OAuth — no API key required. Pro subscribers click “Sign in with WorldMonitor Pro” on the consent page; API Starter / Business / Enterprise users may sign in the same way OR paste a
wm_… key. Free-tier users see a 403 INSUFFICIENT_TIER at the OAuth step.OAuth is not needed for get_sources: it is the sole credential-free, daily-quota-free data tool. Anonymous calls use a separate fail-closed limit of 10 requests/minute/IP. Other data tools require a user-bound credential. Cache-backed tools marked free-account can use the small confirmed-free allowance; live-fetch tools marked subscription require Pro.wm_…) clients and most OAuth contexts use a hard default of 50 quota-consuming tools/call / resources/read calls per UTC day; OAuth allowances are plan-resolved, with API Starter and API Business currently held to that same 50/day default and enterprise OAuth able to be unlimited. Only legacy operator keys explicitly allowlisted by the deployment skip the daily reservation. Every authenticated context is also protected by the 60 requests/minute limiter. get_sources and the metadata helper describe_tool are exempt from the daily quota.
Pro subscribers can connect Claude Desktop / Cursor / claude.ai without ever pasting an API key — see Pro sign-in flow below. API Starter+ holders may continue to paste a wm_… key on the consent page (the original flow), or use the same OAuth path as Pro.
Endpoints
Server identifier:
worldmonitor v1.17.0.
Registry listings: the server is published in the official MCP registry as app.worldmonitor/mcp — a domain-verified namespace, so clients that resolve servers through the registry get the same endpoint and metadata as the server card above — and listed on Smithery and mcp.so.
Protocol negotiation
WorldMonitor’s static server card at/.well-known/mcp/server-card.json advertises protocol version 2025-06-18, and the live initialize handshake negotiates it by default — so the advertised floor and the negotiated version stay in lock-step:
- By default,
initializesupports both2025-03-26and2025-06-18. - Clients requesting
2025-06-18receive2025-06-18; clients pinned to2025-03-26continue receiving2025-03-26. - Setting
MCP_PROTOCOL_FLOOR_2025_06_18=offpins the server back to the legacy2025-03-26-only floor; a client that then requests2025-06-18receives the safe default2025-03-26.
outputSchema metadata is emitted on tools/list regardless of the negotiated protocol version. Older 2025-03-26 clients should ignore unknown fields, while newer clients can use the schema immediately.
Streamable HTTP responses
WorldMonitor supports the Streamable HTTP POST flow with either JSON or SSE responses:- Clients that omit
text/event-streamfromAcceptreceive the standard JSON-RPC JSON response body. - Clients that send
Accept: application/json, text/event-streamcan receive atext/event-streamresponse for successful JSON-RPC POSTs. initializeSSE responses includeMcp-Session-Id; follow-up POSTs should send that sameMcp-Session-Idheader.- Each SSE response carries the JSON-RPC result as a single
messageevent with an eventid. There is no leading empty priming event — per the WHATWG SSE spec an emptydata:field still dispatches amessage(withdata === ""), which causes strict handshake scanners to fail onJSON.parse(""). - If the client disconnects after the sole event, it can reconnect by sending
GET /mcpwithAccept: text/event-stream, the sameMcp-Session-Id, andLast-Event-ID; resuming after the delivered event returns an empty stream. A client that dropped before receiving the event has no acknowledgedLast-Event-IDand re-issues the POST instead. - A bare
GET /mcp— one withoutLast-Event-ID— is a client opening the optional standalone server→client SSE stream. This stateless edge route offers no server-initiated stream, so it answers405 Method Not Allowed(advertisingAllow), which the MCP spec defines as the graceful “no standalone stream” signal. MCP SDK clients handle this transparently and complete the handshake; theGETverb itself is reserved for the authenticatedLast-Event-IDreplay above.
Last-Event-ID resume as loss-tolerant transport recovery, not durable message storage.
Authentication
Discovery is public.initialize, tools/list, prompts/list, prompts/get, resources/list, resources/templates/list, ping, logging/setLevel, and the notifications/initialized handshake are servable without credentials, so any agent (or agent-readiness scanner) can connect to https://worldmonitor.app/mcp, read the server identity, and enumerate the full tool, prompt, and resource catalogs before authenticating — the same metadata already published in the static server card. These methods return only public catalog metadata (names, descriptions, URIs / URI templates, static workflow-template prose — no data, no quota); every capability advertised by the anonymous initialize is anonymously exercisable, so a strict MCP client (Claude Desktop, mcp-remote, the reference SDKs) completes its full post-connect enumeration without stalling on an auth wall. resources/read of a public resource (a concrete, metadata-only freshness/health probe surfaced by resources/list, such as worldmonitor://seed-meta/freshness) is also public and quota-free — an anonymous agent can read it cleanly. Anonymous discovery is rate-limited to 60 requests/minute per client IP. get_sources is the sole credential-free, daily-quota-free data tool; its anonymous path has a separate fail-closed ceiling of 10 calls/minute/IP. Other data-bearing calls require credentials. Every tools/list and describe_tool entry carries _meta["worldmonitor/access"]: "free" means anonymous and quota-free, "free-account" means available to a signed-in free account (cache-backed data calls spend its allowance; describe_tool does not), and "subscription" means Pro-only. Resource templates carry the same marker as their backing tool. A credential presented on a discovery method is still validated (a bad key returns 401, never a silent anonymous downgrade).
The MCP handler accepts two auth modes, in priority order:
- OAuth 2.1 bearer —
Authorization: Bearer <token>where<token>was issued by/api/oauth/token. This is what Claude Desktop, claude.ai, Cursor, and MCP Inspector use automatically. Required for any client that hits MCP from a browser origin. - Direct API key —
X-WorldMonitor-Key: wm_0123456789abcdef0123456789abcdef01234567for user-issued keys, or an opaque operator-issued enterprise key. Intended for server-side scripts,curl, and custom integrations. Do not send an API key as aBearertoken — it will fail OAuth resolution and return401 invalid_token.
X-WorldMonitor-Key: wm_… requests validate the key owner and active entitlement, then use the same per-user minute bucket and 50/day default as the OAuth path. Legacy deployment-allowlisted operator keys use a per-key minute bucket and skip the daily reservation.
Redirect URI allowlist
Dynamic Client Registration is not open to arbitrary HTTPS redirects. Only these prefixes are accepted:https://claude.ai/api/mcp/auth_callbackhttps://claude.com/api/mcp/auth_callbackhttp://localhost:<port>/http://127.0.0.1:<port>(any port) — for Claude Code, MCP Inspector, local development
Token lifetimes
Pro sign-in flow
Pro subscribers (and API Starter+ users who’d rather not paste a key) can authorize MCP clients via their existing WorldMonitor account — no API key needed.-
Add the server URL in your MCP client. The canonical entrypoint is:
(
https://worldmonitor.app/mcpworks too — it proxies the same handler.) -
Click “Sign in with WorldMonitor Pro” on the consent page. This is the default CTA. You’ll bounce through
worldmonitor.app/mcp-grant(Clerk-protected — sign in if needed), then back toapi.worldmonitor.app/oauth/authorize-pro, then to your client’s redirect. -
Done. No
wm_…key is created or stored on your machine. The client receives a standard OAuth 2.1 access token (1 h TTL, 7 d refresh).
If the sign-in step reports that your subscription could not be verified — a
503 page, or 503 TIER_VERIFICATION_UNAVAILABLE from the grant endpoints — that is transient and says nothing about your subscription. Wait the advertised Retry-After and start the connection again from your client; the authorization session is single-use, so restart it rather than reloading the page. A confirmed non-Pro account gets 403 INSUFFICIENT_TIER instead, and a lapsed subscription gets 403 with X-Billing-Verification: subscription_lapsed. See Error handling.wm_ user key or operator-issued enterprise key — that path is unchanged.
Daily limit (Pro tier)
- 50 quota-consuming calls per UTC day, reset at 00:00 UTC.
- Data-bearing
tools/callandresources/readof a data-bearing URI-template instantiation consume the Pro daily quota, exceptget_sourcesand the metadata helperdescribe_tool. initialize,tools/list,prompts/list,prompts/get,resources/list,resources/templates/list,logging/setLevel,notifications/initialized,ping,describe_tool, andget_sourcesdo not count against the daily cap.resources/readof a public resource (a metadata-only freshness/health probe, e.g.worldmonitor://seed-meta/freshness) and the authenticated account status resourceworldmonitor://account/mcp-allowanceare likewise exempt.- Hitting the cap returns JSON-RPC error
-32029plus HTTP429with aRetry-Afterheader pointing at the next UTC midnight. - The cap is hard: concurrent
tools/callorresources/readrequests near the boundary use an atomic Redis reservation, so exactly the call that crosses 50 rejects.
wm_… key option plus higher REST/API plan allowances. Their MCP calls still use the 50/day default and the shared 60/minute/user throttle. For batch or high-volume workflows, prefer the REST/API endpoints or contact Enterprise — see Plans & limits.
Connected MCP clients
Each authorization mints a separate row, so revoking Claude Desktop does not affect Cursor.- Manage connected clients in Settings → Connected MCP clients.
- See the live
clientName(e.g. “Claude”, “Cursor”),lastUsedAt, andcreatedAtper token. - A revoke takes effect on the next MCP request (no positive cache).
- Up to 5 active tokens per user. The 6th authorization silently revokes the least-recently-used existing one.
Plans & limits
Per-minute throttling of 60 calls/minute/key (legacy operator-key clients) or 60/minute/user (OAuth and dashboard-key contexts) protects against burst storms across all paid tiers. The per-minute limiter runs before method dispatch, so every authenticated method (including
initialize, tools/list, prompts/list, resources/list, describe_tool, etc.) counts toward 60/min. Anonymous get_sources calls instead use the separate fail-closed 10/minute/IP ceiling. The daily-quota cap is selective — it is consumed by subscription data-bearing tools/call and resources/read reservations for OAuth and dashboard-issued wm_… keys (see Daily limit (Pro tier) above, and the Error Catalog for the full method-exemption tables for both limits).
OAuth and dashboard-key 60/min are per-USER (a user with 3 Claude installations or multiple wm_… keys shares one 60/min pool); legacy operator-key limiting is per-KEY.
Hitting the MCP daily quota returns JSON-RPC error -32029 plus HTTP 429 with a Retry-After header pointing at the next UTC midnight. Hitting the per-minute limit returns the same error code with a short Retry-After.
WorldMonitor also surfaces current MCP plan-limit notices in Settings and sends a bounded-cadence email when a paid user approaches or exceeds their plan allowance. Notices are informational and action-oriented: they offer retry/reset guidance, checkout when the next tier is self-serve, or support contact when it is not. They do not automatically upgrade the account or create overage charges.
Other rate limits
- OAuth authorize: 10 requests / minute / IP
- OAuth token: 10 requests / minute / IP
- Dynamic registration: 5 registrations / minute / IP
429 with a Retry-After header.
Client setup
Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json (macOS) — use the remote MCP entry:
Claude web (claude.ai)
Add via Settings → Connectors → Add custom connector:- Name:
WorldMonitor - URL:
https://worldmonitor.app/mcp
Cursor
~/.cursor/mcp.json:
MCP Inspector (debugging)
Tool catalog
The server exposes a registry of tools. Most are cache-reads over pre-seeded Redis keys (sub-second). The slower, non-cache paths are the six live LLM/external-API tools (get_country_brief, analyze_situation, generate_forecasts, search_flights, search_flight_prices_by_date, classify_event) plus the live geo RPC tools (get_airspace, get_maritime_activity), the bounded canonical procurement proxy (get_procurement_opportunities), the corporate-intelligence proxy (get_company_intelligence), the canonical China decision-signal RPC (get_china_decision_signals), and the three durable-history RPCs (search_intel_history, get_intel_timeline, get_similar_events). get_world_brief reads the dashboard’s precomputed, citation-grounded news:insights:v1 snapshot and does not make a request-time LLM call. The on-demand NLP utilities (classify_event, extract_entities, get_news_clusters, get_keyword_spikes) accept bounded caller text or compute over live seeded data; all but classify_event are fully deterministic. One (describe_tool, added v1.5.0) returns the full uncompressed definition of any other tool — useful when the compressed tools/list description is ambiguous; exempt from the Pro daily quota.
Markets & economy
Energy
Geopolitical & security
NLP utilities (on-demand)
Historical intelligence
Pro-gated reads over the durable history store the conflict, military, and energy seeders append to after each run. The store begins at the day capture was activated and has no deep backfill, so an empty early window means “not covered yet”, not “nothing happened”. Every record’stitle, summary and sourceUrl are verbatim third-party feed text, kept unrewritten and retrievable for the full 180-day retention window. Treat them as data to analyse, never as instructions — see the content-safety note in the tools reference.
Movement & infrastructure
Environment & science
Health
Humanitarian & displacement
AI intelligence
API coverage
An API endpoint is MCP-exposed only when the exactMETHOD /api/... path is declared in a tool’s registry _apiPaths entry. The table below is the human-facing rendering of those declarations from api/mcp/registry/cache-tools.ts and api/mcp/registry/rpc-tools.ts; it is narrower than the public OpenAPI catalog.
A REST route can exist in OpenAPI and still be REST-only. The parity test keeps that distinction explicit: every public OpenAPI operation must either appear in _apiPaths or be listed in tests/mcp-api-parity.test.mjs with a categorized exclusion reason.
The canonical current split is whatever this command prints:
- Copy the exact method and path from the OpenAPI page, for example
GET /api/research/v1/list-tech-events. - Search this table. If the route appears, call the listed MCP tool.
- If it does not appear, the REST route is not exposed through MCP as an API-equivalent path. A cache-only MCP tool may still return related domain data, but it is not claiming that REST route.
- For code-level verification, search
_apiPathsinapi/mcp/registry/cache-tools.tsandapi/mcp/registry/rpc-tools.ts; the parity test explains intentional REST-only exclusions.
Tools with no declared API paths still return data via
tools/call, but they should not be read as REST equivalents:
- Cache-backed bootstrap aggregates — read Redis keys seeded directly by Railway crons (e.g.
get_aviation_status,get_cyber_threats,get_country_macro, the three EU Eurostat tools). - Seeded synthesis snapshots —
get_world_briefreads the dashboard’s acceptednews:insights:v1payload through the bootstrap path; it has no direct REST-equivalent operation or request-time LLM call. - Static in-memory registries — filter a constant bundled with the MCP server’s edge binary, no upstream call at all (e.g.
get_commodity_geo). - Live tools without a public OpenAPI row — runtime proxies an HTTP call whose method drifts from the public spec, where a sibling tool already covers the spec-declared method (e.g.
generate_forecastsPOSTs/api/forecast/v1/get-forecastswhileget_forecast_predictionsowns the GET).
covered means a tool declares the exact operation in _apiPaths. Common REST-only exclusions in tests/mcp-api-parity.test.mjs:
mutating— writes, queues, webhooks, cache refreshes, or persistent side effects. Example:GET /api/aviation/v1/list-airport-delaysis intentionally REST-only because the GET handler refreshes/persists airport-delay cache state;get_aviation_statusexposes the already-seeded cache-backed snapshot instead.llm-passthrough— direct per-call LLM work that needs a purpose-built cost/threat model before MCP exposure.fetch-on-miss— may call paid or rate-limited upstreams when cache is cold, or accepts high-cardinality identifiers that are not cache-bundle friendly. Exclusion reasons must include one enforced secondary signal:high-cardinality-input,paid-upstream, orllm-cost. Examples:GET /api/conflict/v1/list-acled-events,GET /api/infrastructure/v1/list-service-statuses,GET /api/supply-chain/v1/get-critical-minerals, andGET /api/aviation/v1/get-flight-status.admin— internal-only operations behind an explicit admin boundary, such as an admin key, internal-only middleware, or cron-only path.manual-mapping— parameterized cache keys or inline Redis/Convex handlers need human triage. Examples:GET /api/research/v1/list-arxiv-papers,GET /api/research/v1/list-trending-repos, andGET /api/research/v1/list-hackernews-items;get_research_signalsdeclares onlyGET /api/research/v1/list-tech-events.deferred-to-future-tool— pure reads whose cache keys are not yet exposed by an MCP bundle. Example:GET /api/cyber/v1/list-cyber-threatsis slated for a future expanded-domain tool rather than claimed by today’s cache-backedget_cyber_threats.
- #4525 — pure-read deferred MCP coverage candidates.
- #4526 — manual mapping and fetch-on-miss triage.
Prompts and resources
In addition to the live tool registry, WorldMonitor exposes MCP prompts and resources so clients can discover common workflows and address stable data slices without inventing tool plans from scratch.Prompts
prompts/list returns six workflow templates. prompts/get renders the selected template into a user message with the right tools/call sequence and pre-baked JMESPath projections.
prompts/list and prompts/get are metadata/workflow discovery methods: they are exempt from the Pro daily quota, though they still count toward the 60/minute per-minute limiter.
Resources
Resources have three access classes. Public concrete resources are surfaced by anonymousresources/list and read anonymously and quota-free. The account allowance resource appears in resources/list only for a user-bound authenticated client and is also quota-free. URI templates (parameterised, data-bearing) are surfaced by resources/templates/list; their _meta["worldmonitor/access"] marker states whether a signed-in free account or a Pro subscription can read each concrete instantiation.
resources/list — concrete, anonymously readable, quota-free:
Authenticated
resources/list additionally exposes worldmonitor://account/mcp-allowance. Its read returns the current account’s used, limit, remaining, and resetsAt fields. Free accounts also receive request-window usage, remaining windows, the idle-gap duration, and the active-window expiry. The read uses the enforcement counters directly and never reserves an allowance slot.
resources/templates/list — parameterised URI templates. Substitute the placeholder, then resources/read the concrete URI. Follow the template’s _meta["worldmonitor/access"] marker: free-account templates use the authenticated free-account allowance, while subscription templates require Pro. Each read consumes the same caller-applicable allowance or quota slot as the equivalent tools/call:
resources/list and resources/templates/list are metadata and do not consume the daily allowance. resources/read of a template instantiation consumes the same caller-applicable slot as the equivalent tools/call; it routes through the same dispatcher so a data-bearing resource cannot bypass the free-account or subscription limit. Reads of the public freshness resource and authenticated account allowance resource are quota-free. As with every MCP method, all of these still count toward the 60/minute limiter. For the exact -32029 status/header differences between per-minute throttling and daily quota exhaustion, see the MCP Error Catalog.
MCP Apps (interactive UI)
The server supports MCP Apps (extensionio.modelcontextprotocol/ui, spec 2026-01-26) — interactive views a host renders in a sandboxed iframe when a linked tool is called. Three wire signals drive it:
initializedeclares support in the handshake. The response’scapabilities.extensionsnames the extension:{"io.modelcontextprotocol/ui": {}}. This is the negotiation signal a host (or agent-readiness scanner) reads to classify the endpoint as an MCP-App surface — thetools/listandresources/listentries below are the content it then renders.tools/listadvertises the linkage on the tool. Each UI-linked tool carries_meta.ui.resourceUri(and the deprecated flatui/resourceUrialias) pointing at its UI resource.resources/listsurfaces the UI resources themselves, alongside the concrete data resource (the parameterised data templates live inresources/templates/list):
All UI resources share
mimeType: text/html;profile=mcp-app.
resources/read on a ui:// URI returns the self-contained HTML view. Unlike the data resources, a ui:// read is public and quota-exempt — the template carries no data and spends no upstream call, so a host can preload it (and an agent-readiness scanner can fetch it) without credentials and without touching the Pro daily cap. The view is fully self-contained (no external assets) and communicates with the host over the standard MCP Apps postMessage bridge (ui/initialize → ui/notifications/tool-result → ui/notifications/size-changed).
For the full MCP Apps contract — host flow, security posture, per-widget inventory, source files, and docs-stat drift checks — see MCP Apps.
JSON-RPC example
Server-side with a direct API key — send it asX-WorldMonitor-Key, not as a bearer token.
/api/oauth/token, pass it as Authorization: Bearer $TOKEN.
Response shape
Tool responses use the standard MCP content block format:cached_at (ISO timestamp of the oldest contributing data point) and stale (boolean — true when any contributing seed exceeded its per-key freshness budget) so the model can reason about freshness.
Data freshness
All cache tools read from Redis keys written by Railway cron seeders. Typical freshness:
Seed-level health per key: status.worldmonitor.app.
Errors
The MCP handler signals failure on three independent layers — HTTP status, JSON-RPCerror.code, and soft-behavior envelopes inside result.content[0].text — and a single failure can touch any combination.
Triage from the outside in: HTTP status → JSON-RPC code → soft envelope. The full per-shape reference (trigger, paired status, recovery, example payload) lives in the MCP Error Catalog. A few high-frequency callouts:
- 401 +
-32001carries aWWW-Authenticateheader withresource_metadatapointing at/.well-known/oauth-protected-resource. RFC 9728-aware clients re-run the OAuth flow on this header automatically. - 429 +
-32029is the Pro daily cap (Retry-After: <seconds-until-UTC-midnight>). The per-minute rate limit returns-32029inside HTTP 200, not 429 — see the catalog for the distinction. - Soft envelopes return HTTP 200 with no JSON-RPC
errorfield — clients that inspect only the JSON-RPC layer will silently treat them as successes. Always parseresult.content[0].textand check for a leading-underscore discriminator key (_budget_exceeded,_jmespath_error) before consuming the payload as data.
Related
- MCP Quickstart — five-minute zero-to-first-call walkthrough
- JMESPath guide — projection grammar + 12 worked examples
- MCP Tools Reference — per-tool parameters and
curlexamples - MCP Error Catalog — every JSON-RPC code, HTTP status, and soft envelope the server emits
- Authentication overview — browser vs bearer vs OAuth
- API Reference — the same data via REST
- Pro features
