payments

SKILL.md

ContextVM Payments (CEP-8)

Use this skill when you want ContextVM servers to charge for specific capabilities and clients to pay automatically using the TypeScript SDK payments layer.

Payments are implemented as middleware around transports:

  • Server-side middleware gates priced requests: it must not forward to the underlying MCP server until payment is verified.
  • Client-side middleware listens for payment notifications, executes a handler, then continues the original request.

This skill documents how to use the SDK payments layer. For transport setup (signers, relays, encryption), see:

Quick start: charge for one tool (server + client)

Server: price a capability and attach payments

import type { PricedCapability } from '@contextvm/sdk/payments';
import { LnBolt11NwcPaymentProcessor, withServerPayments } from '@contextvm/sdk/payments';

const pricedCapabilities: PricedCapability[] = [
  {
    method: 'tools/call',
    name: 'my-tool',
    amount: 10,
    currencyUnit: 'sats',
    description: 'Example paid tool',
  },
];

const processor = new LnBolt11NwcPaymentProcessor({
  nwcConnectionString: process.env.NWC_SERVER_CONNECTION!,
});

const paidTransport = withServerPayments(baseTransport, {
  processors: [processor],
  pricedCapabilities,
});

Client: attach a handler and pay automatically

import { LnBolt11NwcPaymentHandler, withClientPayments } from '@contextvm/sdk/payments';

const handler = new LnBolt11NwcPaymentHandler({
  nwcConnectionString: process.env.NWC_CLIENT_CONNECTION!,
});

const paidTransport = withClientPayments(baseTransport, {
  handlers: [handler],
});

Core concepts (what to understand once)

Notifications and correlation

CEP-8 payments are expressed as correlated JSON-RPC notifications:

  • notifications/payment_required
  • notifications/payment_accepted
  • notifications/payment_rejected (reject without charging)

They are correlated to the original request via an e tag (request event id). Your app should treat these as notifications, not responses.

PMI (Payment Method Identifier)

Each payment rail is identified by a PMI string (example: bitcoin-lightning-bolt11).

  • Server processors advertise which PMIs they can accept.
  • Client handlers advertise which PMIs they can pay.
  • A payment only works if there is an intersection.

Amounts: advertise vs settle

pricedCapabilities[].amount + currencyUnit are what you advertise (discovery). The selected PMI determines how you settle.

If you use dynamic pricing via resolvePrice, the amount you return must match the unit expected by your chosen processor.

Server patterns

  • Fixed pricing via pricedCapabilities
  • Dynamic pricing via resolvePrice
  • Reject without charging via resolvePrice → { reject: true, message? }
  • Waive payment (prepaid/subscription) via resolvePrice → { waive: true }

Read: references/server-setup.md

Client patterns

  • Multiple handlers (multiple rails)
  • Handling payment_rejected outcomes
  • PMI advertisement via pmi tags (automatic when wrapping with withClientPayments)

Read: references/client-setup.md

Built-in rails (provided by the SDK)

The SDK currently ships multiple built-in payment rails under the same PMI:

  • PMI: bitcoin-lightning-bolt11

Rails:

More rails may be added over time (new PMIs and/or additional implementations under existing PMIs). Prefer selecting rails based on PMI compatibility and operational needs.

Build your own rail (custom PMI)

Implement:

  • a server-side PaymentProcessor (issue + verify)
  • a client-side PaymentHandler (pay)

Read: references/custom-rails.md

Troubleshooting pointers

  • No payment_required: verify request matches method + name in pricedCapabilities.
  • Payment succeeds but no payment_accepted: verify server relay connectivity and processor verification settings.
  • Immediate rejection: handle notifications/payment_rejected and surface the optional message.

For general relay/encryption/connection issues, see ../troubleshooting/SKILL.md.

Reference index

Weekly Installs
20
Repository
contextvm/cvmi
GitHub Stars
1
First Seen
Feb 12, 2026
Installed on
roo15
github-copilot14
codex14
gemini-cli14
cursor14
opencode14