mcp-server-madeonsol 1.8.1 → 1.10.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 +34 -0
- package/dist/index.js +146 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -110,6 +110,15 @@ Add to MCP settings with the same command and env vars.
|
|
|
110
110
|
| `madeonsol_deployer_alerts` | Pump.fun deployer launches with KOL enrichment. Filter by tier (elite/good/moderate/rising/cold). ULTRA unlocks full pagination. |
|
|
111
111
|
| `madeonsol_deployer_trajectory` | Deployer skill curve — streaks, rolling bond rate, trend — available on all tiers |
|
|
112
112
|
|
|
113
|
+
### Deshred Sniper Alerts *(new in 1.10 — Pro/Ultra)*
|
|
114
|
+
|
|
115
|
+
Pre-confirm pump.fun deploy feed reconstructed from shred-level (**deshred**) data — launches surface **~500ms before they confirm on-chain**. Pro sees elite/good deployers; Ultra sees every tier.
|
|
116
|
+
|
|
117
|
+
| Tool | Description |
|
|
118
|
+
|---|---|
|
|
119
|
+
| `madeonsol_sniper_recent` | Newest-first deshred deploy feed. Pro: elite/good · Ultra: all tiers. `watchlist: true` (Ultra) narrows to your custom deployer watchlist |
|
|
120
|
+
| `madeonsol_sniper_by_deployer` | Deshred deploys for a single deployer wallet (Ultra) |
|
|
121
|
+
|
|
113
122
|
### Wallet Tracker
|
|
114
123
|
|
|
115
124
|
| Tool | Description |
|
|
@@ -191,6 +200,31 @@ Every "first KOL buy on a token mint" event. Filterable by **scout tier** (S/A/B
|
|
|
191
200
|
|
|
192
201
|
> **Don't poll — push.** Median lead time before the second KOL is 12 seconds. WebSocket channel: `kol:first_touches` (PRO+).
|
|
193
202
|
|
|
203
|
+
### Price Alerts *(new in 1.9)*
|
|
204
|
+
|
|
205
|
+
CRUD for token dip/recovery price alerts. Fires when a token's market cap crosses your threshold. PRO=5 rules, ULTRA=25.
|
|
206
|
+
|
|
207
|
+
| Tool | Description |
|
|
208
|
+
|---|---|
|
|
209
|
+
| `madeonsol_price_alerts_list` | List your price alert rules |
|
|
210
|
+
| `madeonsol_price_alerts_create` | Create a dip/recovery alert. Returns `webhook_secret` once — store it |
|
|
211
|
+
| `madeonsol_price_alerts_get` | Get one alert rule by ID |
|
|
212
|
+
| `madeonsol_price_alerts_update` | Update fields or toggle `is_active` |
|
|
213
|
+
| `madeonsol_price_alerts_delete` | Delete permanently |
|
|
214
|
+
|
|
215
|
+
### Scout Leaderboard & KOL Consensus *(new in 1.9)*
|
|
216
|
+
|
|
217
|
+
| Tool | Tier | Description |
|
|
218
|
+
|---|---|---|
|
|
219
|
+
| `madeonsol_scout_leaderboard` | PRO+ | Top scout-tier KOLs ranked by first-touch follow-on rate, win rate, and ROI |
|
|
220
|
+
| `madeonsol_kol_consensus` | PRO+ | Tokens with the strongest KOL agreement signal — weighted by scout score and recent PnL |
|
|
221
|
+
| `madeonsol_peak_history` | PRO+ | Historical peak-density windows for a token — every coordination spike with KOL breakdown |
|
|
222
|
+
| `madeonsol_coordination_history` | PRO+ | Global coordination event log with token, KOL count, score, and outcome |
|
|
223
|
+
|
|
224
|
+
### Wallet Derived Stats *(new in 1.9)*
|
|
225
|
+
|
|
226
|
+
`madeonsol_wallet_stats` now returns a `stats` object with derived fields: `win_rate` (0-1), `roi`, `verdict` ("strong" | "profitable" | "neutral" | "losing"), and `biggest_miss` (token with the highest post-exit gain the wallet missed).
|
|
227
|
+
|
|
194
228
|
### Streaming & Webhooks
|
|
195
229
|
|
|
196
230
|
| Tool | Description |
|
package/dist/index.js
CHANGED
|
@@ -11,11 +11,13 @@ const PORT = parseInt(process.env.PORT || "3100", 10);
|
|
|
11
11
|
const MODE = process.env.MCP_TRANSPORT || "stdio"; // "stdio" or "http"
|
|
12
12
|
let authMode = "none";
|
|
13
13
|
let paidFetch = fetch;
|
|
14
|
+
const UA = "mcp-server-madeonsol/1.10.0";
|
|
14
15
|
function apiKeyHeaders() {
|
|
16
|
+
const h = { "User-Agent": UA };
|
|
15
17
|
if (authMode === "madeonsol") {
|
|
16
|
-
|
|
18
|
+
h.Authorization = `Bearer ${MADEONSOL_API_KEY}`;
|
|
17
19
|
}
|
|
18
|
-
return
|
|
20
|
+
return h;
|
|
19
21
|
}
|
|
20
22
|
async function initAuth() {
|
|
21
23
|
if (MADEONSOL_API_KEY) {
|
|
@@ -260,6 +262,44 @@ function registerTools(server) {
|
|
|
260
262
|
}, readOnlyAnnotations, async ({ period, min_kols, limit }) => ({
|
|
261
263
|
content: [{ type: "text", text: await query("/api/x402/kol/tokens/trending", { period, min_kols, limit }) }],
|
|
262
264
|
}));
|
|
265
|
+
server.tool("madeonsol_sniper_recent", "Deshred pre-confirm pump.fun deploy feed — new launches surface ~500ms before they confirm on-chain (reconstructed from shred-level data). PRO sees elite/good deployers; ULTRA sees every tier. Requires a Pro/Ultra msk_ API key.", {
|
|
266
|
+
deployer_tier: z.enum(["elite", "good", "moderate", "rising", "cold", "unranked"]).optional().describe("Filter by deployer reputation tier (ULTRA)"),
|
|
267
|
+
min_bond_rate: z.number().min(0).max(1).optional().describe("Minimum deployer lifetime bond rate (0-1)"),
|
|
268
|
+
since: z.string().optional().describe("ISO-8601 — only deploys detected after this timestamp"),
|
|
269
|
+
watchlist: z.boolean().optional().describe("ULTRA: narrow to your custom deployer watchlist (any tier)"),
|
|
270
|
+
limit: z.number().min(1).max(200).default(50).describe("Max results"),
|
|
271
|
+
}, readOnlyAnnotations, async ({ deployer_tier, min_bond_rate, since, watchlist, limit }) => {
|
|
272
|
+
if (authMode !== "madeonsol")
|
|
273
|
+
return { content: [{ type: "text", text: "Sniper feed requires MADEONSOL_API_KEY (msk_, Pro/Ultra) — get one at madeonsol.com/pricing." }] };
|
|
274
|
+
const qs = new URLSearchParams({ limit: String(limit) });
|
|
275
|
+
if (deployer_tier)
|
|
276
|
+
qs.set("deployer_tier", deployer_tier);
|
|
277
|
+
if (min_bond_rate != null)
|
|
278
|
+
qs.set("min_bond_rate", String(min_bond_rate));
|
|
279
|
+
if (since)
|
|
280
|
+
qs.set("since", since);
|
|
281
|
+
if (watchlist)
|
|
282
|
+
qs.set("watchlist", "true");
|
|
283
|
+
const res = await fetch(`${BASE_URL}/api/v1/sniper/recent?${qs}`, { headers: apiKeyHeaders() });
|
|
284
|
+
if (!res.ok) {
|
|
285
|
+
const body = await res.text().catch(() => "");
|
|
286
|
+
return { content: [{ type: "text", text: `Error ${res.status}: ${body}` }] };
|
|
287
|
+
}
|
|
288
|
+
return { content: [{ type: "text", text: JSON.stringify(await res.json(), null, 2) }] };
|
|
289
|
+
});
|
|
290
|
+
server.tool("madeonsol_sniper_by_deployer", "Deshred pre-confirm deploys filtered to a single deployer wallet — audit a deployer's recent launches before tracking them. ULTRA only.", {
|
|
291
|
+
wallet: z.string().describe("Deployer wallet address (base58)"),
|
|
292
|
+
limit: z.number().min(1).max(200).default(50).describe("Max results"),
|
|
293
|
+
}, readOnlyAnnotations, async ({ wallet, limit }) => {
|
|
294
|
+
if (authMode !== "madeonsol")
|
|
295
|
+
return { content: [{ type: "text", text: "Sniper feed requires MADEONSOL_API_KEY (msk_, Ultra)." }] };
|
|
296
|
+
const res = await fetch(`${BASE_URL}/api/v1/sniper/by-deployer/${encodeURIComponent(wallet)}?limit=${limit}`, { headers: apiKeyHeaders() });
|
|
297
|
+
if (!res.ok) {
|
|
298
|
+
const body = await res.text().catch(() => "");
|
|
299
|
+
return { content: [{ type: "text", text: `Error ${res.status}: ${body}` }] };
|
|
300
|
+
}
|
|
301
|
+
return { content: [{ type: "text", text: JSON.stringify(await res.json(), null, 2) }] };
|
|
302
|
+
});
|
|
263
303
|
server.tool("madeonsol_discovery", "List all available MadeOnSol API endpoints with prices and parameter docs. Free, no auth required.", {}, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }, async () => {
|
|
264
304
|
const res = await fetch(new URL("/api/x402", BASE_URL).toString());
|
|
265
305
|
const data = await res.json();
|
|
@@ -691,6 +731,97 @@ function registerTools(server) {
|
|
|
691
731
|
server.tool("madeonsol_first_touch_subscriptions_delete", "Delete a first-touch subscription permanently. ULTRA only.", { id: z.string().describe("Subscription UUID") }, { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true }, async ({ id }) => ({
|
|
692
732
|
content: [{ type: "text", text: await restQuery("DELETE", `/kol/first-touches/subscriptions/${encodeURIComponent(id)}`) }],
|
|
693
733
|
}));
|
|
734
|
+
// ── Price alerts (PRO/ULTRA, v1.9) ──
|
|
735
|
+
server.tool("madeonsol_price_alerts_list", "List your price alerts. PRO=5 alerts, ULTRA=25. Each alert monitors a token's MC for dip/recovery events.", {}, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async () => ({
|
|
736
|
+
content: [{ type: "text", text: await restQuery("GET", "/price-alerts") }],
|
|
737
|
+
}));
|
|
738
|
+
server.tool("madeonsol_price_alerts_create", "Create a price alert. Captures baseline MC from current token_prices. Fires when MC drops below baseline × (1 − drop_pct/100). Optional recovery_pct fires again on recovery. Returns webhook_secret ONCE — store it.", {
|
|
739
|
+
token_mint: z.string().describe("Solana mint address (base58)"),
|
|
740
|
+
drop_pct: z.number().min(0.01).max(99.99).describe("Drop % threshold (0.01–99.99). Alert fires when MC drops below baseline × (1 − drop_pct/100)."),
|
|
741
|
+
recovery_pct: z.number().min(0.01).max(1000).optional().describe("Recovery % (0.01–1000). After dip fires, re-fires when MC rises above dip_low × (1 + recovery_pct/100)."),
|
|
742
|
+
name: z.string().optional().describe("Optional label"),
|
|
743
|
+
delivery_mode: z.enum(["webhook", "websocket", "both"]).optional().describe("Default 'webhook'"),
|
|
744
|
+
webhook_url: z.string().url().optional().describe("Required when delivery_mode includes 'webhook'"),
|
|
745
|
+
}, { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }, async (args) => {
|
|
746
|
+
const body = {};
|
|
747
|
+
for (const [k, v] of Object.entries(args))
|
|
748
|
+
if (v !== undefined)
|
|
749
|
+
body[k] = v;
|
|
750
|
+
return { content: [{ type: "text", text: await restQuery("POST", "/price-alerts", body) }] };
|
|
751
|
+
});
|
|
752
|
+
server.tool("madeonsol_price_alerts_get", "Get one price alert by id.", { id: z.number().describe("Alert id") }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ id }) => ({
|
|
753
|
+
content: [{ type: "text", text: await restQuery("GET", `/price-alerts/${id}`) }],
|
|
754
|
+
}));
|
|
755
|
+
server.tool("madeonsol_price_alerts_update", "Update alert name, delivery mode, webhook URL, or is_active. Thresholds (drop_pct, recovery_pct) are immutable.", {
|
|
756
|
+
id: z.number().describe("Alert id"),
|
|
757
|
+
name: z.string().nullable().optional(),
|
|
758
|
+
delivery_mode: z.enum(["webhook", "websocket", "both"]).optional(),
|
|
759
|
+
webhook_url: z.string().url().nullable().optional(),
|
|
760
|
+
is_active: z.boolean().optional(),
|
|
761
|
+
}, { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }, async ({ id, ...patch }) => {
|
|
762
|
+
const body = {};
|
|
763
|
+
for (const [k, v] of Object.entries(patch))
|
|
764
|
+
if (v !== undefined)
|
|
765
|
+
body[k] = v;
|
|
766
|
+
return { content: [{ type: "text", text: await restQuery("PATCH", `/price-alerts/${id}`, body) }] };
|
|
767
|
+
});
|
|
768
|
+
server.tool("madeonsol_price_alerts_delete", "Delete a price alert and its event history.", { id: z.number().describe("Alert id") }, { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true }, async ({ id }) => ({
|
|
769
|
+
content: [{ type: "text", text: await restQuery("DELETE", `/price-alerts/${id}`) }],
|
|
770
|
+
}));
|
|
771
|
+
server.tool("madeonsol_price_alerts_events", "Fired price alert event history (30-day retention). Each event records the dip or recovery moment with actual MC values.", {
|
|
772
|
+
alert_id: z.number().optional().describe("Filter to a specific alert"),
|
|
773
|
+
event_type: z.enum(["dip", "recovery"]).optional().describe("Filter by event type"),
|
|
774
|
+
since: z.string().optional().describe("ISO 8601 — events after this timestamp"),
|
|
775
|
+
limit: z.number().min(1).max(200).optional().describe("Max events to return"),
|
|
776
|
+
}, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async (args) => {
|
|
777
|
+
const url = new URL(`${BASE_URL}/api/v1/price-alerts/events`);
|
|
778
|
+
for (const [k, v] of Object.entries(args)) {
|
|
779
|
+
if (v !== undefined)
|
|
780
|
+
url.searchParams.set(k, String(v));
|
|
781
|
+
}
|
|
782
|
+
const res = await fetch(url.toString(), { headers: { "Content-Type": "application/json", ...apiKeyHeaders() } });
|
|
783
|
+
const text = res.ok ? JSON.stringify(await res.json(), null, 2) : `Error ${res.status}: ${await res.text().catch(() => "")}`;
|
|
784
|
+
return { content: [{ type: "text", text }] };
|
|
785
|
+
});
|
|
786
|
+
// ── v1.9 new read endpoints ──
|
|
787
|
+
server.tool("madeonsol_scout_leaderboard", "Scout leaderboard — top KOLs ranked by scout score, first-touch frequency, and swarm attraction rate (% of first-touched tokens that attract 3+ follow-on KOLs within 4h). ULTRA only.", {
|
|
788
|
+
limit: z.number().min(1).max(100).optional().describe("Max entries to return"),
|
|
789
|
+
scout_tier: z.enum(["S", "A", "B", "C"]).optional().describe("Filter to a specific scout tier"),
|
|
790
|
+
sort: z.enum(["swarm_3plus_pct", "n_first_touches_30d", "swarm_5plus_pct", "scout_score"]).optional().describe("Sort axis"),
|
|
791
|
+
}, readOnlyAnnotations, async (args) => {
|
|
792
|
+
const url = new URL(`${BASE_URL}/api/v1/kol/scouts/leaderboard`);
|
|
793
|
+
for (const [k, v] of Object.entries(args)) {
|
|
794
|
+
if (v !== undefined)
|
|
795
|
+
url.searchParams.set(k, String(v));
|
|
796
|
+
}
|
|
797
|
+
const res = await fetch(url.toString(), { headers: { "Content-Type": "application/json", ...apiKeyHeaders() } });
|
|
798
|
+
const text = res.ok ? JSON.stringify(await res.json(), null, 2) : `Error ${res.status}: ${await res.text().catch(() => "")}`;
|
|
799
|
+
return { content: [{ type: "text", text }] };
|
|
800
|
+
});
|
|
801
|
+
server.tool("madeonsol_coordination_history", "Coordination history — past coordination alert fires with token, coordination score, KOL count, and timing. ULTRA only.", {
|
|
802
|
+
limit: z.number().min(1).max(100).optional().describe("Max entries to return"),
|
|
803
|
+
since: z.string().optional().describe("ISO 8601 — events after this timestamp"),
|
|
804
|
+
min_score: z.number().min(0).max(100).optional().describe("Minimum coordination score"),
|
|
805
|
+
}, readOnlyAnnotations, async (args) => {
|
|
806
|
+
const url = new URL(`${BASE_URL}/api/v1/kol/coordination/history`);
|
|
807
|
+
for (const [k, v] of Object.entries(args)) {
|
|
808
|
+
if (v !== undefined)
|
|
809
|
+
url.searchParams.set(k, String(v));
|
|
810
|
+
}
|
|
811
|
+
const res = await fetch(url.toString(), { headers: { "Content-Type": "application/json", ...apiKeyHeaders() } });
|
|
812
|
+
const text = res.ok ? JSON.stringify(await res.json(), null, 2) : `Error ${res.status}: ${await res.text().catch(() => "")}`;
|
|
813
|
+
return { content: [{ type: "text", text }] };
|
|
814
|
+
});
|
|
815
|
+
server.tool("madeonsol_kol_consensus", "KOL consensus on a specific token: total buyers/sellers, exit rate, net SOL flow, median entry MC. ULTRA adds individual buyer + exited wallet arrays.", {
|
|
816
|
+
mint: z.string().describe("Token mint address (base58)"),
|
|
817
|
+
}, readOnlyAnnotations, async ({ mint }) => ({
|
|
818
|
+
content: [{ type: "text", text: await restQuery("GET", `/tokens/${encodeURIComponent(mint)}/kol-consensus`) }],
|
|
819
|
+
}));
|
|
820
|
+
server.tool("madeonsol_peak_history", "Peak MC history for a token: all-time high MC, decline from peak %, MC at bond, MC at 1h/6h/24h/7d after bond, time-to-bond, and deploy/bond timestamps.", {
|
|
821
|
+
mint: z.string().describe("Token mint address (base58)"),
|
|
822
|
+
}, readOnlyAnnotations, async ({ mint }) => ({
|
|
823
|
+
content: [{ type: "text", text: await restQuery("GET", `/tokens/${encodeURIComponent(mint)}/peak-history`) }],
|
|
824
|
+
}));
|
|
694
825
|
console.error("[madeonsol-mcp] Webhook & streaming tools enabled");
|
|
695
826
|
}
|
|
696
827
|
else {
|
|
@@ -735,7 +866,7 @@ async function main() {
|
|
|
735
866
|
res.end(JSON.stringify({
|
|
736
867
|
name: "madeonsol",
|
|
737
868
|
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.",
|
|
738
|
-
version: "1.
|
|
869
|
+
version: "1.10.0",
|
|
739
870
|
tools: [
|
|
740
871
|
{ name: "madeonsol_kol_feed", description: "Get real-time Solana KOL trades from 1,000+ tracked wallets." },
|
|
741
872
|
{ name: "madeonsol_kol_coordination", description: "Get KOL convergence signals — tokens multiple KOLs are accumulating." },
|
|
@@ -792,6 +923,16 @@ async function main() {
|
|
|
792
923
|
{ name: "madeonsol_coordination_alerts_get", description: "Get one coordination alert rule. PRO/ULTRA." },
|
|
793
924
|
{ name: "madeonsol_coordination_alerts_update", description: "Update fields on a coordination alert rule. PRO/ULTRA." },
|
|
794
925
|
{ name: "madeonsol_coordination_alerts_delete", description: "Delete a coordination alert rule. PRO/ULTRA." },
|
|
926
|
+
{ name: "madeonsol_price_alerts_list", description: "List your price alerts. PRO/ULTRA." },
|
|
927
|
+
{ name: "madeonsol_price_alerts_create", description: "Create a price alert with dip/recovery thresholds. PRO/ULTRA." },
|
|
928
|
+
{ name: "madeonsol_price_alerts_get", description: "Get one price alert by id. PRO/ULTRA." },
|
|
929
|
+
{ name: "madeonsol_price_alerts_update", description: "Update a price alert. PRO/ULTRA." },
|
|
930
|
+
{ name: "madeonsol_price_alerts_delete", description: "Delete a price alert. PRO/ULTRA." },
|
|
931
|
+
{ name: "madeonsol_price_alerts_events", description: "Fired price alert event history (30d retention). PRO/ULTRA." },
|
|
932
|
+
{ name: "madeonsol_scout_leaderboard", description: "Scout leaderboard — top KOLs by scout score and swarm attraction. ULTRA." },
|
|
933
|
+
{ name: "madeonsol_coordination_history", description: "Past coordination alert fires with score and timing. ULTRA." },
|
|
934
|
+
{ name: "madeonsol_kol_consensus", description: "KOL consensus on a token: buyers/sellers, exit rate, net flow. ULTRA gets wallet arrays." },
|
|
935
|
+
{ name: "madeonsol_peak_history", description: "Peak MC history: ATH, decline %, MC at bond, MC at 1h/6h/24h/7d after bond." },
|
|
795
936
|
],
|
|
796
937
|
homepage: "https://madeonsol.com/solana-api",
|
|
797
938
|
repository: "https://github.com/LamboPoewert/mcp-server-madeonsol",
|
|
@@ -807,7 +948,7 @@ async function main() {
|
|
|
807
948
|
transport = new StreamableHTTPServerTransport({
|
|
808
949
|
sessionIdGenerator: undefined,
|
|
809
950
|
});
|
|
810
|
-
const server = new McpServer({ name: "madeonsol", version: "1.
|
|
951
|
+
const server = new McpServer({ name: "madeonsol", version: "1.10.0" });
|
|
811
952
|
registerTools(server);
|
|
812
953
|
await server.connect(transport);
|
|
813
954
|
}
|
|
@@ -845,7 +986,7 @@ async function main() {
|
|
|
845
986
|
}
|
|
846
987
|
else {
|
|
847
988
|
// Stdio transport for local use (Claude Desktop, Cursor, Claude Code)
|
|
848
|
-
const server = new McpServer({ name: "madeonsol", version: "1.
|
|
989
|
+
const server = new McpServer({ name: "madeonsol", version: "1.10.0" });
|
|
849
990
|
registerTools(server);
|
|
850
991
|
const transport = new StdioServerTransport();
|
|
851
992
|
await server.connect(transport);
|
package/package.json
CHANGED