Sample MCP server that gates tools behind active subscriptions using PayMCP with Stripe as the billing provider and OAuth/OIDC for authentication.
- Protects MCP tools with bearer tokens from Auth0, generic OIDC, or Keycloak
- Enforces paid access to tools (demo
addtool) via Stripe subscriptions - Exposes OAuth discovery metadata at the root for MCP clients
- Copy
.env.exampleto.envand fill in your auth + Stripe values. - Install deps:
pdm install -d. - Run the server:
pdm run server.py(default: http://localhost:8000). - Connect with an MCP client, authenticate, and call the
addtool - access requires an active Stripe subscription matchingSTRIPE_SUBSCRIPTION_ID.
HOST/PORT: MCP server host/port (defaults:localhost:8000).OIDC_ISSUER: Issuer URL for Auth0 / generic OIDC (leave empty if using Keycloak-style config).AUTH_HOST,AUTH_PORT,AUTH_REALM: Keycloak location if not usingOIDC_ISSUER.OAUTH_CLIENT_ID,OAUTH_CLIENT_SECRET: OAuth client credentials.STRIPE_SECRET_KEY: Stripe secret key for PayMCP.STRIPE_SUBSCRIPTION_ID: Stripe price ID that represents the required plan.
Auth0
- In Auth0 Dashboard: Applications -> APIs -> Create API. Set
Identifierto your MCP server hostname (e.g.,http://localhost:8000/mcp). - Create a Client Application and copy
domain,client ID,client secretinto.env(OIDC_ISSUER,OAUTH_CLIENT_ID,OAUTH_CLIENT_SECRET). - Authentication -> Database: create Username-Password-Authentication connection.
- Username-Password-Authentication connection -> Promote that connection to Domain Level.
- Settings -> Advanced Settings: enable Dynamic Client Registration (DCR) and Resource Parameter Compatibility Profile.
Keycloak
Use the official MCP authorization walkthrough: https://modelcontextprotocol.io/docs/tutorials/security/authorization. Then set AUTH_HOST, AUTH_PORT, AUTH_REALM, OAUTH_CLIENT_ID, and OAUTH_CLIENT_SECRET in .env (leave OIDC_ISSUER empty).
- Create a product in the Stripe dashboard and a recurring price.
- Set
STRIPE_SUBSCRIPTION_IDto that price ID. - Set
STRIPE_SECRET_KEYto your Stripe secret key.
PayMCP will use these to check subscription status and to generate checkout/manage links exposed to the MCP client.
- Dev server:
pdm run server.py
The MCP server runs over HTTP with OAuth-protected endpoints (/ for session requests). OAuth metadata is published automatically for clients via mcpAuthMetadataRouter.
- OAuth bearer tokens are verified against your provider and must target the MCP resource (
HOST:PORT). - The demo
addtool declares a subscription requirement via_meta.subscription.plan = STRIPE_SUBSCRIPTION_ID; PayMCP enforces it. - PayMCP adds three helper methods to let users obtain a checkout link and manage their subscription directly in chat.
- 401 or audience errors: ensure the API
Identifier(Auth0) or resource indicator matcheshttp://HOST:PORT/mcp. - Invalid JWT shape: confirm your provider issues JWT access tokens (not opaque tokens).
- Stripe errors: double-check
STRIPE_SECRET_KEYand thatSTRIPE_SUBSCRIPTION_IDexists and is active.