mcp-server-madeonsol 1.22.0 → 1.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,6 +13,8 @@ MCP server for [MadeOnSol](https://madeonsol.com) Solana KOL intelligence API. U
13
13
 
14
14
  > Real-time Solana trading intelligence: track 1,069 KOL wallets with <3s latency, score 23,000+ Pump.fun deployers, surface deshred deploy signals **~500ms before on-chain confirmation**, detect multi-KOL coordination, surface bundle-cohort holdings (which same-slot wallets still hold a token's supply), verify any wallet's CURRENT on-chain holdings straight from its token accounts, and stream every DEX trade across 9+ programs. Free tier: 200 requests/day, every endpoint — no signup payment. Get a key at [madeonsol.com/pricing](https://madeonsol.com/pricing).
15
15
 
16
+ > **New in 1.23.0 — live holder census: exact holder count, labelled holders, and pools that are named, not just excluded.** The new `madeonsol_token_holders` tool binds `GET /tokens/{mint}/holders` (PRO+): every token account of the mint read from the ledger at `confirmed` and merged per owner, so `concentration.holder_count` is EXACT (distinct non-zero owners minus pools / bonding curves / burns) — never a trade-derived estimate; it is `null` only when the provider refuses the census for a mega-cap, in which case you get the top-20 view and `source.census_fallback_reason` says so. Each disclosed owner carries our labels (`deployer` / `kol` / `early_buyer` / `bundle` / `bot` / `dump_cluster` — empty means unknown to us, not clean), and `excluded[]` NAMES what was taken out of the circulating denominator: `reason` = `pool` (with `dex` + `pool_address`), `bonding_curve` (pump.fun / LaunchLab), `burn`, or `program_account` only when we genuinely cannot attribute the PDA; `pool_pct` / `burned_pct` / `program_pct` split the exclusion. Amounts are raw u64 **strings**. Disclosure: PRO ranks 1–10, ULTRA 1–50, BUSINESS 1–100 — the maths is tier-independent. Big tokens take 5–30 s upstream: you get `503 holder_scan_in_progress` with `retry_after_seconds: 20` while the scan finishes into the cache, and the retry is instant.
17
+
16
18
  > **New in 1.22.0 — two prices on the trade tape, and the right one is now the default.** The trade tape now tells you what a trade actually cost. `price_sol`/`price_usd` on each trade are THIS trade's executed price — `sol_amount / token_amount`, reconciling exactly with the amounts on the same row and with the PnL endpoints. Because `sol_amount` is the wallet's net SOL movement, that is the trader's all-in effective rate: swap fee and any account rent included, not the pool mid. The market-cap tracker's canonical pool price moved to the new **`market_price_sol`/`market_price_usd`** fields — it is sampled once per token per pool update, so every trade in the same slot shares it. Until now `price_sol` carried that canonical value and disagreed with the row's own amounts by a **7.9% median** (p90 ~74%): a stale market price reads low in a pump and high in a dump, so anything you averaged out of the tape inherited the bias instead of cancelling it. Use `price_sol` for cost basis, fills and PnL; `market_price_sol` for a per-token series independent of trade size and direction. Both `madeonsol_token_trades` and `madeonsol_wallet_trades` carry all four fields, and both tool descriptions spell out which price to use so an agent does not average the wrong one.
17
19
 
18
20
  > **New in 1.21.0 — the Deployer Hunter surface completed.** Seven new operations that existed on the API but had no SDK binding: `madeonsol_deployer_leaderboard`, `madeonsol_deployer_stats`, `madeonsol_deployer_profile`, `madeonsol_deployer_tokens`, `madeonsol_deployer_alert_stats`, `madeonsol_deployer_best_tokens` and `madeonsol_deployer_recent_bonds`. Read `bonding_rate` (lifetime) against `recent_bond_rate` (rolling) — the gap between them is the signal, not either number alone. `runner_rate` only means something once `labeled_tokens >= 3`, and an **untracked wallet returns a profile with zeroed counters, not a 404**, so check `total_deployed` before reading a 0% bond rate as a track record. Dependency ranges are now bounded to the versions actually tested (`@x402/*` `^2.x`, `@solana/kit` `^5.5.1`) instead of open-ended `>=0.0.1`, and the lazily-imported x402 peers are marked optional — a keyed install no longer pulls the whole Solana stack.
@@ -231,6 +233,7 @@ Scored from 1M+ early-buyer records (wallets seen in the first 20 buyers of Pump
231
233
  | `madeonsol_token_bundle` | All | Bundle-cohort holdings — which same-slot bundle wallets bought a token and how much of supply they still hold (`held_pct_of_supply` headline, plus `bundle_kind`, `held_ratio`, `fully_exited`). BASIC: bundle block only. PRO: top-10 flags. ULTRA: full cohort + identities |
232
234
  | `madeonsol_token_pools` | PRO+ | Per-venue liquidity map — every DEX pool a token trades in (pump.fun/PumpSwap/Raydium/Meteora/Orca) with per-pool `liquidity_usd`, `is_active` (live vs parked), plus a `summary` (pool/DEX counts, `total_liquidity_usd`, `primary_pool`, `top_pool_share_pct` concentration) |
233
235
  | `madeonsol_token_depth` | **New 1.20** · PRO+ | Per-pool price impact / slippage — `quotes[]` per SOL buy size (`tokens_out`, `avg_price_sol`, `price_impact_pct`) + `to_move_price` (SOL to move price 1%/5%/10%). `sizes` max 8, default `[0.5, 1, 5, 10]`; unsupported pools (CLMM/DLMM/DBC) flagged with a `reason` |
236
+ | `madeonsol_token_holders` | **New** · PRO+ | Live holder census + concentration — who holds NOW (vs `madeonsol_token_cap_table` = who bought first). `concentration.holder_count` is EXACT (mint-scoped `getProgramAccounts` census merged per owner; `null` only when the provider refuses a mega-cap → top-20 fallback with `source.census_fallback_reason`, never trade-estimated). Each disclosed owner labelled `deployer` / `kol` / `early_buyer` / `bundle` / `bot` / `dump_cluster` (empty = unknown, not clean). Pools / bonding curves / burns EXCLUDED from the circulating denominator and NAMED in `excluded[]` (`reason`: `pool` + `dex` + `pool_address`, `bonding_curve`, `burn`, `program_account`); `amount_raw` is a raw u64 STRING. Disclosure PRO 10 / ULTRA 50 / BUSINESS 100. Big tokens: first call may be HTTP 503 `holder_scan_in_progress` (`retry_after_seconds: 20`) — scan continues + cached, retry is instant |
234
237
  | `madeonsol_tokens_batch_risk` | PRO+ | Bulk rug-risk/safety scoring for up to 50 mints — same shape as `madeonsol_token_risk` + `as_of`. Untracked mints return `{ mint, error: "not_tracked" }` without failing the batch; counts as one request |
235
238
  | `madeonsol_token_candles` | PRO+ | Historical OHLCV candles (1m–1d). PRO=OHLCV 30d; ULTRA=+net flow, liquidity delta, MEV volume, full history |
236
239
  | `madeonsol_token_flow` | PRO+ | Trade-flow aggregate (organic-vs-fake volume) over a 1h/24h `window` — unique wallets/buyers/sellers, buy/sell counts + SOL, `net_sol`, `trades_per_wallet` wash-trading proxy |
package/dist/index.js CHANGED
@@ -675,6 +675,9 @@ function registerTools(server) {
675
675
  server.tool("madeonsol_token_pools", "Per-venue liquidity map for a Solana token — every DEX pool it trades in (pump.fun/PumpSwap/Raydium/Meteora/Orca) with per-pool liquidity, live vs parked (is_active), plus a summary (total liquidity, pool/DEX counts, primary/deepest pool, top_pool_share_pct concentration). Shows WHERE liquidity sits and how fragmented it is, vs the single aggregate number from the token endpoint.", { mint: z.string().describe("Token mint address (base58)") }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ mint }) => ({
676
676
  content: [{ type: "text", text: await restQuery("GET", `/tokens/${encodeURIComponent(mint)}/pools`) }],
677
677
  }));
678
+ server.tool("madeonsol_token_holders", "Live holder census + concentration for a Solana token — WHO HOLDS NOW (madeonsol_token_cap_table is who bought first). Read live from the ledger at confirmed: every token account of the mint (mint-scoped getProgramAccounts), merged per owner, ranks 1–100 retained. concentration.holder_count is EXACT — distinct non-zero owners minus the excluded pools/curves/burns — and is null ONLY when the provider refuses the census for a mega-cap (TRUMP/JUP/BONK class): then source.method=getTokenLargestAccounts, source.census_fallback_reason is set and only the top-20 view is served; it is NEVER estimated from trades. Every disclosed owner carries labels[] from MadeOnSol wallet intelligence — deployer / kol / early_buyer / buyer / bundle / bot / dump_cluster (+ kol_name, early_buyer_rank, bot_confidence, historical_win_rate); an EMPTY labels[] means unknown to us, NOT verified clean. Liquidity pools, bonding curves, vaults and burn addresses are EXCLUDED from the circulating denominator and NAMED in excluded[] with reason = pool (dex + pool_address set) | bonding_curve (pump.fun/LaunchLab) | burn | program_account (off-curve owner we could not attribute); concentration splits them into pool_pct / burned_pct / program_pct (over TOTAL supply), while top1/top10/top20/top50/top100_share and deployer/kol/early_buyer/bundle/bot/dump_cluster_pct are over circulating (supply minus excluded). amount_raw / supply_raw / circulating_raw are raw u64 returned as decimal STRINGS — never coerce to a float. Disclosure is tier-gated: PRO ranks 1–10, ULTRA 1–50, BUSINESS 1–100 (the maths is tier-independent). Large established tokens take 5–30 s to enumerate upstream: the first call may return HTTP 503 with error_kind=holder_scan_in_progress and retry_after_seconds=20 — the scan keeps running and is cached, so retry after ~20 s and the answer is instant. 404 not_a_mint = not a mint on-chain; 503 holder_rpc_unavailable (retry 15 s) = we fail closed rather than guess. PRO+ — BASIC receives HTTP 403.", { mint: z.string().describe("Token mint address (base58)") }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ mint }) => ({
679
+ content: [{ type: "text", text: await restQuery("GET", `/tokens/${encodeURIComponent(mint)}/holders`) }],
680
+ }));
678
681
  server.tool("madeonsol_token_depth", "Per-pool price-impact / slippage for a token — answers 'how much SOL moves this token's price N%' and the impact of each buy size, per pool (NOT router-optimal). Each computable pool returns spot_price_sol, fee_pct, a quotes[] entry per requested SOL size (size_sol, tokens_out, avg_price_sol, price_impact_pct), and to_move_price — the SOL required to move price 1%/5%/10%. Constant-product AMMs are served from stream reserves (source=stream, with reserves_age_ms); pump.fun/bonk bonding curves from a LIVE read of the curve's virtual reserves (source=live_rpc). Pools that can't be priced honestly — concentrated CLMM/Orca/DLMM, Meteora-DBC curves, unclassified models — come back in unsupported_pools[] with a reason (e.g. concentrated_liquidity_depth_not_supported, curve_graduated_use_amm_pool) instead of a wrong number. primary_pool = deepest computable pool; found=false means no pools tracked. PRO/ULTRA only — BASIC receives HTTP 403.", {
679
682
  mint: z.string().describe("Token mint address (base58)"),
680
683
  sizes: z.array(z.number().gt(0).max(10000)).min(1).max(8).optional()
@@ -1130,6 +1133,7 @@ async function main() {
1130
1133
  { name: "madeonsol_alpha_wallet", description: "Full alpha profile + bot signals for one wallet. ULTRA only." },
1131
1134
  { name: "madeonsol_alpha_linked", description: "Behaviorally linked wallets (co-bought 3+ tokens within 2s). ULTRA only." },
1132
1135
  { name: "madeonsol_token_cap_table", description: "First non-deployer early buyers for a token, enriched. PRO=10, ULTRA=20." },
1136
+ { name: "madeonsol_token_holders", description: "Live holder census + concentration — who holds NOW. Exact holder_count (null only if the provider refuses a mega-cap), labelled owners, pools/curves/burns excluded and named. PRO=10, ULTRA=50, BUSINESS=100 disclosed; 503 holder_scan_in_progress → retry in 20 s." },
1133
1137
  { name: "madeonsol_token_buyer_quality", description: "0–100 buyer quality score for a token's first-buyer cohort." },
1134
1138
  { name: "madeonsol_token_depth", description: "Per-pool price impact / slippage — quotes per SOL buy size + SOL to move price 1%/5%/10%; unsupported pools flagged with a reason. PRO+." },
1135
1139
  { name: "madeonsol_token_candles", description: "Historical OHLCV price candles (1m–1d). PRO=OHLCV 30d; ULTRA=+net flow, liquidity delta, full history." },
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "1.22.0";
1
+ export declare const VERSION = "1.23.0";
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // AUTO-GENERATED by ../gen-version.mjs (npm prebuild) from package.json. Do not edit.
2
- export const VERSION = "1.22.0";
2
+ export const VERSION = "1.23.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-server-madeonsol",
3
- "version": "1.22.0",
3
+ "version": "1.23.0",
4
4
  "mcpName": "io.github.MadeOnSol/madeonsol",
5
5
  "description": "MCP server for MadeOnSol Solana KOL intelligence API — use from Claude, Cursor, or any MCP client. Free tier 200 req/day, no payment to start.",
6
6
  "type": "module",