mcp-server-madeonsol 0.8.1 → 1.0.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 @@ Two options (in priority order):
13
13
  | **MadeOnSol API key** (recommended) | `MADEONSOL_API_KEY` | Developers — [get a free key](https://madeonsol.com/developer) |
14
14
  | x402 micropayments | `SVM_PRIVATE_KEY` | AI agents with Solana wallets |
15
15
 
16
+ > **v1.0 breaking change:** RapidAPI auth (`RAPIDAPI_KEY`) has been removed. The MadeOnSol RapidAPI marketplace was retired on 2026-04-19. Get a free `msk_` key at [madeonsol.com/developer](https://madeonsol.com/developer).
17
+
16
18
  ## Install
17
19
 
18
20
  ```bash
@@ -76,6 +78,36 @@ Add to MCP settings with the same command and env vars.
76
78
  | `madeonsol_wallet_tracker_trades` | Historical swap/transfer events for watched wallets (120-day retention) |
77
79
  | `madeonsol_wallet_tracker_summary` | Per-wallet stats: swap counts, SOL bought/sold, last event |
78
80
 
81
+ ### Alpha Wallet Intelligence
82
+
83
+ Scored from 47,000+ early-buyer records (wallets seen in the first 20 buyers of Pump.fun tokens).
84
+
85
+ | Tool | Tier | Description |
86
+ |---|---|---|
87
+ | `madeonsol_alpha_leaderboard` | BASIC+ | Top profitable early-buyer wallets. BASIC=25 (truncated), PRO=100, ULTRA=500 + bot signals |
88
+ | `madeonsol_alpha_wallet` | ULTRA | Full per-token breakdown + bot_signals array |
89
+ | `madeonsol_alpha_linked` | ULTRA | Wallets behaviorally linked (co-bought 3+ tokens within 2s) |
90
+
91
+ ### Token Quality
92
+
93
+ | Tool | Tier | Description |
94
+ |---|---|---|
95
+ | `madeonsol_token_cap_table` | PRO+ | First non-deployer early buyers, enriched with PnL/KOL/bot flags. PRO=10, ULTRA=20 |
96
+ | `madeonsol_token_buyer_quality` | BASIC+ | 0–100 buyer-quality score (5-min cached). BASIC=score+signal only |
97
+
98
+ ### Copy-Trade Rules (PRO/ULTRA)
99
+
100
+ Server-side rules that fire signals when a watched source wallet trades. Delivered via webhook (HMAC-signed) and/or WebSocket.
101
+
102
+ | Tool | Description |
103
+ |---|---|
104
+ | `madeonsol_copytrade_list` | List your rules |
105
+ | `madeonsol_copytrade_create` | Create a rule. Returns `webhook_secret` once — store it |
106
+ | `madeonsol_copytrade_get` | Get one rule |
107
+ | `madeonsol_copytrade_update` | Update fields or toggle `is_active` |
108
+ | `madeonsol_copytrade_delete` | Delete permanently |
109
+ | `madeonsol_copytrade_signals` | Recent fired signals (up to 7 days) |
110
+
79
111
  ### Streaming & Webhooks
80
112
 
81
113
  | Tool | Description |
package/dist/index.js CHANGED
@@ -6,7 +6,6 @@ import { z } from "zod";
6
6
  import { createServer } from "node:http";
7
7
  const BASE_URL = process.env.MADEONSOL_API_URL || "https://madeonsol.com";
8
8
  const MADEONSOL_API_KEY = process.env.MADEONSOL_API_KEY; // Native key from madeonsol.com/developer
9
- const RAPIDAPI_KEY = process.env.RAPIDAPI_KEY; // RapidAPI subscription key
10
9
  const PRIVATE_KEY = process.env.SVM_PRIVATE_KEY; // x402 micropayments (for AI agents)
11
10
  const PORT = parseInt(process.env.PORT || "3100", 10);
12
11
  const MODE = process.env.MCP_TRANSPORT || "stdio"; // "stdio" or "http"
@@ -16,12 +15,6 @@ function apiKeyHeaders() {
16
15
  if (authMode === "madeonsol") {
17
16
  return { Authorization: `Bearer ${MADEONSOL_API_KEY}` };
18
17
  }
19
- if (authMode === "rapidapi") {
20
- return {
21
- "x-rapidapi-key": RAPIDAPI_KEY,
22
- "x-rapidapi-host": "madeonsol-solana-kol-tracker-tools-api.p.rapidapi.com",
23
- };
24
- }
25
18
  return {};
26
19
  }
27
20
  async function initAuth() {
@@ -30,11 +23,6 @@ async function initAuth() {
30
23
  console.error("[madeonsol-mcp] Using MadeOnSol API key (Bearer auth)");
31
24
  return;
32
25
  }
33
- if (RAPIDAPI_KEY) {
34
- authMode = "rapidapi";
35
- console.error("[madeonsol-mcp] Using RapidAPI key");
36
- return;
37
- }
38
26
  if (PRIVATE_KEY) {
39
27
  try {
40
28
  const { wrapFetchWithPayment } = await import("@x402/fetch");
@@ -54,10 +42,10 @@ async function initAuth() {
54
42
  console.error("[madeonsol-mcp] x402 setup failed:", err);
55
43
  }
56
44
  }
57
- console.error("[madeonsol-mcp] No auth configured. Set MADEONSOL_API_KEY (get one free at madeonsol.com/developer), RAPIDAPI_KEY, or SVM_PRIVATE_KEY.");
45
+ console.error("[madeonsol-mcp] No auth configured. Set MADEONSOL_API_KEY (get one free at madeonsol.com/developer) or SVM_PRIVATE_KEY.");
58
46
  }
59
47
  async function query(path, params) {
60
- // API key and RapidAPI auth use /api/v1/ endpoints; x402 uses /api/x402/
48
+ // API key uses /api/v1/ endpoints; x402 uses /api/x402/
61
49
  const apiPath = authMode === "x402" || authMode === "none"
62
50
  ? path
63
51
  : path.replace("/api/x402/", "/api/v1/");
@@ -80,31 +68,63 @@ async function query(path, params) {
80
68
  }
81
69
  function registerTools(server) {
82
70
  const readOnlyAnnotations = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true };
83
- server.tool("madeonsol_kol_feed", "Get real-time Solana KOL trades from 1,000+ tracked wallets.", {
71
+ server.tool("madeonsol_kol_feed", "Get real-time Solana KOL trades from 1,000+ tracked wallets. PRO+ adds size/age/strategy/winrate filters.", {
84
72
  limit: z.number().min(1).max(100).default(10).describe("Number of trades to return (1-100)"),
85
73
  action: z.enum(["buy", "sell"]).optional().describe("Filter by trade type: buy or sell"),
86
74
  kol: z.string().optional().describe("Filter by specific KOL wallet address (base58)"),
87
- }, readOnlyAnnotations, async ({ limit, action, kol }) => {
75
+ min_sol: z.number().optional().describe("PRO+: minimum SOL size per trade"),
76
+ token_age_max_min: z.number().optional().describe("PRO+: max token age in minutes at time of trade"),
77
+ exclude_sells: z.boolean().optional().describe("PRO+: drop sell-side trades"),
78
+ min_kol_winrate: z.number().optional().describe("PRO+: minimum 7d winrate of the KOL (0-100)"),
79
+ strategy: z.enum(["sniper", "flipper", "swinger", "holder", "mixed"]).optional().describe("PRO+: filter by auto-tagged strategy"),
80
+ }, readOnlyAnnotations, async ({ limit, action, kol, min_sol, token_age_max_min, exclude_sells, min_kol_winrate, strategy }) => {
88
81
  const params = { limit };
89
82
  if (action)
90
83
  params.action = action;
91
84
  if (kol)
92
85
  params.kol = kol;
86
+ if (min_sol !== undefined)
87
+ params.min_sol = min_sol;
88
+ if (token_age_max_min !== undefined)
89
+ params.token_age_max_min = token_age_max_min;
90
+ if (exclude_sells)
91
+ params.exclude_sells = "true";
92
+ if (min_kol_winrate !== undefined)
93
+ params.min_kol_winrate = min_kol_winrate;
94
+ if (strategy)
95
+ params.strategy = strategy;
93
96
  return { content: [{ type: "text", text: await query("/api/x402/kol/feed", params) }] };
94
97
  });
95
- server.tool("madeonsol_kol_coordination", "Get KOL convergence signals — tokens being accumulated by multiple KOLs simultaneously.", {
98
+ server.tool("madeonsol_kol_coordination", "Get KOL convergence signals — tokens being accumulated by multiple KOLs simultaneously. PRO+ adds cluster quality filters.", {
96
99
  period: z.enum(["1h", "6h", "24h", "7d"]).default("24h").describe("Time period for coordination analysis"),
97
100
  min_kols: z.number().min(2).max(50).default(3).describe("Minimum number of KOLs converging on the same token"),
98
101
  limit: z.number().min(1).max(50).default(20).describe("Number of coordination signals to return"),
99
- }, readOnlyAnnotations, async ({ period, min_kols, limit }) => ({
100
- content: [{ type: "text", text: await query("/api/x402/kol/coordination", { period, min_kols, limit }) }],
101
- }));
102
- server.tool("madeonsol_kol_leaderboard", "Get KOL performance rankings by PnL and win rate.", {
103
- period: z.enum(["today", "7d", "30d"]).default("7d").describe("Time period for leaderboard: today, 7d, or 30d"),
102
+ min_avg_winrate: z.number().optional().describe("PRO+: require cluster avg winrate_7d >= N (0-100)"),
103
+ unique_strategies: z.number().optional().describe("PRO+: require >= N distinct strategies in cluster"),
104
+ }, readOnlyAnnotations, async ({ period, min_kols, limit, min_avg_winrate, unique_strategies }) => {
105
+ const params = { period, min_kols, limit };
106
+ if (min_avg_winrate !== undefined)
107
+ params.min_avg_winrate = min_avg_winrate;
108
+ if (unique_strategies !== undefined)
109
+ params.unique_strategies = unique_strategies;
110
+ return { content: [{ type: "text", text: await query("/api/x402/kol/coordination", params) }] };
111
+ });
112
+ server.tool("madeonsol_kol_leaderboard", "Get KOL performance rankings by PnL and win rate. PRO+ can sort by alternative axes (winrate/roi/profit_factor/early_entry).", {
113
+ period: z.enum(["today", "7d", "30d", "90d", "180d"]).default("7d").describe("Time period (trade retention is 180d)"),
104
114
  limit: z.number().min(1).max(50).default(20).describe("Number of KOLs to return in ranking"),
105
- }, readOnlyAnnotations, async ({ period, limit }) => ({
106
- content: [{ type: "text", text: await query("/api/x402/kol/leaderboard", { period, limit }) }],
107
- }));
115
+ sort: z.enum(["pnl", "winrate", "profit_factor", "roi", "early_entry"]).optional().describe("PRO+: sort axis (default 'pnl')"),
116
+ strategy: z.enum(["sniper", "flipper", "swinger", "holder", "mixed"]).optional().describe("PRO+: filter by strategy tag"),
117
+ min_winrate: z.number().optional().describe("PRO+: minimum winrate cutoff (0-100)"),
118
+ }, readOnlyAnnotations, async ({ period, limit, sort, strategy, min_winrate }) => {
119
+ const params = { period, limit };
120
+ if (sort)
121
+ params.sort = sort;
122
+ if (strategy)
123
+ params.strategy = strategy;
124
+ if (min_winrate !== undefined)
125
+ params.min_winrate = min_winrate;
126
+ return { content: [{ type: "text", text: await query("/api/x402/kol/leaderboard", params) }] };
127
+ });
108
128
  server.tool("madeonsol_deployer_alerts", "Get real-time alerts from Pump.fun deployers with KOL buy enrichment. PRO/ULTRA subscribers can filter by deployer tier (elite/good/moderate/rising/cold).", {
109
129
  limit: z.number().min(1).max(100).default(10).describe("Number of deployer alerts to return (1-100)"),
110
130
  offset: z.number().min(0).default(0).describe("Pagination offset for deployer alerts"),
@@ -123,8 +143,7 @@ function registerTools(server) {
123
143
  wallet: z.string().describe("KOL wallet address (base58)"),
124
144
  period: z.enum(["7d", "30d"]).default("30d").describe("Time period: 7d or 30d"),
125
145
  }, readOnlyAnnotations, async ({ wallet, period }) => {
126
- const hasRestAuth = authMode === "madeonsol" || authMode === "rapidapi";
127
- if (hasRestAuth) {
146
+ if (authMode === "madeonsol") {
128
147
  const headers = { ...apiKeyHeaders() };
129
148
  const res = await fetch(`${BASE_URL}/api/v1/kol/${wallet}/timing?period=${period}`, { headers });
130
149
  if (!res.ok) {
@@ -133,13 +152,12 @@ function registerTools(server) {
133
152
  }
134
153
  return { content: [{ type: "text", text: JSON.stringify(await res.json(), null, 2) }] };
135
154
  }
136
- return { content: [{ type: "text", text: "KOL timing requires API key or RapidAPI key auth." }] };
155
+ return { content: [{ type: "text", text: "KOL timing requires MADEONSOL_API_KEY (msk_) get one free at madeonsol.com/developer." }] };
137
156
  });
138
157
  server.tool("madeonsol_deployer_trajectory", "Deployer skill curve — streaks, rolling bond rate, improvement trend, and deployment cadence for a Pump.fun deployer.", {
139
158
  wallet: z.string().describe("Deployer wallet address (base58)"),
140
159
  }, readOnlyAnnotations, async ({ wallet }) => {
141
- const hasRestAuth = authMode === "madeonsol" || authMode === "rapidapi";
142
- if (hasRestAuth) {
160
+ if (authMode === "madeonsol") {
143
161
  const headers = { ...apiKeyHeaders() };
144
162
  const res = await fetch(`${BASE_URL}/api/v1/deployer-hunter/${wallet}/trajectory`, { headers });
145
163
  if (!res.ok) {
@@ -148,21 +166,51 @@ function registerTools(server) {
148
166
  }
149
167
  return { content: [{ type: "text", text: JSON.stringify(await res.json(), null, 2) }] };
150
168
  }
151
- return { content: [{ type: "text", text: "Deployer trajectory requires API key or RapidAPI key auth (Pro/Ultra)." }] };
169
+ return { content: [{ type: "text", text: "Deployer trajectory requires MADEONSOL_API_KEY (msk_, Pro/Ultra) get one at madeonsol.com/developer." }] };
152
170
  });
153
- server.tool("madeonsol_kol_hot_tokens", "KOL momentum tokens — tokens with accelerating KOL buy interest, early signals before coordination triggers.", {
171
+ server.tool("madeonsol_kol_hot_tokens", "KOL momentum tokens — tokens with accelerating KOL buy interest, early signals before coordination triggers. PRO+ adds buyer-quality filters.", {
154
172
  period: z.enum(["1h", "6h"]).default("6h").describe("Time period: 1h or 6h"),
155
173
  min_kols: z.number().min(1).max(20).default(1).describe("Minimum KOL buyers to include a token"),
156
174
  limit: z.number().min(1).max(50).default(20).describe("Number of hot tokens to return"),
157
- }, readOnlyAnnotations, async ({ period, min_kols, limit }) => ({
158
- content: [{ type: "text", text: await query("/api/x402/kol/tokens/hot", { period, min_kols, limit }) }],
175
+ min_avg_winrate: z.number().optional().describe("PRO+: require avg winrate_7d of buyers >= N (0-100)"),
176
+ unique_strategies: z.number().optional().describe("PRO+: require >= N distinct strategies among buyers"),
177
+ }, readOnlyAnnotations, async ({ period, min_kols, limit, min_avg_winrate, unique_strategies }) => {
178
+ const params = { period, min_kols, limit };
179
+ if (min_avg_winrate !== undefined)
180
+ params.min_avg_winrate = min_avg_winrate;
181
+ if (unique_strategies !== undefined)
182
+ params.unique_strategies = unique_strategies;
183
+ return { content: [{ type: "text", text: await query("/api/x402/kol/tokens/hot", params) }] };
184
+ });
185
+ server.tool("madeonsol_kol_token_entry_order", "Ranked KOL first-buyers for a specific token, ordered by entry timestamp. PRO+ adds percentile_pnl_7d per entry.", {
186
+ mint: z.string().describe("Token mint address (base58)"),
187
+ limit: z.number().min(1).max(200).default(50).describe("Max ranked entries to return"),
188
+ }, readOnlyAnnotations, async ({ mint, limit }) => ({
189
+ content: [{ type: "text", text: await query(`/api/x402/kol/tokens/${encodeURIComponent(mint)}/entry-order`, { limit }) }],
159
190
  }));
191
+ server.tool("madeonsol_kol_compare_wallets", "Side-by-side comparison of 2-5 KOL wallets — strategy, winrates, ROI, percentile. PRO+ adds 30d overlap tokens (bought by 2+ of the wallets).", {
192
+ wallets: z.array(z.string()).min(2).max(5).describe("2-5 wallet addresses. BASIC=2, PRO=4, ULTRA=5."),
193
+ }, readOnlyAnnotations, async ({ wallets }) => ({
194
+ content: [{ type: "text", text: await query("/api/x402/kol/compare", { wallets: wallets.join(",") }) }],
195
+ }));
196
+ server.tool("madeonsol_kol_alerts_recent", "Live KOL alert feed — consensus clusters, fresh-token KOL buys, and heating-up wallets in one unified stream.", {
197
+ window: z.enum(["5m", "15m", "1h", "6h", "24h"]).default("15m").describe("Lookback window"),
198
+ types: z.array(z.enum(["consensus_cluster", "fresh_token_kol_buy", "heating_up"])).optional().describe("Filter to specific alert types"),
199
+ min_severity: z.enum(["low", "medium", "high"]).optional().describe("Minimum severity to include"),
200
+ limit: z.number().min(1).max(200).default(50).describe("Max alerts to return"),
201
+ }, readOnlyAnnotations, async ({ window, types, min_severity, limit }) => {
202
+ const params = { window, limit };
203
+ if (types && types.length > 0)
204
+ params.types = types.join(",");
205
+ if (min_severity)
206
+ params.min_severity = min_severity;
207
+ return { content: [{ type: "text", text: await query("/api/x402/kol/alerts/recent", params) }] };
208
+ });
160
209
  server.tool("madeonsol_kol_pnl", "Deep per-wallet PnL breakdown — realized PnL, win rate, profit factor, max drawdown, daily equity curve, closed/open positions. BASIC: summary only. PRO: + curve + closed. ULTRA: + open positions.", {
161
210
  wallet: z.string().describe("KOL wallet address (base58)"),
162
211
  period: z.enum(["7d", "30d", "90d", "180d"]).default("30d").describe("Time period for PnL calculation"),
163
212
  }, readOnlyAnnotations, async ({ wallet, period }) => {
164
- const hasRestAuth = authMode === "madeonsol" || authMode === "rapidapi";
165
- if (hasRestAuth) {
213
+ if (authMode === "madeonsol") {
166
214
  const headers = { ...apiKeyHeaders() };
167
215
  const res = await fetch(`${BASE_URL}/api/v1/kol/${wallet}/pnl?period=${period}`, { headers });
168
216
  if (!res.ok) {
@@ -171,7 +219,7 @@ function registerTools(server) {
171
219
  }
172
220
  return { content: [{ type: "text", text: JSON.stringify(await res.json(), null, 2) }] };
173
221
  }
174
- return { content: [{ type: "text", text: "KOL PnL requires API key or RapidAPI key auth." }] };
222
+ return { content: [{ type: "text", text: "KOL PnL requires MADEONSOL_API_KEY (msk_) get one free at madeonsol.com/developer." }] };
175
223
  });
176
224
  server.tool("madeonsol_kol_trending_tokens", "Tokens ranked by KOL buy volume — pure capital-flow signal. Sub-hour periods (5m/15m/30m) require PRO/ULTRA.", {
177
225
  period: z.enum(["5m", "15m", "30m", "1h", "2h", "4h", "12h"]).default("1h").describe("Time window"),
@@ -187,7 +235,7 @@ function registerTools(server) {
187
235
  });
188
236
  // ── Wallet Tracker tools (REST auth only — all mutating operations) ──
189
237
  {
190
- const hasRestAuth = authMode === "madeonsol" || authMode === "rapidapi";
238
+ const hasRestAuth = authMode === "madeonsol";
191
239
  async function walletTrackerRequest(method, path, body) {
192
240
  const headers = { "Content-Type": "application/json", ...apiKeyHeaders() };
193
241
  const res = await fetch(`${BASE_URL}/api/v1${path}`, {
@@ -257,11 +305,11 @@ function registerTools(server) {
257
305
  console.error("[madeonsol-mcp] Wallet tracker tools enabled");
258
306
  }
259
307
  else {
260
- console.error("[madeonsol-mcp] Wallet tracker tools disabled (requires MADEONSOL_API_KEY or RAPIDAPI_KEY)");
308
+ console.error("[madeonsol-mcp] Wallet tracker tools disabled (requires MADEONSOL_API_KEY)");
261
309
  }
262
310
  }
263
- // ── Webhook & Streaming tools (require API key or RapidAPI key — Pro/Ultra tier) ──
264
- const hasRestAuth = authMode === "madeonsol" || authMode === "rapidapi";
311
+ // ── Webhook & Streaming tools (require MadeOnSol API key — Pro/Ultra tier) ──
312
+ const hasRestAuth = authMode === "madeonsol";
265
313
  if (hasRestAuth) {
266
314
  async function restQuery(method, path, body) {
267
315
  const headers = {
@@ -312,10 +360,99 @@ function registerTools(server) {
312
360
  server.tool("madeonsol_stream_token", "Generate a 24h WebSocket streaming token. Includes ws_url for KOL/deployer streaming (Pro/Ultra) and dex_ws_url for all-DEX trade streaming (Ultra only).", {}, { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }, async () => ({
313
361
  content: [{ type: "text", text: await restQuery("POST", "/stream/token") }],
314
362
  }));
363
+ // ── Alpha wallet intelligence ──
364
+ server.tool("madeonsol_alpha_leaderboard", "Top statistically profitable early-buyer wallets, scored from 47,000+ early-buyer records. BASIC=25 (truncated), PRO=100, ULTRA=500 + bot signals.", {
365
+ period: z.enum(["7d", "30d", "all"]).default("30d").describe("Time window"),
366
+ min_tokens: z.number().min(1).max(20).default(5).describe("Minimum tokens traded by wallet (1-20)"),
367
+ sort: z.enum(["win_rate", "pnl", "roi"]).default("win_rate").describe("Sort axis"),
368
+ exclude_bots: z.boolean().default(true).describe("Exclude wallets flagged as bots"),
369
+ }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ period, min_tokens, sort, exclude_bots }) => {
370
+ const params = { period, min_tokens, sort, exclude_bots: exclude_bots ? "true" : "false" };
371
+ const url = new URL(`${BASE_URL}/api/v1/alpha/leaderboard`);
372
+ for (const [k, v] of Object.entries(params))
373
+ url.searchParams.set(k, String(v));
374
+ const res = await fetch(url.toString(), { headers: { "Content-Type": "application/json", ...apiKeyHeaders() } });
375
+ const text = res.ok ? JSON.stringify(await res.json(), null, 2) : `Error ${res.status}: ${await res.text().catch(() => "")}`;
376
+ return { content: [{ type: "text", text }] };
377
+ });
378
+ server.tool("madeonsol_alpha_wallet", "Full alpha profile for one wallet — per-token breakdown + bot_signals array. ULTRA only.", { wallet: z.string().describe("Wallet address (base58)") }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ wallet }) => ({
379
+ content: [{ type: "text", text: await restQuery("GET", `/alpha/${encodeURIComponent(wallet)}`) }],
380
+ }));
381
+ server.tool("madeonsol_alpha_linked", "Wallets behaviorally linked to a target wallet (co-bought 3+ tokens within 2 seconds). ULTRA only.", { wallet: z.string().describe("Wallet address (base58)") }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ wallet }) => ({
382
+ content: [{ type: "text", text: await restQuery("GET", `/alpha/${encodeURIComponent(wallet)}/linked`) }],
383
+ }));
384
+ // ── Token quality ──
385
+ server.tool("madeonsol_token_cap_table", "First non-deployer early buyers for a token, enriched with PnL, KOL identity, and bot flags. PRO=top 10 (truncated wallets), ULTRA=top 20 (full). BASIC: 403.", { mint: z.string().describe("Token mint address (base58)") }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ mint }) => ({
386
+ content: [{ type: "text", text: await restQuery("GET", `/tokens/${encodeURIComponent(mint)}/cap-table`) }],
387
+ }));
388
+ server.tool("madeonsol_token_buyer_quality", "0–100 buyer-quality score for a token's first-buyer cohort. 5-min cached. BASIC: score+signal only. PRO/ULTRA: full breakdown.", { mint: z.string().describe("Token mint address (base58)") }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ mint }) => ({
389
+ content: [{ type: "text", text: await restQuery("GET", `/tokens/${encodeURIComponent(mint)}/buyer-quality`) }],
390
+ }));
391
+ // ── Copy-Trade rules (PRO/ULTRA) ──
392
+ server.tool("madeonsol_copytrade_list", "List your copy-trade rules. PRO=3 rules, ULTRA=20 rules.", {}, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async () => ({
393
+ content: [{ type: "text", text: await restQuery("GET", "/copytrade/subscriptions") }],
394
+ }));
395
+ server.tool("madeonsol_copytrade_create", "Create a copy-trade rule. Returns webhook_secret ONCE on creation when delivery_mode includes 'webhook' — store it to verify HMAC signatures. PRO=5 source_wallets/rule, ULTRA=50.", {
396
+ source_wallets: z.array(z.string()).min(1).max(50).describe("Wallets to mirror (base58)"),
397
+ sizing_amount: z.number().describe("Amount used by the chosen sizing_mode"),
398
+ name: z.string().optional().describe("Optional human label"),
399
+ min_trade_sol: z.number().optional().describe("Minimum source-wallet trade size to fire a signal"),
400
+ only_action: z.enum(["buy", "sell", "both"]).optional().describe("Filter to one side (default 'both')"),
401
+ sizing_mode: z.enum(["fixed", "proportional", "percent_source"]).optional().describe("How sizing_amount is interpreted"),
402
+ delivery_mode: z.enum(["webhook", "websocket", "both"]).optional().describe("Where to deliver fired signals"),
403
+ webhook_url: z.string().url().optional().describe("Required when delivery_mode includes 'webhook'"),
404
+ }, { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }, async (args) => {
405
+ const body = { source_wallets: args.source_wallets, sizing_amount: args.sizing_amount };
406
+ for (const k of ["name", "min_trade_sol", "only_action", "sizing_mode", "delivery_mode", "webhook_url"]) {
407
+ if (args[k] !== undefined)
408
+ body[k] = args[k];
409
+ }
410
+ return { content: [{ type: "text", text: await restQuery("POST", "/copytrade/subscriptions", body) }] };
411
+ });
412
+ server.tool("madeonsol_copytrade_get", "Get one copy-trade rule by id.", { id: z.number().describe("Subscription id") }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ id }) => ({
413
+ content: [{ type: "text", text: await restQuery("GET", `/copytrade/subscriptions/${id}`) }],
414
+ }));
415
+ server.tool("madeonsol_copytrade_update", "Update fields on a copy-trade rule, including is_active toggle.", {
416
+ id: z.number().describe("Subscription id"),
417
+ name: z.string().nullable().optional(),
418
+ source_wallets: z.array(z.string()).optional(),
419
+ min_trade_sol: z.number().optional(),
420
+ only_action: z.enum(["buy", "sell", "both"]).optional(),
421
+ sizing_mode: z.enum(["fixed", "proportional", "percent_source"]).optional(),
422
+ sizing_amount: z.number().optional(),
423
+ delivery_mode: z.enum(["webhook", "websocket", "both"]).optional(),
424
+ webhook_url: z.string().url().nullable().optional(),
425
+ is_active: z.boolean().optional(),
426
+ }, { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }, async ({ id, ...patch }) => {
427
+ const body = {};
428
+ for (const [k, v] of Object.entries(patch)) {
429
+ if (v !== undefined)
430
+ body[k] = v;
431
+ }
432
+ return { content: [{ type: "text", text: await restQuery("PATCH", `/copytrade/subscriptions/${id}`, body) }] };
433
+ });
434
+ server.tool("madeonsol_copytrade_delete", "Delete a copy-trade rule permanently.", { id: z.number().describe("Subscription id") }, { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true }, async ({ id }) => ({
435
+ content: [{ type: "text", text: await restQuery("DELETE", `/copytrade/subscriptions/${id}`) }],
436
+ }));
437
+ server.tool("madeonsol_copytrade_signals", "Recent fired copy-trade signals (up to 7 days). Filter by subscription_id, since (ISO8601), and limit (1–500).", {
438
+ subscription_id: z.number().optional().describe("Filter to one rule"),
439
+ since: z.string().optional().describe("ISO8601 timestamp — only signals fired at-or-after this time"),
440
+ limit: z.number().min(1).max(500).default(50).describe("Max signals to return (1–500)"),
441
+ }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ subscription_id, since, limit }) => {
442
+ const url = new URL(`${BASE_URL}/api/v1/copytrade/signals`);
443
+ url.searchParams.set("limit", String(limit));
444
+ if (subscription_id !== undefined)
445
+ url.searchParams.set("subscription_id", String(subscription_id));
446
+ if (since)
447
+ url.searchParams.set("since", since);
448
+ const res = await fetch(url.toString(), { headers: { "Content-Type": "application/json", ...apiKeyHeaders() } });
449
+ const text = res.ok ? JSON.stringify(await res.json(), null, 2) : `Error ${res.status}: ${await res.text().catch(() => "")}`;
450
+ return { content: [{ type: "text", text }] };
451
+ });
315
452
  console.error("[madeonsol-mcp] Webhook & streaming tools enabled");
316
453
  }
317
454
  else {
318
- console.error("[madeonsol-mcp] Webhook/streaming tools disabled (requires MADEONSOL_API_KEY or RAPIDAPI_KEY)");
455
+ console.error("[madeonsol-mcp] Webhook/streaming tools disabled (requires MADEONSOL_API_KEY)");
319
456
  }
320
457
  // Prompts — pre-built analysis templates
321
458
  server.prompt("solana_kol_analysis", "Analyze current Solana KOL trading activity — what are smart money wallets buying and selling?", { period: z.string().default("24h").describe("Time period: 1h, 6h, 24h, or 7d") }, ({ period }) => ({
@@ -355,8 +492,8 @@ async function main() {
355
492
  res.writeHead(200, { "Content-Type": "application/json" });
356
493
  res.end(JSON.stringify({
357
494
  name: "madeonsol",
358
- description: "Solana KOL trading intelligence and deployer analytics. Real-time data from 1,000+ KOL wallets and 4000+ Pump.fun deployers. Supports API key, RapidAPI, or x402 micropayments.",
359
- version: "0.1.0",
495
+ description: "Solana KOL trading intelligence and deployer analytics. Real-time data from 1,000+ KOL wallets, 6,700+ Pump.fun deployers, 47,000+ scored alpha wallets, copy-trade rules, and wallet tracker. Supports MadeOnSol API key (msk_) or x402 micropayments.",
496
+ version: "1.0.0",
360
497
  tools: [
361
498
  { name: "madeonsol_kol_feed", description: "Get real-time Solana KOL trades from 1,000+ tracked wallets." },
362
499
  { name: "madeonsol_kol_coordination", description: "Get KOL convergence signals — tokens multiple KOLs are accumulating." },
@@ -368,6 +505,9 @@ async function main() {
368
505
  { name: "madeonsol_kol_hot_tokens", description: "KOL momentum tokens — accelerating buy interest." },
369
506
  { name: "madeonsol_kol_pnl", description: "Deep per-wallet PnL: equity curve, risk metrics, positions." },
370
507
  { name: "madeonsol_kol_trending_tokens", description: "Tokens ranked by KOL buy volume (5m–12h windows)." },
508
+ { name: "madeonsol_kol_token_entry_order", description: "Ranked KOL first-buyers for a specific token." },
509
+ { name: "madeonsol_kol_compare_wallets", description: "Side-by-side comparison of 2-5 KOL wallets (overlap in PRO+)." },
510
+ { name: "madeonsol_kol_alerts_recent", description: "Unified live KOL alert feed: clusters, fresh buys, heating-up." },
371
511
  { name: "madeonsol_discovery", description: "List all available endpoints with prices. Free." },
372
512
  { name: "madeonsol_create_webhook", description: "Register a webhook for real-time push notifications. Pro/Ultra." },
373
513
  { name: "madeonsol_list_webhooks", description: "List your registered webhooks. Pro/Ultra." },
@@ -379,6 +519,17 @@ async function main() {
379
519
  { name: "madeonsol_wallet_tracker_remove", description: "Remove a wallet from your watchlist." },
380
520
  { name: "madeonsol_wallet_tracker_trades", description: "Historical swap/transfer events for watched wallets." },
381
521
  { name: "madeonsol_wallet_tracker_summary", description: "Per-wallet stats: swap counts, SOL bought/sold." },
522
+ { name: "madeonsol_alpha_leaderboard", description: "Top profitable early-buyer wallets — 47,000+ scored. BASIC=25, PRO=100, ULTRA=500." },
523
+ { name: "madeonsol_alpha_wallet", description: "Full alpha profile + bot signals for one wallet. ULTRA only." },
524
+ { name: "madeonsol_alpha_linked", description: "Behaviorally linked wallets (co-bought 3+ tokens within 2s). ULTRA only." },
525
+ { name: "madeonsol_token_cap_table", description: "First non-deployer early buyers for a token, enriched. PRO=10, ULTRA=20." },
526
+ { name: "madeonsol_token_buyer_quality", description: "0–100 buyer quality score for a token's first-buyer cohort." },
527
+ { name: "madeonsol_copytrade_list", description: "List your copy-trade rules. PRO/ULTRA." },
528
+ { name: "madeonsol_copytrade_create", description: "Create a copy-trade rule with webhook + WS delivery. PRO/ULTRA." },
529
+ { name: "madeonsol_copytrade_get", description: "Get one copy-trade rule. PRO/ULTRA." },
530
+ { name: "madeonsol_copytrade_update", description: "Update a copy-trade rule. PRO/ULTRA." },
531
+ { name: "madeonsol_copytrade_delete", description: "Delete a copy-trade rule. PRO/ULTRA." },
532
+ { name: "madeonsol_copytrade_signals", description: "Recent fired copy-trade signals (up to 7 days). PRO/ULTRA." },
382
533
  ],
383
534
  homepage: "https://madeonsol.com/solana-api",
384
535
  repository: "https://github.com/LamboPoewert/mcp-server-madeonsol",
@@ -394,7 +545,7 @@ async function main() {
394
545
  transport = new StreamableHTTPServerTransport({
395
546
  sessionIdGenerator: undefined,
396
547
  });
397
- const server = new McpServer({ name: "madeonsol", version: "0.1.0" });
548
+ const server = new McpServer({ name: "madeonsol", version: "1.0.0" });
398
549
  registerTools(server);
399
550
  await server.connect(transport);
400
551
  }
@@ -432,7 +583,7 @@ async function main() {
432
583
  }
433
584
  else {
434
585
  // Stdio transport for local use (Claude Desktop, Cursor, Claude Code)
435
- const server = new McpServer({ name: "madeonsol", version: "0.1.0" });
586
+ const server = new McpServer({ name: "madeonsol", version: "1.0.0" });
436
587
  registerTools(server);
437
588
  const transport = new StdioServerTransport();
438
589
  await server.connect(transport);
package/glama.json CHANGED
@@ -1,54 +1,49 @@
1
1
  {
2
2
  "name": "mcp-server-madeonsol",
3
3
  "display_name": "MadeOnSol",
4
- "description": "Solana KOL trading intelligence and deployer analytics. Real-time data from 950+ KOL wallets and 6,700+ Pump.fun deployers. Supports free API key, RapidAPI, or x402 micropayments.",
5
- "version": "0.3.0",
4
+ "description": "Solana KOL trading intelligence and deployer analytics. Real-time data from 1,000+ KOL wallets, 6,700+ Pump.fun deployers, 47,000+ scored alpha wallets, server-side copy-trade rules, and wallet tracker. Supports free MadeOnSol API key (msk_) or x402 micropayments.",
5
+ "version": "1.0.0",
6
6
  "homepage": "https://madeonsol.com/solana-api",
7
7
  "repository": "https://github.com/LamboPoewert/mcp-server-madeonsol",
8
8
  "license": "MIT",
9
9
  "categories": ["blockchain", "finance", "web3"],
10
- "tags": ["solana", "kol", "trading", "x402", "micropayments", "defi", "api", "deployer", "pump-fun"],
10
+ "tags": ["solana", "kol", "trading", "x402", "micropayments", "defi", "api", "deployer", "pump-fun", "copy-trade"],
11
11
  "tools": [
12
- {
13
- "name": "madeonsol_kol_feed",
14
- "description": "Get real-time Solana KOL trades from 950+ tracked wallets."
15
- },
16
- {
17
- "name": "madeonsol_kol_coordination",
18
- "description": "Get KOL convergence signals tokens multiple KOLs are accumulating."
19
- },
20
- {
21
- "name": "madeonsol_kol_leaderboard",
22
- "description": "Get KOL performance rankings by PnL and win rate."
23
- },
24
- {
25
- "name": "madeonsol_deployer_alerts",
26
- "description": "Get elite Pump.fun deployer alerts with KOL enrichment."
27
- },
28
- {
29
- "name": "madeonsol_discovery",
30
- "description": "List all available endpoints with prices. Free, no auth required."
31
- },
32
- {
33
- "name": "madeonsol_create_webhook",
34
- "description": "Register a webhook for real-time push notifications. Pro/Ultra."
35
- },
36
- {
37
- "name": "madeonsol_list_webhooks",
38
- "description": "List your registered webhooks. Pro/Ultra."
39
- },
40
- {
41
- "name": "madeonsol_delete_webhook",
42
- "description": "Delete a webhook by ID. Pro/Ultra."
43
- },
44
- {
45
- "name": "madeonsol_test_webhook",
46
- "description": "Send a test payload to verify a webhook. Pro/Ultra."
47
- },
48
- {
49
- "name": "madeonsol_stream_token",
50
- "description": "Get a 24h WebSocket streaming token. Pro/Ultra."
51
- }
12
+ { "name": "madeonsol_kol_feed", "description": "Get real-time Solana KOL trades from 1,000+ tracked wallets." },
13
+ { "name": "madeonsol_kol_coordination", "description": "Get KOL convergence signals — tokens multiple KOLs are accumulating." },
14
+ { "name": "madeonsol_kol_leaderboard", "description": "Get KOL performance rankings by PnL and win rate." },
15
+ { "name": "madeonsol_deployer_alerts", "description": "Get Pump.fun deployer alerts with KOL enrichment." },
16
+ { "name": "madeonsol_kol_pairs", "description": "KOL affinity matrix — which KOLs co-trade the same tokens." },
17
+ { "name": "madeonsol_kol_timing", "description": "KOL entry/exit timing profile. Pro/Ultra." },
18
+ { "name": "madeonsol_deployer_trajectory", "description": "Deployer skill curvestreaks, trend. Pro/Ultra." },
19
+ { "name": "madeonsol_kol_hot_tokens", "description": "KOL momentum tokens — accelerating buy interest." },
20
+ { "name": "madeonsol_kol_pnl", "description": "Deep per-wallet PnL: equity curve, risk metrics, positions." },
21
+ { "name": "madeonsol_kol_trending_tokens", "description": "Tokens ranked by KOL buy volume (5m–12h windows)." },
22
+ { "name": "madeonsol_kol_token_entry_order", "description": "Ranked KOL first-buyers for a specific token." },
23
+ { "name": "madeonsol_kol_compare_wallets", "description": "Side-by-side comparison of 2-5 KOL wallets (overlap in PRO+)." },
24
+ { "name": "madeonsol_kol_alerts_recent", "description": "Unified live KOL alert feed: clusters, fresh buys, heating-up." },
25
+ { "name": "madeonsol_discovery", "description": "List all available endpoints with prices. Free, no auth required." },
26
+ { "name": "madeonsol_create_webhook", "description": "Register a webhook for real-time push notifications. Pro/Ultra." },
27
+ { "name": "madeonsol_list_webhooks", "description": "List your registered webhooks. Pro/Ultra." },
28
+ { "name": "madeonsol_delete_webhook", "description": "Delete a webhook by ID. Pro/Ultra." },
29
+ { "name": "madeonsol_test_webhook", "description": "Send a test payload to verify a webhook. Pro/Ultra." },
30
+ { "name": "madeonsol_stream_token", "description": "Get a 24h WebSocket streaming token. Pro/Ultra." },
31
+ { "name": "madeonsol_wallet_tracker_watchlist", "description": "List your tracked wallets and remaining capacity." },
32
+ { "name": "madeonsol_wallet_tracker_add", "description": "Add a wallet to your watchlist." },
33
+ { "name": "madeonsol_wallet_tracker_remove", "description": "Remove a wallet from your watchlist." },
34
+ { "name": "madeonsol_wallet_tracker_trades", "description": "Historical swap/transfer events for watched wallets." },
35
+ { "name": "madeonsol_wallet_tracker_summary", "description": "Per-wallet stats: swap counts, SOL bought/sold." },
36
+ { "name": "madeonsol_alpha_leaderboard", "description": "Top profitable early-buyer wallets — 47,000+ scored. BASIC=25, PRO=100, ULTRA=500." },
37
+ { "name": "madeonsol_alpha_wallet", "description": "Full alpha profile + bot signals for one wallet. ULTRA only." },
38
+ { "name": "madeonsol_alpha_linked", "description": "Behaviorally linked wallets (co-bought 3+ tokens within 2s). ULTRA only." },
39
+ { "name": "madeonsol_token_cap_table", "description": "First non-deployer early buyers for a token, enriched. PRO=10, ULTRA=20." },
40
+ { "name": "madeonsol_token_buyer_quality", "description": "0–100 buyer quality score for a token's first-buyer cohort." },
41
+ { "name": "madeonsol_copytrade_list", "description": "List your copy-trade rules. PRO/ULTRA." },
42
+ { "name": "madeonsol_copytrade_create", "description": "Create a copy-trade rule with webhook + WS delivery. PRO/ULTRA." },
43
+ { "name": "madeonsol_copytrade_get", "description": "Get one copy-trade rule. PRO/ULTRA." },
44
+ { "name": "madeonsol_copytrade_update", "description": "Update a copy-trade rule. PRO/ULTRA." },
45
+ { "name": "madeonsol_copytrade_delete", "description": "Delete a copy-trade rule. PRO/ULTRA." },
46
+ { "name": "madeonsol_copytrade_signals", "description": "Recent fired copy-trade signals (up to 7 days). PRO/ULTRA." }
52
47
  ],
53
48
  "transports": ["stdio", "http"],
54
49
  "runtime": "node"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-server-madeonsol",
3
- "version": "0.8.1",
3
+ "version": "1.0.0",
4
4
  "mcpName": "io.github.lambopoewert/madeonsol",
5
5
  "description": "MCP server for MadeOnSol Solana KOL intelligence API — use from Claude, Cursor, or any MCP client",
6
6
  "type": "module",