# Rate limit per un server MCP: finestra, quota e 429 utile

Un server MCP regge i picchi con un contatore per account, una finestra dichiarata e un 429 con Retry-After. Ecco i numeri e i compromessi.

> Pagina: https://ui.eneawork.it/blog/mcp-rate-limit-design
> Markdown: https://ui.eneawork.it/blog/mcp-rate-limit-design.md

*2026-11-01*

Un server MCP regge i picchi con un contatore per account, una finestra dichiarata e una risposta 429 che dice quando riprovare. Il resto è strumentazione.

Il gate in backend/mcp.js e i piani in backend/entitlements.js, letti il 1 novembre 2026, danno questi limiti per minuto: 120 richieste anonime per IP da RATE_MCP_PER_MIN, 120 sul piano free, 600 sul pro, 1.200 su team, business e premium, ognuno sovrascrivibile da una variabile d'ambiente. La finestra è fissa, 60.000 ms per account, e la risposta è 429 con Retry-After: 60 e l'errore JSON-RPC -32002. La pagina Tools della revisione MCP 2025-06-18, letta su modelcontextprotocol.io il 1 novembre 2026, mette «Rate limit tool invocations» fra i requisiti dei server. L'endpoint EneUI ha risposto a tools/list con 3.655 byte in 218 ms, misurati il 1 novembre 2026. Il catalogo dietro conta 111.985 componenti, 1.556 blocchi e 12.808 icone da 1.472 librerie, letti da /api/stats lo stesso giorno.

## La chiave conta più del numero

Un limite per indirizzo IP punisce un ufficio dietro un NAT e non ferma chi ruota gli IP. Un limite per token segue l'account: il team condivide una quota, e un client non può eluderla cambiando rete. EneUI fa così: contatore sull'identificativo dell'account quando arriva un bearer token, contatore per IP quando la chiamata è anonima.

## Quattro piani, un tetto dichiarato

La colonna oraria è il limite per minuto moltiplicato per 60: è un tetto dichiarato, non una seconda quota. Un contatore al minuto non impedisce di spendere tutto in dieci secondi, e questo è il primo compromesso da accettare.

## Finestra fissa o scivolosa

La finestra fissa costa una mappa e un timestamp: si azzera ogni 60 secondi e non richiede memoria storica. Il difetto è il bordo: un client può fare 600 richieste alle 12:00:59 e altre 600 alle 12:01:00, cioè il doppio del limite in due secondi. Se il burst al bordo è un problema, serve una finestra scivolosa o un token bucket, e serve memoria condivisa.

## Cosa deve dire un 429

curl -si https://ui.eneawork.it/mcp \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | head -n 9

Il comando mostra status e header della risposta. Quando il contatore è pieno compaiono 429, Retry-After: 60 e un corpo JSON-RPC con codice -32002 che nomina il limite e il piano. Un client che legge quel messaggio sa se aspettare o chiedere un upgrade; un client che riceve un 429 muto riprova subito e peggiora la situazione.

## Il contatore vive in memoria

EneUI tiene le finestre in una Map indicizzata per account. È la scelta giusta per un processo solo e la scelta sbagliata per due istanze: dopo un riavvio il conteggio riparte da zero, e con due processi il limite effettivo raddoppia. Con più istanze il contatore va in Redis o nel database, altrimenti il numero nel listino è una promessa che il sistema non mantiene.

## La limitazione

La risposta di EneUI non porta header di quota: il client scopre il limite solo quando lo colpisce. Manca anche un costo dichiarato per richiesta, quindi un agente non può pianificare il budget prima di chiamare. Chi vuole un client educato deve leggere il 429, aspettare i secondi indicati e ridurre il numero di tool esposti, non aumentare i tentativi.

## Dove continuare

L'autenticazione che rende possibile il conteggio per account è in OAuth per un server MCP, e la forma dei tool che consumano quota è in progettare un tool MCP. Per il protocollo e i trasporti leggi che cos'è MCP. Il catalogo dietro il server è in 111.985 componenti e 1.556 blocchi; un record con licenza MIT dichiarata a monte è agent dock di dqnamo.

## FAQ

### Quale limite metto su un server MCP nuovo?

Parti da un numero misurabile e basso: EneUI espone 120 richieste al minuto per l'anonimo (gate per IP), 120 per il piano free, 600 per il pro e 1.200 per il team, letti in backend/mcp.js e backend/entitlements.js il 1 novembre 2026. Alza il numero quando i log mostrano account bloccati a metà lavoro, non quando un client protesta.

### Meglio un 429 o un errore JSON-RPC nel corpo?

Entrambi: lo status HTTP 429 dice al trasporto che è un limite, e il corpo JSON-RPC con codice -32002 dice al client quale limite e quale piano. Aggiungi Retry-After con i secondi mancanti, altrimenti il client riprova subito.

### Conto le richieste per IP o per token?

Per token quando il client è autenticato, per IP quando è anonimo. L'IP da solo punisce chi condivide un NAT e premia chi ruota gli indirizzi. EneUI usa il gate per IP solo per il traffico senza credenziali.

### Finestra fissa o token bucket?

La finestra fissa costa una mappa e va bene per un processo solo. Il token bucket spiana il burst al bordo, ma richiede stato condiviso e quindi Redis o database quando il server ha più istanze.

### Il protocollo MCP definisce un rate limit?

No, non fissa il meccanismo. La revisione 2025-06-18 mette «Rate limit tool invocations» fra i requisiti dei server nella pagina Tools, quindi il limite esiste ma lo implementa il server, con le sue chiavi e le sue risposte.
