@402md/mcp

@402md/mcp

An MCP server that transforms SKILL.md files into executable tools for AI agents, allowing them to discover and pay for services via the x402 protocol. It supports automatic payments on Stellar and EVM networks, enabling seamless integration of premium API skills.

Category
Visit Server

README

@402md/mcp

npm version License: MIT Node.js TypeScript MCP

MCP server that transforms SKILL.md files into executable tools for AI agents. Point to any skill — URL, local file, or marketplace name — and the server parses it, auto-pays via x402, and returns the result.

Table of Contents

Quick Start

npx @402md/mcp

Or install globally:

npm install -g @402md/mcp
402md-mcp

The server starts in read-only mode by default. You can browse and inspect skills immediately. To execute paid endpoints, configure a wallet (see Wallet Setup).

Networks

The server supports four networks across two blockchain ecosystems:

Stellar

Network ID Use Case USDC Contract
Stellar Mainnet stellar Production payments with real USDC Native Stellar USDC (Centre)
Stellar Testnet stellar-testnet Development & testing with free testnet USDC Testnet USDC

Stellar is the default and preferred network. It offers sub-second finality, near-zero fees (~0.00001 XLM per tx), and native USDC support.

  • Testnet faucet: Use Stellar Laboratory to create and fund testnet accounts.
  • Mainnet: Fund your account via any Stellar DEX, exchange, or on-ramp that supports USDC on Stellar.

EVM (Base)

Network ID Use Case USDC Contract
Base Mainnet base Production payments on Base L2 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
Base Sepolia base-sepolia Development & testing on Base testnet Sepolia USDC

Base is an Ethereum L2 with low gas fees and fast confirmations.

  • Sepolia faucet: Get testnet ETH from Alchemy Faucet or Coinbase Faucet (needed for gas). Then bridge or mint testnet USDC.
  • Mainnet: Bridge USDC to Base from Ethereum, or buy directly on Base via Coinbase or any supported on-ramp.

Choosing a Network

  • Just getting started? Use stellar-testnet — no real money, instant setup with create_wallet.
  • Testing EVM skills? Use base-sepolia — free testnet, good for EVM-specific endpoints.
  • Production? Use stellar (lower fees) or base depending on what the skill accepts.

The server automatically selects the best compatible network when calling a skill. If a skill supports multiple networks and your wallet has both keys configured, Stellar is preferred.

Wallet Setup

There are three ways to configure a wallet, listed by priority (highest first):

Option 1: Environment Variables (recommended for production)

# Stellar
export STELLAR_SECRET="SCZANGBA5YHTNYVVV3C7CAZMCLXPILHSE6PGYV2FHHUQ5DGQJWRZ4GXT"
export NETWORK="stellar-testnet"

# EVM (Base)
export EVM_PRIVATE_KEY="0x4c0883a69102937d6231471b5dbb6204fe512961708279f23efb3c0c90..."
export NETWORK="base-sepolia"

# Both (FULL mode)
export STELLAR_SECRET="S..."
export EVM_PRIVATE_KEY="0x..."
export NETWORK="stellar"  # default network when both are available

Option 2: create_wallet Tool (recommended for development)

If no wallet is configured, ask your AI agent to use the create_wallet tool:

"Create a new wallet on stellar-testnet"

This generates a keypair and saves it to ~/.402md/wallet.json. The server reloads automatically.

Important: create_wallet refuses to run if a wallet is already configured. To replace an existing wallet, delete ~/.402md/wallet.json manually first.

Option 3: Wallet File (manual)

Create ~/.402md/wallet.json manually:

{
  "stellarSecret": "SCZANGBA5YHTNYVVV3C7CAZMCLXPILHSE6PGYV2FHHUQ5DGQJWRZ4GXT",
  "evmPrivateKey": "0x4c0883a69102937d6231471b5dbb6204fe512961708279f23efb3c0c90...",
  "network": "stellar-testnet",
  "createdAt": "2026-01-15T10:30:00.000Z"
}

The file is created with 0o600 permissions (owner read/write only). The directory ~/.402md/ is created with 0o700.

Generating Keys Manually

Stellar:

# Using stellar-sdk in Node.js
node -e "const { Keypair } = require('@stellar/stellar-sdk'); const kp = Keypair.random(); console.log('Secret:', kp.secret()); console.log('Public:', kp.publicKey())"

EVM:

# Using viem in Node.js
node -e "const { generatePrivateKey, privateKeyToAccount } = require('viem/accounts'); const pk = generatePrivateKey(); const acc = privateKeyToAccount(pk); console.log('Private Key:', pk); console.log('Address:', acc.address)"

# Or using openssl
openssl rand -hex 32 | sed 's/^/0x/'

How Payments Work

The payment flow is handled automatically by the x402 protocol:

Agent calls use_skill("my-skill", "/api/generate")
  │
  ├─ 1. Resolve skill → parse SKILL.md manifest
  ├─ 2. Validate manifest (schema, required fields)
  ├─ 3. Check budget limits (per-call & daily)
  ├─ 4. Select compatible network (skill networks ∩ wallet networks)
  ├─ 5. Create PaymentClient for that network
  ├─ 6. client.fetch(url) → x402 auto-payment:
  │     a. First request returns 402 Payment Required
  │     b. Client signs USDC payment (on-chain)
  │     c. Retries request with payment proof header
  │     d. Server verifies payment, returns response
  ├─ 7. Record spending (amount, skill, endpoint, network)
  └─ 8. Return response to agent

The agent never sees the payment mechanics — it just calls use_skill and gets a result. All USDC amounts use 6 decimal places (e.g., "0.050000").

What Happens If the Endpoint Fails?

If payment succeeds but the endpoint returns an error (4xx/5xx), the spending is still recorded (the payment was already made on-chain) but the tool returns isError: true with a clear message:

Endpoint returned 500. Payment was sent but the request failed.

{"error": "Internal server error"}

This lets the agent (or user) know to contact the skill provider.

Claude Desktop Configuration

Add to your claude_desktop_config.json:

Stellar Testnet (getting started)

{
  "mcpServers": {
    "402md": {
      "command": "npx",
      "args": ["-y", "@402md/mcp"],
      "env": {
        "STELLAR_SECRET": "SCZANGBA5YHTNYVVV3C7CAZMCLXPILHSE6PGYV2FHHUQ5DGQJWRZ4GXT",
        "NETWORK": "stellar-testnet",
        "MAX_PER_CALL": "0.10",
        "MAX_PER_DAY": "5.00"
      }
    }
  }
}

Base Sepolia (EVM testing)

{
  "mcpServers": {
    "402md": {
      "command": "npx",
      "args": ["-y", "@402md/mcp"],
      "env": {
        "EVM_PRIVATE_KEY": "0x4c0883a69102937d623147...",
        "NETWORK": "base-sepolia",
        "MAX_PER_CALL": "0.10",
        "MAX_PER_DAY": "5.00"
      }
    }
  }
}

Production (both networks)

{
  "mcpServers": {
    "402md": {
      "command": "npx",
      "args": ["-y", "@402md/mcp"],
      "env": {
        "STELLAR_SECRET": "S...",
        "EVM_PRIVATE_KEY": "0x...",
        "NETWORK": "stellar",
        "MAX_PER_CALL": "1.00",
        "MAX_PER_DAY": "50.00"
      }
    }
  }
}

Read-only (no wallet)

{
  "mcpServers": {
    "402md": {
      "command": "npx",
      "args": ["-y", "@402md/mcp"]
    }
  }
}

Environment Variables

Variable Default Description
STELLAR_SECRET Stellar secret key (starts with S). Enables Stellar payments.
EVM_PRIVATE_KEY EVM private key (hex, starts with 0x). Enables Base payments.
NETWORK stellar Default network: stellar, stellar-testnet, base, base-sepolia
MAX_PER_CALL 0.10 Maximum USDC allowed per individual skill call
MAX_PER_DAY 20.00 Maximum USDC allowed per calendar day
REGISTRY_URL https://api.402.md 402.md marketplace API base URL

Environment variables always take priority over the wallet file (~/.402md/wallet.json).

Wallet File

Located at ~/.402md/wallet.json. Created automatically by create_wallet or manually.

{
  "stellarSecret": "S...",
  "evmPrivateKey": "0x...",
  "network": "stellar-testnet",
  "createdAt": "2026-01-15T10:30:00.000Z"
}
  • Permissions: 0o600 (read/write owner only)
  • Directory: ~/.402md/ with 0o700
  • Merge behavior: saveWalletConfig merges new fields with existing data, so adding an EVM key won't erase an existing Stellar key
  • Priority: env vars > wallet file > defaults

Budget & Spending Limits

The server enforces two spending limits:

Limit Default Env Variable Description
Per-call 0.10 USDC MAX_PER_CALL Maximum for a single skill invocation
Per-day 20.00 USDC MAX_PER_DAY Maximum total across all calls in a calendar day

Budget is checked before each payment. If a call would exceed either limit, the request is rejected with an error (no payment is made).

Use spending_summary to check current spending and configured limits:

{
  "spentToday": "1.2500",
  "spentSession": "0.3000",
  "limits": {
    "maxPerCall": "1.00",
    "maxPerDay": "50.00"
  },
  "recentPayments": [
    {
      "skillName": "image-gen",
      "endpoint": "/api/generate",
      "amount": "0.15",
      "network": "stellar-testnet",
      "timestamp": "2026-01-15T14:30:00.000Z"
    }
  ]
}

Tools

use_skill

Execute a paid SKILL.md endpoint. Resolves the skill, validates the manifest, auto-pays via x402, and returns the result.

Parameter Type Required Description
skill string Yes Skill source: URL, local file path, or marketplace name
endpoint string No Endpoint path (defaults to first endpoint in manifest)
method string No HTTP method: GET, POST, PUT, DELETE, PATCH (defaults to spec)
body string No Request body as JSON string
headers object No Additional request headers

Requires: configured wallet (STELLAR_ONLY, EVM_ONLY, or FULL mode).

Validation: the manifest is validated before any payment is attempted. If the SKILL.md is invalid, the tool returns an error without spending.

Examples:

# By marketplace name
use_skill({ skill: "image-gen", body: '{"prompt": "a sunset"}' })

# By URL
use_skill({ skill: "https://example.com/SKILL.md", endpoint: "/api/v2/generate" })

# By local file
use_skill({ skill: "./skills/my-skill/SKILL.md", method: "POST", body: '{"input": "hello"}' })

# With custom headers
use_skill({ skill: "translate", headers: { "X-Target-Lang": "pt-BR" }, body: '{"text": "hello"}' })

read_skill

Read and parse a SKILL.md without executing it. Returns full manifest details, endpoints, pricing, and validation results. Works in any mode (including READ_ONLY).

Parameter Type Required Description
skill string Yes Skill source: URL, local file path, or marketplace name

Returns: name, description, version, author, base URL, endpoints (with pricing and schemas), payment info (networks, asset, payTo), tags, category, validation result, and current wallet mode.

check_balance

Check the USDC balance and address for the configured wallet.

No parameters.

Returns:

{
  "address": "GCXZ...",
  "balance": "45.250000 USDC",
  "network": "stellar-testnet",
  "mode": "STELLAR_ONLY"
}

spending_summary

View spending summary: amounts spent today and in the current session, budget limits, and the last 10 payments.

No parameters.

Returns: see Budget & Spending Limits for output format.

create_wallet

Generate a new wallet keypair and save it to ~/.402md/wallet.json.

Parameter Type Required Description
network string Yes stellar, stellar-testnet, base, or base-sepolia

Network-to-wallet mapping:

  • stellar or stellar-testnet → generates a Stellar keypair (Keypair.random())
  • base or base-sepolia → generates an EVM keypair (generatePrivateKey())

Safety:

  • Refuses to run if a wallet is already configured (any mode except READ_ONLY).
  • To replace an existing wallet, delete ~/.402md/wallet.json first.
  • New keys are merged with existing config — adding an EVM wallet won't erase a Stellar key.

Returns:

{
  "type": "stellar",
  "publicKey": "GCXZ...",
  "network": "stellar-testnet",
  "savedTo": "/Users/you/.402md/wallet.json",
  "note": "Fund this address on the Stellar testnet faucet before use."
}

search_skills

Search the 402.md marketplace for available skills.

Parameter Type Required Description
query string Yes Search keywords
maxPrice string No Max price per call in USDC (e.g., "0.50")
category string No Filter by category

Returns: up to 20 results with name, description, min price, and supported networks.

Modes

The server operates in one of four modes based on which keys are available:

Mode Condition Available Tools
READ_ONLY No keys configured read_skill, search_skills, create_wallet
STELLAR_ONLY STELLAR_SECRET set All tools — pays via Stellar
EVM_ONLY EVM_PRIVATE_KEY set All tools — pays via Base
FULL Both keys set All tools — pays via best available network

In FULL mode, when a skill supports both Stellar and EVM networks, Stellar is preferred (lower fees and faster finality).

Skill Resolution

The skill parameter in use_skill and read_skill accepts three formats:

Format Example How It Resolves
URL https://example.com/SKILL.md Fetches directly via HTTP
Local file ./skills/my-skill/SKILL.md Reads from filesystem
Marketplace name image-gen Queries {REGISTRY_URL}/api/v1/discovery/skills/{name}/skill-md

Local file detection: any source starting with /, ./, ../, or ending with .md is treated as a file path.

Architecture

┌──────────────────────────────────────────────────────┐
│  AI Agent (Claude, etc.)                             │
│  Calls MCP tools: use_skill, check_balance, etc.     │
└──────────────┬───────────────────────────────────────┘
               │ stdio (MCP protocol)
┌──────────────▼───────────────────────────────────────┐
│  @402md/mcp Server                                   │
│                                                      │
│  ┌─────────────┐  ┌────────────┐  ┌───────────────┐ │
│  │ Use Tools   │  │ Wallet     │  │ Registry      │ │
│  │ use_skill   │  │ check_bal  │  │ search_skills │ │
│  │ read_skill  │  │ spending   │  │               │ │
│  │             │  │ create_wal │  │               │ │
│  └──────┬──────┘  └─────┬──────┘  └───────┬───────┘ │
│         │               │                 │          │
│  ┌──────▼──────┐  ┌─────▼──────┐  ┌───────▼───────┐ │
│  │ resolveSkill│  │ Spending   │  │ fetch()       │ │
│  │ validateSkil│  │ Tracker    │  │ → Registry API│ │
│  │ selectNetwrk│  │ (budget)   │  │               │ │
│  └──────┬──────┘  └────────────┘  └───────────────┘ │
│         │                                            │
│  ┌──────▼──────────────────────────────────────────┐ │
│  │ ClientCache → PaymentClient (@402md/x402)       │ │
│  │   ├─ StellarClient (@stellar/stellar-sdk)       │ │
│  │   └─ EvmClient (viem)                           │ │
│  └──────┬──────────────────────────────────────────┘ │
└─────────┼────────────────────────────────────────────┘
          │ x402 payment protocol
┌─────────▼────────────────────────────────────────────┐
│  Skill Provider (HTTP server)                        │
│  Returns 402 → receives payment proof → returns data │
└──────────────────────────────────────────────────────┘

Key patterns:

  • Lazy client loading: ClientCache creates PaymentClient instances on first use per network
  • Budget enforcement: SpendingTracker wraps BudgetTracker from @402md/x402 — checked before, recorded after
  • Smart network selection: intersects skill's supported networks with wallet capabilities, prefers Stellar
  • Config reload: create_wallet triggers config.reload() so new keys take effect immediately
  • Optional deps: @stellar/stellar-sdk and viem are optional — only loaded when the corresponding network is used

Examples

End-to-end: first-time setup to skill execution

User: "Search for image generation skills"
→ Agent calls search_skills({ query: "image generation" })
→ Returns list of skills with pricing

User: "Create a wallet so we can use one"
→ Agent calls create_wallet({ network: "stellar-testnet" })
→ Returns public key + "fund on testnet faucet"

User: "Use the image-gen skill to create a sunset"
→ Agent calls use_skill({ skill: "image-gen", body: '{"prompt":"a sunset over mountains"}' })
→ Server resolves skill → validates → checks budget → pays → returns image URL

User: "How much have we spent?"
→ Agent calls spending_summary()
→ Returns { spentToday: "0.0500", spentSession: "0.0500", limits: { maxPerCall: "0.10", maxPerDay: "20.00" }, ... }

Using a local SKILL.md during development

User: "Test my local skill"
→ Agent calls read_skill({ skill: "./my-skill/SKILL.md" })
→ Returns parsed manifest with validation errors/warnings

→ Agent calls use_skill({ skill: "./my-skill/SKILL.md", endpoint: "/api/test" })
→ Executes against your local server

Budget rejection

→ Agent calls use_skill for a skill priced at 5.00 USDC
→ MAX_PER_CALL is 0.10
→ Error: "Exceeds per-call limit (0.10 USDC)"
→ No payment is made

Development

Prerequisites

  • Node.js >= 18
  • npm

Setup

git clone https://github.com/402md/mcp.git
cd mcp
npm install

Scripts

Command Description
npm run build Build with tsup (ESM, shebang included)
npm run dev Build in watch mode
npm run typecheck Run TypeScript type checking (tsc --noEmit)
npm run lint Lint source files with ESLint
npm run lint:fix Lint and auto-fix
npm run format Format with Prettier
npm run format:check Check formatting without writing
npm test Run tests with Vitest
npm run test:watch Run tests in watch mode

Project Structure

mcp/
├── src/
│   ├── index.ts          # CLI entry point (stdio transport)
│   ├── server.ts         # MCP server setup, tool registration
│   ├── config.ts         # Env vars + wallet file → McpConfig
│   ├── types.ts          # McpConfig, SpendingRecord, WalletFileConfig
│   ├── clients.ts        # ClientCache + network selection logic
│   ├── resolve.ts        # Skill resolution (URL / file / registry)
│   ├── spending.ts       # SpendingTracker (budget enforcement)
│   ├── wallet-store.ts   # Read/write ~/.402md/wallet.json
│   └── tools/
│       ├── use.ts        # use_skill, read_skill
│       ├── wallet.ts     # check_balance, spending_summary, create_wallet
│       └── registry.ts   # search_skills
├── __tests__/
│   ├── config.test.ts
│   ├── spending.test.ts
│   ├── resolve.test.ts
│   └── wallet-store.test.ts
├── tsup.config.ts        # Build config (ESM, shebang, sourcemaps)
├── tsconfig.json
├── eslint.config.mjs
└── .prettierrc

Code Conventions

  • No semicolons, single quotes, no trailing commas (Prettier)
  • ESM only ("type": "module", .js extensions in imports)
  • Strict TypeScript (strict: true)
  • Tools are thin handlers — business logic lives in modules (spending.ts, clients.ts, resolve.ts)
  • @stellar/stellar-sdk and viem are optional deps, dynamically imported only when the matching network is used

Adding a New Tool

  1. Create or edit a file in src/tools/
  2. Export a register*Tools(server, config, spending, clientCache) function
  3. Call it from src/server.ts
  4. Add tests in __tests__/
  5. Run npm run typecheck && npm run lint && npm test

Running Locally

# Build and run
npm run build
node dist/index.js

# Or in dev mode (rebuilds on change)
npm run dev

# In another terminal, test with MCP inspector
npx @modelcontextprotocol/inspector node dist/index.js

To test with environment variables:

STELLAR_SECRET="S..." NETWORK="stellar-testnet" node dist/index.js

License

MIT

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured