# Receta: servidor MCP de pago

> Cobra por cada llamada a las herramientas de un servidor MCP, con créditos. Una persona compra un paquete una vez; cada llamada primero descuenta y luego trabaja.

Los agentes no tienen que pagar por su cuenta. Una persona compra un paquete de créditos en el navegador y después cada llamada a una herramienta consulta el saldo, descuenta créditos con una clave de idempotencia y trabaja. Cuando no hay créditos, la herramienta responde con un enlace de recarga que el agente muestra a la persona. Sin x402, sin billetera en el agente, sin cobros automáticos.

> **Nota:** Con un asistente: la skill `paid-mcp-tools` del plugin de Perly Pay hace esta receta en tu proyecto. El ejemplo ejecutable es `examples/paid-mcp-server` (MIT) en el repositorio del plugin.

## Cómo funciona

1. **Un paquete de créditos** — Como en [créditos de API](https://pay.perly.io/docs/recipe-api-credits.md). Pon precio a cada herramienta y escríbelo en su descripción.
2. **Quién llama** — Un servidor alojado asocia la clave de API de cada suscriptor con el `external_id` de un cliente. `PERLY_PAY_SECRET_KEY` solo está en tu servidor.
3. **Primero descontar, luego trabajar** — `credits.consume` con el nombre de la herramienta como `action` y una clave nueva que tu servidor genera en cada llamada; luego el trabajo.
4. **¿No alcanza?** — Devuelve un resultado de herramienta con `isError: true` y el enlace de recarga, no un error de protocolo: los clientes lo muestran.
5. **Ayudantes gratis** — Herramientas `balance` y `top_up`, para que el agente pueda explicar qué pasa.

**A paid tool**

```js
server.registerTool("summarize", { description: "Costs 3 credits.", inputSchema: { text: z.string() } }, async ({ text }, extra) => {
  const refused = await charge(userId, 3, "summarize", extra.requestId); // credits.consume, or a top-up message
  if (refused) return { isError: true, content: [{ type: "text", text: refused }] };
  return { content: [{ type: "text", text: summarize(text) }] };
});
```

## Ejecuta el ejemplo

1. **Instala** — `npm install` en `examples/paid-mcp-server` (Node 20.12+).
2. **Clave** — Copia `.env.example` a `.env` y pon una clave de prueba (`sk_test_…`) en `PERLY_PAY_SECRET_KEY`.
3. **Prepara** — `npm run setup` crea el producto y el precio con tu clave e imprime sus ids para `.env`.
4. **Ejecuta** — `npm start` (o `npm run dev`), según diga su README.
5. **Paga sin billetera** — Añádelo a Claude Code (`claude mcp add paid-tools -- npx tsx "$PWD/src/server.ts"`) y ejecuta `word_stats`: la respuesta es la página de recarga. Elige un paquete, pulsa **Simulate payment** y ejecútalo otra vez.

## Errores comunes

- `PERLY_PAY_SECRET_KEY` en una configuración MCP que otros copian. Aloja el servidor tú mismo o haz que llame a tu backend.
- Descontar después del trabajo: un descuento fallido significa entonces trabajo gratis.
- Tomar la clave del descuento del id de JSON-RPC: lo elige el cliente, y el mismo id devuelve el primer descuento, así que la herramienta vuelve a trabajar gratis.
