payments

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ContextVM Payments (CEP-8)

ContextVM 支付(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:
  • ../typescript-sdk/SKILL.md
  • ../server-dev/SKILL.md
  • ../client-dev/SKILL.md
当你希望ContextVM服务器为特定能力收费,且客户端通过TypeScript SDK支付层自动完成支付时,可以使用本技能。
支付功能以传输中间件的形式实现:
  • 服务端中间件会拦截付费请求:只有在支付验证通过后,才会将请求转发给底层MCP服务器。
  • 客户端中间件监听支付通知,执行处理程序后,再继续处理原始请求。
本技能介绍如何使用SDK支付层。关于传输设置(签名器、中继、加密),请参考:
  • ../typescript-sdk/SKILL.md
  • ../server-dev/SKILL.md
  • ../client-dev/SKILL.md

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

快速开始:为单个工具设置收费(服务端 + 客户端)

Server: price a capability and attach payments

服务端:为能力定价并接入支付

ts
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,
});
ts
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

客户端:接入处理程序并自动支付

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

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

const paidTransport = withClientPayments(baseTransport, {
  handlers: [handler],
});
ts
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
    (CEP-21: 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.
CEP-8支付通过关联的JSON-RPC通知实现:
  • notifications/payment_required
  • notifications/payment_accepted
  • notifications/payment_rejected
    (CEP-21:不收费直接拒绝)
它们通过
e
标签(请求事件ID)与原始请求关联。你的应用应将这些视为通知,而非响应。

PMI (Payment Method Identifier)

PMI(支付方式标识符)

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.
每种支付渠道由PMI字符串标识(示例:
bitcoin-lightning-bolt11
)。
  • 服务端处理器会通告其支持的PMI。
  • 客户端处理程序会通告其可支付的PMI。
  • 只有当两者有交集时,支付才能成功。

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.
pricedCapabilities[].amount
+
currencyUnit
是你公示的金额(用于发现)。所选的PMI决定了结算方式。
如果通过
resolvePrice
使用动态定价,返回的金额必须与所选处理器期望的单位匹配。

Server patterns

服务端模式

  • Fixed pricing via
    pricedCapabilities
  • Dynamic pricing via
    resolvePrice
  • Reject without charging (CEP-21) via
    resolvePrice → { reject: true, message? }
Read:
references/server-setup.md
  • 通过
    pricedCapabilities
    设置固定定价
  • 通过
    resolvePrice
    设置动态定价
  • 通过
    resolvePrice → { reject: true, message? }
    实现不收费直接拒绝(CEP-21)
参考:
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
  • 多个处理程序(多支付渠道)
  • 处理
    payment_rejected
    结果
  • 通过
    pmi
    标签通告PMI(使用
    withClientPayments
    包装时自动完成)
参考:
references/client-setup.md

Built-in rails (provided by the SDK)

内置支付渠道(SDK提供)

The SDK currently ships multiple built-in payment rails under the same PMI:
  • PMI:
    bitcoin-lightning-bolt11
Rails:
  • Lightning over NWC (NIP-47)
    • Server:
      LnBolt11NwcPaymentProcessor
    • Client:
      LnBolt11NwcPaymentHandler
    • Read:
      references/lightning-nwc.md
  • Lightning via LNbits (REST API)
    • Server:
      LnBolt11LnbitsPaymentProcessor
    • Client:
      LnBolt11LnbitsPaymentHandler
    • Read:
      references/lightning-lnbits.md
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.
当前SDK在同一PMI下提供多种内置支付渠道:
  • PMI:
    bitcoin-lightning-bolt11
渠道:
  • 基于NWC的Lightning(NIP-47)
    • 服务端:
      LnBolt11NwcPaymentProcessor
    • 客户端:
      LnBolt11NwcPaymentHandler
    • 参考:
      references/lightning-nwc.md
  • 基于LNbits的Lightning(REST API)
    • 服务端:
      LnBolt11LnbitsPaymentProcessor
    • 客户端:
      LnBolt11LnbitsPaymentHandler
    • 参考:
      references/lightning-lnbits.md
未来可能会添加更多渠道(新PMI或现有PMI下的额外实现)。建议根据PMI兼容性和业务需求选择支付渠道。

Build your own rail (custom PMI)

构建自定义渠道(自定义PMI)

Implement:
  • a server-side
    PaymentProcessor
    (issue + verify)
  • a client-side
    PaymentHandler
    (pay)
Read:
references/custom-rails.md
需实现:
  • 服务端
    PaymentProcessor
    (生成账单 + 验证支付)
  • 客户端
    PaymentHandler
    (完成支付)
参考:
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
.
  • payment_required
    通知:验证请求是否匹配
    pricedCapabilities
    中的
    method
    +
    name
  • 支付成功但无
    payment_accepted
    通知:验证服务端中继连接和处理器验证设置。
  • 立即被拒绝:处理
    notifications/payment_rejected
    并显示可选的
    message
    信息。
关于通用中继/加密/连接问题,请参考
../troubleshooting/SKILL.md

Reference index

参考索引

  • references/cep-8-overview.md
  • references/server-setup.md
  • references/client-setup.md
  • references/lightning-nwc.md
  • references/lightning-lnbits.md
  • references/custom-rails.md
  • references/cep-8-overview.md
  • references/server-setup.md
  • references/client-setup.md
  • references/lightning-nwc.md
  • references/lightning-lnbits.md
  • references/custom-rails.md