hfmarketdata-mcp demo — asking Claude Code for the CL term structure

hfmarketdata-mcp

The official MCP server for HF Market Data — 1-minute to daily bars for stocks, ETFs, futures, crypto, indices and FX since 2007, individual futures contracts, custom continuous series, term structures, options chains with Greeks and point-in-time SEC fundamentals, straight into Claude Code, Cursor, Codex or any MCP client.

npm node MCP tools tests license

--- ## Quickstart (60 seconds) ```bash # 1. Install (pick one) npm i -g hfmarketdata-mcp # from npm (once published) npm i -g https://www.hfmarketdata.io/downloads/hfmarketdata-mcp-1.0.0.tgz # direct tarball, works today # 2. Check the connection (keyless works out of the box: 30 requests/hour) hfmarketdata-mcp --selftest # OK https://www.hfmarketdata.io (312 ms, keyless) — datasets: stock, etf, futures, futures_contracts, crypto, index, fx, options # 3. Add it to Claude Code claude mcp add hfmarketdata -e HFMD_API_KEY=hfmd_live_… -- npx -y hfmarketdata-mcp ``` Then just ask: > *"Plot me the CL term structure"* · *"Compare ESZ25 and ESH26 over 30 days"* · *"Screen US stocks with PE<15 and FCF yield>6% and show their last 3 quarters"* The platform is entirely free. Keyless mode has low hourly limits (30 requests / hour); a free API key (free account at `https://www.hfmarketdata.io/signup`) gives **120 requests / minute**, and higher limits are granted on request by e-mail to contact@spboucher.ai (also free). Set the key as `HFMD_API_KEY`; the server never logs it. Details: . ## Tools | Tool | What it does | Backed by | |---|---|---| | `search_symbols` | Find tickers (stock/etf/crypto/index/fx), futures roots or optionable underlyings | `/v1/{asset}/tickers`, `/v1/futures/roots`, `/v1/options/tickers` | | `get_bars` | OHLCV bars 1min…1day for one or many symbols; vendor continuous futures; individual contracts (`ESZ25`) | `/v1/bars/{asset}/{ticker}`, `/v1/bars/{asset}?tickers=`, `/v1/futures/contract/{symbol}/bars` | | `get_futures_contracts` | Every expiration of a root with expiry / FND / status / volume / OI | `/v1/futures/{root}/contracts` | | `get_futures_chain` | Listed contracts as of a date, front month first | `/v1/futures/{root}/chain` | | `get_continuous` | Server-built continuous series: `roll=volume\|open_interest\|calendar`, `adjust=none\|back_adjusted\|ratio`, `depth` | `/v1/futures/{root}/continuous` | | `get_term_structure` | The curve on a date (prices, spreads, OI) — contango / backwardation | `/v1/futures/{root}/term-structure` | | `get_options_chain` | EOD chain with IV and Greeks, filters by expiry / strikes / side; `list_expirations` | `/v1/options/chain/{t}`, `/v1/options/expirations/{t}` | | `get_coverage` | What exists for a contract or a ticker's fundamentals, gaps included | `/v1/futures/contract/{s}/coverage`, `/v1/fundamentals/{t}/coverage` | | `get_financial_statements` | Income / balance / cash-flow, annual or quarterly, point-in-time; single XBRL fact history with `concept` | `/v1/fundamentals/{t}/statements`, `/v1/fundamentals/{t}/facts/{concept}` | | `get_ratios` | Latest P/E, P/B, EV/EBITDA, FCF yield, ROE, margins, leverage… | `/v1/fundamentals/{t}/ratios` | | `get_ratios_daily` | Daily ratio history recomputed with the fundamentals known that day | `/v1/fundamentals/{t}/ratios/daily` | | `screen_fundamentals` | `filters="pe<15,roe>0.15,fcf_yield>0.06"` + `sort="fcf_yield:desc"` (+ `as_of`) | `/v1/fundamentals/screener` | | `get_filings` | 10-K / 10-Q / 8-K / 4 / 13F… with URLs | `/v1/fundamentals/{t}/filings` | | `subscribe_filings` | Opens `wss://…/v1/stream`, subscribes to `filings`, returns up to N messages within a bounded time window | websocket | **Resources:** `hfmarketdata://status` (live dataset inventory) · `hfmarketdata://limits` (rate limits + your headroom). **Prompts:** `term-structure-analysis(root, as_of?, compare_to?)` · `compare-contracts(symbol_a, symbol_b, days?)` · `fundamentals-snapshot(ticker, quarters?)`. ### Behaviour every tool shares - `HFMD_BASE_URL` (default `https://www.hfmarketdata.io`) and `HFMD_API_KEY` (optional) are the only configuration. - `format=json` is always requested; both the v1 envelope `{count,data}` and the v2 envelope `{data,meta}` are understood. - Outputs are compact tables `{"columns":[…],"rows":[[…]]}`. The default `limit` is 500 rows (max 5 000); above **200 rows** the tool returns the count, the first/last 15 rows, per-column numeric ranges and a hint to narrow the request — so a careless "all 1-minute bars since 2010" cannot flood the context. - Rate-limit headroom (`X-RateLimit-Remaining-*`, reset) is appended to every result; a **429** comes back as a clear message with `Retry-After` and a reminder that a free API key lifts the low keyless limits. - Errors are uniform: `HF Market Data error : [Docs: …]`, whether the API answered with the v2 `{"error":{code,message,docs}}` envelope or the legacy `{"detail"}`. - `subscribe_filings` is bounded by design (`max_messages` ≤ 100, `timeout_seconds` ≤ 120) and closes the socket when it returns; it needs Node ≥ 22 (global `WebSocket`) or Node 20 with `--experimental-websocket`. - Read-only: no tool ever writes anything anywhere. ## Configuration snippets ### Claude Code ```bash claude mcp add hfmarketdata -e HFMD_API_KEY=hfmd_live_… -- npx -y hfmarketdata-mcp # tarball install instead of npm: npm i -g https://www.hfmarketdata.io/downloads/hfmarketdata-mcp-1.0.0.tgz && claude mcp add hfmarketdata -e HFMD_API_KEY=hfmd_live_… -- hfmarketdata-mcp ``` Or in `.mcp.json` at the root of a project (shared with your team): ```json { "mcpServers": { "hfmarketdata": { "command": "npx", "args": ["-y", "hfmarketdata-mcp"], "env": { "HFMD_API_KEY": "hfmd_live_…" } } } } ``` ### Cursor — `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global) ```json { "mcpServers": { "hfmarketdata": { "command": "npx", "args": ["-y", "hfmarketdata-mcp"], "env": { "HFMD_API_KEY": "hfmd_live_…" } } } } ``` One-click (best effort): `cursor://anysphere.cursor-deeplink/mcp/install?name=hfmarketdata&config=` — generated for you on . ### Codex — `~/.codex/config.toml` ```toml [mcp_servers.hfmarketdata] command = "npx" args = ["-y", "hfmarketdata-mcp"] env = { HFMD_API_KEY = "hfmd_live_…" } ``` ### Claude Desktop — `claude_desktop_config.json` ```json { "mcpServers": { "hfmarketdata": { "command": "npx", "args": ["-y", "hfmarketdata-mcp"], "env": { "HFMD_API_KEY": "hfmd_live_…" } } } } ``` Keyless? Simply drop the `env` block. ## Example session ``` > Compare ESZ25 and ESH26 over 30 days ⏺ get_coverage(kind="futures_contract", symbol="ESZ25") … get_bars(asset="futures_contract", symbol="ESZ25", start="2025-08-05") … ⏺ Over the last 30 sessions ESH26 traded at a 61.5 → 58.0 point premium to ESZ25 (calendar spread narrowing 3.5 pts as financing expectations eased). Volume is still 96 % in ESZ25; the roll window usually opens ~8 sessions before the December expiry (2025-12-19). One session (2025-09-01, Labor Day) is missing in both legs — not interpolated. ``` ## Development ```bash npm install npm test # vitest — 45 tests, every tool mocked (fetch + websocket) npm run build # tsc → dist/ node dist/index.js --selftest node scripts/live-smoke.mjs # real stdio round-trip against www.hfmarketdata.io npm run inspect # MCP Inspector UI ``` ### Release ```bash npm version 1.0.x npm run build && npm test npm pack # → hfmarketdata-mcp-1.0.x.tgz (this is what /downloads serves) npm publish --dry-run # inspect the file list npm publish --access public # requires the maintainer's npm login (npm login / NPM_TOKEN) ``` Until the package is on the npm registry, `npx -y hfmarketdata-mcp` resolves nothing: use the tarball URL above or `npm i -g ./hfmarketdata-mcp-1.0.0.tgz`. ## Project layout ``` src/index.ts bin — stdio transport, --help/--version/--selftest src/server.ts createServer(): 14 tools · 2 resources · 3 prompts src/tools.ts tool catalogue (zod schemas + handlers), runTool() src/client.ts fetch wrapper: auth, format=json, rate headers, uniform HfmdError src/format.ts compact tables, head/tail summaries src/stream.ts bounded websocket consumer src/resources.ts hfmarketdata://status · hfmarketdata://limits src/prompts.ts term-structure-analysis · compare-contracts · fundamentals-snapshot test/ vitest (mocked fetch + fake WebSocket + in-memory MCP transport) scripts/ live-smoke.mjs · record-demo.md ``` ## Licence MIT © Simon-Pierre Boucher — data by [FirstRate Data](https://firstratedata.com) and SEC EDGAR, served by [HF Market Data](https://www.hfmarketdata.io). Questions: contact@spboucher.ai.