MCP Server
Connect Claude, GPT, or any MCP-compatible AI agent directly to live Resolved Markets data. The server exposes orderbooks, snapshots, market metadata, and Hyperliquid perps as MCP tools — your agent can call them just like any other function.
What is MCP?
The Model Context Protocol is an open standard for connecting AI assistants to external data and tools. Once configured, your agent can ask things like "compare the BTC 5m spread on Polymarket to the BTC perp on Hyperliquid right now" and the agent will call the right tools automatically — no glue code needed.
Three ways to connect
All paths use the same backend. Tier limits (Free = all crypto + 300 rpm + 5K credits/mo; Pro = all crypto + 300 rpm + 50K credits + WebSocket; Scale = all markets + Hyperliquid + 1000 rpm + 500K credits; Enterprise = everything + 3000 rpm + 5M credits + Team access) are enforced server-side against your account.
1. Claude.ai web (one-click OAuth — easiest)
Connect directly from Claude on the web. No API key to copy, no config files — sign in once and Claude is connected. An API key is minted in your Resolved Markets account behind the scenes (visible in /api-keys labeled Claude · MCP), and you can revoke access any time from that page.
- Go to claude.ai/customize/connectors.
- Click the + button (top right), then choose Add custom connector.
- Enter a name (e.g. Resolved Markets) and paste this as the Remote MCP server URL:
https://mcp.resolvedmarkets.com/mcp - Leave OAuth Client ID and OAuth Client Secret empty — dynamic registration handles them automatically.
- Click Connect. A popup will open on resolvedmarkets.com.
- Sign in to your Resolved Markets account (or create one).
- Review the consent screen and click Allow access. You'll be redirected back to Claude with the connector now Connected.
Open a Claude conversation, pick the Resolved Markets connector from the tools menu, and ask something like “what BTC prediction markets are live right now?”.
2. Hosted endpoint with API key (Claude Desktop, Claude Code, ChatGPT, custom agents)
Connect any MCP client to https://mcp.resolvedmarkets.com/mcp and pass your key in the X-API-Key header. Zero install, always up to date. Use this for clients that don't support OAuth or when you want to script with a long-lived key.
For Claude Desktop or Claude Code, bridge via mcp-remote:
{
"mcpServers": {
"resolvedmarkets": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"https://mcp.resolvedmarkets.com/mcp",
"--header", "X-API-Key: rm_your_api_key_here"
]
}
}
}Authorization: Bearer rm_... is also accepted if your client prefers it.
3. Self-hosted / local (npm)
Run the package locally — the stdio process reads the key once from HF_API_KEY. Best for offline tooling or multi-tenant agents that manage keys themselves.
Claude Desktop — add to claude_desktop_config.json:
{
"mcpServers": {
"resolvedmarkets": {
"command": "npx",
"args": ["-y", "@elcara-hq/resolvedmarkets-mcp"],
"env": {
"HF_API_URL": "https://api.resolvedmarkets.com",
"HF_API_KEY": "rm_your_api_key_here"
}
}
}
}Claude Code:
claude mcp add resolvedmarkets -- npx -y @elcara-hq/resolvedmarkets-mcp export HF_API_KEY=rm_your_api_key_here
One-off via npx:
HF_API_KEY=rm_your_api_key_here npx @elcara-hq/resolvedmarkets-mcp
Recommended call patterns
Most agent tasks fall into one of five patterns. Following these avoids wasted calls and keeps tier-limit errors from masking real problems.
- Discover what's available →
list_categories→list_markets(filter by category/subcategory). - Live state of a known market →
get_market(slug → conditionId) →get_orderbook. - Historical analysis of one market → resolve to a conditionId →
get_market_summary(7-day overview) →query_snapshots(paginated time-series, the core analysis tool). - Point-in-time market state →
get_snapshot(searches up to 1h before the requested UTC timestamp). - Cross-market comparison (Polymarket vs. Hyperliquid perps) →
get_orderbook+get_exchange_orderbook(Pro+ only).
Slugs vs. conditionIds. Slugs (e.g. btc-updown-5m) are human-readable and rotate as new windows open — they only resolve to currently active markets. The conditionId is a stable 0x-prefixed string that uniquely identifies a market for its whole lifetime; most tools require it. Always pass a slug through get_market first to lock down the conditionId before calling deeper analysis tools.
Tools — full reference
All 12 tools, with parameter schemas and key behavior. Pasting any of these signatures into your agent prompt is enough for it to call the tool correctly. Tier requirements are noted inline; calls that exceed the caller's tier return a structured hint with the upgrade path.
Discovery & metadata
list_categories
List all market categories with counts and capture intervals.
- Parameters: none.
- Returns: array of
{ category, subcategories[], active_count, capture_interval_ms }. - Tier: any (including free).
- Use first to understand what data is available before listing markets.
list_markets
List currently-tracked (live) markets with token IDs, slugs, expiry, and category metadata.
- Parameters (all optional):
category— one ofcrypto|sports|economics|weather|social|equitiessubcategory— e.g.BTC,NBA,FOMC,NYC,Elon,SPX
- Tier: any. Free & Pro see all crypto coins (crypto only); Scale/Enterprise see all categories.
- Do not use for closed/past markets — use
list_historical_marketsinstead.
list_historical_markets
List closed or past markets. Each row includes snapshot_count + first_seen / last_seen so you can pick one to analyze.
- Parameters (all optional):
mode—recent(default, paginated, fast) orfull(everything ever stored, heavier)crypto—BTC|ETH|SOL|XRP(crypto category only)timeframe—5m|15m|1h|1d(crypto category only)category,subcategory— same aslist_marketslimit— 1–500, default 100. Used only whenmode="recent".
- Tier: all tiers (including Free) have unlimited history.
get_market
Resolve a single market by slug into conditionId + token IDs + status.
- Parameters:
slug(required) — full, partial, or timestamped, e.g.btc-updown-5m.
- Returns:
{ market_id, crypto, timeframe, tokenIdUp, tokenIdDown, expiresIn, active, expired }. - Tier: any.
- Use this before tools that take a
market_idwhen you only have the slug.
Live orderbook
get_orderbook
Live orderbook for a market — bid/ask arrays, best bid/ask, mid price, and depth for both UP and DOWN tokens.
- Parameters (exactly ONE required):
market_id— 0x-prefixed conditionId.- OR
slug— only works for active markets, e.g.btc-updown-5m.
- Returns:
{ up: { bids[], asks[], mid, spread, depth }, down: {…} }. - Tier: Free is limited to 20 orderbook levels per side. Pro / Enterprise see full depth.
- Common error: passing both
market_idandslug, or neither, returns a clear validation error.
get_exchange_orderbook
Live orderbook from a centralized exchange (currently Hyperliquid perpetual futures). Useful for comparing Polymarket prediction prices against the underlying perp.
- Parameters:
exchange—hyperliquid_perp(default; only value today).symbol(required) —BTC|ETH|SOL|XRP.
- Tier: Pro+ required. Free tier hits 403 with upgrade hint.
Historical snapshots
get_snapshot
Orderbook snapshot at (or just before) a specific UTC timestamp. The backend searches up to 1 hour before the requested time.
- Parameters:
timestamp(required) — UTC,YYYY-MM-DD HH:MM:SS[.mmm]or ISO 8601.market_id— filter to a conditionId.crypto/timeframe— same enums aslist_historical_markets.include_book— boolean, defaultfalse. Off keeps the response small.
- Tier: all tiers have unlimited history (no 24h cap).
get_latest_snapshots
The 5 most recent snapshots across all markets. Mainly a data-freshness probe.
- Parameters (all optional):
crypto,timeframe,include_book. - Tier: any. Subject to per-row tier restrictions on which markets show up.
query_snapshots
Paginated time-series of orderbook snapshots for one market. The core analysis tool.
- Parameters:
market_id(required) — conditionId.side—UPorDOWN. Restricting to one side roughly halves response size and speeds queries.from/to— UTC range,YYYY-MM-DD HH:MM:SS.limit— 1–5000 (default 500). Cap drops to 2000 wheninclude_book=truebecause payloads get much larger.offset— pagination, default 0.include_book— boolean, defaultfalse. Per-row bid/ask arrays.order—ascordesc(defaultdesc).
- Returns:
{ market_id, total, limit, offset, data: [snapshot, …] }. Loop onoffsetusingdata.length&totalto page through the full window. - Tier: all tiers see the full archive — history is unlimited on every plan.
- Best practice: for trend analysis, fetch without
include_bookfirst to study mid/spread; pullinclude_book=trueonly on a smaller refined window if you need the full book.
get_exchange_snapshots
Historical orderbook snapshots from an exchange (Hyperliquid perps), sampled at ~1/sec. Lightweight rows — best bid/ask, mid, spread, depth, no full arrays.
- Parameters:
exchange,symbol(required),from,to,limit(1–5000, default 500). - Defaults to last 24h if no range given.
- Tier: Pro+ required.
Aggregates & system
get_market_summary
Aggregated 7-day statistics for one market.
- Parameters:
market_id(required) — conditionId. Useget_marketto resolve a slug first. - Returns: snapshot count, avg/min/max mid price & spread, avg crypto price, per-side (UP/DOWN) breakdowns.
- Tier: any (subject to tier history depth).
get_system_stats
System-wide health and price snapshot. Combines authenticated /v1/stats with public stats; either can be null if unavailable.
- Parameters: none.
- Returns:
{ stats, publicStats }with active market count, total snapshots, per-crypto breakdown, current crypto prices (BTC/ETH/SOL/XRP), pipeline health. - Tier: any.
Tier limits at a glance
Every tool call passes through the same tier check. When a request exceeds the caller's tier, the tool returns a structured error explaining the limit and pointing to the upgrade page; the agent can relay this to the user verbatim.
| Limit | Free | Pro | Scale | Enterprise |
|---|---|---|---|---|
| Monthly credits | 5,000 | 50,000 | 500,000 | 5,000,000 |
| Crypto markets | BTC, ETH, SOL, XRP | BTC, ETH, SOL, XRP | BTC, ETH, SOL, XRP | BTC, ETH, SOL, XRP |
| Orderbook depth | Full | Full | Full | Full |
| History depth | Full archive | Full archive | Full archive | Full archive |
| Rate limit (req / min) | 300 | 300 | 1,000 | 3,000 |
| Sports / Economics / Weather / Social / Equities | — | — | ✓ | ✓ |
Hyperliquid perps (get_exchange_*) | — | — | ✓ | ✓ |
| WebSocket connections | — | 1 | 5 | 10 |
| API keys | 2 | 5 | 10 | 20 |
| MCP access | full | full | full | full |
Resources
MCP resources are read-only data sources the host can pull as context. Both resources below return JSON identical to the equivalent REST endpoint and refresh on each read.
| URI | Description | Equivalent REST |
|---|---|---|
markets://live | Currently active markets with token IDs and metadata | GET /v1/markets/live |
prices://latest | Current cryptocurrency prices and pipeline/exchange stats | GET /v1/public-stats |
Common errors & how to fix them
| Symptom | Likely cause | Fix |
|---|---|---|
401 on every call | No API key, malformed key, or revoked key | Generate or restore a key at /api-keys. Hosted endpoint with API-key auth must pass X-API-Key or Authorization: Bearer rm_… on every request. |
403 with tier hint | Tool requires Scale+ (e.g. get_exchange_orderbook or a non-crypto category, which Free/Pro can’t access) | Upgrade at /pricing to Scale or Enterprise for all markets and exchange data. |
429 rate-limited | Burst over your tier's req/min cap | Wait retryAfterMs from the response or upgrade. Free=60, Pro=500, Enterprise=3000 rpm. |
get_orderbook returns "market not found" | Slug expired (window rolled over) or wrong conditionId | Re-run get_market or list_markets to get the current slug / conditionId. |
query_snapshots returns empty data array | Window is before the market existed, or from > to | Check list_historical_markets first for first_seen / last_seen. Order: from < to. |
| Tool times out on large window | include_book=true with a wide range | Drop include_book (cap is 5000 vs 2000 rows) or shrink the range and page with offset. |
| Session 401 mid-conversation (hosted) | 30-minute session expired | Re-initialize. mcp-remote and the claude.ai connector handle this automatically; raw HTTP clients must re-send initialize with the key. |
mcp_registration_failed in claude.ai connector | URL entered without /mcp path, or browser already cached a previous failed connector | Use https://mcp.resolvedmarkets.com/mcp (with the path). Delete the failed connector and re-add. |
Environment Variables
Used only for the self-hosted/local install. The hosted endpoint needs none of these.
| Variable | Default | Description |
|---|---|---|
HF_API_URL | http://localhost:3001 | Backend API URL. Use https://api.resolvedmarkets.com for production. |
HF_API_KEY | — | Your API key (rm_...). Required for authenticated tools. |
MCP_TRANSPORT | stdio | Transport mode: stdio or http |
MCP_PORT | 3002 | HTTP port (when using HTTP transport) |
Security
- Requests without a key (or with a malformed key) are rejected with
401before a session is opened. - The key is re-validated on every request using constant-time comparison — a request that arrives on an existing session with a mismatched key is rejected as a hijack attempt.
- Sessions auto-expire 30 minutes after
initialize. After that, clients must re-initialize.mcp-remotehandles this transparently. - Never paste your key into a shared MCP config or commit it to a repo — treat it like a password.
Example queries
Once connected, ask your AI agent any of the questions below. Each example shows thetool chain the agent will likely call so you can predict the cost and verify the result.
Single-call questions
- “What market categories does Resolved Markets track?” —
list_categories - “What BTC prediction markets are live right now?” —
list_markets({ category: "crypto", subcategory: "BTC" }) - “How's the data pipeline performing?” —
get_system_stats - “Show me the latest snapshots to confirm data is live” —
get_latest_snapshots
Two-call lookups
- “Show me the live orderbook for
btc-updown-5m” →get_market("btc-updown-5m")→get_orderbook({ market_id }) - “Give me a 7-day summary for the current SOL 15m market” →
list_markets({ category: "crypto", subcategory: "SOL" })→get_market_summary({ market_id })
Time-series analysis
- “What was the BTC 5m spread around 2026-03-02 10:42 UTC?” →
get_snapshot({ timestamp, crypto: "BTC", timeframe: "5m" }) - “Pull the last 500 snapshots for that market and chart the spread trend” →
query_snapshots({ market_id, limit: 500, order: "asc" })→ client-side aggregation - “Show me the full orderbook depth every minute for the last hour” →
query_snapshots({ market_id, from, to, include_book: true, limit: 2000 })
Cross-market comparison (Pro+)
- “Compare the Polymarket BTC prediction price to the Hyperliquid BTC perp right now” →
get_orderbook({ slug: "btc-updown-5m" })+get_exchange_orderbook({ symbol: "BTC" }) - “Was Hyperliquid BTC perp leading or lagging Polymarket during the last 4 hours?” → both
query_snapshotsandget_exchange_snapshotsover the same range, correlate offline.
Discovery-first workflows
- “Find me an interesting volatile market right now” →
list_markets({ category: "crypto" })→ for each →get_market_summary→ pick the one with the widest spread range. - “Are there any active sports markets with under 30 minutes to expiry?” →
list_markets({ category: "sports" })→ filter onexpiresIn.
HTTP Transport
For remote integrations or custom agents, run the local server in HTTP mode:
MCP_TRANSPORT=http MCP_PORT=3002 npx @elcara-hq/resolvedmarkets-mcp
Endpoint: POST http://localhost:3002/mcp

