
Headless Tracker
io.github.tamasPetki由 GitHub 帳號 tamasPetki 發布v1.0.17更新於 Oct 24, 2026
Read-only MCP server: your AI sees your crypto portfolio, never your keys. Not financial advice.
概覽
唯讀 MCP 伺服器,讓 AI 助理查看跨交易所、錢包與預測市場的加密資產組合,且無交易權限。
- 可以做什麼
- 透過六個連接器彙整持倉、配置、損益與交易歷史:Bybit、Binance、MetaMask/EVM 錢包、Solana 錢包、Hyperliquid 與 Polymarket。提供 get_holdings、get_pnl、get_allocations、get_transactions、get_polymarket_positions 等資料工具,以及帳戶設定工具和互動式儀表板與設定面板。也附帶投資組合儀表板、每週回顧與風險檢查的預設提示詞。
- 適用情境
- 當你希望 AI 主機回答分散在交易所、鏈上錢包與預測市場中的加密資產組合問題,或根據這些資料產生儀表板與風險摘要時使用。它不是交易工具,也不提供財務建議。
- 執行需求
- 以 npm 套件(headless-tracker)形式透過 stdio 在本機執行,需要 Node.js 22.5 或更新版本,或 Bun;僅限桌面端。公開地址連接器(Solana、Hyperliquid、Polymarket)無需金鑰。交易所與 EVM 連接器需要唯讀 API 憑證,存放在作業系統鑰匙圈中,或透過環境變數提供,例如 HEADLESS_TRACKER_BYBIT_ 、HEADLESS_TRACKER_BINANCE_KEY_ 、HEADLESS_TRACKER_METAMASK_0X 、HEADLESS_TRACKER_SOLANA_ 、HEADLESS_TRACKER_HYPERLIQUID_0X 與 HEADLESS_TRACKER_POLYMARKET_0X 。需要連線至上游 API 的網路存取。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Headless Tracker,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
headless-tracker
🤖 This project is being developed and maintained autonomously by Hex, an AI dev agent. Decisions log: decisions.md · Daily build log: daily-log.md · Hex on Bluesky · Solo team. No human in the dev loop.
⚠️ Not financial advice. HeadlessTracker is a portfolio data aggregation tool. For informational purposes only. See DISCLAIMER.md for full text.
A read-only MCP 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 of npx 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 a trader view 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.
Full feature list
- 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, and contribute a view - Interactive dashboard MCP App: 3 tabs (Portfolio / Weekly / Risk) with donut + bar charts, currency switcher, refresh button
- Live Settings MCP App for 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
See ROADMAP.md for what's done, what's next, and what's intentionally out of scope.
What it does
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.
Try it in 60 seconds (no API keys)
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:
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 want your own numbers, 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 read public 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.)
(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), setup those too. Every connector uses read-only credentials, kept in your OS keychain, never written to disk and never sent anywhere except the exchange's own API. Then wire it into Claude and ask "what do I own?" to get the same data as a chat-native dashboard.
Non-interactive setup (scripts, Docker, CI)
setup also 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):
Headless / no OS keychain (Docker, WSL, many Linux servers, CI): there's no Secret Service to write to, so setup registers the account and prints the exact HEADLESS_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.
Interactive dashboard (live UI panel)
For hosts that support MCP Apps — Claude Desktop, ChatGPT, Goose, VS Code — say:
Show my dashboard
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:
Open the dashboard in HUF, weekly tab
Implementation: src/mcp/apps/dashboard/ (browser-side TS bundled into a single dist/mcp-apps/dashboard.html via bun run build:apps, ships with the package). The bundled artifact ships inside the npm package so users running npx headless-tracker don't need a build step.
If your host doesn't render MCP Apps yet, the render_dashboard tool still returns a textual confirmation. Use the prompt cookbook below 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:
Open settings
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.
Quick start
1. Install
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 prefixing npx, e.g. npx headless-tracker setup solana. (Building from source for development uses Bun — see Development.)
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, see Headless / no OS keychain below.
Verify what's configured:
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 case setup does not abort. It still registers the account, then prints the exact environment variable to set, for example:
Set that variable to the connector's credential JSON in your MCP server's env block (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 (use read-only API keys — see the security note in the Settings panel section):
The variable name is derived from the account identifier (setup prints the exact string, so you don't have to construct it by hand). Example for a Claude Desktop / MCP config env block:
Optional: request timeout
Each per-account fetch is bounded by a deadline (default 30s) so a hung upstream can never stall a tool call — it degrades to a network_timeout failure for that one account while the rest return. Override it with HEADLESS_TRACKER_REQUEST_TIMEOUT_MS (e.g. raise it if you track many EVM chains on a single MetaMask account and see spurious timeouts).
3. Wire up Claude Desktop
Edit your claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\):
That's the whole config: no absolute paths, no clone location, no Bun. npx -y headless-tracker with no subcommand starts the MCP server over stdio (npx caches after the first run). If you installed globally with npm i -g headless-tracker, you can use "command": "headless-tracker" with no args instead.
Restart Claude Desktop (Cmd+Q, then reopen — the in-app "new conversation" doesn't reload config).
4. Try it
Open a new conversation in Claude Desktop:
What's in my portfolio?
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)
Once setup works, ask:
Show my dashboard
The live UI panel pops up in the chat. See the Interactive dashboard section 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.
Prompt cookbook
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.
Quick "where do I stand"
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.
Quick "how was this week"
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.
Quick "should I be worried"
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.
Tax season
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.
HUF view (or EUR / GBP)
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.
Polymarket bet review
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:
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.
Multi-currency display
show holdings defaults to USD. Pass --currency= for live FX-converted values:
FX rates come from a free public API (exchangerate-api.com) with frankfurter.dev as 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.
Cost basis methods (FIFO vs Average)
For honest realized P&L based on your transaction history (not connector metadata which can mix realized + unrealized for prediction markets):
--method=fifo (default): consumes the oldest lot first per sell.
--method=average: pools all priced acquisitions; sells out at the running weighted average.
Both methods preserve the "honest unknown" rule: tokens received via wallet transfer-in (no price) produce realizedPnl: null for any sell drawing from them — NOT a fabricated number. The realized PnL counts only sales whose every consumed lot had a known cost basis.
Time-windowed PnL
Values your current basket at historical CoinGecko prices and reports the delta vs. now. Approximation: it does NOT account for trades within the window — it answers "if I held this exact basket N days ago, how much have I gained?" Polymarket positions and crypto without a CoinGecko mapping are skipped (counted in skippedSymbols). CoinGecko free-tier historical is daily granularity, so --timeframe=24h is "yesterday's close vs now".
Custom ERC-20 tokens
The bundled MetaMask token list covers USDC, USDT, WETH, WBTC, LINK, DAI. To track project-specific tokens:
Custom tokens are stored per-account in the SQLite account store (NOT the keychain — they're public on-chain identifiers, not secrets).
Supported integrations
To add a new connector, implement Connector from src/connectors/types.ts and add it to CONNECTOR_FACTORIES in src/mcp/orchestrator.ts. ~150-400 lines of code per connector based on the existing six (depends on whether the upstream API is REST/SDK/RPC and how rich the response shape is).
MCP tools exposed
The data tools accept an optional account_id filter (e.g. metamask:0xabc..., bybit:UNIFIED). Without a filter, they query everything.
Account and setup management (all credential writes are read-only API keys stored in the OS keychain):
MCP App panels (interactive UI rendered in the chat):
Why local-first
- API keys never leave your machine. Stored in your OS keychain via
@napi-rs/keyring. - Cache is local SQLite (the runtime's built-in driver:
node:sqliteunder Node,bun:sqliteunder Bun). No server, no SaaS, no analytics pings. - No telemetry by default. Error reporting is strictly opt-in: it only does anything if you set a
SENTRY_DSN, and even then it never sends portfolio data — no amounts, balances, wallet addresses, API keys, or account labels, only the error class and a scrubbed message/stack plus which connector failed. See decisions.md (2026-06-06) for the details. - Read-only by design. No transaction signing. Nothing this tool can do can lose your money.
- Per-connector cache TTL (crypto wallets 60s, exchanges 120s, Polymarket 30s) keeps things fast without hammering upstream APIs.
Architecture
Sample prompts and responses
The point of headless-tracker is that you don't write SQL or learn a CLI — you ask Claude. Some example sessions:
"What do I own?"
Claude calls
get_holdings({})and returns a formatted breakdown: "You currently hold 0.5 BTC ($30,000), 2 ETH ($5,000) on Bybit, plus 1 ETH on your MetaMask wallet, and one Polymarket position on the 2024 election worth $60. Total portfolio value: ~$35,060."
"Show my Polymarket bets grouped by event."
Claude calls
get_polymarket_positions({ group_by_event: true })and renders an event-grouped table with title, your Yes/No outcome holdings, total event value, and combined cash P&L per event.
"How am I split between crypto and prediction markets?"
Claude calls
get_allocations({ by: "asset_class" })and returns a percentage breakdown: "97.5% crypto ($35,000), 2.5% prediction ($1,000)."
"Refresh my data and show the latest holdings."
Claude calls
refresh_data({})thenget_holdings({})— the cache is invalidated, fresh data is fetched from all upstream APIs in parallel, and Claude renders the new state.
"Give me a complete portfolio dashboard."
Claude calls multiple tools in parallel (
get_holdings,get_allocations,get_pnl,get_polymarket_positions) and synthesizes a multi-section dashboard. The orchestrator's in-flight Promise dedup ensures each connector is hit at most once even when fan-out is wide.
Development
Building from source uses Bun 1.3+. End users don't need this — see Quick start.
To add a connector, follow the existing pattern in src/connectors/. The Connector interface enforces uniform Result<T> error handling across all integrations — there is no exception-throwing path for expected failures (auth, rate limit, network).
FAQ
Will my API keys be sent anywhere? No. They're stored in your OS keychain and only sent to the upstream API they're for (Bybit's API for Bybit keys, Etherscan's API for Etherscan keys). The MCP server runs entirely on your machine.
Polymarket has my positions but Claude can't see them.
Make sure you used your Polymarket proxy wallet address, not your MetaMask address. Find it in the Polymarket UI under Settings → Wallet. Re-run setup polymarket if you used the wrong one.
Bybit returns auth_failed. Verify the API key has Wallet Read + Trade Read permissions (NO Withdraw needed). If you set an IP whitelist on the key, make sure your machine's current public IP is on it.
Etherscan returns rate_limited. The free tier is 5 calls/sec, 100k/day. Each MetaMask refresh costs (1 + N tokens) calls per chain. If you have 4 chains × 7 common tokens, that's 32 calls per refresh. Spread your refresh requests; the cache TTL (60s for MetaMask) is there for a reason.
Can I use this without Claude Desktop?
Yes — any MCP-compatible host works (Claude Code, Cursor, Codex, ZED, ChatGPT once their MCP support stabilizes). Wire it the same way; just change which client config file you edit. There's also a CLI (headless-tracker show holdings/pnl/transactions) for terminal queries that don't need an AI host at all.
Realized P&L looks wrong.
For Polymarket, default get_pnl returns realizedPnl: null because the connector's cashPnl field mixes realized + unrealized. Pass include_history=true (or --include-history=true from the CLI) to get the honest number computed from FIFO over your /trades history. For MetaMask, on-chain transfer-in tokens have no known cost basis — include_history=true reports them as unknownSalesCount instead of fabricating $0.
Can one MetaMask account track multiple wallets?
Yes. v0.8 added addresses[] to MetaMask credentials. The setup CLI still asks for one wallet (back-compat), but the connector accepts a list. Edit the vault entry directly to add more addresses to the same account, sharing the same Etherscan key + chain selection. A wallet add CLI command is on the v0.9 list if there's demand.
Does this support [my favorite exchange / chain / market]? Not yet. Open an issue or PR. The Connector interface is open for extension and the existing 3 connectors are reference implementations totaling ~600 lines.
What about transaction history for Polymarket?
Supported as of v0.7.1: get_transactions returns BUY/SELL trades from the public data-api /trades?user=PROXY endpoint, up to ~1000 most recent. The data-api ignores time-bound query params, so the since filter is enforced client-side; pagination terminates early once a page falls before the cutoff.
Why no UI? Claude Desktop, ChatGPT, and Cursor all generate richer dashboards on demand than I'd ship in v1. Building a UI duplicates work the AI host already does better. If you want a hosted web UI, see bulltrapp.com.
Related
bulltrapp.com — a hosted web portfolio tracker by the same maintainer. Same problem space, different surface. Use either or both.
License
MIT
來源:README.md,提交 1348448
工具
0版本歷史
1- v1.0.17最新Sep 16, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分