Pump.fun MCP Server

  • src
import { Connection, PublicKey, LAMPORTS_PER_SOL } from "@solana/web3.js"; import { AnchorProvider } from "@coral-xyz/anchor"; import { PumpFunSDK, DEFAULT_DECIMALS } from "pumpdotfun-sdk"; import dotenv from "dotenv"; import path from "path"; import { rootDir, safeStringify } from "./utils.js"; dotenv.config({ path: path.join(rootDir, ".env") }); export function initializeSDK() { 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 provider = new AnchorProvider( connection, { publicKey: new PublicKey("11111111111111111111111111111111"), signTransaction: async () => { throw new Error("Not implemented"); }, signAllTransactions: async () => { throw new Error("Not implemented"); }, }, { commitment: "confirmed" } ); return { sdk: new PumpFunSDK(provider), connection, }; } export async function getTokenInfo(tokenAddress: string) { const { sdk } = initializeSDK(); console.log("SDK initialized"); const mintPublicKey = new PublicKey(tokenAddress); console.log("Getting bonding curve account..."); const bondingCurveAccount = await sdk.getBondingCurveAccount(mintPublicKey); if (!bondingCurveAccount) { console.log(`No token found with address ${tokenAddress}`); return null; } const tokenTotalSupply = (bondingCurveAccount as any).tokenTotalSupply; const formattedSupply = tokenTotalSupply ? Number(tokenTotalSupply) / Math.pow(10, DEFAULT_DECIMALS) : "Unknown"; return { tokenAddress, bondingCurveAccount, formattedSupply, pumpfunUrl: `https://pump.fun/${tokenAddress}`, }; } export function formatTokenInfo( tokenInfo: ReturnType<typeof getTokenInfo> extends Promise<infer T> ? NonNullable<T> : never ) { return [ `Token: ${tokenInfo.tokenAddress}`, `Supply: ${tokenInfo.formattedSupply}`, `Pump.fun URL: ${tokenInfo.pumpfunUrl}`, ].join("\n"); } export function createMcpResponse(text: string) { return { content: [ { type: "text" as const, text, }, ], }; } async function main() { const tokenAddress = process.argv[2]; if (!tokenAddress) { console.error("Please provide a token address as a command line argument"); process.exit(1); } console.log(`Checking token info for: ${tokenAddress}`); try { const tokenInfo = await getTokenInfo(tokenAddress); if (!tokenInfo) { return; } console.log("Raw account data:"); console.log(safeStringify(tokenInfo.bondingCurveAccount)); console.log("\nObject structure:"); console.log("Type:", typeof tokenInfo.bondingCurveAccount); console.log( "Constructor:", tokenInfo.bondingCurveAccount.constructor?.name ); console.log("Properties:", Object.keys(tokenInfo.bondingCurveAccount)); console.log("\nProperty types:"); for (const key of Object.keys(tokenInfo.bondingCurveAccount)) { const value = (tokenInfo.bondingCurveAccount as any)[key]; console.log(`${key}: ${typeof value}`); } try { const { sdk } = initializeSDK(); console.log("\nAttempting to get global account..."); const globalAccount = await sdk.getGlobalAccount(); console.log("Global account:", safeStringify(globalAccount)); } catch (error) { console.log("Error getting global account:", error); } console.log("\nToken Information:"); const formattedInfo = formatTokenInfo(tokenInfo); console.log(formattedInfo); const mcpResponse = createMcpResponse(formattedInfo); console.log("\nMCP Response (for reference):"); console.log(JSON.stringify(mcpResponse, null, 2)); } catch (error: any) { console.error("Error getting token info:", error); } } const isMainModule = import.meta.url === `file://${process.argv[1]}`; if (isMainModule) { main().catch(console.error); } export default { getTokenInfo, formatTokenInfo, createMcpResponse, initializeSDK, safeStringify, };