agentpump-mcp 1.1.3 → 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.
Files changed (2) hide show
  1. package/index.js +32 -8
  2. package/package.json +1 -1
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";
@@ -50,6 +51,15 @@ function tradeKeys(mint, curve, cAta, uAta, user) {
50
51
  ];
51
52
  }
52
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));
53
63
 
54
64
  // --- Raydium CPMM helpers (trade graduated/listed tokens; 1% fee to treasury) ---
55
65
  let _ray;
@@ -65,7 +75,7 @@ function estimate(inAmt, inRes, outRes, ci) {
65
75
  return CurveCalculator.swapBaseInput(inAmt, inRes, outRes, ci.tradeFeeRate, ci.creatorFeeRate, ci.protocolFeeRate, ci.fundFeeRate, false);
66
76
  }
67
77
 
68
- const s = new McpServer({ name: "agentpump", version: "1.1.0" });
78
+ const s = new McpServer({ name: "agentpump", version: "1.1.4" });
69
79
 
70
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 () => {
71
81
  if (existsSync(WFILE)) return ok("Wallet already exists: " + loadKp().publicKey.toBase58());
@@ -78,30 +88,30 @@ s.tool("sol_balance", "Check the wallet's SOL balance.", {}, { title: "Balance",
78
88
  const kp = loadKp(); const b = await conn.getBalance(kp.publicKey); return ok((b / LAMPORTS_PER_SOL).toFixed(4) + " SOL\n" + kp.publicKey.toBase58());
79
89
  });
80
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 }) => {
81
- const kp = loadKp(); const mint = await createMint(conn, kp, kp.publicKey, null, 6); // returns a PublicKey
82
- await sendAndConfirmTransaction(conn, new Transaction().add(metaIx(mint, kp.publicKey, kp.publicKey, name, symbol)), [kp]); // on-chain name/symbol so it shows on the launchpad
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
83
93
  const curve = curveOf(mint), cAta = ataOf(mint, curve);
84
- await sendAndConfirmTransaction(conn, new Transaction().add(createAssociatedTokenAccountIdempotentInstruction(kp.publicKey, cAta, curve, mint)), [kp]);
85
- 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));
86
96
  const ix = new TransactionInstruction({ programId: PROGRAM, data: Buffer.concat([Buffer.from([1]), u64(V_SOL), u64(SUPPLY)]), keys: [
87
97
  { pubkey: CONFIG, isSigner: false, isWritable: true }, { pubkey: curve, isSigner: false, isWritable: true }, { pubkey: mint, isSigner: false, isWritable: false },
88
98
  { pubkey: cAta, isSigner: false, isWritable: true }, { pubkey: kp.publicKey, isSigner: true, isWritable: true }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
89
99
  ] });
90
- await sendAndConfirmTransaction(conn, new Transaction().add(ix), [kp]);
100
+ await send(new Transaction().add(ix), [kp]);
91
101
  return ok(`Launched ${symbol}. Token: ${mint.toBase58()}\nTradeable on the curve; graduates to Raydium at 10 SOL.`);
92
102
  });
93
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 }) => {
94
104
  const kp = loadKp(); const mint = new PublicKey(ms); const curve = curveOf(mint), cAta = ataOf(mint, curve), uAta = ataOf(mint, kp.publicKey);
95
105
  const tx = new Transaction().add(createAssociatedTokenAccountIdempotentInstruction(kp.publicKey, uAta, kp.publicKey, mint))
96
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)]) }));
97
- const sig = await sendAndConfirmTransaction(conn, tx, [kp]); return ok("Bought. " + sig);
107
+ const sig = await send(tx, [kp]); return ok("Bought. " + sig);
98
108
  });
99
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 }) => {
100
110
  const kp = loadKp(); const mint = new PublicKey(ms); const curve = curveOf(mint), cAta = ataOf(mint, curve), uAta = ataOf(mint, kp.publicKey);
101
111
  const acc = await getAccount(conn, uAta); const amt = (acc.amount * BigInt(Math.round(percent))) / 100n;
102
112
  if (amt <= 0n) throw new Error("nothing to sell");
103
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)]) });
104
- const sig = await sendAndConfirmTransaction(conn, new Transaction().add(ix), [kp]); return ok("Sold. " + sig);
114
+ const sig = await send(new Transaction().add(ix), [kp]); return ok("Sold. " + sig);
105
115
  });
106
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 }) => {
107
117
  const kp = loadKp(); const mint = new PublicKey(ms);
@@ -139,4 +149,18 @@ s.tool("sol_raydium_sell", "Sell a percentage of a graduated/listed token on Ray
139
149
  return ok(`Sold on Raydium. tx ${r.txId}\n1% fee (${(feePaid / LAMPORTS_PER_SOL).toFixed(5)} SOL) sent to treasury.`);
140
150
  });
141
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
+
142
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",
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": {