SPB Git

spb/hfmarketdata

Public

Open high-frequency market data platform — FirstRate full-history downloader, DuckDB/Parquet lake, open REST API and React docs platform (www.hfmarketdata.io)

mcp: serveur MCP officiel hfmarketdata-mcp (14 outils, 2 ressources, 3 prompts, stdio) + tests vitest + tarball téléchargeable

- TypeScript, @modelcontextprotocol/sdk + zod, fetch natif, Node >= 20
- outils : search_symbols, get_bars, get_futures_contracts, get_futures_chain, get_continuous, get_term_structure, get_options_chain, get_coverage, get_financial_statements, get_ratios, get_ratios_daily, screen_fundamentals, get_filings, subscribe_filings (websocket borné)
- sorties compactes {columns,rows}, résumé tête/queue au-delà de 200 lignes, en-têtes X-RateLimit-* et 429 explicités, erreurs uniformes
- README vitrine (Claude Code / Cursor / Codex / Claude Desktop), guide d'enregistrement de la démo, smoke test live
- hfmarketdata/web/public/downloads/hfmarketdata-mcp-1.0.0.tgz (npm pack) servi par le SPA fallback

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Sep 4, 2026) parent 7ee2ef9 Browse files

25 changed files +4,926 −0

added hfmarketdata/web/public/downloads/.gitignore +4 −0
@@ -0,0 +1,4 @@
1 +# Distributables served at https://www.hfmarketdata.io/downloads/ — committed on purpose
2 +# (the repository root ignores *.zip for data archives; re-include ours here).
3 +!*.zip
4 +!*.tgz
added hfmarketdata/web/public/downloads/hfmarketdata-mcp-1.0.0.tgz +0 −0

Binary file not shown.

added mcp/.gitignore +3 −0
@@ -0,0 +1,3 @@
1 +node_modules/
2 +dist/
3 +*.tgz
added mcp/LICENSE +21 −0
@@ -0,0 +1,21 @@
1 +MIT License
2 +
3 +Copyright (c) 2026 Simon-Pierre Boucher
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in all
13 +copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 +SOFTWARE.
added mcp/README.md +185 −0
@@ -0,0 +1,185 @@
1 +<p align="center">
2 + <img src="docs/demo.gif" alt="hfmarketdata-mcp demo — asking Claude Code for the CL term structure" width="820" />
3 +</p>
4 +
5 +<h1 align="center">hfmarketdata-mcp</h1>
6 +
7 +<p align="center">
8 + The official <a href="https://modelcontextprotocol.io">MCP</a> server for <a href="https://www.hfmarketdata.io">HF Market Data</a> —
9 + 1-minute to daily bars for stocks, ETFs, futures, crypto, indices and FX since 2007, individual futures contracts, custom continuous series,
10 + term structures, options chains with Greeks and point-in-time SEC fundamentals, straight into Claude Code, Cursor, Codex or any MCP client.
11 +</p>
12 +
13 +<p align="center">
14 + <a href="https://www.npmjs.com/package/hfmarketdata-mcp"><img alt="npm" src="https://img.shields.io/npm/v/hfmarketdata-mcp?color=5ee7a5&label=npm" /></a>
15 + <img alt="node" src="https://img.shields.io/badge/node-%E2%89%A5%2020-5ee7a5" />
16 + <img alt="MCP" src="https://img.shields.io/badge/MCP-stdio-37b3ff" />
17 + <img alt="tools" src="https://img.shields.io/badge/tools-14-37b3ff" />
18 + <img alt="tests" src="https://img.shields.io/badge/vitest-45%20passing-5ee7a5" />
19 + <a href="./LICENSE"><img alt="license" src="https://img.shields.io/badge/license-MIT-lightgrey" /></a>
20 +</p>
21 +
22 +---
23 +
24 +## Quickstart (60 seconds)
25 +
26 +```bash
27 +# 1. Install (pick one)
28 +npm i -g hfmarketdata-mcp # from npm (once published)
29 +npm i -g https://www.hfmarketdata.io/downloads/hfmarketdata-mcp-1.0.0.tgz # direct tarball, works today
30 +
31 +# 2. Check the connection (keyless works out of the box: 30 requests/hour)
32 +hfmarketdata-mcp --selftest
33 +# OK https://www.hfmarketdata.io (312 ms, keyless) — datasets: stock, etf, futures, futures_contracts, crypto, index, fx, options
34 +
35 +# 3. Add it to Claude Code
36 +claude mcp add hfmarketdata -e HFMD_API_KEY=hfmd_live_… -- npx -y hfmarketdata-mcp
37 +```
38 +
39 +Then just ask:
40 +
41 +> *"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"*
42 +
43 +A free account (`https://www.hfmarketdata.io/signup`) gives you an API key and **120 requests / minute** instead of 30 / hour. Set it as `HFMD_API_KEY`; the server never logs it.
44 +
45 +## Tools
46 +
47 +| Tool | What it does | Backed by |
48 +|---|---|---|
49 +| `search_symbols` | Find tickers (stock/etf/crypto/index/fx), futures roots or optionable underlyings | `/v1/{asset}/tickers`, `/v1/futures/roots`, `/v1/options/tickers` |
50 +| `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` |
51 +| `get_futures_contracts` | Every expiration of a root with expiry / FND / status / volume / OI | `/v1/futures/{root}/contracts` |
52 +| `get_futures_chain` | Listed contracts as of a date, front month first | `/v1/futures/{root}/chain` |
53 +| `get_continuous` | Server-built continuous series: `roll=volume\|open_interest\|calendar`, `adjust=none\|back_adjusted\|ratio`, `depth` | `/v1/futures/{root}/continuous` |
54 +| `get_term_structure` | The curve on a date (prices, spreads, OI) — contango / backwardation | `/v1/futures/{root}/term-structure` |
55 +| `get_options_chain` | EOD chain with IV and Greeks, filters by expiry / strikes / side; `list_expirations` | `/v1/options/chain/{t}`, `/v1/options/expirations/{t}` |
56 +| `get_coverage` | What exists for a contract or a ticker's fundamentals, gaps included | `/v1/futures/contract/{s}/coverage`, `/v1/fundamentals/{t}/coverage` |
57 +| `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}` |
58 +| `get_ratios` | Latest P/E, P/B, EV/EBITDA, FCF yield, ROE, margins, leverage… | `/v1/fundamentals/{t}/ratios` |
59 +| `get_ratios_daily` | Daily ratio history recomputed with the fundamentals known that day | `/v1/fundamentals/{t}/ratios/daily` |
60 +| `screen_fundamentals` | `filters="pe<15,roe>0.15,fcf_yield>0.06"` + `sort="fcf_yield:desc"` (+ `as_of`) | `/v1/fundamentals/screener` |
61 +| `get_filings` | 10-K / 10-Q / 8-K / 4 / 13F… with URLs | `/v1/fundamentals/{t}/filings` |
62 +| `subscribe_filings` | Opens `wss://…/v1/stream`, subscribes to `filings`, returns up to N messages within a bounded time window | websocket |
63 +
64 +**Resources:** `hfmarketdata://status` (live dataset inventory) · `hfmarketdata://limits` (tiers + your headroom).
65 +**Prompts:** `term-structure-analysis(root, as_of?, compare_to?)` · `compare-contracts(symbol_a, symbol_b, days?)` · `fundamentals-snapshot(ticker, quarters?)`.
66 +
67 +### Behaviour every tool shares
68 +
69 +- `HFMD_BASE_URL` (default `https://www.hfmarketdata.io`) and `HFMD_API_KEY` (optional) are the only configuration.
70 +- `format=json` is always requested; both the v1 envelope `{count,data}` and the v2 envelope `{data,meta}` are understood.
71 +- 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.
72 +- Rate-limit headroom (`X-RateLimit-Remaining-*`, reset) is appended to every result; a **429** comes back as a clear message with `Retry-After` and the keyless → key upgrade hint.
73 +- Errors are uniform: `HF Market Data error <status> <CODE>: <message> [Docs: …]`, whether the API answered with the v2 `{"error":{code,message,docs}}` envelope or the legacy `{"detail"}`.
74 +- `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`.
75 +- Read-only: no tool ever writes anything anywhere.
76 +
77 +## Configuration snippets
78 +
79 +### Claude Code
80 +
81 +```bash
82 +claude mcp add hfmarketdata -e HFMD_API_KEY=hfmd_live_… -- npx -y hfmarketdata-mcp
83 +# tarball install instead of npm:
84 +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
85 +```
86 +
87 +Or in `.mcp.json` at the root of a project (shared with your team):
88 +
89 +```json
90 +{
91 + "mcpServers": {
92 + "hfmarketdata": {
93 + "command": "npx",
94 + "args": ["-y", "hfmarketdata-mcp"],
95 + "env": { "HFMD_API_KEY": "hfmd_live_…" }
96 + }
97 + }
98 +}
99 +```
100 +
101 +### Cursor — `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global)
102 +
103 +```json
104 +{
105 + "mcpServers": {
106 + "hfmarketdata": {
107 + "command": "npx",
108 + "args": ["-y", "hfmarketdata-mcp"],
109 + "env": { "HFMD_API_KEY": "hfmd_live_…" }
110 + }
111 + }
112 +}
113 +```
114 +
115 +One-click (best effort): `cursor://anysphere.cursor-deeplink/mcp/install?name=hfmarketdata&config=<base64 of the JSON object above>` — generated for you on <https://www.hfmarketdata.io/integrations/cursor>.
116 +
117 +### Codex — `~/.codex/config.toml`
118 +
119 +```toml
120 +[mcp_servers.hfmarketdata]
121 +command = "npx"
122 +args = ["-y", "hfmarketdata-mcp"]
123 +env = { HFMD_API_KEY = "hfmd_live_…" }
124 +```
125 +
126 +### Claude Desktop — `claude_desktop_config.json`
127 +
128 +```json
129 +{ "mcpServers": { "hfmarketdata": { "command": "npx", "args": ["-y", "hfmarketdata-mcp"], "env": { "HFMD_API_KEY": "hfmd_live_…" } } } }
130 +```
131 +
132 +Keyless? Simply drop the `env` block.
133 +
134 +## Example session
135 +
136 +```
137 +> Compare ESZ25 and ESH26 over 30 days
138 +
139 +⏺ get_coverage(kind="futures_contract", symbol="ESZ25") … get_bars(asset="futures_contract", symbol="ESZ25", start="2025-08-05") …
140 +⏺ Over the last 30 sessions ESH26 traded at a 61.5 → 58.0 point premium to ESZ25 (calendar spread narrowing 3.5 pts as
141 + financing expectations eased). Volume is still 96 % in ESZ25; the roll window usually opens ~8 sessions before the
142 + December expiry (2025-12-19). One session (2025-09-01, Labor Day) is missing in both legs — not interpolated.
143 +```
144 +
145 +## Development
146 +
147 +```bash
148 +npm install
149 +npm test # vitest — 45 tests, every tool mocked (fetch + websocket)
150 +npm run build # tsc → dist/
151 +node dist/index.js --selftest
152 +node scripts/live-smoke.mjs # real stdio round-trip against www.hfmarketdata.io
153 +npm run inspect # MCP Inspector UI
154 +```
155 +
156 +### Release
157 +
158 +```bash
159 +npm version 1.0.x
160 +npm run build && npm test
161 +npm pack # → hfmarketdata-mcp-1.0.x.tgz (this is what /downloads serves)
162 +npm publish --dry-run # inspect the file list
163 +npm publish --access public # requires the maintainer's npm login (npm login / NPM_TOKEN)
164 +```
165 +
166 +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`.
167 +
168 +## Project layout
169 +
170 +```
171 +src/index.ts bin — stdio transport, --help/--version/--selftest
172 +src/server.ts createServer(): 14 tools · 2 resources · 3 prompts
173 +src/tools.ts tool catalogue (zod schemas + handlers), runTool()
174 +src/client.ts fetch wrapper: auth, format=json, rate headers, uniform HfmdError
175 +src/format.ts compact tables, head/tail summaries
176 +src/stream.ts bounded websocket consumer
177 +src/resources.ts hfmarketdata://status · hfmarketdata://limits
178 +src/prompts.ts term-structure-analysis · compare-contracts · fundamentals-snapshot
179 +test/ vitest (mocked fetch + fake WebSocket + in-memory MCP transport)
180 +scripts/ live-smoke.mjs · record-demo.md
181 +```
182 +
183 +## Licence
184 +
185 +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.
added mcp/docs/README.md +5 −0
@@ -0,0 +1,5 @@
1 +# docs/
2 +
3 +`demo.gif` — the README hero animation. Not recorded yet: follow `../scripts/record-demo.md`
4 +(vhs tape included) and commit the result here, then copy it to
5 +`hfmarketdata/web/public/downloads/mcp-demo.gif` for the Integrations page.
added mcp/package-lock.json +2847 −0
Large diff (2,847 lines) is not loaded by default to keep the page fast.Load diff
added mcp/package.json +65 −0
Large diff (65 lines) is not loaded by default to keep the page fast.Load diff
added mcp/scripts/live-smoke.mjs +21 −0
Large diff (21 lines) is not loaded by default to keep the page fast.Load diff
added mcp/scripts/record-demo.md +54 −0
Large diff (54 lines) is not loaded by default to keep the page fast.Load diff
added mcp/src/client.ts +206 −0
Large diff (206 lines) is not loaded by default to keep the page fast.Load diff
added mcp/src/format.ts +136 −0
Large diff (136 lines) is not loaded by default to keep the page fast.Load diff
added mcp/src/index.ts +62 −0
Large diff (62 lines) is not loaded by default to keep the page fast.Load diff
added mcp/src/prompts.ts +96 −0
Large diff (96 lines) is not loaded by default to keep the page fast.Load diff
added mcp/src/resources.ts +61 −0
Large diff (61 lines) is not loaded by default to keep the page fast.Load diff
added mcp/src/server.ts +77 −0
Large diff (77 lines) is not loaded by default to keep the page fast.Load diff
added mcp/src/stream.ts +79 −0
Large diff (79 lines) is not loaded by default to keep the page fast.Load diff
added mcp/src/tools.ts +429 −0
Large diff (429 lines) is not loaded by default to keep the page fast.Load diff
added mcp/test/client.test.ts +74 −0
Large diff (74 lines) is not loaded by default to keep the page fast.Load diff
added mcp/test/format.test.ts +58 −0
Large diff (58 lines) is not loaded by default to keep the page fast.Load diff
added mcp/test/helpers.ts +88 −0
Large diff (88 lines) is not loaded by default to keep the page fast.Load diff
added mcp/test/server.test.ts +77 −0
Large diff (77 lines) is not loaded by default to keep the page fast.Load diff
added mcp/test/tools.test.ts +252 −0
Large diff (252 lines) is not loaded by default to keep the page fast.Load diff
added mcp/tsconfig.json +18 −0
Large diff (18 lines) is not loaded by default to keep the page fast.Load diff
added mcp/vitest.config.ts +8 −0
Large diff (9 lines) is not loaded by default to keep the page fast.Load diff
Menu

Theme