Skip to content

zelvf/holder-launch

v0.1.0

Prepare pump.fun token launches with mandatory holder rewards and verify launch status. Approval takes place on a separate review page.

Holder Launch

A private pump.fun token-launch integration for ChatGPT and Claude. The MCP server prepares drafts and verifies status. A separate browser page handles wallet signing or approval to spend from a configured sponsor wallet.

Status: implemented and locally tested; not deployed, installed in ChatGPT/Claude, approved for a public directory, or tested by minting a real token. Mainnet spending is off by default. This is a single-operator prototype, not a public multi-tenant launch service.

Wallet recommendation

Use the requester's own wallet as the default. They cover launch costs and sign the exact reviewed transaction. You do not need to hold their keys or subsidize arbitrary launches.

For your personal use or selected users, enable a separate sponsor wallet funded with a small amount of SOL. The sponsor signs on the server after approval on the review page. Daily spending and launch-count limits apply. Do not use your main wallet as the sponsor.

Both modes permanently set holderReward: true. There is no setting to redirect fees to the operator or to disable holder rewards. Cashback and mayhem mode are off. The application charges no additional fee and performs no initial buy.

Creator fees fund pump.fun holder rewards. This does not redirect network fees, protocol fees or other platform charges. Pump.fun controls eligible holders, payout timing and distribution expenses. The token supply is created using pump.fun's bonding-curve mechanism; it is not airdropped into a reward wallet. Holder rewards arise from later trading.

Official references: holder rewards, coin creation, fees.

Run on Windows

Requires Node.js 24 or newer.

npm.cmd ci --ignore-scripts
npm.cmd run setup
npm.cmd run build
npm.cmd start

Open http://localhost:3434. setup creates .env with a random operator password, without printing it. Read the password locally in that file to sign in. Never send it or a wallet private key to an assistant. Existing .env files are preserved.

The preview can create and review drafts. It cannot simulate or broadcast a mainnet launch until ENABLE_MAINNET_LAUNCH=true. No AI API key is required: the connected assistant invokes MCP tools.

Prepare real token metadata

Host your image and metadata JSON on IPFS or a durable public HTTPS service. The metadata URI must be at most 200 characters. A typical JSON file is:

{
  "name": "Community Token",
  "symbol": "COMM",
  "description": "A community token with pump.fun holder rewards.",
  "image": "ipfs://YOUR_IMAGE_CID",
  "showName": true
}

Pass the JSON file URI, not the image URI, to the launch tool. This version accepts existing metadata; it does not upload or pin images. The server never fetches arbitrary metadata URLs. Make sure the URI is public, permanent, and matches the reviewed name and symbol.

Enable launch modes

Configure these values locally or in your host's secret manager:

SettingPurpose
PUBLIC_BASE_URLPublic HTTPS origin used for review links and OAuth discovery
SOLANA_RPC_URLReliable Solana mainnet RPC endpoint
ENABLE_MAINNET_LAUNCH=trueAllows simulation, signing and broadcast after browser approval
MAX_LAUNCH_COST_SOLMaximum accepted simulation estimate, default 0.03 SOL
SPONSOR_KEYPAIR_PATHOptional path to a dedicated 64-byte Solana CLI keypair JSON file
SPONSOR_DAILY_BUDGET_SOLSponsor reservation cap per UTC day, default 0.1 SOL
SPONSOR_DAILY_LAUNCH_LIMITSponsor launches per UTC day, default 5
OPERATOR_PASSWORDAt least 8 characters for spending-disabled use; 24 before enabling mainnet launches; generated by setup

For user-wallet launches, connect Phantom or Solflare on the review page and ensure the public address matches the draft. The browser requests a signature; the server verifies the exact message and every required signature before broadcasting.

For sponsored launches, mount the keypair file outside the repository and set its absolute path. The server loads it without sending it to the model or browser. Review the token, simulate, then approve the sponsor payment on the review page. There is no unrestricted autonomous spending tool in MCP.

Network fees and rent are estimated by RPC simulation. The sponsor reserves the entire configured maximum for each submission, rather than trusting a smaller estimate. Reservations stay charged for the day after failure or uncertainty. A cap is an application control, not an on-chain spending vault; the operator must protect the sponsor key and avoid using it elsewhere.

Connect ChatGPT

For a temporary spending-disabled test with the already-installed Cloudflare CLI, run these in two terminals from this folder:

# Terminal 1: keep running; copy the HTTPS address it prints.
cloudflared tunnel --url http://127.0.0.1:3435 --no-autoupdate --protocol http2

# Terminal 2: replace the example origin with that generated HTTPS address.
npm.cmd run preview:chatgpt -- https://YOUR_TEMPORARY_HOST.trycloudflare.com

This preview uses a separate test database on port 3435 and always disables mainnet spending and sponsor-key loading, regardless of the regular .env settings. It uses the same OPERATOR_PASSWORD as the local service. Add the generated address followed by /mcp to ChatGPT using the steps below. The address changes when the tunnel restarts; the computer and both processes must remain running. Do not enable Cloudflare's interactive email gate for MCP: the assistant's requests cannot pass a browser-only login gate.

To verify the temporary endpoint without printing credentials or spending SOL:

node --env-file-if-exists=.env scripts/verify-connection.mjs https://YOUR_TEMPORARY_HOST.trycloudflare.com

The check exercises OAuth PKCE, discovers tools, calls get_launch_policy, and revokes its temporary access. It does not register the plugin in your ChatGPT account.

  1. Host the service at a public HTTPS origin with a persistent disk, or use a supported development tunnel. Set PUBLIC_BASE_URL to that origin and restart.
  2. Open ChatGPT Plugins → plus → Add custom MCP server. Account and workspace policies may affect availability.
  3. Enter the endpoint https://YOUR_HOST/mcp and choose OAuth. The service supports discovery, dynamic client registration, authorization-code PKCE (S256), scoped access tokens, rotating refresh tokens and revocation.
  4. Authenticate on this service's own page using the operator password within 30 minutes. If the authorization page expires, start a fresh connection from ChatGPT. The assistant receives permission to prepare drafts and read status, not to sign transactions.
  5. Enable the resulting private connection in a new conversation.

Example prompt:

Prepare a pump.fun token named Community Token, symbol COMM, with metadata at [my JSON URI]. Use my public wallet [address]. Enable holder rewards and give me the review link. Do not say it is launched until confirmation is verified.

Generate a portable plugin package after choosing the endpoint:

npm.cmd run package:plugin -- https://YOUR_HOST/mcp

The output is dist/holder-launch/plugin.json plus mcp.json. Without an argument it targets local development at http://localhost:3434/mcp; this is not a public connector endpoint. Packaging does not register, install, publish or approve a plugin.

Platform restriction: OpenAI's current public plugin guidelines list execution of crypto transfers and investment trades among prohibited activities. Keeping approval outside chat is an architectural separation, not a claim of an exemption or directory eligibility. Public distribution of this token-launch product requires platform review and may not be accepted. The current version is for private development and evaluation.

Sources: connect a custom MCP server, OAuth, plugin packaging, plugin guidelines.

Connect Claude

The same MCP endpoint can be used without rewriting the backend. In Claude's connector settings, add a custom remote connector, enter https://YOUR_HOST/mcp, use OAuth with Register automatically, and authenticate on the service's page. The server implements DCR, not CIMD client-identity fetching. Exact menus and access depend on the Claude plan and organization settings.

The request still ends with a separate browser review link. Wallet signing requires a browser with the relevant wallet extension. Remote connector requests originate from Claude's infrastructure, so a local-only server is not sufficient for this remote configuration.

The server accepts ChatGPT's connection-specific https://chatgpt.com/connector/oauth/{callback_id} callback shape and the fixed callbacks in OAUTH_REDIRECT_URIS. If another host uses a different callback, add that exact callback URI to OAUTH_REDIRECT_URIS. Do not replace the allowlist with an unrestricted wildcard.

Source: Claude custom connectors.

MCP tools

ToolBehavior
get_launch_policyRead available modes, fee behavior, mainnet switch and caps
prepare_token_launchPersist an idempotent draft and return its private review URL; no mint or spend
get_launch_statusCheck transaction status and verify the on-chain holder-reward flag and recipient PDA

prepare_token_launch accepts requestKey, name, symbol, metadataUri, mode (user_wallet or sponsored), and a public wallet for user-wallet mode. Reuse the same requestKey when retrying the same request. A different payload with the same key is rejected.

State flow: draft → prepared → submitted → confirmed. Confirmation requires a successful Solana transaction plus a Pump-owned bonding curve with isHolderReward=true and its expected holder-reward creator PDA. Failed transactions become failed; failed reward verification becomes verification_failed. Neither is reported as success.

The signature is saved before broadcast. A network timeout leaves the launch pending with its saved signature, rather than triggering another token creation. If a submission remains unknown or a transaction expires, reconcile the saved signature before preparing a replacement. This prototype intentionally does not automatically rebuild or rebroadcast uncertain transactions.

Hosting and storage

SQLite stores drafts, OAuth registrations/tokens and budget reservations under data/. Use a single service with persistent storage and backups. Do not deploy this database on an ephemeral serverless filesystem or scale it across independent disks.

The included Dockerfile runs Node 24 as a non-root user. A deployment must mount /app/data, provide the environment variables, terminate HTTPS, and preserve the configured external Host header. The container listens on port 3434. A sponsor keypair is mounted read-only outside /app/data if that mode is used. Container execution has not been tested in this workspace.

All OAuth clients belong to the same operator. Browser spend authorization is separate from MCP authorization. A public multi-user product needs real user accounts, isolated launch ownership, requester-specific quotas, sponsor eligibility and a managed signing service before rollout.

Validation and release limits

npm.cmd run check

Ten automated tests cover SDK instruction decoding, real transaction construction with controlled RPC responses, mainnet/feature checks, validation, idempotency, signature and message tampering, sponsor budget limits, uncertain submission recovery, failed reward verification, and a complete OAuth/PKCE + MCP HTTP flow.

Browser QA exercised password login, draft creation, review, disabled spending, and desktop/mobile layout. A read-only live RPC check confirmed Solana mainnet and isHolderRewardEnabled=true on 2026-10-23. No real wallet signature, paid token launch, payout, hosted ChatGPT connection or hosted Claude connection was executed.

npm audit currently reports 14 findings in the Pump/Solana dependency tree (7 high, 7 moderate). The direct rate-limiter advisory was fixed. Remaining roots include bigint-buffer, toml, stream-json and uuid; npm's suggested forced fix downgrades Pump SDK to a version unsuitable for holder rewards. See SECURITY.md. Do not describe this build as audited or ready for a public funded service.