Skip to content

Examples

Basic MCP Server with Payment

A minimal MCP server that charges $0.01 per search call:

ts
import Fastify from 'fastify';
import { PayrePay } from '@payre/pay';

const app = Fastify();
const payre = new PayrePay({ secretKey: process.env.PAYRE_SECRET_KEY });

const sessions = new Map();

// MCP initialize
app.post('/mcp', async (req, reply) => {
  const { method, params, id } = req.body;

  if (method === 'initialize') {
    const sessionId = crypto.randomUUID();
    sessions.set(sessionId, { initialized: true });
    reply.header('mcp-session-id', sessionId);
    return {
      jsonrpc: '2.0', id,
      result: {
        protocolVersion: '2025-03-26',
        capabilities: { tools: { listChanged: false } },
        serverInfo: { name: 'my-paid-server', version: '1.0.0' },
      },
    };
  }

  if (method === 'tools/list') {
    return {
      jsonrpc: '2.0', id,
      result: {
        tools: [{
          name: 'search',
          description: 'Search documents ($0.01/call)',
          inputSchema: {
            type: 'object',
            properties: { query: { type: 'string' } },
            required: ['query'],
          },
        }],
      },
    };
  }

  if (method === 'tools/call') {
    const apiKey = req.headers['x-payre-key'];
    if (!apiKey) {
      return {
        jsonrpc: '2.0', id,
        result: {
          content: [{ type: 'text', text: 'Payment required. Set X-Payre-Key header.' }],
          isError: true,
        },
      };
    }

    try {
      const receipt = await payre.charge({ apiKey, tool: 'search', amount: 0.01 });
      const results = await doSearch(params.arguments.query);
      return {
        jsonrpc: '2.0', id,
        result: {
          content: [{ type: 'text', text: JSON.stringify(results) }],
          _meta: { receipt },
        },
      };
    } catch (err) {
      return {
        jsonrpc: '2.0', id,
        result: {
          content: [{ type: 'text', text: `Payment failed: ${err.message}` }],
          isError: true,
        },
      };
    }
  }
});

app.listen({ port: 3001 });

Multi-Tool Pricing

A server with three tools at different price points:

ts
import { PayrePay } from '@payre/pay';

const payre = new PayrePay({ secretKey: process.env.PAYRE_SECRET_KEY });

const pricing = payre.pricing({
  'search':    0.005,   // $0.005 -- cheap, high volume
  'summarize': 0.01,    // $0.01  -- moderate
  'generate':  0.05,    // $0.05  -- expensive, uses LLM
});

async function handleToolCall(toolName, args, request) {
  const receipt = await pricing.charge({
    apiKey: request.headers['x-payre-key'],
    tool: toolName,
  });

  switch (toolName) {
    case 'search':    return doSearch(args.query);
    case 'summarize': return doSummarize(args.text);
    case 'generate':  return doGenerate(args.prompt);
  }
}

Freemium Model

Give users 5 free calls, then require payment:

ts
const freeTierUsage = new Map();  // apiKey -> count

async function handleToolCall(params, request) {
  const apiKey = request.headers['x-payre-key'];

  // Track free tier
  const used = freeTierUsage.get(apiKey) ?? 0;

  if (used < 5) {
    // Free tier
    freeTierUsage.set(apiKey, used + 1);
    return doSearch(params.query);
  }

  // Paid tier
  const receipt = await payre.charge({
    apiKey,
    tool: 'search',
    amount: 0.005,
  });

  return doSearch(params.query);
}

Consumer: Calling a Paid MCP Server

From the consumer side, using Claude Desktop or any MCP client:

json
{
  "mcpServers": {
    "paid-search": {
      "url": "https://search-server.example.com/mcp",
      "headers": {
        "X-Payre-Key": "pyr_ck_live_your_key_here"
      }
    }
  }
}

Or with curl:

bash
# Initialize
curl -X POST https://search-server.example.com/mcp \
  -H "Content-Type: application/json" \
  -H "X-Payre-Key: pyr_ck_live_xxx" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","clientInfo":{"name":"test","version":"1.0"}}}'

# Call tool (charges $0.01)
curl -X POST https://search-server.example.com/mcp \
  -H "Content-Type: application/json" \
  -H "X-Payre-Key: pyr_ck_live_xxx" \
  -H "mcp-session-id: <session-id-from-init>" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search","arguments":{"query":"hello world"}}}'