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.
- package/README.md +23 -19
- package/dist/index.js +81 -49
- 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
|
|
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
|
-
"
|
|
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 |
|
|
37
|
-
|
|
38
|
-
| `madeonsol_kol_feed` |
|
|
39
|
-
| `madeonsol_kol_coordination` |
|
|
40
|
-
| `madeonsol_kol_leaderboard` |
|
|
41
|
-
| `madeonsol_deployer_alerts` |
|
|
42
|
-
| `madeonsol_discovery` |
|
|
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
|
|
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
|
|
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
|
|
9
|
-
const RAPIDAPI_KEY = process.env.RAPIDAPI_KEY; //
|
|
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
|
-
|
|
14
|
-
if (
|
|
15
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
31
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
88
|
-
|
|
89
|
-
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
171
|
+
console.error("[madeonsol-mcp] Webhook & streaming tools enabled");
|
|
140
172
|
}
|
|
141
173
|
else {
|
|
142
|
-
console.error("[madeonsol-mcp]
|
|
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
|
|
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
|
|
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.
|
|
186
|
-
{ name: "madeonsol_kol_coordination", description: "Get KOL convergence signals — tokens multiple KOLs are accumulating.
|
|
187
|
-
{ name: "madeonsol_kol_leaderboard", description: "Get KOL performance rankings by PnL and win rate.
|
|
188
|
-
{ name: "madeonsol_deployer_alerts", description: "Get elite Pump.fun deployer alerts with KOL enrichment.
|
|
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.
|
|
191
|
-
{ name: "madeonsol_list_webhooks", description: "List your registered webhooks.
|
|
192
|
-
{ name: "madeonsol_delete_webhook", description: "Delete a webhook by ID.
|
|
193
|
-
{ name: "madeonsol_test_webhook", description: "Send a test payload to verify a webhook.
|
|
194
|
-
{ name: "madeonsol_stream_token", description: "Get a 24h WebSocket streaming token
|
|
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