Skip to main content

Quickstart

Get PayMCP up and running in your MCP server in just a few minutes.

Installation

Install PayMCP:

pip install paymcp

Requirements

  • Python 3.8+ or Node.js 16+
  • An MCP server framework (Official MCP SDK recommended)
  • Hosted server environment (not STDIO mode)
  • API keys from your chosen payment provider

Basic Setup

1. Initialize Your MCP Server

from mcp.server.fastmcp import FastMCP, Context
from paymcp import PayMCP, price
from paymcp.providers import StripeProvider

mcp = FastMCP("My AI Assistant")

2. Configure PayMCP

PayMCP(mcp, providers=[StripeProvider(apiKey="sk_test_...")])

Adding Pricing

@mcp.tool()
@price(amount=0.50, currency="USD")
def generate_ai_image(prompt: str, ctx: Context) -> str:
"""Generate an AI image from a text prompt"""
return f"Generated image for: {prompt}"

Different Price Points

@mcp.tool()
@price(amount=0.05, currency="USD")
def check_text_grammar(text: str, ctx: Context) -> str:
"""Check and correct grammar in text"""
return corrected_text

@mcp.tool()
@price(amount=2.99, currency="USD")
def analyze_document(document: str, ctx: Context) -> dict:
"""Perform detailed document analysis"""
return analysis_results

Subscriptions

Gate tools behind an active subscription instead of pay-by-request.

from paymcp import subscription

@mcp.tool()
@subscription(plan="price_pro_monthly") # or a list of accepted plan IDs
async def generate_report(ctx: Context) -> str:
return "Your report"

Coordination Modes

Choose the mode (AUTO, RESUBMIT, ELICITATION, TWO_STEP, X402, PROGRESS, or DYNAMIC_TOOLS) that works best for your use case:

AUTO (Default)

Automatically detects client capabilities. If X402 is configured and supported by the client, it uses X402; otherwise it uses ELICITATION when supported and falls back to RESUBMIT.

PayMCP(mcp, providers=[StripeProvider(apiKey="sk_test_...")], mode=Mode.AUTO)

RESUBMIT (Retry-after-error)

Adds an optional payment_id to the original tool signature.

PayMCP(mcp, providers=[StripeProvider(apiKey="sk_test_...")], mode=Mode.RESUBMIT)

Call sequence

  1. First call: PayMCP invokes the tool without a payment_id, responds with Payment Required Error containing a payment_url plus payment_id, and instructs the client to retry.
  2. Second call: The client calls the same tool again with the returned payment_id; PayMCP validates payment server-side and runs your original tool logic if paid.

ELICITATION (Interactive)

For real-time interactions.

PayMCP(mcp, providers=[StripeProvider(apiKey="sk_test_...")], mode=Mode.ELICITATION)

Shows payment link immediately when tool is called (if supported by client) Waits for payment confirmation before proceeding

TWO_STEP

Splits tool execution into two steps.

PayMCP(mcp, providers=[StripeProvider(apiKey="sk_test_...")], mode=Mode.TWO_STEP)

Confirmation tool will be added automatically.

X402 (On-chain)

Use this mode only with an x402-capable client and the X402 provider. See the X402 Provider guide for setup details.

PayMCP(mcp, providers=[X402Provider(pay_to=[{"address": "0xAddress"}],facilitator={"apiKeyId":"YOUR_CDP_KEY_ID","apiKeySecret":"YOUR_CDP_KEY_SECRET"})], mode=Mode.X402)

PROGRESS (Experimental)

For experimental auto-checking of payment status.

PayMCP(mcp, providers=[StripeProvider(apiKey="sk_test_...")], mode=Mode.PROGRESS)

Shows payment link and progress indicator (if supported by client) Automatically proceeds when payment is received

DYNAMIC_TOOLS (Guided Tool Lists)

For clients that support dynamic tool lists and listChanged notifications:

PayMCP(
mcp,
providers=[StripeProvider(apiKey="sk_test_...")],
mode=Mode.DYNAMIC_TOOLS
)

# Temporarily hides/shows tools to steer the next valid action

See the list of MCP clients and their capabilities here: https://modelcontextprotocol.io/clients

Configuring StateStore

By default, PayMCP uses an in-memory StateStore, which does not persist across server restarts. It's highly recommended to use RedisStateStore in production environments.

from redis.asyncio import from_url
from paymcp import PayMCP, RedisStateStore

redis = await from_url("redis://localhost:6379")
PayMCP(
mcp,
providers=[''' ... ''' ],
state_store=RedisStateStore(redis)
)

Testing Your Integration

1. Start Your Server

# server.py
from mcp.server.fastmcp import FastMCP, Context
from paymcp import PayMCP, price
from paymcp.providers import StripeProvider

mcp = FastMCP("Test Server")
PayMCP(mcp, providers=[StripeProvider(apiKey="sk_test_...")])

@mcp.tool()
@price(amount=1.00, currency="USD")
def test_payment_integration(name: str, ctx: Context) -> str:
"""Test payment integration with greeting"""
return f"Hello, {name}! Payment successful."

if __name__ == "__main__":
mcp.run(transport="streamable-http")

2. Connect Your MCP Client

For testing, we recommend using the MCP Inspector.

  1. Run your MCP server code.
  2. Check the console for the /mcp URL (e.g. http://127.0.0.1:8000/mcp).
  3. Start the inspector with:
    npx @modelcontextprotocol/inspector@latest
  4. In MCP Inspector, select streamable HTTP as the transport type and enter your /mcp URL.

3. Use Test Credentials

Always use test/sandbox credentials during development:

  • Stripe: Use sk_test_... keys and test card 4242424242424242
  • PayPal: Set sandbox=True
  • Square: Use sandbox environment
  • Walleot: Use test API keys
  • Coinbase Commerce: No sandbox is available, so test with very small amounts.
  • USDC (Base): Use Base-sepolia network (eip155:84532)
  • USDC (Solana): Use devnet network (solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1)

Next Steps

Basic setup complete! Your MCP tools will now ask for payment before running.

Explore More:

Need help? Check our troubleshooting guide or open an issue.