KEMBAR78
GitHub - PayMCP/paymcp: Provider-agnostic payment layer for MCP (Model Context Protocol) tools and agents.
Skip to content

PayMCP/paymcp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

80 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PayMCP

Provider-agnostic payment layer for MCP (Model Context Protocol) tools and agents.

paymcp is a lightweight SDK that helps you add monetization to your MCP‑based tools, servers, or agents. It supports multiple payment providers and integrates seamlessly with MCP's tool/resource interface.

See the full documentation.


🔧 Features

  • ✅ Add @price(...) decorators to your MCP tools to enable payments
  • 🔁 Choose between different payment flows (elicit, progress, dynamic_tools, etc.)
  • 🔌 Built-in support for major providers (see list) — plus a pluggable interface for custom providers.
  • ⚙️ Easy integration with FastMCP or other MCP servers

🚀 Quickstart

Install the SDK from PyPI:

pip install mcp paymcp

Initialize PayMCP:

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

mcp = FastMCP("AI agent name")

PayMCP(
    mcp,
    providers=[
        StripeProvider(api_key=os.getenv("STRIPE_API_KEY")),
    ],
    payment_flow=PaymentFlow.TWO_STEP # optional, TWO_STEP (default) / ELICITATION / PROGRESS / DYNAMIC_TOOLS
)

Use the @price decorator on any tool:

@mcp.tool()
@price(amount=0.99, currency="USD")
def add(a: int, b: int, ctx: Context) -> int: # `ctx` is required by the PayMCP tool signature — include it even if unused
    """Adds two numbers and returns the result."""
    return a + b

Demo server: For a complete setup, see the example repo: python-paymcp-server-demo.

🧭 Payment Flows

The payment_flow parameter controls how the user is guided through the payment process. Choose the strategy that fits your use case:

  • PaymentFlow.TWO_STEP (default)
    Splits the tool into two separate MCP methods.
    The first step returns a payment_url and a next_step method for confirmation.
    The second method (e.g. confirm_add_payment) verifies payment and runs the original logic.
    Supported in most clients.

  • PaymentFlow.ELICITATION Sends the user a payment link when the tool is invoked. If the client supports it, a payment UI is displayed immediately. Once the user completes payment, the tool proceeds.

  • PaymentFlow.PROGRESS
    Shows payment link and a progress indicator while the system waits for payment confirmation in the background. The result is returned automatically once payment is completed.

  • PaymentFlow.DYNAMIC_TOOLS Steer the client and the LLM by changing the visible tool set at specific points in the flow (e.g., temporarily expose confirm_payment_*), thereby guiding the next valid action.

All flows require the MCP client to support the corresponding interaction pattern. When in doubt, start with TWO_STEP.


🗄️ State Storage

By default, when using the TWO_STEP payment flow, PayMCP stores pending tool arguments (for confirming payment) 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.

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

redis = await from_url("redis://localhost:6379")
PayMCP(
    mcp,
    providers=[
        StripeProvider(api_key=os.getenv("STRIPE_API_KEY")),
    ],
    state_store=RedisStateStore(redis)
)

🧩 Supported Providers

Built-in support is available for the following providers. You can also write a custom provider.

🔌 Writing a Custom Provider

Any provider must subclass BasePaymentProvider and implement create_payment(...) and get_payment_status(...).

from paymcp.providers import BasePaymentProvider

class MyProvider(BasePaymentProvider):

    def create_payment(self, amount: float, currency: str, description: str):
        # Return (payment_id, payment_url)
        return "unique-payment-id", "https://example.com/pay"

    def get_payment_status(self, payment_id: str) -> str:
        return "paid"

PayMCP(mcp, providers=[MyProvider(api_key="...")])

📄 License

MIT License

About

Provider-agnostic payment layer for MCP (Model Context Protocol) tools and agents.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages