agentpump-mcp 1.1.2 → 1.1.4
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/index.js +42 -7
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
} from "@solana/spl-token";
|
|
14
14
|
import { Raydium, TxVersion, CurveCalculator, CREATE_CPMM_POOL_PROGRAM } from "@raydium-io/raydium-sdk-v2";
|
|
15
15
|
import BN from "bn.js";
|
|
16
|
+
import bs58 from "bs58";
|
|
16
17
|
import { homedir } from "os";
|
|
17
18
|
import { join } from "path";
|
|
18
19
|
import { mkdirSync, readFileSync, writeFileSync, existsSync, chmodSync } from "fs";
|
|
@@ -25,7 +26,17 @@ const rpcFetch = async (u, o) => { let err; for (const url of RPCS) { try { cons
|
|
|
25
26
|
const conn = new Connection(RPC, { commitment: "confirmed", fetch: rpcFetch });
|
|
26
27
|
const [CONFIG] = PublicKey.findProgramAddressSync([Buffer.from("config")], PROGRAM);
|
|
27
28
|
const V_SOL = 2500000000n, SUPPLY = 1000000000n * 1000000n;
|
|
29
|
+
const META = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s");
|
|
28
30
|
const u64 = (n) => { const b = Buffer.alloc(8); b.writeBigUInt64LE(BigInt(n)); return b; };
|
|
31
|
+
const mstr = (s) => { const b = Buffer.from(s, "utf8"); const l = Buffer.alloc(4); l.writeUInt32LE(b.length); return Buffer.concat([l, b]); };
|
|
32
|
+
function metaIx(mint, auth, payer, name, sym) {
|
|
33
|
+
const [md] = PublicKey.findProgramAddressSync([Buffer.from("metadata"), META.toBuffer(), mint.toBuffer()], META);
|
|
34
|
+
const data = Buffer.concat([Buffer.from([33]), mstr(name), mstr(sym), mstr(""), Buffer.from([0, 0]), Buffer.from([0]), Buffer.from([0]), Buffer.from([0]), Buffer.from([1]), Buffer.from([0])]);
|
|
35
|
+
return new TransactionInstruction({ programId: META, keys: [
|
|
36
|
+
{ pubkey: md, isSigner: false, isWritable: true }, { pubkey: mint, isSigner: false, isWritable: false }, { pubkey: auth, isSigner: true, isWritable: false },
|
|
37
|
+
{ pubkey: payer, isSigner: true, isWritable: true }, { pubkey: auth, isSigner: false, isWritable: false }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
|
|
38
|
+
], data });
|
|
39
|
+
}
|
|
29
40
|
const WDIR = join(homedir(), ".agentpump"), WFILE = join(WDIR, "wallet.json");
|
|
30
41
|
const curveOf = (m) => PublicKey.findProgramAddressSync([Buffer.from("curve"), m.toBuffer()], PROGRAM)[0];
|
|
31
42
|
const ataOf = (m, o) => getAssociatedTokenAddressSync(m, o, true);
|
|
@@ -40,6 +51,15 @@ function tradeKeys(mint, curve, cAta, uAta, user) {
|
|
|
40
51
|
];
|
|
41
52
|
}
|
|
42
53
|
const ok = (t) => ({ content: [{ type: "text", text: t }] });
|
|
54
|
+
// retry once on transient RPC/simulation flaps (stale blockhash, rate-limit, node hiccup) — the tx didn't land, so it's safe
|
|
55
|
+
async function retryTransient(fn) {
|
|
56
|
+
try { return await fn(); }
|
|
57
|
+
catch (e) { const m = ((e && e.message) || "") + "";
|
|
58
|
+
if (/custom program error/i.test(m)) throw e; // deterministic on-chain rejection — a retry can't fix it
|
|
59
|
+
if (/simulat|blockhash|not found|expired|timed out|timeout|429|too many|fetch failed|ECONN|socket|rate limit/i.test(m)) { await new Promise((r) => setTimeout(r, 1000)); return await fn(); }
|
|
60
|
+
throw e; }
|
|
61
|
+
}
|
|
62
|
+
const send = (tx, signers) => retryTransient(() => sendAndConfirmTransaction(conn, tx, signers));
|
|
43
63
|
|
|
44
64
|
// --- Raydium CPMM helpers (trade graduated/listed tokens; 1% fee to treasury) ---
|
|
45
65
|
let _ray;
|
|
@@ -55,7 +75,7 @@ function estimate(inAmt, inRes, outRes, ci) {
|
|
|
55
75
|
return CurveCalculator.swapBaseInput(inAmt, inRes, outRes, ci.tradeFeeRate, ci.creatorFeeRate, ci.protocolFeeRate, ci.fundFeeRate, false);
|
|
56
76
|
}
|
|
57
77
|
|
|
58
|
-
const s = new McpServer({ name: "agentpump", version: "1.1.
|
|
78
|
+
const s = new McpServer({ name: "agentpump", version: "1.1.4" });
|
|
59
79
|
|
|
60
80
|
s.tool("sol_create_wallet", "Create the agent's Solana wallet (saved locally, hidden). Returns the address to fund.", {}, { title: "Create wallet", readOnlyHint: false }, async () => {
|
|
61
81
|
if (existsSync(WFILE)) return ok("Wallet already exists: " + loadKp().publicKey.toBase58());
|
|
@@ -68,29 +88,30 @@ s.tool("sol_balance", "Check the wallet's SOL balance.", {}, { title: "Balance",
|
|
|
68
88
|
const kp = loadKp(); const b = await conn.getBalance(kp.publicKey); return ok((b / LAMPORTS_PER_SOL).toFixed(4) + " SOL\n" + kp.publicKey.toBase58());
|
|
69
89
|
});
|
|
70
90
|
s.tool("sol_launch", "Launch a new token on AgentPump (bonding curve). Costs ~0.02 SOL in rent.", { name: z.string(), symbol: z.string() }, { title: "Launch token", readOnlyHint: false, openWorldHint: true }, async ({ name, symbol }) => {
|
|
71
|
-
const kp = loadKp(); const mint = await createMint(conn, kp, kp.publicKey, null, 6); // returns a PublicKey
|
|
91
|
+
const kp = loadKp(); const mint = await retryTransient(() => createMint(conn, kp, kp.publicKey, null, 6)); // returns a PublicKey
|
|
92
|
+
await send(new Transaction().add(metaIx(mint, kp.publicKey, kp.publicKey, name, symbol)), [kp]); // on-chain name/symbol so it shows on the launchpad
|
|
72
93
|
const curve = curveOf(mint), cAta = ataOf(mint, curve);
|
|
73
|
-
await
|
|
74
|
-
await mintTo(conn, kp, mint, cAta, kp, SUPPLY);
|
|
94
|
+
await send(new Transaction().add(createAssociatedTokenAccountIdempotentInstruction(kp.publicKey, cAta, curve, mint)), [kp]);
|
|
95
|
+
await retryTransient(() => mintTo(conn, kp, mint, cAta, kp, SUPPLY));
|
|
75
96
|
const ix = new TransactionInstruction({ programId: PROGRAM, data: Buffer.concat([Buffer.from([1]), u64(V_SOL), u64(SUPPLY)]), keys: [
|
|
76
97
|
{ pubkey: CONFIG, isSigner: false, isWritable: true }, { pubkey: curve, isSigner: false, isWritable: true }, { pubkey: mint, isSigner: false, isWritable: false },
|
|
77
98
|
{ pubkey: cAta, isSigner: false, isWritable: true }, { pubkey: kp.publicKey, isSigner: true, isWritable: true }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
|
|
78
99
|
] });
|
|
79
|
-
await
|
|
100
|
+
await send(new Transaction().add(ix), [kp]);
|
|
80
101
|
return ok(`Launched ${symbol}. Token: ${mint.toBase58()}\nTradeable on the curve; graduates to Raydium at 10 SOL.`);
|
|
81
102
|
});
|
|
82
103
|
s.tool("sol_buy", "Buy a token on its bonding curve (pre-graduation). For graduated tokens use sol_raydium_buy.", { mint: z.string(), sol: z.number() }, { title: "Buy (curve)", readOnlyHint: false, openWorldHint: true }, async ({ mint: ms, sol: amt }) => {
|
|
83
104
|
const kp = loadKp(); const mint = new PublicKey(ms); const curve = curveOf(mint), cAta = ataOf(mint, curve), uAta = ataOf(mint, kp.publicKey);
|
|
84
105
|
const tx = new Transaction().add(createAssociatedTokenAccountIdempotentInstruction(kp.publicKey, uAta, kp.publicKey, mint))
|
|
85
106
|
.add(new TransactionInstruction({ programId: PROGRAM, keys: tradeKeys(mint, curve, cAta, uAta, kp.publicKey), data: Buffer.concat([Buffer.from([2]), u64(Math.round(amt * LAMPORTS_PER_SOL)), u64(0)]) }));
|
|
86
|
-
const sig = await
|
|
107
|
+
const sig = await send(tx, [kp]); return ok("Bought. " + sig);
|
|
87
108
|
});
|
|
88
109
|
s.tool("sol_sell", "Sell a percentage of a token holding back to the bonding curve (pre-graduation). For graduated tokens use sol_raydium_sell.", { mint: z.string(), percent: z.number() }, { title: "Sell (curve)", readOnlyHint: false, openWorldHint: true }, async ({ mint: ms, percent }) => {
|
|
89
110
|
const kp = loadKp(); const mint = new PublicKey(ms); const curve = curveOf(mint), cAta = ataOf(mint, curve), uAta = ataOf(mint, kp.publicKey);
|
|
90
111
|
const acc = await getAccount(conn, uAta); const amt = (acc.amount * BigInt(Math.round(percent))) / 100n;
|
|
91
112
|
if (amt <= 0n) throw new Error("nothing to sell");
|
|
92
113
|
const ix = new TransactionInstruction({ programId: PROGRAM, keys: tradeKeys(mint, curve, cAta, uAta, kp.publicKey), data: Buffer.concat([Buffer.from([3]), u64(amt), u64(0)]) });
|
|
93
|
-
const sig = await
|
|
114
|
+
const sig = await send(new Transaction().add(ix), [kp]); return ok("Sold. " + sig);
|
|
94
115
|
});
|
|
95
116
|
s.tool("sol_raydium_buy", "Buy any graduated/listed token on Raydium (after it leaves the bonding curve). Charges a 1% fee.", { mint: z.string(), sol: z.number() }, { title: "Buy (Raydium)", readOnlyHint: false, openWorldHint: true }, async ({ mint: ms, sol: amt }) => {
|
|
96
117
|
const kp = loadKp(); const mint = new PublicKey(ms);
|
|
@@ -128,4 +149,18 @@ s.tool("sol_raydium_sell", "Sell a percentage of a graduated/listed token on Ray
|
|
|
128
149
|
return ok(`Sold on Raydium. tx ${r.txId}\n1% fee (${(feePaid / LAMPORTS_PER_SOL).toFixed(5)} SOL) sent to treasury.`);
|
|
129
150
|
});
|
|
130
151
|
|
|
152
|
+
s.tool("sol_withdraw", "Send SOL out of the agent wallet to any address. Omit 'sol' to send the whole balance (minus the network fee).", { to: z.string(), sol: z.number().optional() }, { title: "Withdraw SOL", readOnlyHint: false, openWorldHint: true }, async ({ to, sol }) => {
|
|
153
|
+
const kp = loadKp(); const dest = new PublicKey(to);
|
|
154
|
+
const bal = await conn.getBalance(kp.publicKey); const FEE_L = 5000;
|
|
155
|
+
let lamports = (sol == null) ? bal - FEE_L : Math.round(sol * LAMPORTS_PER_SOL);
|
|
156
|
+
if (lamports > bal - FEE_L) lamports = bal - FEE_L;
|
|
157
|
+
if (lamports <= 0) throw new Error("balance too low to withdraw (need to cover the ~0.000005 SOL network fee)");
|
|
158
|
+
const sig = await send(new Transaction().add(SystemProgram.transfer({ fromPubkey: kp.publicKey, toPubkey: dest, lamports })), [kp]);
|
|
159
|
+
return ok(`Sent ${(lamports / LAMPORTS_PER_SOL).toFixed(6)} SOL to ${to}\n${sig}`);
|
|
160
|
+
});
|
|
161
|
+
s.tool("sol_export_key", "Reveal the agent wallet's private key (base58) so it can be imported into Phantom/Solflare. Anyone with this key controls the funds — only show it to the wallet owner.", {}, { title: "Export private key", readOnlyHint: true }, async () => {
|
|
162
|
+
const kp = loadKp();
|
|
163
|
+
return ok("Private key (import into Phantom → 'Import Private Key'):\n" + bs58.encode(kp.secretKey) + "\n\n⚠️ Anyone with this key controls the wallet. Keep it secret.");
|
|
164
|
+
});
|
|
165
|
+
|
|
131
166
|
await s.connect(new StdioServerTransport());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentpump-mcp",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"description": "MCP server to launch & trade tokens on AgentPump (Solana bonding-curve launchpad) from AI agents. Trade graduated tokens on Raydium.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -37,4 +37,4 @@
|
|
|
37
37
|
"zod": "^3.23.8"
|
|
38
38
|
},
|
|
39
39
|
"mcpName": "io.github.axiosdevs/agentpump-mcp"
|
|
40
|
-
}
|
|
40
|
+
}
|