A side-by-side look at the Scienter and HeadlessTracker MCP servers: transport, auth, tools, quality signals, and the config to install either one in Claude, Cursor, Windsurf or VS Code.
Verdict: choose Scienter for finance & fintech work over a hosted endpoint; choose HeadlessTracker for finance & fintech as a local process. You can also run both side by side in one mcpServers block.
solana_token, solana_deployer, wallet_score.get_holdings, refresh_data, get_pnl.Rows where the two servers differ are marked.
| Spec | S Scienter | |
|---|---|---|
| Category | Finance & Fintech | Finance & Fintech |
| Quality signal | 51/100 · Good | 64/100 · Good |
| Install command | Confirmed | Confirmed |
| Transport | Remote HTTP/SSE | Local subprocess (stdio) |
| Auth | Not declared | other |
| Pricing | Not declared | Free |
| Required env vars | None listed | None listed |
| Verified owner | Community listing | Community listing |
| GitHub stars | — | 6 |
| Directory activity | 0 views 0 installs 0 upvotes | 2 views 0 installs 0 upvotes |
| Tools | 8 | 15 |
| Full listing | View Scienter | View HeadlessTracker |
solana_tokenWho created a Solana token, and what that wallet's OTHER launches did. Takes a mint — the identifier a user actually has — and resolves the wallet that created it, which requires a census that watched Solana launches prospectively since 2026-09-08.
EVERY NUMBER IT RETURNS COUNTS LAUNCHES BY THAT WALLET, NOT EVENTS IN THIS TOKEN. Never write that the token had launches or has a death rate; the true statement is about its maker, and it is a reason to look harder at the token rather than a measurement of it.
Three outcomes, and they must not be collapsed:
- flagged: every settled launch by the creating wallet has died.
- not flagged: that wallet has a settled record and at least one launch survived. This is NOT a positive finding; it means the screen does not fire.
- no record: either the mint is not one the census publishes evidence for, or its wallet has no settled launch on record. This is the answer for most of the chain and it is NOT a clean result — it is a statement about coverage. Never report it as clear.
What the flag is worth, scored once on a later window: flagged launches were still listed a day later about 0.8% of the time against about 4.3% for the rest, non-overlapping 95% intervals.
It is a NEGATIVE screen. It does not identify anything worth buying, and over this same data every return bucket loses money after costs. Never restate it as a recommendation, a risk score, or a safety verdict.
Case is significant: a mis-cased mint is a different mint and will answer no record.
Call this when a user asks about a specific Solana token, who made it, or whether its creator has a history. Use solana_deployer instead when a deployer wallet is already known.
Args:
- mint (string): a base58 Solana mint address, exact case.solana_deployerWhat the wallet that deployed a Solana token has done before: how many of its launches settled, how many died, and whether every one of them did. Built from a census that has watched Solana launches prospectively since 2026-09-08, which is why it can answer a question about the deployer rather than about the token.
Three outcomes, and they must not be collapsed:
- flagged: every settled launch by this wallet has died.
- not flagged: a settled record exists and at least one launch survived. This is NOT a positive finding; it means the screen does not fire.
- no record: no settled launch by this wallet was ever recorded. This is the answer for most of the chain and it is NOT a clean record — it is a statement about coverage, never about conduct. Never report it as clear.
What the flag is worth, scored once on a later window: flagged launches were still listed a day later about 0.8% of the time against about 4.3% for the rest, non-overlapping 95% intervals.
It is a NEGATIVE screen. It does not identify anything worth buying, and over this same data every return bucket loses money after costs. Never restate it as a recommendation, a risk score, or a safety verdict.
Case is significant: Solana addresses are base58, and a mis-cased address is a different address that will answer no record.
Call this when a user asks who made a Solana token, whether a deployer has a history, or whether a launch's creator has ever had one survive.
Args:
- address (string): a base58 Solana wallet address, exact case.wallet_scoreScienter's forensic read on one blockchain address: public block-explorer facts (age, activity, balance, bounded-window flows), the published exchange-wallet label when the address is one, the clustering engine's entity when it answers, and itemised findings with citations.
This does NOT return a risk score. Scienter publishes no calibrated wallet-risk model and this tool will never emit a number to grade an address by. It returns evidence, and it reports explicitly when a check did not run -- an empty findings list with findings_checked=false means the engine did not answer and must not be read as a clean result.
Args:
- address (string): an EVM 0x address or a base58 Solana address.ofac_checkScreen one blockchain address against the U.S. Treasury OFAC SDN (Specially Designated Nationals) list: a direct match on the address itself, plus the engine's two-hop proximity walk over the address's real transfer history. Two separate claims, reported separately.
Three direct-match outcomes, and they must not be collapsed:
- a match: the address is published on the SDN list. The designated entity, its type, its sanctions programs and the chain OFAC filed it under are returned.
- no match: the whole published list was searched and the address is not on it. That is a real finding about one list on one date.
- not screened: the list could not be read, so nothing was checked. Never report this as clear; point the user at https://sanctionssearch.ofac.treas.gov/ instead.
Proximity: when proximity_checked is true the engine walked up to two hops of transfer history (its warehouse or a live read) looking for a listed address, and reports found or not, the hop count, the path and how far it went. Being N hops from a listed address is a fact about the graph, never a designation. When proximity_checked is false nothing was walked and the result says so.
Limits to repeat whenever the result is restated: SDN list only (not the EU, UN or UK/OFSI lists, and not OFAC's non-SDN lists such as SSI, NS-MBS and CAPTA); as published on a stated date; a walk bounded by hops and a node budget. A miss is not a sanctions clearance.
Call this when a user asks about sanctions exposure, designation, or OFAC status for an address, so the answer is grounded in what was actually searched.
Args:
- address (string): an EVM 0x address or a base58 Solana address.cex_attributionLook up whether an address is a labelled centralised-exchange wallet in Scienter's published exchange-wallet table, whether any address clustered with it is, and what the address's own exchange activity looks like: its deposits to labelled exchange wallets and any per-user deposit addresses inferred from its behaviour, read from real transfer history (activity.checked says whether that read ran).
The table is small (tens of addresses, from public block-explorer labels, activity-checked on chain) and a miss means no label is held -- not that the address is unaffiliated with an exchange.
Critical limit on what a hit means: an exchange hot or cold wallet is paid by millions of unrelated people. Two addresses that both funded the same exchange wallet are two customers of that exchange and nothing more. Each row carries a clusterable flag saying whether it can be used to link addresses at all; this must be repeated whenever the result is restated.
Args:
- address (string): an EVM 0x address or a base58 Solana address.bridge_traceTrace an address's cross-chain bridge transfers: which transfers touched which bridge contracts, toward which chains, for how much, with the transaction hash of each.
Scienter matches the address's transfer history (its own warehouse first, a live provider inside a budget after that) against a registry of bridge contracts across seven protocols. The registry is partial by construction, so an empty result means none of the tracked contracts were touched -- never that the funds did not bridge. The coverage and the caveat come back in the same payload and must be repeated whenever the result is restated.
Three outcomes: transfers found (listed with amounts and hashes); none of the registry's contracts touched (a bounded negative); not traced (the engine did not answer, and nothing may be inferred). `truncated: true` means the provider's row cap was hit and every count is a lower bound. EVM addresses only; a Solana address is out of scope, which is a different fact from clear.
Args:
- address (string): an EVM 0x address (a base58 Solana address answers out of scope).leaderboard_queryList the addresses Scienter's risk model has flagged most recently, highest score first, with each row's chain, score, model version, top evidence and timestamps.
Every row is a model output about a token contract's on-chain behaviour -- not a legal finding, not an audit, and not an allegation against any person. Widely held tokens are excluded by an allowlist and the suppressed count is reported, so this is a filtered view of the model's output.
An empty list is reported as one of three things and they must not be conflated: a quiet day (the scorer ran and nothing crossed the threshold; a finding), a flag table no scorer has ever written (a gap in coverage; ever_written is false), or an unconfirmed read. A producer that did not answer at all is a fourth, reported as not_deployed.
Args:
- limit (integer, optional): maximum rows to return, 1-100 (default 20).receipts_lookupSearch Scienter's published forensic receipts -- written reconstructions of specific on-chain incidents -- by address or free text, and get back titles, dates, subjects and public URLs a human can open.
There are only tens of receipts in total, each written for one investigation, so most addresses have none. No match is the normal case and is NOT evidence that nothing happened to or around the address. Unverified drafts are withheld from results and counted separately.
Args:
- address (string, optional): match receipts whose subject or deployer contains this.
- q (string, optional): free-text match over title, description and tags.
- limit (integer, optional): maximum receipts to return, 1-50 (default 20).
Passing neither address nor q lists the most recent published receipts.get_holdingsReturns current portfolio holdings across all connected accounts. Use this when the user asks: 'what do I own', 'show my portfolio', 'current positions', 'what's my balance', 'show my holdings', 'how much BTC do I have', or wants any snapshot of crypto/stock/prediction-market positions. For Polymarket-specific questions (which markets, outcomes, resolution or redeemable status), prefer get_polymarket_positions. For a ranked split / biggest positions, prefer get_allocations. Each holding includes: symbol, asset class (crypto / stock / prediction / cash), quantity, current price, USD value, and connector-specific metadata (e.g. chain for EVM, market title for Polymarket, accountType for Bybit). Inputs (all optional): - account_id: scope to one account, e.g. 'metamask:0xabc123...' or 'bybit:UNIFIED'. Omit to query ALL configured accounts. - asset_class: scope to one of 'crypto' / 'stock' / 'prediction' / 'cash'. 'prediction' = Polymarket conditional tokens; 'cash' = stablecoins (USDC/USDT) + fiat. Omit for all classes. - currency: 'USD' | 'EUR' | 'GBP' | 'HUF'. Default 'USD'. When set to anything other than USD, value/currentPrice/avgCost are converted via live FX rates (free API + fallback). The conversion source and fetchedAt are surfaced in `meta.fx`. Underlying connector data is unchanged — this is a display-layer convenience for users thinking in EUR/HUF/GBP. Results are cached per-connector (crypto wallets 60s, exchanges 120s, Polymarket 30s). Use 'refresh_data' tool first if the user explicitly asks for fresh / latest data. Returns position data only. Not financial advice.refresh_dataInvalidates the PORTFOLIO TRACKER cache (Bybit/Binance/MetaMask/Polymarket/Solana/Hyperliquid holdings + transactions) and forces a fresh fetch from upstream APIs on the next call. Use this when the user asks: 'refresh my portfolio', 'update my holdings', 'get the latest portfolio prices', 'fetch fresh portfolio data', 'check current crypto prices', 'my balances look stale', 'force an update', 'my data is outdated', or implies real-time freshness is required FOR THE TRACKER. Optionally scope to a single connector (bybit, binance, metamask, polymarket, solana, hyperliquid). Without a scope, invalidates everything tracker-related. DO NOT call this tool when the user means: refreshing a webpage, refreshing an OAuth token, refreshing browser cache, refreshing data from a non-tracker MCP server. It only invalidates the headless-tracker SQLite cache. After calling this, follow up with get_holdings or another data tool to actually fetch the fresh data — refresh_data only marks the cache as stale, it does not trigger fetches on its own.get_pnlReturns aggregate profit/loss across all configured accounts. Use this when the user asks: 'how am I doing', 'what's my P&L', 'am I up or down', 'show profit', 'show losses', or wants any portfolio performance summary. Returned fields per account and across the total: - currentValue (USD) — current portfolio value - costBasis (USD) — sum of avgCost * quantity (where the connector tracks it) - unrealizedPnl (USD) — currentValue - costBasis (for positions still held) - realizedPnl (USD) — already-closed P&L from connector metadata - notes — caveats per connector (e.g. MetaMask doesn't track cost basis) Inputs (optional): - account_id: scope to one account. - timeframe: '24h' | '7d' | '30d' | 'ytd' | 'all'. When set to anything other than 'all', the result includes a `windowDelta` block computed from CoinGecko historical prices. APPROXIMATION CAVEAT: it values your CURRENT basket at historical prices vs current prices — it does NOT account for trades within the window. Communicate this honestly to the user. Polymarket positions and tokens without a CoinGecko mapping are skipped (counted in `skippedSymbols`). CoinGecko free-tier historical is daily granularity, so '24h' = 'yesterday's close'. - include_history (boolean, default false): also pulls transactions and runs a cost-basis ledger over them, returning `realizedFromHistory` per account + total. Costs an extra round-trip per account but unlocks honest realized PnL on tokens born on-chain (LP rewards, swaps, native airdrops). Tokens that arrived via wallet transfer-in (no price) get `unknownSalesCount` not inflated knownRealized — explicit honesty about what cost basis we know. POLYMARKET-SPECIFIC: when include_history=true, the Polymarket account's realizedPnl is replaced by the cost-basis-from-/trades number. Default mode leaves Polymarket realizedPnl null because the connector's cashPnl mixes realized + unrealized — set include_history=true to get the real realized number. - method ('fifo' | 'average', default 'fifo'): cost basis method used when include_history=true. FIFO consumes oldest lot first per sell; Average Cost pools all priced acquisitions and sells out at the running average. If the user mentions 'average cost' / 'avg cost' / 'weighted', use 'average'. Both methods preserve the 'honest unknown' rule: any sell drawing from an unpriced deposit/transfer returns realizedPnl=null, NOT a fabricated number. Has NO effect when include_history=false. - currency ('USD' | 'EUR' | 'GBP' | 'HUF', default 'USD'): when set to anything other than USD, ALL numeric fields (currentValue, costBasis, realizedPnl, unrealizedPnl, windowDelta numbers, realizedFromHistory.knownRealized) are converted via live FX rates. The fx.source + fetchedAt are surfaced in `meta.fx`. Use this for currency-consistent rendering when the user asked their dashboard to be in HUF/EUR/GBP — otherwise per-tab currencies will mismatch. Returns position data only. Not financial advice.get_polymarket_positionsReturns Polymarket prediction-market positions, grouped by event when possible. Use this when the user asks about their Polymarket bets specifically: 'show my Polymarket positions', 'how am I doing on Polymarket', 'what bets do I have', 'show my prediction market positions', 'election bets', 'sports bets', etc. For general portfolio queries that mention Polymarket alongside crypto/stocks, prefer get_holdings (with optional asset_class='prediction' filter). Each position includes: - market title (human-readable question, e.g. 'Will X win the 2024 election?') - outcome ('Yes' / 'No' / specific candidate name) - quantity (conditional tokens held, each worth 0-1 USDC) - currentPrice (0-1, market's current implied probability) - currentValue (USD), avgCost (USD per token), cashPnl (realized + unrealized) - redeemable (true if market resolved and you can claim payout) - mergeable (true if you can merge Yes+No tokens for guaranteed USDC) - endDate (when the market resolves) Inputs (optional): - account_id: scope to one Polymarket account (if you have multiple). - group_by_event: 'true' (default) groups Yes+No outcomes for the same market; 'false' returns one row per asset. - resolved_only: 'true' returns only redeemable positions (markets that have resolved). Default 'false' returns everything. Returns position data only. Not financial advice.get_transactionsReturns transaction history (trades, deposits, withdrawals, fees, ERC-20 token transfers) across configured accounts. Use this when the user asks: 'what trades did I make', 'show my transactions', 'transaction history', 'recent buys', 'recent sells', 'show my deposits', 'when did I buy X', 'what did I do this week', etc. Each transaction includes: - type: trade / buy / sell / deposit / withdraw / fee / interest / reward / transfer / resolve - symbol, quantity, price (per-unit at time of transaction) - fee + feeCurrency - timestamp (ISO 8601) - metadata (connector-specific: chain, hash, market, etc.) Inputs (optional): - account_id: scope to one account. - since: shorthand ('24h', '7d', '30d', '90d') OR epoch ms (e.g. 1700000000000). Default: ~last 50 transactions per account regardless of date. Coverage caveats (V0): - Bybit: full transaction log - MetaMask: native chain transfers + ERC-20 token transfers (USDC, USDT, etc.) - Polymarket: BUY/SELL trades from the /trades endpoint (up to ~1000 most recent). Returns transaction data only. Not financial advice.get_allocationsReturns portfolio allocation breakdown — current USD value grouped by a chosen dimension. Use this when the user asks: 'how is my portfolio split', 'allocation breakdown', 'what % is in crypto', 'chain breakdown', 'show my biggest position', 'concentration'. Groups available: - 'asset_class' (default): crypto / stock / prediction / cash (cash = stablecoins like USDC/USDT + fiat) - 'connector': bybit / metamask / polymarket - 'account': one row per configured account - 'chain': EVM chain (Ethereum / Polygon / etc.) — only meaningful for MetaMask holdings - 'symbol': BTC / ETH / individual market — best for top-N concentration analysis Each group row includes: label, currentValue (USD), percentOfTotal, holdingCount. Sorted descending by currentValue. Inputs: - by: which dimension to group by (see above). Default 'asset_class'. - top: limit to top N rows (e.g. top: 10 for biggest positions). Default no limit. Returns position data only. Not financial advice.list_accountsLists configured PORTFOLIO TRACKER accounts (Bybit exchange / Binance exchange / MetaMask wallets / Polymarket / Solana wallets / Hyperliquid) without exposing credentials. Use when the user asks: 'what tracker accounts are configured', 'show my portfolio accounts', 'list my exchange connections', 'which crypto exchanges are linked', 'which wallets am I tracking', 'what addresses am I tracking'. Returns: id, connectorId (bybit | binance | metamask | polymarket | solana | hyperliquid), label, createdAt, and connector-specific public metadata (e.g. chainIds and addresses for MetaMask, accountType for Bybit, address for Solana/Hyperliquid, key fingerprint for Binance). Credentials are NEVER returned — they stay in the OS keychain. DO NOT call this tool when the user means: email accounts, social media accounts, GitHub accounts, cloud accounts, OS user accounts, or any 'accounts' from a different domain or MCP server. It's specifically the headless-tracker exchange/wallet connections.setup_connectorCreates a new account by writing READ-ONLY credentials to the OS keychain. Use when the user asks: 'add a Bybit account', 'connect Binance', 'connect my MetaMask wallet', 'set up Polymarket', 'connect my Solana wallet', 'track my Hyperliquid', 'add my Hyperliquid wallet', 'add new exchange'. BEHAVIOR CONTRACT FOR YOU (the LLM): - After this tool succeeds, confirm ONLY the account label and account_id back to the user. - NEVER echo, log, paraphrase, or repeat the credential values (apiKey, apiSecret, etherscanApiKey) in your response. - If the user pastes credentials inline in chat, suggest they use the Settings UI (render_settings tool) form instead — the form keeps secrets out of the conversation transcript. Credentials are validated against the upstream API before they're persisted; if validation fails, nothing is written. Storage: OS keychain (macOS Keychain / Linux Secret Service / Windows Credential Vault) via @napi-rs/keyring. Same path as the CLI setup flow. All six connectors use READ-ONLY credentials by design (Bybit 'Read' only, Binance 'Enable Reading' only, Etherscan is a public-data rate-limit token, Polymarket proxy wallet is already public, Solana/Hyperliquid addresses are public on-chain identifiers — Hyperliquid needs no key or signature at all). Inputs (one of bybit / binance / metamask / polymarket / solana / hyperliquid required): - connector: 'bybit' | 'binance' | 'metamask' | 'polymarket' | 'solana' | 'hyperliquid' - bybit: { apiKey, apiSecret, accountType: 'UNIFIED'|'CONTRACT'|'SPOT'|'FUND' (primary, also the account ID), accountTypes?: array of additional types to fan out across (e.g. ['FUND'] alongside UNIFIED so funding-wallet balances are tracked too) } - binance: { apiKey, apiSecret, includeFutures (optional bool, default false), recvWindow (optional ms) } - metamask: { address, etherscanApiKey, chainIds (number[]), trackCommonTokens (bool), hasEtherscanPro (bool) } - polymarket: { proxyWallet (0x...), sizeThreshold (default 0.01) } - solana: { address (base58), rpcUrl (optional premium RPC), dustThresholdUsd (optional, default 0.5) } - hyperliquid: { address (0x... EVM address you trade from), dustThresholdUsd (optional, default 0.5). No API key — public address only. Tracks perp account equity + open positions + spot balances. }add_wallet_addressAdds an additional wallet address to an existing MetaMask or Solana account. Use when the user asks: 'add another wallet', 'track a second address', 'add MetaMask address', 'add Solana address'. The new address shares the parent account's settings (Etherscan key + chains for MetaMask; RPC URL for Solana). Wallet addresses are public on-chain identifiers — NO new secrets are stored. Just updates the keychain entry's `addresses[]` field. Inputs: - account_id: id of the existing account (e.g. 'metamask:0xabc...' or 'solana:Abc...') - address: EVM 0x-hex address (40 hex chars) for MetaMask accounts, or base58 (32-44 chars) for Solana accountsremove_accountDeletes an account from the AccountStore AND its credentials from the OS keychain. ONE-WAY operation. The Settings UI requires explicit user confirmation before calling this. Use when the user asks: 'remove the Bybit account', 'disconnect Polymarket', 'forget that wallet'. Inputs: - account_id: id of the account to remove (e.g. 'bybit:UNIFIED', 'metamask:0xabc...'). Returns: ok, removedAccountId; or error if the account was not found.add_custom_tokenAdds a project-specific ERC-20 token to a MetaMask account's tracked-tokens list. The bundled common tokens (USDC, USDT, WETH, WBTC, LINK, DAI) are tracked by default; this is for additional tokens like project / governance tokens. Use when the user asks: 'track ARB token', 'add UNI to my wallet', 'monitor a custom ERC-20'. Token data is PUBLIC on-chain (contract + symbol + decimals) — NO secrets, NO keychain involved. Inputs: - account_id: target MetaMask account (e.g. 'metamask:0xabc...') - chain_id: numeric (1=Ethereum, 137=Polygon, 56=BSC, 8453=Base, 42161=Arbitrum, 10=Optimism) - contract: 0x-prefixed contract address (40 hex) - symbol: 1-20 chars - decimals: 0-36 integerremove_custom_tokenRemoves a custom ERC-20 token from a MetaMask account's tracked-tokens list. Public on-chain data, no keychain involvement. Use when the user asks: 'stop tracking ARB', 'remove that token from MetaMask', 'untrack a project token'. Inputs: - account_id: target MetaMask account (e.g. 'metamask:0xabc...') - chain_id: numeric (1=Ethereum, 137=Polygon, 56=BSC, 8453=Base, 42161=Arbitrum, 10=Optimism) - contract: 0x-prefixed contract address (40 hex) Returns ok or a not_found error if the token wasn't tracked under that account+chain.Paste either block (or both) into your client config, e.g. claude_desktop_config.json or ~/.cursor/mcp.json. We only show a config when the install command is confirmed.
{
"mcpServers": {
"scienter": {
"url": "https://scienter.xyz/mcp"
}
}
}
{
"mcpServers": {
"tamaspetki-headlesstracker": {
"command": "npx",
"args": [
"-y",
"headless-tracker"
]
}
}
}