Vai al contenuto

Runbook: verificare il MCP editoriale controllato

Quando usarlo

Usare questo runbook per validare il contratto MCP nel repository e, soltanto dentro una futura Issue operativa autorizzata, verificare la connessione development con MCP Inspector o ChatGPT.

La validazione repository non autorizza deployment, configurazione Access, creazione o lettura di secret remoti, mutazioni D1, chiamate Mailjet o connessioni client live.

Prerequisiti

Per la prova locale:

  • checkout pulito della revisione da validare;
  • versione Node dichiarata dal repository;
  • dipendenze installate con npm ci;
  • nessuna credenziale reale nei file o nella shell condivisa;
  • nessun Worker locale già in ascolto sulle porte richieste dai test.

Per la prova development aggiungere:

  • Issue operativa in stato corretto e PR mergiata da Fra;
  • esatta revisione main congelata;
  • Worker, custom domain e applicazione Access development non ambigui;
  • identità umana allowlisted;
  • service identity upstream dedicata e limitata esattamente a admin:read, quattro permessi stretti Issue e sei permessi create/update specifici per risorsa, editorial:plan, editorial:apply, più gli otto permessi email separati documentati, senza editorial:write, broad campaign:draft o permessi deployment;
  • secret inseriti solo nel secret store Cloudflare;
  • stato before editoriale e operativo acquisito con letture sanificate.

Procedura

1. Validare il repository

Eseguire dalla root:

npm run types:check:mcp
npm run typecheck:mcp
npm run test:mcp
npm run build:mcp
npm run check:mcp:contract
npm run check:mcp:development
npm run check:mcp:production

Il validator richiede esattamente nodejs_compat e global_fetch_strictly_public nella configurazione Wrangler root del Worker MCP. Development e production devono ereditare la stessa scelta, conservare i custom domain e gli upstream API esatti e non dichiarare Service Binding, D1 o altre capability. Rimuovere intenzionalmente il flag deve far fallire il test del contratto statico.

La suite deve provare input chiusi, Unicode e caratteri di controllo, limite del body MCP, limite della risposta, timeout, retry solo GET, assenza di retry POST/PUT/PATCH, status upstream, redirect cross-host, preflight canonico, idempotenza del job attivo, conflitto di revisione, separazione fra qualità, modifica, decisione, pubblicazione, unpublication separata e ogni gate email, idempotenza/single-flight, timezone e finestra schedule, outcome unknown, prompt injection inerte e log sanitizzati. Deve inoltre provare planning senza scritture o prenotazione ID, baseline e concorrenza dell'allocatore, retry idempotente, piano stale, duplicati, failure parziale e ripresa per step. Il build deve confermare che il bundle non contiene binding D1/Queue/provider o capability provider/HTTP/SQL generiche, recipient enumeration e deployment, e che unpublish è costruibile soltanto attraverso il tool e la route approvati.

apps/mcp/.dev.vars.example elenca soltanto i nomi necessari. Se serve una sessione locale autorizzata, copiarlo in .dev.vars e inserire valori reali solo nel file ignorato. Non stampare, esportare o committare quel file. La suite automatica non richiede secret e usa dipendenze isolate.

2. Verificare con MCP Inspector

Questo passaggio è remoto e appartiene alla finestra development autorizzata. Avviare Inspector in ascolto locale:

npx -y @modelcontextprotocol/inspector@latest

Mantenere client e proxy sulle interfacce localhost predefinite. Non disattivare l'autenticazione del proxy e non usare HOST=0.0.0.0.

Nella UI:

  1. scegliere Streamable HTTP;
  2. inserire https://mcp.development.architecturecoffee.it/mcp;
  3. completare il flusso OAuth/Access senza copiare token negli appunti o nei log;
  4. eseguire initialize e tools/list;
  5. verificare esattamente i trentaquattro tool e le annotazioni coerenti con lettura, mutazione preparatoria o decisione umana;
  6. chiamare overview, una ricerca bounded per ogni risorsa, un dettaglio per ogni risorsa e il preflight di generazione;
  7. inviare proprietà extra, status incompatibile e identificatore traversal e verificare l'errore chiuso;
  8. verificare che contenuto simile a istruzioni torni invariato come dato;
  9. riconciliare lo stato after con il baseline before.

Non passare assertion o service token come header CLI. Access deve essere il confine OAuth autorevole.

Se la ripresa operativa #229 restituisce UPSTREAM_UNAVAILABLE prima che la richiesta raggiunga l'API Worker, verificare prima che la revisione distribuita contenga il flag root e che l'upstream sia il custom domain development esatto. Non sostituire il percorso con workers.dev, preview URL, origine privata o Service Binding. Dopo la correzione repository-owned, rigenerare build e dry-run; deployment e prova di rete restano esclusivamente nella finestra operativa autorizzata di #229.

3. Aggiornare i tool in ChatGPT

Questo passaggio resta nell'Issue operativa development:

  1. creare o aggiornare la connessione con l'URL /mcp esatto;
  2. configurare production come Architecture Coffee Editorial MCP con tag @aceMCP, senza suffisso PROD nel nome o nel tag;
  3. configurare development come Architecture Coffee Editorial MCP - DEV con tag @aceMCP-dev;
  4. verificare che le descrizioni corrispondano al metadata canonico in apps/mcp/src/connection-metadata.ts;
  5. completare il login Access con l'identità allowlisted;
  6. forzare una nuova scansione dei tool dopo ogni cambio di metadata;
  7. aprire una nuova conversazione normale;
  8. verificare che @aceMCP selezioni il servizio production autorevole predefinito in una richiesta editoriale normale;
  9. verificare che @aceMCP-dev selezioni development soltanto quando la richiesta corrente nomina DEV o development;
  10. simulare un errore production senza invocare DEV e verificare che non avvenga fallback o commistione di evidenza;
  11. verificare overview, ricerca, dettaglio e planning con richieste chiaramente read-only; il planning non deve cambiare ID o conteggi;
  12. in una prova di mutazione development esplicitamente autorizzata, confermare la versione corrente del piano, applicarla, leggere lo stato e ripetere l'apply per provare il replay senza duplicati;
  13. verificare che approvazione/rifiuto, pubblicazione e unpublish richiedano comandi correnti separati, senza confirmed: true, compensazione o chaining;
  14. verificare che non compaiano Mailjet/HTTP/SQL generici, recipient enumeration, deployment o altri tool non approvati;
  15. chiudere la sessione di prova e riconciliare nuovamente lo stato.

4. Verificare log e assenza di side effect

Per ogni invocazione correlare soltanto:

  • request ID;
  • nome tool;
  • classe risorsa;
  • esito e durata;
  • codice errore interno bounded;
  • conteggio restituito e indicatore di truncation;
  • ambiente.

Confrontare before e after per contenuto editoriale, Issue, job, campagne, attempt, feedback e audit rilevanti. Per il sottoinsieme read-only i conteggi e checksum devono essere identici. Una futura prova di mutazione autorizzata deve predefinire e riconciliare soltanto il delta editoriale atteso; campagne, attempt provider, feedback e deployment devono restare invariati. Non conservare query, identificatori di contenuto, subject, email, assertion, cookie, authorization code, service token, body upstream o payload provider.

Verifiche attese

  • initialize e tools/list completano su Streamable HTTP;
  • esistono soltanto i tre tool di retrieval, i quattro tool intent-oriented, gli otto tool Issue, i sei tool risorsa e i sedici tool email controllati;
  • retrieval, preflight, qualità e job readback hanno readOnlyHint: true;
  • generazione e modifica draft sono mutazioni preparatorie idempotenti;
  • approvazione, rifiuto e pubblicazione sono azioni umane distruttive e non-idempotenti;
  • subscribe, unsubscribe, schedule e delivery richiedono comandi correnti distinti; prepare e content upload non li concatenano;
  • tutti i tool hanno openWorldHint: false;
  • nessuna invocazione emette più di quattro richieste upstream;
  • host, path, metodo e header sono server-owned;
  • risposta, timeout e retry restano nei limiti documentati;
  • log e errori non contengono dati sensibili;
  • lo stato read-only coincide e ogni eventuale delta autorizzato è esattamente quello predefinito;
  • nessuna chiamata raggiunge D1 direttamente; i test repository non raggiungono Mailjet o altri provider esterni.

Condizioni di stop

Fermarsi immediatamente se:

  • la revisione non coincide con main autorizzato;
  • il dominio, l'ambiente o l'applicazione Access sono ambigui;
  • discovery espone un tool o un'annotazione inattesi;
  • una richiesta upstream esce dalle coppie route/metodo documentate;
  • compare un binding D1, Queue, provider o storage di sessione;
  • manca global_fetch_strictly_public, compare un override per ambiente o viene introdotto un Service Binding MCP-to-API;
  • l'identità upstream non ha esattamente i ventidue permessi stretti previsti oppure include broad campaign:draft o deployment;
  • un errore o log espone contenuto, query, identità o credenziali;
  • il checksum read-only o il delta autorizzato diverge;
  • Inspector o ChatGPT richiede una configurazione non prevista;
  • serve una mutazione remota non compresa nell'Issue operativa.

Rollback o recupero

La prova repository non muta stato e non richiede rollback. Correggere il codice, rigenerare il bundle e ripetere l'intera validazione.

Durante una prova development:

  1. disconnettere il client MCP;
  2. revocare o disabilitare la service identity dedicata e la policy Access coinvolta secondo l'Issue operativa;
  3. non riusare credenziali potenzialmente esposte;
  4. riportare il Worker alla revisione autorizzata precedente, se il deployment era compreso nella finestra;
  5. ripetere soltanto letture di riconciliazione;
  6. registrare l'esito senza copiare evidenza privata.

Non cancellare o riscrivere D1 come forma di rollback del server MCP.

Evidenza da conservare

  • commit esatto e run CI;
  • versione Node e comandi eseguiti;
  • conteggio test MCP e risultato di typecheck, build, dry-run e bundle check;
  • trentaquattro nomi tool e annotazioni;
  • request ID, esiti e durate bounded;
  • checksum o conteggi sanitizzati before/after;
  • conferma di zero route fuori allowlist, zero binding D1/provider e zero chiamate Mailjet/deployment nella prova repository;
  • eventuale codice errore sanitizzato e decisione di stop.

Non conservare token, cookie, assertion, audience, client ID reali, secret, email, recipient, query, contenuto editoriale completo o evidenza provider privata.