Connect
Streamable HTTP, protocol 2025-11-25Server URL: https://swolecharts.com/mcp. No account and no payment. A free API key is optional; send it as an X-API-Key header (never in the URL).
Claude Code:
claude mcp add --transport http swolecharts https://swolecharts.com/mcp claude mcp add --transport http swolecharts https://swolecharts.com/mcp --header "X-API-Key: YOUR_KEY"
Clients that read an mcpServers JSON config:
{"mcpServers": {"swolecharts": {"type": "http", "url": "https://swolecharts.com/mcp",
"headers": {"X-API-Key": "YOUR_KEY"}}}}
Leave out headers to call without a key. Supported protocol versions: 2025-11-25, 2025-06-18.
Tools
all read-only| Tool | What it returns |
|---|---|
market_snapshot | Market snapshot. Current price, open interest, 24h volume and 8-hour-normalised funding for one coin's markets across tracked exchanges, sorted by open interest. USD is exchange quote notional; funding is a fraction (0.0001 = 0.01% per 8 hours). |
funding_history | Funding rate history. Funding rate history as an 8-hour-normalised fraction per bucket: each market's average in the bucket, OI-weighted across markets. Up to 10 years where settlement backfill exists. Descriptive history, not projected income. |
oi_history | Open interest history. Open interest in USD per bucket: the sum over markets of each market's last observation in the bucket (not summed across time). Up to 730 days. |
liquidations_history | Liquidations history. Liquidated long and short notional in USD per bucket, from exchange liquidation reports (some venues publish only a sample). Missing buckets are omitted, never zero-filled. Up to 730 days. |
spike_feed | Volume spike feed. Persisted one-minute volume spike alerts, newest first, within a UTC window of at most 24 hours (default: the last hour). Page with next_cursor. Fetch outcomes with spike_outcomes. |
spike_outcomes | Volume spike outcomes. Observed price returns 5, 15 and 60 minutes after up to 50 volume spikes (ids from spike_feed). Return = later close / alert price - 1; directional return flips sign for sell spikes. Observed history only, no probabilities or predictions. |
xray_risk_ranking | Perp index risk ranking (estimate). Perpetuals ranked by estimated liquidation exposure within a price band divided by the estimated order-book depth of their mark-price index to that band (USD; ratio). Only fresh full-coverage rows are ranked; partial ones are listed apart; stale or insufficient ones are counted only. Static-book estimates from public exchange data: not a real cost to move any price, not a mark-price forecast, not trading advice or instructions. Sensitivity is uncalibrated (sensitivity_calibrated=false). |
xray_risk_history | Perp index risk history (estimate). One perpetual's estimated index depth, liquidation exposure and exposure-to-depth ratio per band over time (5-minute or hourly, at most 300 points; longer windows are clamped to end at the requested end), with coverage states and the current index composition (exchange, pair, weight). Static-book estimates from public exchange data: not a real cost to move any price, not a mark-price forecast, not trading advice or instructions. Sensitivity is uncalibrated (sensitivity_calibrated=false). |
History tools take exactly one of base (e.g. BTC) or market (binance:perp:BTCUSDT), and either range (24h, 30d, 1y; default 1d) or start+end in UTC ending in Z, never in the future. Optional step (1m, 5m, 15m, 1h, 4h, 1d), venue and type (perp, spot, all). Funding reaches back up to 10 years where settlement backfill exists; OI and liquidations 730 days. At most 1500 points per call (6000 with a key); a finer step is raised and reported as coarsened. market_snapshot returns up to 50 markets of one coin, spike_feed up to 200 spikes per page in a window of at most 24 hours, spike_outcomes up to 50 ids.
Units, freshness and gaps
- Every result is one JSON envelope, as
structuredContentand as a text block:status(ok, partial, unavailable),as_of,freshness,provenance(stores and method),coverage(requested and available bounds, recordinggaps),units,warningsanddata. - USD is exchange quote notional. Funding, returns and shares are fractions:
0.0001= 0.01%. Funding is normalised to 8 hours; nothing is annualised. Times are UTC. - Missing buckets are omitted, never zero-filled. A period the recorder was down is a gap (
recording_gap, status partial); unknown coverage says so (coverage_unknown). - History buckets are timed by their start; a current window is
freshwhile its newest bucket is at most one step plus 15 minutes old. A completed window ishistorical, not stale. - When a store is down a tool returns
status: unavailablewithisError: trueand aretry_after_shint, never an empty success. Spike outcomes are observed returns only:pendinguntil due,unavailablewithmissing_outcomewhen overdue. No predictions or probabilities.
Limits and errors
| Rule | Value |
|---|---|
Tool calls, shared with /api/series | 30/min per IP without a key, 120/min per key; cached answers count too |
| initialize, tools/list, ping and rejected calls | 60/min per IP |
| Calls in progress | 4 at once; beyond that HTTP 429 with Retry-After |
| Request body / result | 32 KiB / 1 MiB |
| Unknown key | HTTP 401 |
| Bad arguments, unknown tool | JSON-RPC error -32602 |
| Batch requests, GET streams, sessions | not supported (-32600, HTTP 405) |
Try it with curl
H='-H Content-Type:application/json -H Accept:application/json,text/event-stream'
curl -s $H https://swolecharts.com/mcp -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'
curl -s $H -H MCP-Protocol-Version:2025-11-25 https://swolecharts.com/mcp -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
curl -s $H -H MCP-Protocol-Version:2025-11-25 https://swolecharts.com/mcp \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"oi_history","arguments":{"base":"BTC","range":"7d","step":"1h"}}}'
Python, standard library only:
import json, urllib.request
URL = "https://swolecharts.com/mcp"
HEAD = {"Content-Type": "application/json", "Accept": "application/json, text/event-stream"}
def rpc(i, method, params=None):
body = json.dumps({"jsonrpc": "2.0", "id": i, "method": method, "params": params or {}}).encode()
req = urllib.request.Request(URL, body, dict(HEAD, **{"MCP-Protocol-Version": "2025-11-25"}))
with urllib.request.urlopen(req, timeout=15) as r:
return json.load(r)["result"]
rpc(1, "initialize", {"protocolVersion": "2025-11-25", "capabilities": {}, "clientInfo": {"name": "demo", "version": "1"}})
print([t["name"] for t in rpc(2, "tools/list")["tools"]])
out = rpc(3, "tools/call", {"name": "market_snapshot", "arguments": {"base": "BTC", "limit": 3}})["structuredContent"]
print(out["status"], out["data"]["markets"] if out["data"] else out["reason"])
Usage counting
We count calls per tool per UTC day and estimate distinct callers with a keyed, rotating hash sketch. No arguments, IP addresses, keys, prompts or per-request logs are stored. Terms are the API terms: free, no SLA, attribution when you publish, no resale.