Pump.fun MCP Server

  • src
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; import { Connection, Keypair } from "@solana/web3.js"; import { AnchorProvider } from "@coral-xyz/anchor"; import { PumpFunSDK } from "pumpdotfun-sdk"; import path from "path"; import dotenv from "dotenv"; import { rootDir } from "./utils.js"; import { getTokenInfo, formatTokenInfo, createMcpResponse, } from "./get-token-info.js"; import { buyToken, formatBuyResult } from "./buy-token.js"; import { sellToken, formatSellResult } from "./sell-token.js"; import { listAccounts, formatListAccountsResult } from "./list-accounts.js"; import { getAccountBalance } from "./get-token-balance.js"; import { createToken, formatCreateTokenResult } from "./create-token.js"; dotenv.config({ path: path.join(rootDir, ".env") }); const server = new McpServer({ name: "pumpfun", version: "1.0.0", }); function getProvider() { const rpcUrl = process.env.HELIUS_RPC_URL; if (!rpcUrl) { throw new Error("HELIUS_RPC_URL environment variable is not set"); } const connection = new Connection(rpcUrl); const wallet = new Keypair(); return new AnchorProvider( connection, { publicKey: wallet.publicKey, signTransaction: async () => { throw new Error("Not implemented"); }, signAllTransactions: async () => { throw new Error("Not implemented"); }, }, { commitment: "confirmed" } ); } function getSDK() { const provider = getProvider(); return new PumpFunSDK(provider); } server.tool( "get-token-info", "Get information about a Pump.fun token", { tokenAddress: z.string().describe("The token's mint address"), }, async ({ tokenAddress }, extra) => { try { console.error(`Checking token info for: ${tokenAddress}`); const tokenInfo = await getTokenInfo(tokenAddress); if (!tokenInfo) { return { content: [ { type: "text" as const, text: `No token found with address ${tokenAddress}`, }, ], }; } const formattedInfo = formatTokenInfo(tokenInfo); return createMcpResponse(formattedInfo); } catch (error: any) { console.error("Error getting token info:", error); return { content: [ { type: "text" as const, text: `Error getting token info: ${ error?.message || "Unknown error" }`, }, ], }; } } ); server.tool( "create-token", "Create a new Pump.fun token", { name: z.string().describe("Token name"), symbol: z.string().describe("Token symbol"), description: z.string().describe("Token description"), imageUrl: z.string().optional().describe("URL to token image (optional)"), initialBuyAmount: z .number() .min(0.0001) .describe("Initial buy amount in SOL"), accountName: z .string() .default("default") .describe( "Name of the account to use (will be created if it doesn't exist)" ), }, async ({ name, symbol, description, imageUrl, initialBuyAmount, accountName, }) => { try { const result = await createToken( name, symbol, description, imageUrl, initialBuyAmount, accountName ); const formattedResult = formatCreateTokenResult(result); return createMcpResponse(formattedResult); } catch (error: any) { console.error("Error creating token:", error); return { content: [ { type: "text", text: `Error creating token: ${error?.message || "Unknown error"}`, }, ], }; } } ); server.tool( "buy-token", "Buy a Pump.fun token", { tokenAddress: z.string().describe("The token's mint address"), buyAmount: z.number().min(0.0001).describe("Amount to buy in SOL"), accountName: z .string() .default("default") .describe("Name of the account to use"), slippageBasisPoints: z .number() .default(100) .describe("Slippage tolerance in basis points (1% = 100)"), }, async ({ tokenAddress, buyAmount, accountName, slippageBasisPoints }) => { try { console.error(`Buying token: ${tokenAddress}, amount: ${buyAmount} SOL`); const result = await buyToken( tokenAddress, buyAmount, accountName, slippageBasisPoints ); const formattedResult = formatBuyResult(result); return createMcpResponse(formattedResult); } catch (error: any) { console.error("Error buying token:", error); return { content: [ { type: "text" as const, text: `Error buying token: ${error?.message || "Unknown error"}`, }, ], }; } } ); server.tool( "sell-token", "Sell a Pump.fun token", { tokenAddress: z.string().describe("The token's mint address"), sellAmount: z .number() .min(0) .describe("Amount of tokens to sell (0 for all)"), accountName: z .string() .default("default") .describe("Name of the account to use"), slippageBasisPoints: z .number() .default(100) .describe("Slippage tolerance in basis points (1% = 100)"), }, async ({ tokenAddress, sellAmount, accountName, slippageBasisPoints }) => { try { console.error( `Selling token: ${tokenAddress}, amount: ${ sellAmount === 0 ? "ALL" : sellAmount }` ); const result = await sellToken( tokenAddress, sellAmount, accountName, slippageBasisPoints ); const formattedResult = formatSellResult(result); return createMcpResponse(formattedResult); } catch (error: any) { console.error("Error selling token:", error); return { content: [ { type: "text" as const, text: `Error selling token: ${error?.message || "Unknown error"}`, }, ], }; } } ); server.tool( "list-accounts", "List all accounts in the keys folder", {}, async () => { try { console.error("Listing accounts"); const result = await listAccounts(); const formattedResult = formatListAccountsResult(result); return createMcpResponse( formattedResult || "Error: No account information available" ); } catch (error: any) { console.error("Error listing accounts:", error); return { content: [ { type: "text" as const, text: `Error listing accounts: ${ error?.message || "Unknown error" }`, }, ], }; } } ); server.tool( "get-account-balance", "Get the SOL and token balances for an account", { accountName: z .string() .default("default") .describe("Name of the account to check"), tokenAddress: z .string() .optional() .describe("Optional token address to check balance for"), }, async ({ accountName, tokenAddress }) => { try { const result = await getAccountBalance(accountName, tokenAddress); return { content: [ { type: "text", text: result, }, ], }; } catch (error: any) { console.error("Error getting account balance:", error); return { content: [ { type: "text", text: `Error getting account balance: ${ error?.message || "Unknown error" }`, }, ], }; } } ); async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error("Pump Fun MCP Server running on stdio"); } main().catch((error) => { console.error("Fatal error in main():", error); process.exit(1); });