Headless Tracker

by tamaspetki

Not rated
GitHub

About

Stop building portfolio dashboards — describe the view you want and let Claude render it. Read-only MCP server for Bybit, Binance, EVM wallets, Solana, and Polymarket.

Details

Author
tamaspetki
Categories
Finance, Other

Non-interactive setup (scripts, Docker, CI)

setupalso runs without prompts — pass flags, and keep any secret in an environment variable (never on the command line, so it stays out of your shell history):

# public-address connectors: everything via flags, zero secrets headless-tracker setup solana --address=<base58> --dust=0.5 headless-tracker setup hyperliquid --address=0x... # perp + spot, no key headless-tracker setup polymarket --proxy-wallet=0x... # connectors with a secret: non-secret config via flags, secret via env HT_SETUP_ETHERSCAN_KEY=… headless-tracker setup metamask --address=0x... --chains=1,137 HT_SETUP_API_KEY=… HT_SETUP_API_SECRET=… headless-tracker setup bybit --account-type=UNIFIED --also=FUND

Headless / no OS keychain(Docker, WSL, many Linux servers, CI): there's no Secret Service to write to, sosetupregisters the account and prints the exactHEADLESS_TRACKER_<CONNECTOR>_<ACCOUNT>env var to set with a JSON credential object — e.g.HEADLESS_TRACKER_SOLANA_<ADDR>='{"address":"…","dustThresholdUsd":0.5}'. Set it in your MCP server's environment and the data tools read credentials from there. Nothing is ever written to disk.

For hosts that support](#3-wire-up-claude-desktop)MCP Apps— Claude Desktop, ChatGPT, Goose, VS Code — say:

The host renders a sandboxed iframe in the chat panel with three live tabs:

- Portfolio— total value KPIs, top positions table, allocation-by-symbol donut (top 7 + "Other" tail), warnings + failures
- Weekly— 7-day window delta KPIs, recent trades table, skipped-symbols disclosure (with reasons)
- Risk— concentration audit (single-position, venue, stablecoin reserve, prediction-market overweight) scored PASS / WARN / ALERT, by-venue donut

Plus a currency switcher (USD / EUR / GBP / HUF) and a refresh button. The iframe makes its own follow-up tool calls as the user clicks tabs — no extra prompting needed once it's open. Optional args:

Implementation:src/mcp/apps/dashboard/(browser-side TS bundled into a singledist/mcp-apps/dashboard.htmlviabun run build:apps, ships with the package). The bundled artifact ships inside the npm package so users runningnpx headless-trackerdon't need a build step.

If your host doesn't render MCP Apps yet, therender_dashboardtool still returns a textual confirmation. Use theprompt cookbookbelow as a fallback — same workflows, same data, just no live UI panel.

Settings panel (live UI for setup + admin)

For setup that doesn't drop you into a terminal, ask:

The Settings MCP App opens with four tabs:

- Accounts— list of configured accounts with a Remove button (one-way confirm dialog; deletes from both the OS keychain and the registry).
- Add Account— forms for Bybit / Binance / MetaMask / Solana / Hyperliquid / Polymarket. Each form validates against the upstream API before persisting credentials. Explicit security disclosure at the top: credentials submitted via the form transit Claude Desktop's process en route to the keychain.All six connectors use READ-ONLY credentials by design(Bybit "Read" only, no Withdraw; Binance "Enable Reading" only, no Trade or Withdraw; Etherscan is a public-data rate-limit token; Polymarket proxy wallet is already public; Solana and Hyperliquid addresses are public on-chain identifiers — Hyperliquid needs no key or signature at all). Worst-case leak = portfolio-read, never fund movement. For zero-trust, the CLI flow (bun run setup <connector>) stays available.
- Wallets— add an additional wallet address to an existing MetaMask OR Solana account (multi-wallet under one MCP account, sharing the same Etherscan key/chain selection or RPC URL).
- Custom Tokens— list / add / remove ERC-20 tokens per chain. Token data is public on-chain; no keychain involvement.

Either path (CLI or Settings UI) writes to the same~/.headless-tracker/cache.db+ OS keychain, so accounts created via either show up immediately in the dashboard and CLI.

No clone, no build step, no Bun required. The package runs under plain Node (≥ 22.5) or Bun. Install it globally:

Or run any command without installing by prefixingnpx, e.g.npx headless-tracker setup solana. (Building from source for development uses Bun — see[Development.)

🤖This project is being developed and maintained autonomously byHex, an AI dev agent. Decisions log:decisions.md· Daily build log:daily-log.md· Hex onBluesky· Solo team. No human in the dev loop.

⚠️Not financial advice.HeadlessTracker is a portfolio data aggregation tool. For informational purposes only. SeeDISCLAIMER.mdfor full text.

Aread-onlyMCP server that lets your AI host (Claude Desktop, Claude Code, Cursor, ChatGPT) see your whole crypto portfolio across exchanges, on-chain wallets, and prediction markets — without ever giving it your API keys, and with no ability to trade or move funds. It reads the numbers; it can't touch the money.

↑ What your AI host renders from HeadlessTracker's data — one question, six venues, one view. The server returns the numbers; the host draws the picture.(Sample data; the visual is what a host renders on top of the tool output.)

↑ And the raw input: real output ofnpx headless-tracker demo— six venues, no accounts, no API keys. Then ask your AI host about it.

Same data, a different question.Ask “how are my positions doing?” and your AI renders atraderview instead. There is no single dashboard — the host draws the one you ask for.(Templates coming: contribute a view, not a connector.)

The thesis: AI hosts (Claude Desktop, Claude Code, Cursor, ChatGPT) generate dashboards on demand from structured data. Building yet another tracker UI is wasted work in 2026 — there is no single UI to build, your AI renders whatever view you ask for. Build the data layer; let the AI host be the renderer.

Status:Production-ready and live on npm (version badge above). Six connectors (Bybit, Binance, MetaMask/EVM, Solana, Hyperliquid, Polymarket), 15 MCP tools, an interactive multi-tab dashboard panel, a CLI for terminal queries, and a 428-test suite. Runs under plain Node (npx headless-tracker) or Bun, working end-to-end with Claude Desktop.

- 6 connectors:Bybit, Binance Spot+Futures, MetaMask multi-chain + multi-wallet, Solana multi-wallet, Hyperliquid (perp + spot, address-only), Polymarket
- 15 MCP tools:6 data + 7 account/token management + 2 MCP App panels
- 3 MCP prompts (views):portfolio-dashboard,weekly-review,risk-check— see
TEMPLATES.md, andcontribute a view
- Interactive dashboard MCP App:3 tabs (Portfolio / Weekly / Risk) with donut + bar charts, currency switcher, refresh button
- Live Settings MCP Appfor setup and admin
- CLI portfolio queries:show holdings / pnl / transactions(no Claude required)
- Custom ERC-20 token lists; FIFO + Average Cost on transaction history
- Multi-currency display(USD/EUR/GBP/HUF); CoinGecko + Jupiter spot and historical prices
- Time-windowed PnL(--timeframe=24h|7d|30d|ytd)
- 428-test suite; runs under plain Node or Bun
- Read-only & local-first:no orders/withdrawals/transfers; 4 of 6 connectors need only a public address; secrets live in your OS keychain and never enter the model's context — see
SECURITY.md

SeeROADMAP.mdfor what's done, what's next, and what's intentionally out of scope.

Connects to your accounts (read-only), normalizes everything into a single schema, exposes it as MCP tools. Then you ask Claude (or any MCP host):

- "What do I own?"
- "How is my portfolio split between crypto and prediction markets?"
- "Show my Polymarket positions grouped by event."
- "Refresh Bybit and tell me my BTC P&L."

The AI host generates the chart, the table, the breakdown. You don't build a UI.

The zero-setup version — one command, no accounts, no keys, not even an address.See a full sample portfolio (five venues; crypto + cash + prediction markets) rendered exactly as your AI host receives it:

account symbol class qty value price ────────────────────── ─────────────────── ────────── ──────── ─────── ─────── bybit:UNIFIED BTC crypto 0.420000 $25704 $61200 binance:spot SOL crypto 95.0000 $14440 $152.00 metamask:0xd8d2…f1a3 WBTC crypto 0.150000 $9150 $61000 solana:7vfC…Wd9k JUP crypto 1800.00 $1656 $0.9200 polymarket:0x9c1a…7b20 RATE-CUT-2026 (YES) prediction 1500.00 $930.00 $0.6200 … Total: $104126 (15 positions across 5 venues) Allocation by asset class: crypto $88024 84.5% ████████████████████ cash $14900 14.3% ███ prediction $1202 1.2% █

It also prints the plain-English questions you'd ask Claude ("what do I own across everything?", "how is it split?") mapped to the MCP tool that answers each. When you wantyour ownnumbers, it's the same loop with a real address or read-only key:

You shouldn't have to hand a new tool your exchange keys just to find out whether it's any good. Solana, Hyperliquid, and Polymarket readpublic on-chain addresses, so you can point HeadlessTracker at any wallet you can see (your own included) with zero credentials. (Hyperliquid is fully keyless — perp positions, account equity, and spot balances all read from just the address you trade from.)

# install (or prefix any command with npx) npm install -g headless-tracker # add a public Solana wallet: no API key, just the address headless-tracker setup solana # Solana address (base58): <paste any public address> # (press ENTER through the optional RPC + dust prompts) # print the holdings right in your terminal, no Claude required headless-tracker show holdings
account symbol class qty value price ───────────────── ────── ────── ──────── ─────── ──────── solana:7Xk2…q9Fa SOL crypto 12.4081 $2604 $209.88 solana:7Xk2…q9Fa USDC crypto 540.0000 $540.00 $1.00 solana:7Xk2…q9Fa JUP crypto 1200.00 $612.00 $0.5100 Total: $3756 (3 positions across 1 accounts)

(Example output; the account id is shortened here for width. Your numbers come from the live chain.)

That is the whole loop: install, point at a public address, see normalized holdings. When you want your private accounts (Bybit, Binance),setupthose too. Every connector usesread-onlycredentials, kept in your OS keychain, never written to disk and never sent anywhere except the exchange's own API. Thenwire it into Claudeand ask"what do I own?"to get the same data as a chat-native dashboard.

Non-interactive setup (scripts, Docker, CI)

setupalso runs without prompts — pass flags, and keep any secret in an environment variable (never on the command line, so it stays out of your shell history):

# public-address connectors: everything via flags, zero secrets headless-tracker setup solana --address=<base58> --dust=0.5 headless-tracker setup hyperliquid --address=0x... # perp + spot, no key headless-tracker setup polymarket --proxy-wallet=0x... # connectors with a secret: non-secret config via flags, secret via env HT_SETUP_ETHERSCAN_KEY=… headless-tracker setup metamask --address=0x... --chains=1,137 HT_SETUP_API_KEY=… HT_SETUP_API_SECRET=… headless-tracker setup bybit --account-type=UNIFIED --also=FUND

Headless / no OS keychain(Docker, WSL, many Linux servers, CI): there's no Secret Service to write to, sosetupregisters the account and prints the exactHEADLESS_TRACKER_<CONNECTOR>_<ACCOUNT>env var to set with a JSON credential object — e.g.HEADLESS_TRACKER_SOLANA_<ADDR>='{"address":"…","dustThresholdUsd":0.5}'. Set it in your MCP server's environment and the data tools read credentials from there. Nothing is ever written to disk.

For hosts that supportMCP Apps— Claude Desktop, ChatGPT, Goose, VS Code — say:

The host renders a sandboxed iframe in the chat panel with three live tabs:

- Portfolio— total value KPIs, top positions table, allocation-by-symbol donut (top 7 + "Other" tail), warnings + failures
- Weekly— 7-day window delta KPIs, recent trades table, skipped-symbols disclosure (with reasons)
- Risk— concentration audit (single-position, venue, stablecoin reserve, prediction-market overweight) scored PASS / WARN / ALERT, by-venue donut

Plus a currency switcher (USD / EUR / GBP / HUF) and a refresh button. The iframe makes its own follow-up tool calls as the user clicks tabs — no extra prompting needed once it's open. Optional args:

Implementation:src/mcp/apps/dashboard/(browser-side TS bundled into a singledist/mcp-apps/dashboard.htmlviabun run build:apps, ships with the package). The bundled artifact ships inside the npm package so users runningnpx headless-trackerdon't need a build step.

If your host doesn't render MCP Apps yet, therender_dashboardtool still returns a textual confirmation. Use theprompt cookbookbelow as a fallback — same workflows, same data, just no live UI panel.

Settings panel (live UI for setup + admin)

For setup that doesn't drop you into a terminal, ask:

The Settings MCP App opens with four tabs:

- Accounts— list of configured accounts with a Remove button (one-way confirm dialog; deletes from both the OS keychain and the registry).
- Add Account— forms for Bybit / Binance / MetaMask / Solana / Hyperliquid / Polymarket. Each form validates against the upstream API before persisting credentials. Explicit security disclosure at the top: credentials submitted via the form transit Claude Desktop's process en route to the keychain.All six connectors use READ-ONLY credentials by design(Bybit "Read" only, no Withdraw; Binance "Enable Reading" only, no Trade or Withdraw; Etherscan is a public-data rate-limit token; Polymarket proxy wallet is already public; Solana and Hyperliquid addresses are public on-chain identifiers — Hyperliquid needs no key or signature at all). Worst-case leak = portfolio-read, never fund movement. For zero-trust, the CLI flow (bun run setup <connector>) stays available.
- Wallets— add an additional wallet address to an existing MetaMask OR Solana account (multi-wallet under one MCP account, sharing the same Etherscan key/chain selection or RPC URL).
- Custom Tokens— list / add / remove ERC-20 tokens per chain. Token data is public on-chain; no keychain involvement.

Either path (CLI or Settings UI) writes to the same~/.headless-tracker/cache.db+ OS keychain, so accounts created via either show up immediately in the dashboard and CLI.

No clone, no build step, no Bun required. The package runs under plain Node (≥ 22.5) or Bun. Install it globally:

Or run any command without installing by prefixingnpx, e.g.npx headless-tracker setup solana. (Building from source for development uses Bun — seeDevelopment.)

2. Configure your accounts (interactive)

Run setup for each integration you want. Each prompts for credentials, validates them, and stores them in your OS keychain (macOS Keychain, Linux Secret Service, Windows Credential Vault). On a headless box with no keychain, seeHeadless / no OS keychainbelow.

headless-tracker setup bybit headless-tracker setup binance headless-tracker setup metamask headless-tracker setup solana headless-tracker setup polymarket

Headless / no OS keychain (Docker, WSL, servers, CI)

The OS keychain needs a running secret service (Secret Service / D-Bus on Linux, Keychain on macOS, Credential Vault on Windows). Plenty of real environments don't have one: a Docker container, WSL, a bare Linux server, a CI job. There, the keychain write fails.

In that casesetupdoesnotabort. It still registers the account, then prints the exact environment variable to set, for example:

⚠ OS keychain unavailable, so credentials were NOT stored (...). The account is registered. ... set the HEADLESS_TRACKER_SOLANA_<ADDR> environment variable to a JSON object in your MCP server's env, then restart.

Set that variable to the connector's credential JSON in your MCP server'senvblock (or your shell), then restart. The env var always takes precedence over the keychain, so this also works as an explicit override. Per-connector JSON shapes (useread-onlyAPI keys — see the security note in the Settings panel section):

The variable name is derived from the account identifier (setupprints the exact string, so you don't have to construct it by hand). Example for a Claude Desktop / MCP configenvblock:

"env": { "HEADLESS_TRACKER_SOLANA_<ADDR>": "{\"address\":\"<base58 address>\"}" }

Each per-account fetch is bounded by a deadline (default 30s) so a hung upstream can never stall a tool call — it degrades to anetwork_timeoutfailure for that one account while the rest return. Override it withHEADLESS_TRACKER_REQUEST_TIMEOUT_MS(e.g. raise it if you track many EVM chains on a single MetaMask account and see spurious timeouts).

Edit yourclaude_desktop_config.json(macOS:~/Library/Application Support/Claude/, Windows:%APPDATA%\Claude\):

{ "mcpServers": { "headless-tracker": { "command": "npx", "args": ["-y", "headless-tracker"] } } }

That's the whole config: no absolute paths, no clone location, no Bun.npx -y headless-trackerwith no subcommand starts the MCP server over stdio (npx caches after the first run). If you installed globally withnpm i -g headless-tracker, you can use"command": "headless-tracker"with noargsinstead.

Restart Claude Desktop (Cmd+Q, then reopen — the in-app "new conversation" doesn't reload config).

Open a new conversation in Claude Desktop:

How is my portfolio split between crypto and prediction markets?

Show my Polymarket positions sorted by current value.

If Claude doesn't see the tools, check~/Library/Logs/Claude/mcp-server-headless-tracker.log.

5. Use the interactive dashboard (MCP App)

The live UI panel pops up in the chat. See theInteractive dashboardsection above for what's in each tab and how to pass args.

6. Use the preset prompts (one-click dashboards)

The MCP server ships three prompt templates. They show up in Claude Desktop's prompt picker (the/or attachment menu, depending on version) and in Claude Code as slash commands. Each one steers Claude through a specific multi-tool workflow:

You can also paste any of these prompts directly — they're plain text. See the cookbook below.

Copy-paste these into any MCP-aware client. Each one expects the headless-tracker MCP server to be configured. None of them require new code on the server side.

Build me a complete portfolio dashboard. Call get_holdings, get_allocations (by asset_class and by symbol), get_pnl, and get_polymarket_positions in parallel and synthesize a single dashboard artifact. Show top 10 positions, asset-class breakdown, total PnL. Be honest about NULL fields — don't fabricate.

Give me a 7-day review. Call get_pnl with timeframe=7d, get_holdings, and get_transactions with since=7d. Surface windowDelta with the approximation caveat ("current basket at historical prices, not trades within the window"), list the trades by exchange, and end with one short observation about what drove the change.

Risk check my portfolio. Call get_holdings and get_allocations (by symbol, by asset_class, by connector). Score each: single-position concentration (ALERT > 40%), venue concentration (ALERT > 70%), stablecoin reserve (WARN < 5%, ALERT = 0%), prediction-market overweight (WARN > 15%). Output as a markdown table.

I need to do my taxes. Call get_transactions for the past year (since=365d). Then call get_pnl with include_history=true and method=fifo. Group realized PnL by symbol and by month. Flag any sales with unknown cost basis (deposits / transfers without price) — those are honest gaps I'll have to research separately.

Show my portfolio in Hungarian forint. Call get_holdings with currency=HUF. Sort by value descending. Sum the total in HUF and tell me whether the FX source was the live API or the static fallback.

Walk me through my Polymarket positions. Call get_polymarket_positions with group_by_event=true. Then call get_pnl with include_history=true to get realized PnL via FIFO over /trades. For each event, show: title, my outcome holdings, current value, realized PnL so far, and end date. Flag any redeemable positions I should claim.

Quick portfolio queries from the CLI (no Claude required)

For the 3-second "what's in my portfolio?" question without opening Claude Desktop:

headless-tracker show holdings headless-tracker show pnl headless-tracker show transactions --since=7d

Each prints a text table. Filters work:show holdings --account-id=bybit:UNIFIED,show holdings --asset-class=crypto,show transactions --since=24h --account-id=metamask:0xabc.

show holdingsdefaults to USD. Pass--currency=for live FX-converted values:

headless-tracker show holdings --currency=HUF headless-tracker show holdings --currency=EUR

FX rates come from a free public API (exchangerate-api.com) withfrankfurter.devas fallback, plus a static fallback if both fail (which surfaces as a warning so you know the displayed numbers may be a few percent stale). Supported:USD,EUR,GBP,HUF.

For honest realized P&L based on your transaction history (not connector metadata which can mix realized + unrealized for prediction markets):

headless-tracker show pnl --include-history=true headless-tracker show pnl --include-history=true --method=average

--method=fifo(default): consumes the oldest lot first per sell.--method=average: pools all priced acquisitions; sells out at the running weighted average.

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.