Paginare (cursor) și cache (ttlMs, cacheScope) în Model Context Protocol (MCP)

Protocol și Arhitectură Specificația MCP 2026-07-28

Cum împart serverele MCP listele lungi în pagini cu cursor opac și cum indică cât timp poate clientul păstra un rezultat în cache.

Specificație & cod MCP
params: {"cursor": "..."}  →  result: {..., "nextCursor": "...", "ttlMs": 300000, "cacheScope": "public"}

Ce face Paginare (cursor) și cache (ttlMs, cacheScope)

Paginarea folosește un cursor opac în locul numerelor de pagină. Serverul alege dimensiunea paginii și pune nextCursor în răspuns dacă mai există rezultate; clientul trimite cursorul în params.cursor la cererea următoare. Operațiile paginate sunt tools/list, prompts/list, resources/list și resources/templates/list. Lipsa lui nextCursor marchează sfârșitul; un șir gol este un cursor valid. Un cursor invalid duce la eroarea -32602.

Cache-ul a apărut în 2026-07-28. Rezultatele finale ale server/discover, tools/list, prompts/list, resources/list, resources/templates/list și resources/read trebuie să conțină ttlMs și cacheScope. ttlMs (în milisecunde, cel puțin 0) spune cât timp rezultatul poate fi considerat proaspăt, ca Cache-Control: max-age; absent sau negativ, se tratează ca 0. Nu este un interval de polling: clientul verifică prospețimea când are nevoie de date. cacheScope este public (fără date specifice utilizatorului, partajabil și de gateway-uri) sau private (doar în același context de autorizare).

Cheia de cache este metoda plus parametrii care influențează rezultatul, de exemplu uri sau cursor. Rezultatele input_required și cele obținute la reîncercări cu inputResponses sau requestState nu se pun în cache. O notificare list_changed sau resources/updated invalidează imediat intrarea. Fiecare pagină are propriul ttlMs, dar toate paginile unei liste au același cacheScope.

Sintaxă și opțiuni

Opțiune / Parametru Descriere
cursor În cerere: poziția de unde continuă lista. Opac; clientul nu îl parsează.
nextCursor În răspuns: cursorul paginii următoare, dacă există.
ttlMs Milisecunde de prospețime. 0 înseamnă imediat expirat.
cacheScope: public Răspunsul nu conține date specifice utilizatorului; orice client sau proxy îl poate servi oricui.
cacheScope: private Răspunsul se reutilizează doar în același context de autorizare (alt token, alt cache).

Exemple practice

Exemplul 1: Pagină de rezultate cu cursor și TTL

{
  "jsonrpc": "2.0",
  "id": "123",
  "result": {
    "resultType": "complete",
    "resources": [...],
    "nextCursor": "eyJwYWdlIjogM30=",
    "ttlMs": 300000,
    "cacheScope": "public"
  }
}

Exemplul 2: Cererea paginii următoare

{
  "jsonrpc": "2.0",
  "id": "124",
  "method": "resources/list",
  "params": {
    "cursor": "eyJwYWdlIjogMn0="
  }
}

Greșeli frecvente și bune practici

  • Interpretezi un cursor gol ca sfârșit al listei. Doar lipsa lui nextCursor înseamnă sfârșit.
  • Marchezi public un rezultat care depinde de utilizator. Poate fi servit altor utilizatori prin cache-uri partajate; cacheScope nu înlocuiește controlul de acces.
  • Folosești ttlMs ca interval de reîmprospătare automată. Dacă totuși faci polling, specificația cere jitter și backoff.

Comenzi înrudite