MCP: collegare l'AI ai sistemi del cliente senza farsi male
Model Context Protocol è il modo serio per dare a un modello accesso a tool e dati interni. Come progettiamo server MCP custom, gestiamo permessi e teniamo l'audit trail.
lintedhub
redazione tecnicaMCP: collegare l'AI ai sistemi del cliente senza farsi male
C'è una differenza enorme fra un agente AI che può rispondere a domande e un agente AI che può fare cose. La prima è una versione più sofisticata di un chatbot; la seconda è un sistema operativo, con tutti i vincoli che ne conseguono. Il pezzo di tecnologia che permette il salto si chiama Model Context Protocol (MCP), ed è oggi uno degli aspetti più interessanti dell'ecosistema AI.
In questo articolo raccontiamo come lo usiamo nei progetti reali, perché è più sicuro di alternative ad-hoc, e cosa serve per non farsi male collegandolo ai sistemi di un cliente.
Cos'è MCP, in due righe
MCP è un protocollo aperto che standardizza il modo in cui un modello linguistico può accedere a:
- Tool (azioni che modificano stato: scrivere un file, creare un ticket, chiamare un'API).
- Resource (dati read-only: contenuto di un documento, schema di un DB, contenuto di una repo).
- Prompt (template parametrizzati riusabili).
La differenza con un'integrazione "fatta in casa" non è la possibilità tecnica (anche con tool calling proprietario si fa quasi tutto), ma la struttura. MCP forza una separazione fra l'agente e i sistemi a cui parla, e quella separazione è esattamente dove inseriamo i controlli di sicurezza.
Perché non basta tool calling diretto
Un'obiezione legittima: "ho già tool calling nell'SDK del modello, perché aggiungere MCP?". La risposta breve: perché tool calling diretto fa lavorare l'agente e i tool nello stesso processo, con gli stessi permessi del codice che lo orchestra. È un pattern accettabile per un MVP, è un pattern pessimo per un sistema in produzione che tocca dati di un cliente.
Con MCP, ogni server vive in un processo isolato, espone solo le capability dichiarate, e parla con l'agente attraverso un canale strutturato. Conseguenze:
- Si possono dare permessi diversi a server diversi (DB con read-only, GitHub con scrittura sui PR, file system con scope ristretto).
- Si può audit-loggare ogni chiamata in modo uniforme.
- Si può riusare lo stesso server MCP fra agenti diversi, senza duplicare la logica di accesso.
- Si può rimuovere un server senza riscrivere l'agente.
È architettura banale, ma applicata al posto giusto fa la differenza fra un sistema controllabile e una bomba a orologeria.
La nostra struttura tipica
Per ogni cliente serio, costruiamo uno o più server MCP custom. Schema mentale:
┌──────────────────┐ MCP ┌─────────────────────┐
│ Agent (LLM) │ ◀───────────────▶ │ Server MCP custom │
│ Claude / OpenAI │ stdio / SSE │ (Node, Python, Go) │
└──────────────────┘ └─────────┬───────────┘
│
▼
┌──────────────────────┐
│ Sistema del cliente │
│ (DB, ERP, ticketing) │
└──────────────────────┘
Il server MCP è il punto in cui mettiamo:
- Auth verso il sistema del cliente (token, mTLS, OAuth, quel che serve).
- Authorization granulare: quali tool sono esposti, quali tabelle/endpoint sono read-only, quali scritture richiedono conferma umana.
- Validation degli input: schema runtime, sanitizzazione, sanity check sulle chiamate "strane".
- Rate limiting per tool: una scrittura su DB ogni N secondi, anche se il modello la ripete.
- Logging strutturato: ogni chiamata, con id di richiesta, parametri, esito, latenza.
L'agente, dal lato suo, vede solo i tool che decidiamo di esporre. Niente di più.
Esempio reale (semplificato)
Per un cliente nel settore B2B abbiamo costruito un server MCP che espone i ticket di assistenza. L'agente può:
// pseudo-schema dei tool esposti
list_tickets({ status, customer_id, limit })
get_ticket({ id })
search_tickets({ query, since })
add_internal_comment({ ticket_id, body })
escalate_ticket({ ticket_id, reason })
Note di design:
- Niente
update_ticket. La modifica di campi sensibili (assignee, priorità, status finale) richiede passaggi umani. add_internal_commentnon è pubblico al cliente finale. È visibile solo agli operatori. Riduce drasticamente il rischio di output AI imbarazzanti.escalate_ticketnotifica un canale Slack, non chiude il ticket. È un'azione "sicura" anche se sbagliata.- Tutti i tool richiedono
actor_id, che identifica l'agente come pseudo-utente nel sistema. Audit trail leggibile come quello di una persona.
Risultato pratico: l'agente smista, classifica, suggerisce risposte, lascia commenti utili. Le decisioni che potrebbero rompere qualcosa restano umane.
Sicurezza, sul serio
Tre regole non negoziabili:
- Least privilege per default. Ogni nuovo tool nasce read-only. La scrittura si abilita solo dopo discussione esplicita e tracciabile.
- Output sanitization. Un agente che riceve dati dal sistema del cliente non deve poterli rimandare grezzi all'utente finale senza filtro. Sanitizzazione lato server MCP.
- Audit log immutabile. Su un sink che l'agente non può scrivere. Append-only. Conserva input, output, durata, esito di ogni tool.
Una buona euristica: se un giudice ti chiedesse "come sa il tuo sistema chi ha fatto cosa, e quando", devi avere risposta in meno di un minuto. Se non ce l'hai, l'audit non è sufficiente.
Quando MCP è eccessivo
Per onestà: MCP non serve sempre. Se il task è "leggi un file e classificalo", basta un'API call. Se il task è "rispondi a una FAQ con RAG", basta una chiamata al modello con il contesto. MCP entra in gioco quando:
- L'agente deve eseguire più tool in sequenza.
- Quei tool toccano sistemi diversi del cliente.
- Serve audit, permessi granulari, isolamento dei processi.
- Il sistema deve essere riusato fra agenti o fra clienti diversi.
In tutti gli altri casi, l'overhead di MCP non è giustificato. La regola d'oro: usare la cosa più semplice che soddisfa i vincoli reali, non la più sofisticata che si potrebbe usare.
In sintesi
MCP è il livello di astrazione che mancava per passare dagli "agenti che parlano" agli "agenti che operano". È diventato il default nei progetti dove l'AI tocca sistemi reali, e probabilmente lo sarà ancora di più nei prossimi mesi.
La parte importante non è il protocollo in sé, è il pattern: separare nettamente l'agente dai sistemi che usa, mettere i controlli al confine, audit-loggare tutto. Quando si rispetta questo pattern, integrare AI in azienda smette di essere un atto di fede e diventa una cosa che si può discutere con un CISO senza imbarazzo.
Hai un progetto in mente?
Trasformiamo scelte tecniche complesse in sistemi in produzione.
Se stai valutando stack, architetture o integrazioni AI, parliamone. Niente pitch: una conversazione tecnica.
ParliamoneContinua a leggere
Tutti gli articoliEval set: il test driven development per i sistemi AI
Senza un eval set scritto, ogni modifica a un prompt è una preghiera. Ecco come costruiamo eval realistici, li mettiamo in CI e perché trattiamo i prompt come codice di produzione.
Direttive scritte: trattare i prompt come codice di produzione
Un prompt non è un messaggio in chat, è un artefatto di sistema. Come strutturiamo direttive, le versioniamo, le rivediamo in PR e perché evitiamo le "chat improvvisate" sui task seri.
Pattern di integrazione AI che abbiamo imparato
Dopo mesi di sviluppo con LLM, ecco i pattern che funzionano davvero in produzione e quelli che sembrano buone idee ma non lo sono.