Skip to main content
Glama
Crypto Market MCP

Crypto Market MCP

Crypto Market MCP

A Model Context Protocol server for crypto market data. It runs over stdio for local clients, and over Streamable HTTP at /mcp when you host it. Paid tools use x402 (USDC on Base). Free tools never ask for payment.

Hosted endpoint (Base mainnet): https://2-31-102-176.sslip.io/mcp

Official registry name: io.github.gojisatoshi888/crypto-market. Each client gets 3 free paid-tool calls per UTC day. After that, paid tools require a USDC payment on Base via x402 (see How an agent pays). get_price and fear_greed stay free.

Tool

What it returns

Default price

get_price(symbols="BTC,ETH")

CoinGecko USD price, 24h change, and volume (ok, prices)

Free

fear_greed()

alternative.me index (value, classification, as_of)

Free

top_movers(limit, min_volume_usd, include_suspicious)

Gainers, losers, filtered_out, and duplicate merges

$0.005

funding_rates(symbols="BTC,ETH,SOL")

Perpetual funding. Binance, then Bybit, then OKX

$0.005

market_brief(symbols="BTC,ETH,SOL")

InferHub brief (max_tokens 800) plus the raw snapshot

$0.03

rug_risk(token_address, chain, include_summary=False)

0–100 score, level, and flags. Chains: ethereum, bsc, base, solana (eth, bnb, sol)

$0.02

The tool bodies are the original crypto_data.py and rug_risk.py logic, including the documented weights and trusted-token handling. Score bands are 0–24 low, 25–49 medium, 50–74 high, and 75–100 critical. Trusted tokens still list issuer-style flags, and those flags do not add points. Honeypot, can't-sell, high tax, dead liquidity, and fake-token flags always do. Successful upstream GETs are cached. Each vendor call uses HTTP_TIMEOUT_SECONDS.

Run locally

Python 3.10+.

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

Stdio (no wallet, payments off unless you set PAYMENTS_ENABLED=true):

python -m crypto_mcp

HTTP, with a health check on /health and MCP on /mcp:

export PAY_TO_ADDRESS=0x49Ac893403009239F96a188d55C2FD40f77A8195
export X402_NETWORK=base-sepolia
python -m crypto_mcp.http_server

The process listens on HOST and PORT (0.0.0.0 and 8080 by default). Open http://127.0.0.1:8080/health.

Docker Compose publishes the HTTP server on 127.0.0.1:44021. If PAY_TO_ADDRESS is unset, Compose uses a dummy address so the process can boot. Put your real address in .env before you accept payments.

docker compose up --build

Related MCP server: santyvv-data-mcp

How an agent pays

Payment follows the x402 MCP transport. There is no HTTP 402 on /mcp, and no extra endpoint. initialize and tools/list are free. A paid tools/call without payment does not run the tool and does not move funds, unless the caller still has a free daily allowance (see below).

  1. The client calls the tool normally.

  2. The server returns a tool result with isError: true. structuredContent is an x402 PaymentRequired object (x402Version 2). content[0].text is that same object as JSON.

  3. accepts[0] is the exact scheme on the configured network (eip155:84532 for Base Sepolia, eip155:8453 for Base). amount is USDC's atomic units (6 decimals, so $0.02 is "20000"). asset is the USDC contract. payTo is PAY_TO_ADDRESS. extra.name and extra.version are the EIP-712 domain for USDC.

  4. The client signs an EIP-3009 transferWithAuthorization for that amount and recipient, and retries the same tools/call with the payload on params._meta["x402/payment"].

  5. This server asks the facilitator to verify, then to settle (it retries once if settlement fails for a transient reason). Only after settlement succeeds does the tool run. A failed settle returns PaymentRequired and never returns paid tool data. The tool result includes the receipt at _meta["x402/payment-response"] (success, transaction, network, payer).

A client that cannot pay stops at step 2. It is not charged.

The Python package x402.mcp (create_x402_mcp_client) does steps 3–5 for an agent that holds an EVM key. This server uses x402's resource server, scheme, and facilitator client. It does not use x402's FastMCP decorator: that decorator imports mcp.server.fastmcp, which mcp 2.3 removed when FastMCP was renamed MCPServer.

Example challenge (values depend on your env):

{
  "isError": true,
  "structuredContent": {
    "x402Version": 2,
    "error": "Payment required to access this resource ($0.02 USDC on eip155:84532)",
    "resource": {"url": "mcp://tool/rug_risk", "mimeType": "application/json"},
    "accepts": [{
      "scheme": "exact",
      "network": "eip155:84532",
      "amount": "20000",
      "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
      "payTo": "0xYourAddress",
      "maxTimeoutSeconds": 60,
      "extra": {"name": "USDC", "version": "2"}
    }]
  }
}

Retry shape:

{
  "method": "tools/call",
  "params": {
    "name": "rug_risk",
    "arguments": {"token_address": "...", "chain": "solana"},
    "_meta": {"x402/payment": {"x402Version": 2, "accepted": {}, "payload": {}, "resource": {}}}
  }
}

The public facilitator at https://x402.org/facilitator is the default for Base Sepolia and needs no API key. Coinbase's CDP facilitator (https://api.cdp.coinbase.com/platform/v2/x402) requires CDP_API_KEY_ID and CDP_API_KEY_SECRET. JWT auth is attached only when FACILITATOR_URL points at that CDP host, so you can store the keys now and keep testnet on x402.org. This process never holds a payment signing key and never sends a payment itself.

To go to Base mainnet after a testnet payment works: set X402_NETWORK=base and FACILITATOR_URL=https://api.cdp.coinbase.com/platform/v2/x402 in .env.prod, then restart the container. Prices and PAY_TO_ADDRESS can stay the same if that address is the wallet you control on Base.

Daily free allowance

Paid tools (rug_risk, market_brief, top_movers, funding_rates) allow FREE_PAID_CALLS_PER_DAY free calls per client per UTC day (default 3, reset at 00:00 UTC). A client is the request IP plus the optional X-Client-Id header. After the allowance is used, those tools require x402 payment. Remaining calls are returned in _meta.freePaidCallsRemaining (also freePaidCallsLimit and freePaidCallsResetsAt). Set FREE_PAID_CALLS_PER_DAY=0 to require payment on every paid-tool call. The count is stored in FREE_TIER_PATH (default /app/data/free_tier.sqlite) so a restart does not reset the day. Owner keys in FREE_API_KEYS still skip both the charge and the daily allowance.

Owner API key

Set FREE_API_KEYS to a comma-separated list. A request with Authorization: Bearer <key> or X-API-Key: <key> skips the charge and the free-tool rate limit. Anyone without a key still has to pay for paid tools.

Connect a client

Remote URL, Cursor (.cursor/mcp.json):

{
  "mcpServers": {
    "crypto-market": {
      "url": "https://2-31-102-176.sslip.io/mcp"
    }
  }
}

Remote URL, Claude Desktop:

{
  "mcpServers": {
    "crypto-market": {
      "type": "http",
      "url": "https://2-31-102-176.sslip.io/mcp"
    }
  }
}

Add the owner header only on clients that should skip payment:

{
  "mcpServers": {
    "crypto-market": {
      "url": "https://2-31-102-176.sslip.io/mcp",
      "headers": {"Authorization": "Bearer YOUR_FREE_API_KEY"}
    }
  }
}

Local stdio:

{
  "mcpServers": {
    "crypto-market": {
      "command": "python",
      "args": ["-m", "crypto_mcp"]
    }
  }
}

Environment

Copy .env.example. Do not commit .env.

Variable

Required

Default

Purpose

PAY_TO_ADDRESS

When payments are on

empty

EVM address that receives USDC

X402_NETWORK

no

base-sepolia

base-sepolia, base, or eip155:<id>

FACILITATOR_URL

no

https://x402.org/facilitator

x402 facilitator. Use the CDP URL for mainnet.

CDP_API_KEY_ID / CDP_API_KEY_SECRET

When using the CDP facilitator

empty

Coinbase CDP API keys. Never commit them.

PAYMENTS_ENABLED

no

on for HTTP, off for stdio

Force the gate on or off

FREE_API_KEYS

no

empty

Comma-separated owner keys

FREE_PAID_CALLS_PER_DAY

no

3

Free paid-tool calls per client per UTC day. 0 disables the allowance.

FREE_TIER_PATH

no

/app/data/free_tier.sqlite

Persisted free-tier counters

PRICE_RUG_RISK

no

$0.02

Per-tool price override

PRICE_MARKET_BRIEF

no

$0.03

Per-tool price override

PRICE_TOP_MOVERS

no

$0.005

Per-tool price override

PRICE_FUNDING_RATES

no

$0.005

Per-tool price override

X402_MAX_TIMEOUT_SECONDS

no

60

Authorization lifetime advertised to the client

INFERHUB_API_KEY

no

empty

Bearer token for market_brief

INFERHUB_MODEL

with the key

empty

Model name sent to InferHub

INFERHUB_BASE_URL

no

https://api.inferhub.dev/v1

OpenAI-compatible base URL

HTTP_TIMEOUT_SECONDS

no

10

Upstream call timeout

CACHE_TTL_SECONDS

no

30

In-memory TTL for upstream GETs

RATE_LIMIT_FREE_PER_MINUTE

no

60

Per-IP limit for free tools on HTTP

HOST

no

0.0.0.0

Bind address

PORT

no

8080

Bind port. Railway sets this

get_price and fear_greed stay free. There is no price env for them.

Free tools are limited per client IP. Behind Railway the first X-Forwarded-For hop is the client. Upstream GETs are cached for CACHE_TTL_SECONDS. InferHub completions are not cached. Every upstream call uses HTTP_TIMEOUT_SECONDS.

Deploy on Railway

This repo is set up for Railway and is not deployed from here.

  1. Push the project to a Git repository you control.

  2. Create a Railway service from that repo. railway.json selects the Dockerfile, checks GET /health, and restarts on failure.

  3. In the service variables, set PAY_TO_ADDRESS=0x49Ac893403009239F96a188d55C2FD40f77A8195 (the owner's Base wallet; EIP-55 checksum checked) and leave X402_NETWORK=base-sepolia for testing. Set FACILITATOR_URL if you are not using the public facilitator. Set INFERHUB_API_KEY and INFERHUB_MODEL only if you want model-written briefs. Set FREE_API_KEYS if you want an owner bypass.

  4. Generate a public domain. The image listens on Railway's PORT.

  5. Open https://<domain>/health. You should see "status": "ok".

  6. Point Cursor or Claude at https://<domain>/mcp.

  7. For mainnet, after a successful Sepolia paid call, set X402_NETWORK=base and FACILITATOR_URL=https://api.cdp.coinbase.com/platform/v2/x402 (CDP keys already in the environment), then restart. Try one paid tool on Sepolia first.

server.json describes the hosted Streamable HTTP server for the official MCP Registry (io.github.gojisatoshi888/crypto-market). smithery.yaml is historical listing metadata only; Smithery's publish API and CLI shut down on 31 October 2026.

Tests

pytest

Payment tests check that an unpaid paid-tool call returns PaymentRequired with the configured amount, network, asset, and payTo; that free tools run; and that FREE_API_KEYS skips the gate. They do not call a facilitator and do not sign a transaction. tests/test_network.py calls CoinGecko and alternative.me and skips itself if those hosts are blocked.

Layout

  • python -m crypto_mcp — stdio

  • python -m crypto_mcp.http_server — Streamable HTTP on /mcp, health on /health

  • crypto_mcp/payments.py — x402 challenge, verify, settle

  • crypto_mcp/market.py — vendor calls

  • crypto_mcp/scoring.py — volume flags and the rug score

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      C
      maintenance
      Enables AI agents to fetch crypto market and on-chain data, including prices across venues, token facts, OHLC candles, market overview, DeFi TVL, and wallet balances, with two free tools and the rest paid per call in USDC on Base via x402.
      8
      48 npm
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Provides onchain intelligence tools for Base, including token risk checks, wallet PnL, and leaderboard data, with paid calls settled per-request in USDC via x402.
      45 npm
      MIT