Skip to content

MCP server

An MCP server that lets an AI coding agent — Claude Code, Claude Desktop, Cursor — build your frontend against the Solana Deads APIs using the official SDKs correctly.

It does not replace the SDKs. Everything it returns points at @solanadeads/gravemint / @solanadeads/gravemarket calls rather than raw HTTP, because an integration that speaks raw HTTP has already skipped the typed errors, the retry and backoff, the rate limiter, and the client-version header we use to see who is on what before we change anything.

Install

jsonc
// claude_desktop_config.json
{
  "mcpServers": {
    "solanadeads": {
      "command": "npx",
      "args": ["-y", "@solanadeads/mcp"],
      "env": { "GRAVEMINT_API_KEY": "gm_live_..." }
    }
  }
}
bash
claude mcp add solanadeads \
  --env GRAVEMINT_API_KEY=gm_live_... \
  -- npx -y @solanadeads/mcp
jsonc
// .cursor/mcp.json
{
  "mcpServers": {
    "solanadeads": {
      "command": "npx",
      "args": ["-y", "@solanadeads/mcp"],
      "env": { "GRAVEMINT_API_KEY": "gm_live_..." }
    }
  }
}

GraveMarket's tools need no credential. GraveMint's are invite-only — without a key the server still runs and simply exposes fewer tools, so you can try it before you have one.

It must be a gm_live_ key

An MCP server runs server-side and sends no Origin header, so a gm_pub_ or gm_test_ browser key is correctly refused — origin binding is exactly what makes those safe to ship in a browser.

The server checks the prefix at startup and tells you, rather than letting you discover it later as an opaque 403 ORIGIN_NOT_ALLOWED. See Keys and origins.

Why you want it

Some rules in the partner contract are ones a language model gets wrong from first principles — the naive version looks entirely reasonable and compiles:

The ruleWhat gets written instead
priceDisplay is a union, not a number`${drop.price} SOL` — wrong for range and unknown, and leaks a price the creator deliberately hid
Never recompute a pricereassembles it from raw phase fields, but the cascade has ten stages and six are invisible to any public read
You sign, we broadcastsendTransaction()CLIENT_BROADCAST_NOT_ALLOWED
Batch errors live in results[].errorCodereads err.code, which is never set for any quantity above 1
walletMints counts bonus mints, eligibility does notderives "mints remaining" from the wrong one

review_integration checks for exactly these, with line numbers and fixes. Run it on your mint code before you ship it:

Review this file for Solana Deads integration mistakes.

Tools

Always available

ToolWhat it does
sdk_referenceThe real method signatures and docs, generated from the SDK source. Read this before writing integration code — it is the authoritative surface, not a summary of one.
review_integrationThe checks above, with line numbers and concrete fixes.

GraveMarket — no credential needed

gravemarket_get_collection · gravemarket_search · gravemarket_get_collection_activity · gravemarket_get_collection_stats

GraveMint — needs GRAVEMINT_API_KEY

The dropgravemint_get_collection · gravemint_check_eligibility · gravemint_get_wallet_mints · gravemint_get_availability

Its art and historygravemint_get_gallery · gravemint_get_recently_minted · gravemint_get_all_minted · gravemint_get_traits · gravemint_get_leaderboards

Pricinggravemint_get_token_prices · gravemint_get_phase_price

Claim codes — 17.6% of live drops use them gravemint_get_claim_codes · gravemint_get_claim_code_benefits · gravemint_validate_claim_code (read-only — it does not redeem or consume a use)

Bountygravemint_get_bounty

Reads are scoped to the collections your key covers. Another drop returns 403 COLLECTION_NOT_IN_SCOPE — the same confinement the HTTP API enforces, so an agent cannot wander into someone else's data even if it tries.

What it deliberately cannot do

Two properties that are structural, not policy — they hold because of how the server is built, not because a flag is set:

  1. It cannot mint. There is no wallet, so it cannot sign, so execute-mint is unreachable no matter what scopes your key carries.
  2. prepare-mint is not exposed. It is read-shaped and would be convenient for showing an agent the response, but it reserves: three-minute NFT locks and a BOGO ledger entry. A tool an agent might call speculatively must not take supply away from real collectors. sdk_reference gives you the response shape for free.

Staying in sync with the SDK

A drifted MCP is worse than none — it teaches an agent methods that do not exist, and the agent has no way to tell it was misled. So the sync is mechanical, in two layers:

  • Removals are a compile error. The SDKs are real dependencies and the tool handlers call them, so a renamed or deleted method fails the package's typecheck. Casts on SDK calls are banned for this reason.
  • Additions are caught by a drift gate that runs before every push: each SDK method must be reachable from a tool or explicitly listed as unexposed with a reason, and the generated reference must be current.

Nothing about the SDK surface is hand-written anywhere in the package.

SDK pages are generated from the published npm tarballs and cannot drift.