Skip to main content
The Phantom MCP server (@phantom/mcp-server) enables AI assistants like Claude to interact with Phantom embedded wallets through natural language. AI agents can view wallet addresses, sign transactions, transfer tokens, and sign messages across Solana, Ethereum, Bitcoin, and Sui.
This MCP server is currently in preview and may change at any time without notice. Always use a separate Phantom account specifically for testing with AI agents. Phantom makes no guarantees around anything your agent may do using this MCP server. Never use accounts containing significant assets.
Looking for the MCP server that gives your AI coding assistant access to Phantom developer documentation? See the Phantom Connect SDK MCP server documentation.

Features

  • SSO authentication: Seamless integration with Phantom’s embedded wallet SSO flow (Google/Apple login)
  • Session persistence: Automatic session management with stamper keys stored locally
  • Multi-chain support: Works with Solana, Ethereum, Bitcoin, and Sui networks
  • Five MCP tools:
    • get_wallet_addresses — Get blockchain addresses for the authenticated embedded wallet
    • sign_transaction — Sign transactions across supported chains
    • transfer_tokens — Transfer SOL or SPL tokens on Solana
    • buy_token — Fetch a Solana swap quote from the Phantom quotes API
    • sign_message — Sign UTF-8 messages with automatic chain-specific routing

Prerequisites

Before using the MCP server, you need an App ID from Phantom Portal.
1

Visit Phantom Portal

Go to phantom.com/portal and sign in with your Google or Apple account.
2

Create an app

Select Create App and fill in the required details.
3

Configure redirect URL

Navigate to Dashboard > View App > Redirect URLs and add http://localhost:8080/callback as a redirect URL. This allows the OAuth callback to work correctly.
4

Get your App ID

Navigate to the Phantom Connect tab to find your App ID. Copy it for use in the MCP server configuration.
The email you use to sign in to Phantom Portal must match the email you use when authenticating in the MCP server. If these don’t match, authentication will fail.

Installation

Use npx to run the server without global installation. This ensures you always use the latest version:
npx -y @phantom/mcp-server

Option 2: Global install

Install the package globally for faster startup:
npm install -g @phantom/mcp-server
Then run:
phantom-mcp

Setup guides

Add the MCP server to your Claude Desktop configuration file.Configuration file location:
  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%/Claude/claude_desktop_config.json
Using npx (recommended):
{
  "mcpServers": {
    "phantom": {
      "command": "npx",
      "args": ["-y", "@phantom/mcp-server"],
      "env": {
        "PHANTOM_APP_ID": "your_app_id_from_portal"
      }
    }
  }
}
Using global install:
{
  "mcpServers": {
    "phantom": {
      "command": "phantom-mcp",
      "env": {
        "PHANTOM_APP_ID": "your_app_id_from_portal"
      }
    }
  }
}
After updating the config, restart Claude Desktop to load the server.

Environment variables

Configure the server behavior using environment variables.

Required

VariableDescription
PHANTOM_APP_IDYour App ID from Phantom Portal (required)

Optional

VariableDescriptionDefault
PHANTOM_CLIENT_SECRETClient secret for confidential clients
PHANTOM_CALLBACK_PORTOAuth callback port8080
PHANTOM_CALLBACK_PATHOAuth callback path/callback
PHANTOM_MCP_DEBUGEnable debug logging (set to 1)

Client types

  • Public client (recommended): Provide only PHANTOM_APP_ID. Uses PKCE for security, similar to the browser SDK.
  • Confidential client: Provide both PHANTOM_APP_ID and PHANTOM_CLIENT_SECRET. Uses HTTP Basic Auth + PKCE.

Authentication flow

On first run, the server will:
  1. Use the App ID from the PHANTOM_APP_ID environment variable
  2. Open your default browser to https://connect.phantom.app for Google/Apple login
  3. Start a local server on port 8080 to receive the SSO callback
  4. Save your session to ~/.phantom-mcp/session.json
Sessions use stamper keys which don’t expire. The embedded wallet is created during SSO authentication and persists across sessions.

Available tools

transfer_tokens always submits a transaction immediately, and buy_token can submit immediately when execute: true. If you need finer control (simulation, review, multi-sig, or custom signing), build your own transaction and use sign_transaction instead.

get_wallet_addresses

Gets all blockchain addresses for the authenticated embedded wallet (Solana, Ethereum, Bitcoin, Sui). Parameters:
ParameterTypeRequiredDescription
derivationIndexnumberNoDerivation index for the addresses (default: 0)
Example request:
{
  "derivationIndex": 0
}
Example response:
{
  "walletId": "05307b6d-2d5a-43d6-8d11-08db650a169b",
  "organizationId": "9b0ea123-5e7f-4dbe-88c5-7d769e2f8c8e",
  "addresses": [
    { "addressType": "Solana", "address": "H8FpYTgx4Uy9aF9Nk9fCTqKKFLYQ9KfC6UJhMkMDzCBh" },
    { "addressType": "Ethereum", "address": "0x8d8b06e017944f5951418b1182d119a376efb39d" },
    { "addressType": "BitcoinSegwit", "address": "bc1qkce5fvaxe759yu5xle5axlh8c7durjsx2wfhr9" },
    { "addressType": "Sui", "address": "0x039039cf69a336cb84e4c1dbcb3fa0c3f133d11b8146c6f7ed0d9f6817529a62" }
  ]
}

sign_transaction

Signs a transaction using the authenticated embedded wallet. Supports Solana, Ethereum, Bitcoin, and other chains. Parameters:
ParameterTypeRequiredDescription
transactionstringYesThe transaction to sign (base64url for Solana, RLP-encoded hex for Ethereum)
networkIdstringYesNetwork identifier (e.g., solana:mainnet, eip155:1)
walletIdstringNoThe wallet ID to use for signing (defaults to authenticated wallet)
derivationIndexnumberNoDerivation index for the account (default: 0)
accountstringNoSpecific account address to use for simulation/signing
Example request:
{
  "transaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQABAgMEBQYH...",
  "networkId": "solana:mainnet",
  "derivationIndex": 0
}
Example response:
{
  "signedTransaction": "base64url-encoded-signed-transaction"
}

transfer_tokens

Transfers SOL or SPL tokens on Solana by building, signing, and sending the transaction. Parameters:
ParameterTypeRequiredDescription
networkIdstringYesSolana network identifier (e.g., solana:mainnet, solana:devnet)
tostringYesRecipient Solana address
amountstringYesTransfer amount as a string (e.g., "0.5" or "1000000")
walletIdstringNoThe wallet ID to use for transfer (defaults to authenticated wallet)
amountUnitstringNoAmount unit: ui for SOL/token units, base for lamports (default: ui)
tokenMintstringNoSPL token mint address (omit for native SOL)
decimalsnumberNoToken decimals (fetched from chain if omitted)
derivationIndexnumberNoDerivation index for the account (default: 0)
rpcUrlstringNoSolana RPC URL (defaults based on networkId)
createAssociatedTokenAccountbooleanNoCreate destination ATA if missing (default: true)
Example request (SOL transfer):
{
  "networkId": "solana:mainnet",
  "to": "H8FpYTgx4Uy9aF9Nk9fCTqKKFLYQ9KfC6UJhMkMDzCBh",
  "amount": "0.1",
  "amountUnit": "ui"
}
Example request (SPL token transfer):
{
  "networkId": "solana:devnet",
  "to": "H8FpYTgx4Uy9aF9Nk9fCTqKKFLYQ9KfC6UJhMkMDzCBh",
  "tokenMint": "So11111111111111111111111111111111111111112",
  "amount": "1.5",
  "amountUnit": "ui"
}
Example response:
{
  "walletId": "05307b6d-2d5a-43d6-8d11-08db650a169b",
  "networkId": "solana:mainnet",
  "from": "H8FpYTgx4Uy9aF9Nk9fCTqKKFLYQ9KfC6UJhMkMDzCBh",
  "to": "H8FpYTgx4Uy9aF9Nk9fCTqKKFLYQ9KfC6UJhMkMDzCBh",
  "tokenMint": null,
  "signature": "5oVZJ8b7k2rGm3rP3Gm5J3tFjR6eUpCkG6TGNKxgqQ7s...",
  "rawTransaction": "base64url-encoded-signed-transaction"
}

buy_token

Fetches a Solana swap quote from the Phantom quotes API. Optionally signs and sends the first quote transaction when execute: true. Parameters:
ParameterTypeRequiredDescription
amountstringYesSell amount (e.g., "0.5" or "1000000")
walletIdstringNoThe wallet ID for the taker address (defaults to authenticated wallet)
networkIdstringNoSolana network identifier (default: solana:mainnet)
buyTokenMintstringNoMint address of the token to buy (omit if buying native SOL)
buyTokenIsNativebooleanNoSet true to buy native SOL (default: false)
sellTokenMintstringNoMint address of the token to sell (omit if selling native SOL)
sellTokenIsNativebooleanNoSet true to sell native SOL (default: true if sellTokenMint is not provided)
amountUnitstringNoAmount unit: ui for token units, base for atomic units (default: base)
slippageTolerancenumberNoSlippage tolerance in percent (0–100)
executebooleanNoIf true, sign and send the first quote transaction after fetching
derivationIndexnumberNoDerivation index for the taker address (default: 0)
Example request:
{
  "networkId": "solana:mainnet",
  "sellTokenIsNative": true,
  "buyTokenMint": "So11111111111111111111111111111111111111112",
  "amount": "0.5",
  "amountUnit": "ui",
  "slippageTolerance": 1,
  "execute": true
}

sign_message

Signs a UTF-8 message using the authenticated embedded wallet. Automatically routes to the correct signing method based on the network. Parameters:
ParameterTypeRequiredDescription
messagestringYesThe UTF-8 message to sign
networkIdstringYesNetwork identifier (e.g., eip155:1, solana:mainnet)
walletIdstringNoThe wallet ID to use for signing (defaults to authenticated wallet)
derivationIndexnumberNoDerivation index for the account (default: 0)
Example request:
{
  "message": "Hello, Phantom!",
  "networkId": "solana:mainnet"
}
Example response:
{
  "signature": "base64url-encoded-signature"
}

Supported networks

Network identifiers follow the CAIP-2/CAIP-10 format.

Solana

NetworkIdentifier
Mainnetsolana:mainnet
Devnetsolana:devnet
Testnetsolana:testnet

Ethereum and EVM chains

NetworkIdentifier
Ethereum Mainneteip155:1
Ethereum Sepoliaeip155:11155111
Polygon Mainneteip155:137
Polygon Amoyeip155:80002
Base Mainneteip155:8453
Base Sepoliaeip155:84532
Arbitrum Oneeip155:42161
Arbitrum Sepoliaeip155:421614

Bitcoin

NetworkIdentifier
Mainnetbip122:000000000019d6689c085ae165831e93

Sui

NetworkIdentifier
Mainnetsui:mainnet
Testnetsui:testnet

Testing

Test the server directly using the MCP inspector:
npx @modelcontextprotocol/inspector npx -y @phantom/mcp-server
This opens an interactive web UI where you can test tool calls without an AI assistant.

Session management

Sessions are stored in ~/.phantom-mcp/session.json and contain wallet and organization identifiers, stamper keys, and user authentication details. Sessions persist indefinitely until explicitly deleted. To reset your session:
rm ~/.phantom-mcp/session.json
Then restart your AI assistant — the server will re-authenticate on next use.

Security

  • PKCE: Uses Proof Key for Code Exchange for secure OAuth authentication
  • Session security: Session files have restrictive Unix permissions (user-only read/write)
  • Request signing: API key stamper prevents request tampering
  • HTTPS: All API requests use HTTPS
  • Ephemeral binding: Callback server uses ephemeral localhost binding

Troubleshooting

  • Ensure you have a default browser configured
  • Manually visit the URL shown in the logs
  • Check if the open command works in your terminal: open https://phantom.app
The OAuth callback server cannot bind to port 8080.Solutions:
  • Stop the process using port 8080: lsof -ti:8080 | xargs kill
  • Change the callback port by setting PHANTOM_CALLBACK_PORT to a different value
Authentication fails when the email used for Phantom Portal doesn’t match the email used during MCP server authentication.Solution: Use the same email address for both Phantom Portal sign-in and MCP server authentication (Google/Apple login).
The server asks you to authenticate every time.Solutions:
  • Check session file exists: ls -la ~/.phantom-mcp/session.json
  • Verify file permissions: chmod 600 ~/.phantom-mcp/session.json
  • Ensure ~/.phantom-mcp directory has correct permissions: chmod 700 ~/.phantom-mcp
Claude Desktop doesn’t show the Phantom tools.Solutions:
  1. Verify the config file contains valid JSON
  2. Check Claude Desktop logs:
    • macOS: ~/Library/Logs/Claude/
    • Windows: %APPDATA%/Claude/logs/
  3. Restart Claude Desktop after config changes
  4. Test the server manually with the MCP inspector (see the Testing section)
Session exists but is rejected by the API.Solutions:
  • Verify your App ID is correct in Phantom Portal
  • Ensure the authentication email matches the Phantom Portal email
  • Delete the session file: rm ~/.phantom-mcp/session.json
  • Restart your AI assistant and re-authenticate when prompted