agentpump-mcp 1.1.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 +73 -0
- package/index.js +129 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# AgentPump MCP
|
|
2
|
+
|
|
3
|
+
Give your AI agent its own **Solana wallet** and let it **launch and trade tokens** on [AgentPump](https://app.agents-coin.com) โ a pump.fun-style bonding-curve launchpad on **Solana mainnet**. Works in Claude, Cursor, and any MCP client.
|
|
4
|
+
|
|
5
|
+
๐ **Website:** https://app.agents-coin.com ยท ๐ช **Launch & trade (web):** https://app.agents-coin.com/pump ยท ๐ฌ **Telegram bot:** https://t.me/AgentsPumpBot
|
|
6
|
+
|
|
7
|
+
The agent's key stays **local** (used only to sign โ never sent to the model or the cloud). You fund the wallet with SOL, then it can create and trade tokens autonomously. 1% per trade. Tokens graduate to Raydium at 10 SOL โ and your agent can keep trading them there too.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
### โก Claude Desktop โ one click (no npm, no terminal)
|
|
14
|
+
1. Download **[`agentpump.mcpb`](https://github.com/axiosdevs/agentpump-mcp/releases/latest/download/agentpump.mcpb)**
|
|
15
|
+
2. Open it with **Claude Desktop** โ *Settings โ Extensions โ Install*
|
|
16
|
+
3. That's it โ a mainnet RPC is built in. (Optional: set your own Helius/QuickNode RPC in the extension settings.)
|
|
17
|
+
|
|
18
|
+
### Any MCP client (Claude Code, Cursor, โฆ) via npx
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"mcpServers": {
|
|
22
|
+
"agentpump": {
|
|
23
|
+
"command": "npx",
|
|
24
|
+
"args": ["-y", "agentpump-mcp@latest"]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### From source
|
|
31
|
+
```bash
|
|
32
|
+
git clone https://github.com/axiosdevs/agentpump-mcp
|
|
33
|
+
cd agentpump-mcp && npm install
|
|
34
|
+
# then point your MCP client at: node /path/to/agentpump-mcp/index.js
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Talk to your agent
|
|
40
|
+
```
|
|
41
|
+
"create a Solana wallet"
|
|
42
|
+
"show my address" โ send real SOL there (no faucet on mainnet)
|
|
43
|
+
"launch a token called Doge AI (DOGEAI)"
|
|
44
|
+
"buy 0.1 SOL of <mint>" โ on the bonding curve
|
|
45
|
+
"sell 50% of <mint>"
|
|
46
|
+
"buy 0.2 SOL of <mint> on Raydium" โ once it graduated/listed
|
|
47
|
+
"sell 100% of <mint> on Raydium"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Tools
|
|
51
|
+
| Tool | What it does |
|
|
52
|
+
|---|---|
|
|
53
|
+
| `sol_create_wallet` | Create the agent's Solana wallet (saved locally, hidden) |
|
|
54
|
+
| `sol_address` | Show the wallet address to deposit SOL into |
|
|
55
|
+
| `sol_balance` | Check the SOL balance |
|
|
56
|
+
| `sol_launch` | Launch a token (name, symbol) on the bonding curve |
|
|
57
|
+
| `sol_buy` | Buy a token on its bonding curve (pre-graduation) |
|
|
58
|
+
| `sol_sell` | Sell a % of a holding back to the bonding curve |
|
|
59
|
+
| `sol_raydium_buy` | Buy a graduated/listed token on **Raydium** (1% fee) |
|
|
60
|
+
| `sol_raydium_sell` | Sell a graduated/listed token on **Raydium** (1% fee) |
|
|
61
|
+
|
|
62
|
+
## How it works
|
|
63
|
+
- **Local key** โ generated on your machine (`~/.agentpump/wallet.json`); only signatures hit the chain.
|
|
64
|
+
- **Real money** โ Solana **mainnet**. Fund the wallet with real SOL. Start small.
|
|
65
|
+
- **Fair launch** โ every token starts on a bonding curve (~80% of supply sold on the curve). 1% trade fee. Graduates to Raydium at 10 SOL, where liquidity is locked (LP burned).
|
|
66
|
+
- **Then trade on Raydium** โ after graduation the agent buys/sells on Raydium with `sol_raydium_*` (1% fee).
|
|
67
|
+
- **Program:** `4M93xdyduoYj4W7LaLRmXrk5PqyGD6SoxzX8CwdKe3VM`
|
|
68
|
+
|
|
69
|
+
## Also available (same launchpad, same 1% fee, auto-routed curve โ Raydium)
|
|
70
|
+
- ๐ช **Web (Phantom):** https://app.agents-coin.com/pump
|
|
71
|
+
- ๐ฌ **Telegram bot:** https://t.me/AgentsPumpBot โ Buy/Sell auto-route to the bonding curve before graduation and to **Raydium** after.
|
|
72
|
+
|
|
73
|
+
MIT licensed.
|
package/index.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// AgentPump MCP โ let an AI agent launch & trade tokens on the AgentPump launchpad (Solana mainnet).
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import {
|
|
7
|
+
Connection, Keypair, PublicKey, SystemProgram, Transaction,
|
|
8
|
+
TransactionInstruction, sendAndConfirmTransaction, LAMPORTS_PER_SOL,
|
|
9
|
+
} from "@solana/web3.js";
|
|
10
|
+
import {
|
|
11
|
+
createMint, getAssociatedTokenAddressSync, mintTo, getAccount,
|
|
12
|
+
createAssociatedTokenAccountIdempotentInstruction, TOKEN_PROGRAM_ID, NATIVE_MINT,
|
|
13
|
+
} from "@solana/spl-token";
|
|
14
|
+
import { Raydium, TxVersion, CurveCalculator, CREATE_CPMM_POOL_PROGRAM } from "@raydium-io/raydium-sdk-v2";
|
|
15
|
+
import BN from "bn.js";
|
|
16
|
+
import { homedir } from "os";
|
|
17
|
+
import { join } from "path";
|
|
18
|
+
import { mkdirSync, readFileSync, writeFileSync, existsSync, chmodSync } from "fs";
|
|
19
|
+
|
|
20
|
+
const RPC = process.env.AGENTPUMP_RPC || "https://mainnet.helius-rpc.com/?api-key=397a9216-3198-4f6b-8304-0bf3f62cf5bd";
|
|
21
|
+
const PROGRAM = new PublicKey("4M93xdyduoYj4W7LaLRmXrk5PqyGD6SoxzX8CwdKe3VM");
|
|
22
|
+
const FEE = new PublicKey("2tGTwpzcLLgp6D33Sns4cMZuz1Zg6rBnzjt3taqTmZz6");
|
|
23
|
+
const conn = new Connection(RPC, "confirmed");
|
|
24
|
+
const [CONFIG] = PublicKey.findProgramAddressSync([Buffer.from("config")], PROGRAM);
|
|
25
|
+
const V_SOL = 2500000000n, SUPPLY = 1000000000n * 1000000n;
|
|
26
|
+
const u64 = (n) => { const b = Buffer.alloc(8); b.writeBigUInt64LE(BigInt(n)); return b; };
|
|
27
|
+
const WDIR = join(homedir(), ".agentpump"), WFILE = join(WDIR, "wallet.json");
|
|
28
|
+
const curveOf = (m) => PublicKey.findProgramAddressSync([Buffer.from("curve"), m.toBuffer()], PROGRAM)[0];
|
|
29
|
+
const ataOf = (m, o) => getAssociatedTokenAddressSync(m, o, true);
|
|
30
|
+
|
|
31
|
+
function loadKp() { if (!existsSync(WFILE)) throw new Error("No wallet yet. Call sol_create_wallet first."); return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(readFileSync(WFILE)))); }
|
|
32
|
+
function tradeKeys(mint, curve, cAta, uAta, user) {
|
|
33
|
+
return [
|
|
34
|
+
{ pubkey: CONFIG, isSigner: false, isWritable: false }, { pubkey: curve, isSigner: false, isWritable: true }, { pubkey: mint, isSigner: false, isWritable: false },
|
|
35
|
+
{ pubkey: cAta, isSigner: false, isWritable: true }, { pubkey: uAta, isSigner: false, isWritable: true }, { pubkey: curve, isSigner: false, isWritable: true },
|
|
36
|
+
{ pubkey: FEE, isSigner: false, isWritable: true }, { pubkey: user, isSigner: true, isWritable: true },
|
|
37
|
+
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
const ok = (t) => ({ content: [{ type: "text", text: t }] });
|
|
41
|
+
|
|
42
|
+
// --- Raydium CPMM helpers (trade graduated/listed tokens; 1% fee to treasury) ---
|
|
43
|
+
let _ray;
|
|
44
|
+
async function ray(kp) { if (!_ray) _ray = await Raydium.load({ connection: conn, owner: kp, cluster: "mainnet", disableLoadToken: true }); return _ray; }
|
|
45
|
+
async function findCpmmPool(raydium, mint) {
|
|
46
|
+
const data = await raydium.api.fetchPoolByMints({ mint1: mint.toBase58(), mint2: NATIVE_MINT.toBase58() });
|
|
47
|
+
const pools = (data?.data || []).filter((p) => p.programId === CREATE_CPMM_POOL_PROGRAM.toBase58());
|
|
48
|
+
if (!pools.length) throw new Error("No Raydium pool found for this token yet โ it may not have graduated/listed, or the pool was just created (indexing can take a few minutes).");
|
|
49
|
+
pools.sort((a, b) => (b.tvl || 0) - (a.tvl || 0));
|
|
50
|
+
return pools[0].id;
|
|
51
|
+
}
|
|
52
|
+
function estimate(inAmt, inRes, outRes, ci) {
|
|
53
|
+
return CurveCalculator.swapBaseInput(inAmt, inRes, outRes, ci.tradeFeeRate, ci.creatorFeeRate, ci.protocolFeeRate, ci.fundFeeRate, false);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const s = new McpServer({ name: "agentpump", version: "1.1.0" });
|
|
57
|
+
|
|
58
|
+
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 () => {
|
|
59
|
+
if (existsSync(WFILE)) return ok("Wallet already exists: " + loadKp().publicKey.toBase58());
|
|
60
|
+
mkdirSync(WDIR, { recursive: true }); const kp = Keypair.generate();
|
|
61
|
+
writeFileSync(WFILE, JSON.stringify(Array.from(kp.secretKey))); chmodSync(WFILE, 0o600);
|
|
62
|
+
return ok("Wallet created: " + kp.publicKey.toBase58() + "\nFund it with SOL to start (no faucet on mainnet).");
|
|
63
|
+
});
|
|
64
|
+
s.tool("sol_address", "Show the agent's Solana wallet address to deposit SOL into.", {}, { title: "Address", readOnlyHint: true }, async () => ok(loadKp().publicKey.toBase58()));
|
|
65
|
+
s.tool("sol_balance", "Check the wallet's SOL balance.", {}, { title: "Balance", readOnlyHint: true }, async () => {
|
|
66
|
+
const kp = loadKp(); const b = await conn.getBalance(kp.publicKey); return ok((b / LAMPORTS_PER_SOL).toFixed(4) + " SOL\n" + kp.publicKey.toBase58());
|
|
67
|
+
});
|
|
68
|
+
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 }) => {
|
|
69
|
+
const kp = loadKp(); const mint = await createMint(conn, kp, kp.publicKey, null, 6);
|
|
70
|
+
const curve = curveOf(mint.publicKey), cAta = ataOf(mint.publicKey, curve);
|
|
71
|
+
await sendAndConfirmTransaction(conn, new Transaction().add(createAssociatedTokenAccountIdempotentInstruction(kp.publicKey, cAta, curve, mint.publicKey)), [kp]);
|
|
72
|
+
await mintTo(conn, kp, mint, cAta, kp, SUPPLY);
|
|
73
|
+
const ix = new TransactionInstruction({ programId: PROGRAM, data: Buffer.concat([Buffer.from([1]), u64(V_SOL), u64(SUPPLY)]), keys: [
|
|
74
|
+
{ pubkey: CONFIG, isSigner: false, isWritable: true }, { pubkey: curve, isSigner: false, isWritable: true }, { pubkey: mint.publicKey, isSigner: false, isWritable: false },
|
|
75
|
+
{ pubkey: cAta, isSigner: false, isWritable: true }, { pubkey: kp.publicKey, isSigner: true, isWritable: true }, { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
|
|
76
|
+
] });
|
|
77
|
+
await sendAndConfirmTransaction(conn, new Transaction().add(ix), [kp]);
|
|
78
|
+
return ok(`Launched ${symbol}. Token: ${mint.publicKey.toBase58()}\nTradeable on the curve; graduates to Raydium at 10 SOL.`);
|
|
79
|
+
});
|
|
80
|
+
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 }) => {
|
|
81
|
+
const kp = loadKp(); const mint = new PublicKey(ms); const curve = curveOf(mint), cAta = ataOf(mint, curve), uAta = ataOf(mint, kp.publicKey);
|
|
82
|
+
const tx = new Transaction().add(createAssociatedTokenAccountIdempotentInstruction(kp.publicKey, uAta, kp.publicKey, mint))
|
|
83
|
+
.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)]) }));
|
|
84
|
+
const sig = await sendAndConfirmTransaction(conn, tx, [kp]); return ok("Bought. " + sig);
|
|
85
|
+
});
|
|
86
|
+
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 }) => {
|
|
87
|
+
const kp = loadKp(); const mint = new PublicKey(ms); const curve = curveOf(mint), cAta = ataOf(mint, curve), uAta = ataOf(mint, kp.publicKey);
|
|
88
|
+
const acc = await getAccount(conn, uAta); const amt = (acc.amount * BigInt(Math.round(percent))) / 100n;
|
|
89
|
+
if (amt <= 0n) throw new Error("nothing to sell");
|
|
90
|
+
const ix = new TransactionInstruction({ programId: PROGRAM, keys: tradeKeys(mint, curve, cAta, uAta, kp.publicKey), data: Buffer.concat([Buffer.from([3]), u64(amt), u64(0)]) });
|
|
91
|
+
const sig = await sendAndConfirmTransaction(conn, new Transaction().add(ix), [kp]); return ok("Sold. " + sig);
|
|
92
|
+
});
|
|
93
|
+
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 }) => {
|
|
94
|
+
const kp = loadKp(); const mint = new PublicKey(ms);
|
|
95
|
+
const lamports = BigInt(Math.round(amt * LAMPORTS_PER_SOL));
|
|
96
|
+
const fee = lamports / 100n, swapIn = lamports - fee;
|
|
97
|
+
const uAta = ataOf(mint, kp.publicKey);
|
|
98
|
+
const raydium = await ray(kp);
|
|
99
|
+
const { poolInfo, poolKeys, rpcData } = await raydium.cpmm.getPoolInfoFromRpc(await findCpmmPool(raydium, mint)); // throws before any fee is charged
|
|
100
|
+
await sendAndConfirmTransaction(conn, new Transaction()
|
|
101
|
+
.add(SystemProgram.transfer({ fromPubkey: kp.publicKey, toPubkey: FEE, lamports: Number(fee) }))
|
|
102
|
+
.add(createAssociatedTokenAccountIdempotentInstruction(kp.publicKey, uAta, kp.publicKey, mint)), [kp]);
|
|
103
|
+
const baseIn = NATIVE_MINT.toBase58() === poolInfo.mintA.address;
|
|
104
|
+
const inA = new BN(swapIn.toString());
|
|
105
|
+
const sr = estimate(inA, baseIn ? rpcData.baseReserve : rpcData.quoteReserve, baseIn ? rpcData.quoteReserve : rpcData.baseReserve, rpcData.configInfo);
|
|
106
|
+
const { execute } = await raydium.cpmm.swap({ poolInfo, poolKeys, inputAmount: inA, swapResult: sr, slippage: 0.1, baseIn, txVersion: TxVersion.V0 });
|
|
107
|
+
const r = await execute({ sendAndConfirm: true });
|
|
108
|
+
return ok(`Bought on Raydium. tx ${r.txId}\n1% fee (${(Number(fee) / LAMPORTS_PER_SOL).toFixed(5)} SOL) sent to treasury.`);
|
|
109
|
+
});
|
|
110
|
+
s.tool("sol_raydium_sell", "Sell a percentage of a graduated/listed token on Raydium. Charges a 1% fee on the SOL proceeds.", { mint: z.string(), percent: z.number() }, { title: "Sell (Raydium)", readOnlyHint: false, openWorldHint: true }, async ({ mint: ms, percent }) => {
|
|
111
|
+
const kp = loadKp(); const mint = new PublicKey(ms);
|
|
112
|
+
const uAta = ataOf(mint, kp.publicKey);
|
|
113
|
+
const acc = await getAccount(conn, uAta); const amt = (acc.amount * BigInt(Math.round(percent))) / 100n;
|
|
114
|
+
if (amt <= 0n) throw new Error("nothing to sell");
|
|
115
|
+
const raydium = await ray(kp);
|
|
116
|
+
const { poolInfo, poolKeys, rpcData } = await raydium.cpmm.getPoolInfoFromRpc(await findCpmmPool(raydium, mint));
|
|
117
|
+
const baseIn = mint.toBase58() === poolInfo.mintA.address;
|
|
118
|
+
const inA = new BN(amt.toString());
|
|
119
|
+
const sr = estimate(inA, baseIn ? rpcData.baseReserve : rpcData.quoteReserve, baseIn ? rpcData.quoteReserve : rpcData.baseReserve, rpcData.configInfo);
|
|
120
|
+
const before = await conn.getBalance(kp.publicKey);
|
|
121
|
+
const { execute } = await raydium.cpmm.swap({ poolInfo, poolKeys, inputAmount: inA, swapResult: sr, slippage: 0.1, baseIn, txVersion: TxVersion.V0 });
|
|
122
|
+
const r = await execute({ sendAndConfirm: true });
|
|
123
|
+
const gained = (await conn.getBalance(kp.publicKey)) - before;
|
|
124
|
+
let feePaid = 0;
|
|
125
|
+
if (gained > 0) { feePaid = Math.floor(gained * 0.01); if (feePaid > 0) await sendAndConfirmTransaction(conn, new Transaction().add(SystemProgram.transfer({ fromPubkey: kp.publicKey, toPubkey: FEE, lamports: feePaid })), [kp]); }
|
|
126
|
+
return ok(`Sold on Raydium. tx ${r.txId}\n1% fee (${(feePaid / LAMPORTS_PER_SOL).toFixed(5)} SOL) sent to treasury.`);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
await s.connect(new StdioServerTransport());
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agentpump-mcp",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "MCP server to launch & trade tokens on AgentPump (Solana bonding-curve launchpad) from AI agents. Trade graduated tokens on Raydium.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"agentpump-mcp": "index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"index.js"
|
|
11
|
+
],
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=18"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mcp",
|
|
17
|
+
"solana",
|
|
18
|
+
"pump",
|
|
19
|
+
"launchpad",
|
|
20
|
+
"raydium",
|
|
21
|
+
"ai-agents",
|
|
22
|
+
"claude"
|
|
23
|
+
],
|
|
24
|
+
"homepage": "https://app.agents-coin.com",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/axiosdevs/agentpump-mcp"
|
|
28
|
+
},
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
32
|
+
"@raydium-io/raydium-sdk-v2": "^0.2.56-alpha",
|
|
33
|
+
"@solana/spl-token": "^0.4.8",
|
|
34
|
+
"@solana/web3.js": "^1.95.3",
|
|
35
|
+
"bn.js": "^5.2.4",
|
|
36
|
+
"zod": "^3.23.8"
|
|
37
|
+
}
|
|
38
|
+
}
|