Skip to main content

API Reference

Complete reference documentation for PayMCP classes, functions, and configuration options.

Core Classes

PayMCP

The main PayMCP class that integrates payment functionality into your MCP server.

class PayMCP:
def __init__(
self,
mcp_instance,
providers: list = None,
mode: Mode = Mode.TWO_STEP,
state_store = None
)

Parameters

ParameterTypeDefaultDescription
mcp_instanceFastMCPRequiredYour MCP server instance
providersUnion[dict, Iterable]{}Payment provider configurations (see Provider Configuration section)
modeModeTWO_STEPCoordination mode strategy
state_storeStateStoreInMemoryStateStoreState Store for TWO_STEP mode

Provider Configuration

Use the canonical provider list format:

providers = [StripeProvider(apiKey="sk_test_...")]

Alternative formats are also supported (config mapping, mixed styles) - see the Alternative Configuration section below.

Examples

from paymcp import PayMCP, Mode
from paymcp.providers import StripeProvider

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

Mode

Enum defining available payment modes.

class Mode(str, Enum):
TWO_STEP = "two_step"
RESUBMIT = "resubmit"
ELICITATION = "elicitation"
PROGRESS = "progress"
DYNAMIC_TOOLS = "dynamic_tools"

Coordination Modes

ModeDescriptionBest For
TWO_STEPSplit into initiate/confirm stepsMaximum compatibility
RESUBMITFirst call returns HTTP 402 with payment_url + payment_id; second call retries with the IDTool retries where the client handles user payment completion
ELICITATIONPayment link during executionReal-time interactions
PROGRESSExperimental auto-checking of payment statusReal-time interactions
DYNAMIC_TOOLSDynamically expose the next valid tool actionClients with listChanged support

For more details about coordination mode concepts, see Coordination Modes.

RESUBMIT specifics

  1. First call: PayMCP invokes your tool without a payment_id, responds with HTTP 402 Payment Required that includes a payment_url and payment_id, and instructs the caller to retry after payment.
  2. Second call: The caller runs the same tool again with the provided payment_id; PayMCP verifies payment server-side and executes your original tool logic if the payment succeeded.

StateStore

By default, when using the TWO_STEP mode, PayMCP stores pending tool arguments in memory using a process-local Map. This is not durable and will not work across server restarts or multiple server instances (no horizontal scaling).

To enable durable and scalable state storage, you can provide a custom StateStore implementation. PayMCP includes a built-in RedisStateStore, which works with any Redis-compatible client.

Example: Using Redis for State Storage

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

redis = await from_url("redis://localhost:6379")
PayMCP(
mcp,
providers={"stripe": {"apiKey": "..."}},
state_store=RedisStateStore(redis)
)

Payment Providers

PayMCP provides an extensible provider system that abstracts payment providers behind a common interface. Providers can be supplied in multiple ways to give you maximum flexibility:

Configuration Methods

from paymcp.providers import StripeProvider

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

Alternative Configuration

PayMCP(mcp, providers={
"stripe": {"apiKey": "..."}
})
from paymcp.providers import StripeProvider

PayMCP(mcp, providers={
"stripe": StripeProvider(apiKey="sk_test_...")
})

This flexibility allows you to:

  • Mix different configuration styles in the same setup
  • Use custom providers alongside built-in ones
  • Dynamically configure providers at runtime
  • Share provider instances across multiple PayMCP setups

Custom Provider Development

BasePaymentProvider

All payment providers must inherit from BasePaymentProvider and implement the required methods.

from paymcp.providers import BasePaymentProvider

class MyProvider(BasePaymentProvider):
def __init__(self, api_key: str, **kwargs):
self.api_key = api_key
super().__init__(**kwargs)

def create_payment(self, amount: float, currency: str, description: str) -> tuple[str, str]:
"""Create a payment and return (payment_id, payment_url)"""
return "payment_id", "https://myprovider.com/pay/payment_id"

def get_payment_status(self, payment_id: str) -> str:
"""Return payment status: 'paid', 'pending', 'failed', or 'cancelled'"""
return "paid"

Decorators

@price

Decorator to add payment requirements to MCP tools.

def price(amount: float, currency: str = "USD")

Parameters

ParameterTypeDefaultDescription
amountfloatRequiredPayment amount
currencystr"USD"ISO 4217 currency code

Example

@mcp.tool()
@price(amount=0.50, currency="USD")
def generate_data_report(input: str, ctx: Context) -> str:
"""Generate a data report from input"""
return f"Report: {input}"

Provider Configuration

Stripe

providers = [StripeProvider(apiKey="sk_test_...")]

Parameters

ParameterTypeRequiredDescription
apiKeystrYesStripe secret key (sk_test_... or sk_live_...)

Walleot

providers = {
"walleot": {
"apiKey": str, # Required: Walleot API key
}
}

Parameters

ParameterTypeRequiredDescription
apiKeystrYesWalleot API key (sk_test_... or sk_live_...)

PayPal

providers = [PayPalProvider(client_id="...", client_secret="...", sandbox=True)]

Parameters

ParameterTypeRequiredDefaultDescription
client_idstrYes-PayPal application client ID
client_secretstrYes-PayPal application client secret
sandboxboolNoTrueUse PayPal sandbox environment

Square

providers = {
"square": {
"access_token": str, # Required: Square access token
"location_id": str, # Required: Square location ID
"sandbox": bool, # Optional: Use sandbox environment
"redirect_url": str, # Optional: Redirect URL
"api_version": str, # Optional: API version
}
}

Parameters

ParameterTypeRequiredDefaultDescription
access_tokenstrYes-Square access token
location_idstrYes-Square location identifier
sandboxboolNoTrueUse Square sandbox environment
redirect_urlstrNo-Post-payment redirect URL
api_versionstrNo"2025-03-19"Square API version

Adyen

providers = {
"adyen": {
"api_key": str, # Required: Adyen API key
"merchant_account": str, # Required: Merchant account name
"sandbox": bool, # Optional: Use test environment
}
}

Parameters

ParameterTypeRequiredDefaultDescription
api_keystrYes-Adyen API key
merchant_accountstrYes-Adyen merchant account identifier
sandboxboolNoTrueUse Adyen test environment

Coinbase Commerce

providers = [CoinbaseProvider(api_key="...")]

Parameters

ParameterTypeRequiredDefaultDescription
api_keystrYes-Coinbase Commerce API key

Context Requirements

All priced tools must include a ctx: Context parameter:

from mcp.server.fastmcp import Context

@mcp.tool()
@price(amount=1.00, currency="USD")
def my_tool(input: str, ctx: Context) -> str:
# ctx parameter is required for PayMCP integration
return process_input(input)

Why Context is Required

The Context parameter provides:

  • User identification for payment tracking
  • Progress reporting capabilities (PROGRESS mode)
  • Elicitation support (ELICITATION mode)
  • Tool execution metadata

Error Handling

PayMCP handles various error scenarios automatically:

Payment Errors

Error TypeDescriptionUser Action
Payment declinedCard/payment method rejectedTry different payment method
Insufficient fundsNot enough balanceAdd funds or use different method
Payment timeoutUser didn't complete paymentRetry the tool call
Invalid currencyCurrency not supportedUse supported currency

Configuration Errors

Error TypeDescriptionSolution
Invalid API keyWrong or expired keyCheck provider dashboard
Missing providerProvider not configuredAdd provider to configuration
Invalid modeUnsupported payment modeUse supported mode

Tool Errors

Error TypeDescriptionSolution
Missing contextNo ctx parameterAdd ctx: Context parameter
Invalid amountAmount less than or equal to 0 or not numericUse valid positive amount

Advanced Configuration

Multiple Providers

# PayMCP uses the first provider by default
# User will be able to choose how he wants to pay (coming soon)
PayMCP(
mcp,
providers={
"stripe": {"apiKey": "sk_..."},
"walleot": {"apiKey": "wk_..."},
"paypal": {
"client_id": "...",
"client_secret": "..."
}
}
)

Environment Variables

Use environment variables for secure credential storage:

import os

PayMCP(
mcp,
providers={
"stripe": {
"apiKey": os.getenv("STRIPE_SECRET_KEY"),
"success_url": os.getenv("STRIPE_SUCCESS_URL"),
"cancel_url": os.getenv("STRIPE_CANCEL_URL")
}
}
)

Version Information

Current PayMCP version: Check with paymcp.__version__

import paymcp
print(f"PayMCP version: {paymcp.__version__}")

Next Steps