Getting started
Getting started
Section titled “Getting started”This page shows the smallest end-to-end setup:
- a server that charges for a single tool
- a client that can pay via Lightning BOLT11 over NWC
If you haven’t set up Nostr transports yet, start with the transport docs first.
1) Server: mark capabilities as priced
Section titled “1) Server: mark capabilities as priced”Define what is paid using pricedCapabilities.
import type { PricedCapability } from '@contextvm/sdk/payments';
export const pricedCapabilities: PricedCapability[] = [ { method: 'tools/call', name: 'my-tool', amount: 10, currencyUnit: 'sats', description: 'Example paid tool', },];2) Server: attach payments middleware
Section titled “2) Server: attach payments middleware”Create a processor, then wrap your server transport.
import { LnBolt11NwcPaymentProcessor, withServerPayments,} from '@contextvm/sdk/payments';import { NostrServerTransport } from '@contextvm/sdk/transport';
const baseTransport = new NostrServerTransport({ signer, relayHandler,});
const processor = new LnBolt11NwcPaymentProcessor({ nwcConnectionString: process.env.NWC_SERVER_CONNECTION!,});
const paidTransport = withServerPayments(baseTransport, { processors: [processor], pricedCapabilities,});Server behavior for priced requests:
- emits
notifications/payment_required(correlated to the request) - waits for settlement verification
- emits
notifications/payment_accepted - forwards the request to the underlying MCP server
3) Client: attach payments middleware
Section titled “3) Client: attach payments middleware”Create a handler and wrap your client transport.
import { LnBolt11NwcPaymentHandler, withClientPayments,} from '@contextvm/sdk/payments';import { NostrClientTransport } from '@contextvm/sdk/transport';
const baseTransport = new NostrClientTransport({ signer, relayHandler, serverPubkey,});
const handler = new LnBolt11NwcPaymentHandler({ nwcConnectionString: process.env.NWC_CLIENT_CONNECTION!,});
const paidTransport = withClientPayments(baseTransport, { handlers: [handler],});Now priced calls will automatically pay when required.
4) Try a paid call
Section titled “4) Try a paid call”Any request that matches pricedCapabilities will trigger the payment flow.
await client.callTool({ name: 'my-tool', arguments: { example: true },});