# Ricetta: server MCP a pagamento

> Fai pagare ogni chiamata ai tool di un server MCP, con i crediti. Una persona compra un pacchetto una volta; ogni chiamata prima scala e poi lavora.

Gli agenti non devono pagare da soli. Una persona compra un pacchetto di crediti nel browser, poi ogni chiamata a un tool controlla il saldo, scala crediti con una chiave di idempotenza e lavora. Quando i crediti finiscono, il tool risponde con un link di ricarica che l’agente mostra alla persona. Niente x402, niente wallet nell’agente, niente addebiti automatici.

> **Nota:** Con un assistente: la skill `paid-mcp-tools` del plugin Perly Pay realizza questa ricetta nel tuo progetto. L’esempio eseguibile è `examples/paid-mcp-server` (MIT) nel repository del plugin.

## Come funziona

1. **Un pacchetto di crediti** — Come nei [crediti API](https://pay.perly.io/docs/recipe-api-credits.md). Dai un prezzo a ogni tool e scrivilo nella sua descrizione.
2. **Chi chiama** — Un server ospitato associa la chiave API di ogni abbonato all’`external_id` di un cliente. `PERLY_PAY_SECRET_KEY` è solo sul tuo server.
3. **Prima scala, poi lavora** — `credits.consume` con il nome del tool come `action` e una nuova chiave che il tuo server genera a ogni chiamata; poi il lavoro.
4. **Non basta?** — Restituisci un risultato del tool con `isError: true` e il link di ricarica, non un errore di protocollo: i client lo mostrano.
5. **Aiuti gratuiti** — I tool `balance` e `top_up`, così l’agente può spiegare cosa succede.

**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) }] };
});
```

## Esegui l’esempio

1. **Installa** — `npm install` in `examples/paid-mcp-server` (Node 20.12+).
2. **Chiave** — Copia `.env.example` in `.env` e metti una chiave di test (`sk_test_…`) in `PERLY_PAY_SECRET_KEY`.
3. **Prepara** — `npm run setup` crea il prodotto e il prezzo con la tua chiave e stampa i loro id per `.env`.
4. **Avvia** — `npm start` (o `npm run dev`), come dice il suo README.
5. **Paga senza wallet** — Aggiungilo a Claude Code (`claude mcp add paid-tools -- npx tsx "$PWD/src/server.ts"`) ed esegui `word_stats`: la risposta è la pagina di ricarica. Scegli un pacchetto, premi **Simulate payment** ed eseguilo di nuovo.

## Errori comuni

- `PERLY_PAY_SECRET_KEY` in una configurazione MCP che altri copiano. Ospita tu il server o fallo chiamare il tuo backend.
- Scalare dopo il lavoro: uno scalo fallito significa allora lavoro gratis.
- Prendere la chiave dello scalo dall’id JSON-RPC: lo sceglie il client, e lo stesso id restituisce il primo scalo, quindi il tool lavora di nuovo gratis.
