mcp-server-madeonsol 0.2.2 → 0.3.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.
Files changed (3) hide show
  1. package/README.md +23 -19
  2. package/dist/index.js +81 -49
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -2,12 +2,24 @@
2
2
 
3
3
  MCP server for [MadeOnSol](https://madeonsol.com) Solana KOL intelligence API. Use from Claude Desktop, Cursor, or any MCP-compatible client.
4
4
 
5
+ ## Authentication
6
+
7
+ Three options (in priority order):
8
+
9
+ | Method | Env var | Best for |
10
+ |---|---|---|
11
+ | **MadeOnSol API key** (recommended) | `MADEONSOL_API_KEY` | Developers — [get a free key](https://madeonsol.com/developer) |
12
+ | RapidAPI key | `RAPIDAPI_KEY` | RapidAPI subscribers |
13
+ | x402 micropayments | `SVM_PRIVATE_KEY` | AI agents with Solana wallets |
14
+
5
15
  ## Install
6
16
 
7
17
  ```bash
8
- npm install -g mcp-server-madeonsol @x402/fetch @x402/svm @x402/core @solana/kit @scure/base
18
+ npm install -g mcp-server-madeonsol
9
19
  ```
10
20
 
21
+ > x402 peer deps (`@x402/fetch @x402/svm @x402/core @solana/kit @scure/base`) are only needed when using `SVM_PRIVATE_KEY`.
22
+
11
23
  ## Configure
12
24
 
13
25
  ### Claude Desktop
@@ -20,7 +32,7 @@ Add to `claude_desktop_config.json`:
20
32
  "madeonsol": {
21
33
  "command": "mcp-server-madeonsol",
22
34
  "env": {
23
- "SVM_PRIVATE_KEY": "your_solana_private_key_base58"
35
+ "MADEONSOL_API_KEY": "msk_your_api_key_here"
24
36
  }
25
37
  }
26
38
  }
@@ -33,29 +45,21 @@ Add to MCP settings with the same command and env vars.
33
45
 
34
46
  ## Tools
35
47
 
36
- | Tool | Price | Description |
37
- |---|---|---|
38
- | `madeonsol_kol_feed` | $0.005 | Real-time KOL trade feed (946 wallets) |
39
- | `madeonsol_kol_coordination` | $0.02 | Multi-KOL convergence signals |
40
- | `madeonsol_kol_leaderboard` | $0.005 | KOL PnL and win rate rankings |
41
- | `madeonsol_deployer_alerts` | $0.01 | Elite Pump.fun deployer launches |
42
- | `madeonsol_discovery` | Free | List all endpoints and prices |
48
+ | Tool | Description |
49
+ |---|---|
50
+ | `madeonsol_kol_feed` | Real-time KOL trade feed (946 wallets) |
51
+ | `madeonsol_kol_coordination` | Multi-KOL convergence signals |
52
+ | `madeonsol_kol_leaderboard` | KOL PnL and win rate rankings |
53
+ | `madeonsol_deployer_alerts` | Elite Pump.fun deployer launches |
54
+ | `madeonsol_discovery` | List all endpoints and prices (free) |
43
55
 
44
- **With `RAPIDAPI_KEY` (Pro/Ultra subscription):**
56
+ **With Pro/Ultra subscription:**
45
57
 
46
58
  | Tool | Description |
47
59
  |---|---|
48
- | `madeonsol_stream_token` | Get 24h WebSocket token for KOL/deployer streaming (Pro/Ultra) and DEX trade stream (Ultra) |
60
+ | `madeonsol_stream_token` | Get 24h WebSocket token for KOL/deployer streaming and DEX trade stream |
49
61
  | Webhook CRUD tools | Create, list, update, delete, test webhooks |
50
62
 
51
- ## How It Works
52
-
53
- The server uses the x402 payment protocol. Each tool call triggers a USDC micropayment on Solana. Your wallet needs SOL (for fees) and USDC.
54
-
55
- Without `SVM_PRIVATE_KEY`, tools return payment requirement info instead of data.
56
-
57
- With `RAPIDAPI_KEY`, webhook and streaming tools are also available. Ultra subscribers get access to the DEX trade stream — a real-time WebSocket feed of all Solana DEX trades filtered by token, wallet, or program.
58
-
59
63
  ## Also Available
60
64
 
61
65
  | Platform | Package |
package/dist/index.js CHANGED
@@ -5,41 +5,73 @@ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/
5
5
  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
- const PRIVATE_KEY = process.env.SVM_PRIVATE_KEY;
9
- const RAPIDAPI_KEY = process.env.RAPIDAPI_KEY; // For webhook/streaming features (Pro/Ultra)
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
+ const PRIVATE_KEY = process.env.SVM_PRIVATE_KEY; // x402 micropayments (for AI agents)
10
11
  const PORT = parseInt(process.env.PORT || "3100", 10);
11
12
  const MODE = process.env.MCP_TRANSPORT || "stdio"; // "stdio" or "http"
13
+ let authMode = "none";
12
14
  let paidFetch = fetch;
13
- async function initPayment() {
14
- if (!PRIVATE_KEY) {
15
- console.error("[madeonsol-mcp] No SVM_PRIVATE_KEY tools will return 402 payment info");
15
+ function apiKeyHeaders() {
16
+ if (authMode === "madeonsol") {
17
+ return { Authorization: `Bearer ${MADEONSOL_API_KEY}` };
18
+ }
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
+ return {};
26
+ }
27
+ async function initAuth() {
28
+ if (MADEONSOL_API_KEY) {
29
+ authMode = "madeonsol";
30
+ console.error("[madeonsol-mcp] Using MadeOnSol API key (Bearer auth)");
16
31
  return;
17
32
  }
18
- try {
19
- const { wrapFetchWithPayment } = await import("@x402/fetch");
20
- const { x402Client } = await import("@x402/core/client");
21
- const { ExactSvmScheme } = await import("@x402/svm/exact/client");
22
- const { createKeyPairSignerFromBytes } = await import("@solana/kit");
23
- const { base58 } = await import("@scure/base");
24
- const signer = await createKeyPairSignerFromBytes(base58.decode(PRIVATE_KEY));
25
- const client = new x402Client();
26
- client.register("solana:*", new ExactSvmScheme(signer));
27
- paidFetch = wrapFetchWithPayment(fetch, client);
28
- console.error(`[madeonsol-mcp] x402 payments enabled, wallet: ${signer.address}`);
33
+ if (RAPIDAPI_KEY) {
34
+ authMode = "rapidapi";
35
+ console.error("[madeonsol-mcp] Using RapidAPI key");
36
+ return;
29
37
  }
30
- catch (err) {
31
- console.error("[madeonsol-mcp] x402 setup failed:", err);
38
+ if (PRIVATE_KEY) {
39
+ try {
40
+ const { wrapFetchWithPayment } = await import("@x402/fetch");
41
+ const { x402Client } = await import("@x402/core/client");
42
+ const { ExactSvmScheme } = await import("@x402/svm/exact/client");
43
+ const { createKeyPairSignerFromBytes } = await import("@solana/kit");
44
+ const { base58 } = await import("@scure/base");
45
+ const signer = await createKeyPairSignerFromBytes(base58.decode(PRIVATE_KEY));
46
+ const client = new x402Client();
47
+ client.register("solana:*", new ExactSvmScheme(signer));
48
+ paidFetch = wrapFetchWithPayment(fetch, client);
49
+ authMode = "x402";
50
+ console.error(`[madeonsol-mcp] x402 payments enabled, wallet: ${signer.address}`);
51
+ return;
52
+ }
53
+ catch (err) {
54
+ console.error("[madeonsol-mcp] x402 setup failed:", err);
55
+ }
32
56
  }
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.");
33
58
  }
34
59
  async function query(path, params) {
35
- const url = new URL(path, BASE_URL);
60
+ // API key and RapidAPI auth use /api/v1/ endpoints; x402 uses /api/x402/
61
+ const apiPath = authMode === "x402" || authMode === "none"
62
+ ? path
63
+ : path.replace("/api/x402/", "/api/v1/");
64
+ const url = new URL(apiPath, BASE_URL);
36
65
  if (params) {
37
66
  for (const [k, v] of Object.entries(params)) {
38
67
  if (v !== undefined)
39
68
  url.searchParams.set(k, String(v));
40
69
  }
41
70
  }
42
- const res = await paidFetch(url.toString());
71
+ const headers = apiKeyHeaders();
72
+ const res = authMode === "x402"
73
+ ? await paidFetch(url.toString())
74
+ : await fetch(url.toString(), { headers });
43
75
  if (!res.ok) {
44
76
  const body = await res.text().catch(() => "");
45
77
  return `Error ${res.status}: ${body}`;
@@ -48,7 +80,7 @@ async function query(path, params) {
48
80
  }
49
81
  function registerTools(server) {
50
82
  const readOnlyAnnotations = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true };
51
- server.tool("madeonsol_kol_feed", "Get real-time Solana KOL trades from 946 tracked wallets. Costs $0.005 USDC per request via x402.", {
83
+ server.tool("madeonsol_kol_feed", "Get real-time Solana KOL trades from 946 tracked wallets.", {
52
84
  limit: z.number().min(1).max(100).default(10).describe("Number of trades to return (1-100)"),
53
85
  action: z.enum(["buy", "sell"]).optional().describe("Filter by trade type: buy or sell"),
54
86
  kol: z.string().optional().describe("Filter by specific KOL wallet address (base58)"),
@@ -60,41 +92,41 @@ function registerTools(server) {
60
92
  params.kol = kol;
61
93
  return { content: [{ type: "text", text: await query("/api/x402/kol/feed", params) }] };
62
94
  });
63
- server.tool("madeonsol_kol_coordination", "Get KOL convergence signals — tokens being accumulated by multiple KOLs simultaneously. Costs $0.02 USDC per request via x402.", {
95
+ server.tool("madeonsol_kol_coordination", "Get KOL convergence signals — tokens being accumulated by multiple KOLs simultaneously.", {
64
96
  period: z.enum(["1h", "6h", "24h", "7d"]).default("24h").describe("Time period for coordination analysis"),
65
97
  min_kols: z.number().min(2).max(50).default(3).describe("Minimum number of KOLs converging on the same token"),
66
98
  limit: z.number().min(1).max(50).default(20).describe("Number of coordination signals to return"),
67
99
  }, readOnlyAnnotations, async ({ period, min_kols, limit }) => ({
68
100
  content: [{ type: "text", text: await query("/api/x402/kol/coordination", { period, min_kols, limit }) }],
69
101
  }));
70
- server.tool("madeonsol_kol_leaderboard", "Get KOL performance rankings by PnL and win rate. Costs $0.005 USDC per request via x402.", {
102
+ server.tool("madeonsol_kol_leaderboard", "Get KOL performance rankings by PnL and win rate.", {
71
103
  period: z.enum(["today", "7d", "30d"]).default("7d").describe("Time period for leaderboard: today, 7d, or 30d"),
72
104
  limit: z.number().min(1).max(50).default(20).describe("Number of KOLs to return in ranking"),
73
105
  }, readOnlyAnnotations, async ({ period, limit }) => ({
74
106
  content: [{ type: "text", text: await query("/api/x402/kol/leaderboard", { period, limit }) }],
75
107
  }));
76
- server.tool("madeonsol_deployer_alerts", "Get real-time alerts from elite Pump.fun deployers with KOL buy enrichment. Costs $0.01 USDC per request via x402.", {
108
+ server.tool("madeonsol_deployer_alerts", "Get real-time alerts from elite Pump.fun deployers with KOL buy enrichment.", {
77
109
  limit: z.number().min(1).max(100).default(10).describe("Number of deployer alerts to return (1-100)"),
78
110
  offset: z.number().min(0).default(0).describe("Pagination offset for deployer alerts"),
79
111
  }, readOnlyAnnotations, async ({ limit, offset }) => ({
80
112
  content: [{ type: "text", text: await query("/api/x402/deployer-hunter/alerts", { limit, offset }) }],
81
113
  }));
82
- server.tool("madeonsol_discovery", "List all available MadeOnSol x402 API endpoints with prices and parameter docs. Free, no payment required.", {}, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }, async () => {
114
+ 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 () => {
83
115
  const res = await fetch(new URL("/api/x402", BASE_URL).toString());
84
116
  const data = await res.json();
85
117
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
86
118
  });
87
- // ── Webhook & Streaming tools (require RAPIDAPI_KEY env var) ──
88
- if (RAPIDAPI_KEY) {
89
- const restHeaders = {
90
- "Content-Type": "application/json",
91
- "x-rapidapi-key": RAPIDAPI_KEY,
92
- "x-rapidapi-host": "madeonsol-solana-kol-tracker-tools-api.p.rapidapi.com",
93
- };
119
+ // ── Webhook & Streaming tools (require API key or RapidAPI key — Pro/Ultra tier) ──
120
+ const hasRestAuth = authMode === "madeonsol" || authMode === "rapidapi";
121
+ if (hasRestAuth) {
94
122
  async function restQuery(method, path, body) {
123
+ const headers = {
124
+ "Content-Type": "application/json",
125
+ ...apiKeyHeaders(),
126
+ };
95
127
  const res = await fetch(`${BASE_URL}/api/v1${path}`, {
96
128
  method,
97
- headers: restHeaders,
129
+ headers,
98
130
  ...(body ? { body: JSON.stringify(body) } : {}),
99
131
  });
100
132
  if (!res.ok) {
@@ -104,7 +136,7 @@ function registerTools(server) {
104
136
  return JSON.stringify(await res.json(), null, 2);
105
137
  }
106
138
  const webhookAnnotations = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true };
107
- server.tool("madeonsol_create_webhook", "Register a webhook URL to receive real-time push notifications for KOL trades and deployer alerts. Requires RapidAPI Pro/Ultra.", {
139
+ server.tool("madeonsol_create_webhook", "Register a webhook URL to receive real-time push notifications for KOL trades and deployer alerts. Requires Pro/Ultra subscription.", {
108
140
  url: z.string().url().describe("HTTPS webhook URL to receive events"),
109
141
  events: z.array(z.enum(["kol:trade", "kol:coordination", "deployer:alert", "deployer:bond"])).min(1).describe("Event types to subscribe to"),
110
142
  min_sol: z.number().optional().describe("Optional: minimum SOL amount filter (for kol:trade)"),
@@ -120,7 +152,7 @@ function registerTools(server) {
120
152
  filters.deployer_tier = deployer_tier;
121
153
  return { content: [{ type: "text", text: await restQuery("POST", "/webhooks", { url, events, filters }) }] };
122
154
  });
123
- server.tool("madeonsol_list_webhooks", "List all your registered webhooks with delivery status and failure counts. Requires RAPIDAPI_KEY env var.", {}, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async () => ({
155
+ server.tool("madeonsol_list_webhooks", "List all your registered webhooks with delivery status and failure counts.", {}, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async () => ({
124
156
  content: [{ type: "text", text: await restQuery("GET", "/webhooks") }],
125
157
  }));
126
158
  server.tool("madeonsol_delete_webhook", "Delete a webhook by ID. Permanently removes the webhook and its delivery history.", {
@@ -133,13 +165,13 @@ function registerTools(server) {
133
165
  }, { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, async ({ webhook_id }) => ({
134
166
  content: [{ type: "text", text: await restQuery("POST", "/webhooks/test", { webhook_id }) }],
135
167
  }));
136
- server.tool("madeonsol_stream_token", "Generate a 24-hour WebSocket streaming token. Response includes ws_url for KOL/deployer streaming (Pro/Ultra) and dex_ws_url for all-DEX trade streaming (Ultra only). DEX stream at wss://madeonsol.com/ws/v1/dex-stream requires at least one filter: token_mint, wallet, or program.", {}, { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }, async () => ({
168
+ 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 () => ({
137
169
  content: [{ type: "text", text: await restQuery("POST", "/stream/token") }],
138
170
  }));
139
- console.error("[madeonsol-mcp] Webhook & streaming tools enabled (RAPIDAPI_KEY set)");
171
+ console.error("[madeonsol-mcp] Webhook & streaming tools enabled");
140
172
  }
141
173
  else {
142
- console.error("[madeonsol-mcp] No RAPIDAPI_KEY — webhook/streaming tools disabled");
174
+ console.error("[madeonsol-mcp] Webhook/streaming tools disabled (requires MADEONSOL_API_KEY or RAPIDAPI_KEY)");
143
175
  }
144
176
  // Prompts — pre-built analysis templates
145
177
  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 }) => ({
@@ -162,7 +194,7 @@ function registerTools(server) {
162
194
  });
163
195
  }
164
196
  async function main() {
165
- await initPayment();
197
+ await initAuth();
166
198
  if (MODE === "http") {
167
199
  // HTTP transport for hosted environments (Smithery, etc.)
168
200
  const httpServer = createServer();
@@ -179,19 +211,19 @@ async function main() {
179
211
  res.writeHead(200, { "Content-Type": "application/json" });
180
212
  res.end(JSON.stringify({
181
213
  name: "madeonsol",
182
- description: "Solana KOL trading intelligence and deployer analytics via x402 micropayments. Real-time data from 946 KOL wallets and 4000+ Pump.fun deployers.",
214
+ description: "Solana KOL trading intelligence and deployer analytics. Real-time data from 946 KOL wallets and 4000+ Pump.fun deployers. Supports API key, RapidAPI, or x402 micropayments.",
183
215
  version: "0.1.0",
184
216
  tools: [
185
- { name: "madeonsol_kol_feed", description: "Get real-time Solana KOL trades from 946 tracked wallets. $0.005 USDC/req." },
186
- { name: "madeonsol_kol_coordination", description: "Get KOL convergence signals — tokens multiple KOLs are accumulating. $0.02 USDC/req." },
187
- { name: "madeonsol_kol_leaderboard", description: "Get KOL performance rankings by PnL and win rate. $0.005 USDC/req." },
188
- { name: "madeonsol_deployer_alerts", description: "Get elite Pump.fun deployer alerts with KOL enrichment. $0.01 USDC/req." },
217
+ { name: "madeonsol_kol_feed", description: "Get real-time Solana KOL trades from 946 tracked wallets." },
218
+ { name: "madeonsol_kol_coordination", description: "Get KOL convergence signals — tokens multiple KOLs are accumulating." },
219
+ { name: "madeonsol_kol_leaderboard", description: "Get KOL performance rankings by PnL and win rate." },
220
+ { name: "madeonsol_deployer_alerts", description: "Get elite Pump.fun deployer alerts with KOL enrichment." },
189
221
  { name: "madeonsol_discovery", description: "List all available endpoints with prices. Free." },
190
- { name: "madeonsol_create_webhook", description: "Register a webhook for real-time push notifications. Requires RAPIDAPI_KEY." },
191
- { name: "madeonsol_list_webhooks", description: "List your registered webhooks. Requires RAPIDAPI_KEY." },
192
- { name: "madeonsol_delete_webhook", description: "Delete a webhook by ID. Requires RAPIDAPI_KEY." },
193
- { name: "madeonsol_test_webhook", description: "Send a test payload to verify a webhook. Requires RAPIDAPI_KEY." },
194
- { name: "madeonsol_stream_token", description: "Get a 24h WebSocket streaming token for KOL/deployer events (Pro/Ultra) and DEX trade stream (Ultra). Requires RAPIDAPI_KEY." },
222
+ { name: "madeonsol_create_webhook", description: "Register a webhook for real-time push notifications. Pro/Ultra." },
223
+ { name: "madeonsol_list_webhooks", description: "List your registered webhooks. Pro/Ultra." },
224
+ { name: "madeonsol_delete_webhook", description: "Delete a webhook by ID. Pro/Ultra." },
225
+ { name: "madeonsol_test_webhook", description: "Send a test payload to verify a webhook. Pro/Ultra." },
226
+ { name: "madeonsol_stream_token", description: "Get a 24h WebSocket streaming token. Pro/Ultra." },
195
227
  ],
196
228
  homepage: "https://madeonsol.com/solana-api",
197
229
  repository: "https://github.com/LamboPoewert/mcp-server-madeonsol",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-server-madeonsol",
3
- "version": "0.2.2",
3
+ "version": "0.3.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",