MCP server personalizzati per Claude Code: estendere il workflow aziendale con tool custom

MCP server personalizzati per Claude Code: estendere il workflow aziendale con tool custom

Un agente di coding generico è utile; un agente che conosce i tuoi sistemi è trasformativo. La differenza la fa il Model Context Protocol, lo standard, ormai donato alla Linux Foundation, che permette di dare a Claude Code accesso controllato a sistemi aziendali reali: un database, un'API gestionale, un CMS, un'automazione interna. Io lo uso ogni giorno: la mia pipeline editoriale parla con un CMS attraverso un confine di questo tipo, e la differenza tra un agente che genera testo nel vuoto e uno che pubblica davvero, verifica lo stato, rigenera un indice, passa tutta da lì. Ma "controllato" è la parola che conta, ed è il filo di questo articolo: costruire un MCP server non è solo costruire un'integrazione, è costruire un confine di sicurezza. Vediamo come si fa in PHP, dallo schema dei tool alla gestione dei permessi, con la disciplina giusta fin dall'inizio.

Un MCP server è due cose insieme: un'integrazione che dà superpoteri all'agente, e una superficie d'attacco che li espone. I tool che definisci sono le mani dell'agente sui tuoi sistemi, e gli scope che concedi sono il loro raggio d'azione. Si progettano insieme, non l'uno dopo l'altro.

Cos'è un MCP server e cosa espone davvero all'agente?

Tecnicamente, un MCP server è un processo che espone all'agente tre tipi di capacità: tool (funzioni che l'agente può invocare, ciascuna con uno schema dell'input), resource (dati che l'agente può leggere) e prompt (template riusabili). Per il workflow aziendale i protagonisti sono i tool: sono le azioni concrete che l'agente acquisisce, e l'agente li scopre, li capisce dalla loro descrizione, e decide di invocarli quando il compito lo richiede. La specifica completa vive su modelcontextprotocol.io; quello che conta per chi costruisce è un'idea semplice e potente: un tool è una funzione con un contratto leggibile da una macchina, e l'insieme dei tool che esponi definisce esattamente cosa l'agente può e non può fare sui tuoi sistemi.

È qui che si gioca tutto. Un tool non è solo una comodità funzionale, è una concessione di potere. Esporre un tool "esegui questa query SQL" dà all'agente le chiavi dell'intero database; esporre un tool "recupera l'ordine con questo id" gli dà una capacità precisa e circoscritta. I due fanno lo stesso lavoro nel caso felice, ma il primo è una voragine di sicurezza e il secondo è un confine. La progettazione dei tool è la progettazione dei permessi, e ignorarlo è la radice del problema di over-broad token scoping che ho analizzato in dettaglio in MCP e over-broad token scoping.

Se vuoi integrare un agente di coding nei sistemi reali della tua azienda senza trasformarlo in un rischio, nel mio hub dedicato all'AI per lo sviluppo raccolgo gli articoli con la metodologia che applico sul campo.

Costruire un MCP server in PHP: lo schema dei tool

In ecosistema PHP costruire un MCP server è oggi alla portata di qualunque sviluppatore, grazie alle librerie MCP first-party comparse nel 2026 accanto al Laravel AI SDK. L'anatomia di un tool è sempre la stessa, e la mostro nella sua forma essenziale, perché è la forma che conta. Un tool ha un nome, una descrizione (che l'agente legge per capire quando usarlo), uno schema dell'input (che vincola cosa l'agente può passare) e un handler che esegue il lavoro:

final class GetOrderTool
{
    public string $name = 'get_order';

    // La descrizione e' cio' che l'agente legge per decidere se invocarlo.
    public string $description = 'Recupera i dati di un ordine dato il suo identificativo.';

    // Lo schema vincola l'input: niente di piu' di un id intero.
    public array $inputSchema = [
        'type'       => 'object',
        'properties' => ['order_id' => ['type' => 'integer']],
        'required'   => ['order_id'],
    ];

    public function handle(array $input, AgentContext $ctx): array
    {
        // Il confine di sicurezza vive QUI: l'ordine e' vincolato all'azienda
        // dell'utente per cui l'agente sta lavorando, non recuperato e basta.
        $order = $this->orders->findScoped((int) $input['order_id'], $ctx->tenantId);
        return $order?->toArray() ?? ['error' => 'not_found'];
    }
}

Tre cose rendono questo tool sicuro, e nessuna è accessoria. Lo schema dell'input impedisce all'agente di passare qualcosa di diverso da un id intero: niente stringhe arbitrarie, niente payload. La descrizione è precisa e ristretta, così l'agente lo invoca per lo scopo giusto. E soprattutto l'handler vincola il dato al contesto: l'ordine viene recuperato già filtrato sull'azienda per cui l'agente lavora, non recuperato e poi sperato. È la differenza tra un tool che fa il suo lavoro e un tool che è un IDOR in attesa di accadere.

La sicurezza non è uno strato sopra: è la forma dei tool

Il principio che applico, e che evita la classe di problemi più comune in queste integrazioni, è di progettare tool stretti e orientati allo scopo, mai generici e potenti. La tentazione di esporre uno strumento onnipotente, "query libera sul database", "chiamata HTTP arbitraria", "esegui questo comando", è fortissima perché è comodo: con un tool solo l'agente può fare tutto. Ma "può fare tutto" è esattamente ciò che un attaccante, capace di iniettare un'istruzione attraverso un contenuto non fidato che l'agente legge, userà contro di te. La regola è quella del least privilege portato al livello dei tool: ogni tool fa una cosa precisa, su un perimetro definito, e la separazione tra lettura e scrittura è netta. I tool di lettura possono stare in autonomia; quelli che scrivono, cancellano o eseguono richiedono una conferma umana o vivono in un contesto isolato.

Questo si lega direttamente all'architettura della harness in cui l'MCP server si inserisce. Un MCP server non vive nel vuoto: è uno degli strati di un sistema che comprende gli hook di validazione, le regole e il motore dei permessi, di cui ho parlato in anatomia di una harness Claude Code di produzione. I tool MCP estendono ciò che l'agente può fare; il perimetro di sicurezza attorno decide cosa di tutto questo è permesso davvero. I due vanno progettati insieme: un tool potente dietro un perimetro rigoroso è gestibile, un tool potente senza perimetro è una bomba.

Lettura e scrittura: due regimi, non uno

La separazione tra lettura e scrittura non è un consiglio astratto, è una scelta che si vede nel codice. Un tool che modifica lo stato non ha la stessa forma di uno che legge: porta con sé una richiesta di conferma o vive in un perimetro che ne contiene le conseguenze. Lo stesso get_order di prima, nella sua versione di scrittura, cambia natura:

final class UpdateOrderStatusTool
{
    public string $name = 'update_order_status';
    public string $description = 'Aggiorna lo stato di un ordine. Operazione che modifica dati.';
    public bool $requiresApproval = true;   // mai in autonomia: passa dal permission engine

    public function handle(array $input, AgentContext $ctx): array
    {
        $order = $this->orders->findScoped((int) $input['order_id'], $ctx->tenantId);
        if ($order === null) {
            return ['error' => 'not_found'];
        }
        $order->setStatus($input['status']);   // scrittura tracciata, vincolata al tenant
        $this->audit->log($ctx, 'order.status.update', $order->id);
        return ['ok' => true];
    }
}

Le differenze sono tutte deliberate. Il flag che richiede approvazione fa sì che il tool non parta mai in autonomia: passa dal motore dei permessi, che lo mette in "chiedi" e non in "consenti". L'azione è tracciata in un audit log, perché ogni scrittura di un agente deve lasciare una traccia di chi, cosa e quando. E il dato resta vincolato al tenant, come in lettura. Tenere i tool di scrittura su questo regime separato spezza la catena più pericolosa, quella tra il leggere un dato e il modificarne un altro su istruzione di un contenuto non fidato.

Collegare, testare e osservare i tool

Costruito il server, l'agente vi si connette attraverso un trasporto, tipicamente stdio per un server locale o HTTP per uno remoto, dichiarato nella configurazione di Claude Code. Da quel momento i tool compaiono tra le capacità dell'agente, che li scopre e li usa quando il compito lo richiede. La scelta del trasporto non è neutra sul piano della sicurezza: un server locale via stdio è raggiungibile solo dalla macchina su cui gira, mentre uno HTTP remoto va protetto come qualunque endpoint esposto, con autenticazione e cifratura del canale. Ma il collegamento, in sé, è la parte facile; la parte che distingue un'integrazione di produzione è il testing, e va detto perché quasi nessuno lo fa.

Un MCP tool è codice che esegue azioni su sistemi reali, quindi va testato come tale, e con un'attenzione in più: vanno testati non solo i casi felici, ma i casi in cui l'agente passa un input inatteso o malevolo. Cosa succede se l'agente invoca get_order con un id che appartiene a un altro tenant? Il test deve verificare che torni not_found, non i dati altrui. Cosa succede se update_order_status riceve uno stato non valido? Il test deve verificare che venga rifiutato. Questi sono i test che intercettano i difetti di sicurezza prima che diventino incidenti, e sono esattamente quelli che mancano nelle integrazioni costruite in fretta.

C'è infine l'osservabilità: ogni invocazione di tool va loggata con il tool, l'input, l'esito e il contesto. Serve per il debugging, ma soprattutto serve per la sicurezza, perché la sequenza delle chiamate, una lettura sensibile seguita a stretto giro da una scrittura su un canale esterno, è il segnale di un abuso in corso. Senza quel log non sai cosa l'agente ha fatto attraverso i tuoi tool; con quel log, il comportamento dell'agente sui tuoi sistemi diventa governabile e verificabile.

Da agente generico a agente integrato: il payoff

Quando i tool sono fatti bene, il salto di valore è tangibile. L'agente smette di essere un assistente che ti aiuta a scrivere codice e diventa un collaboratore che opera dentro i tuoi processi. Nella mia pipeline, l'agente non si limita a generare un articolo: invoca un tool per validarlo contro il linter editoriale, uno per importarlo nel CMS, uno per rigenerare l'indice, uno per verificare lo stato del risultato. Ognuno di questi è un MCP tool stretto e con un perimetro chiaro, e insieme trasformano una sequenza di operazioni manuali in un flusso che l'agente esegue con i controlli giusti al posto giusto. Lo stesso vale per un'azienda: un MCP server che espone tool per interrogare il gestionale in lettura, aprire un ticket, controllare lo stato di un ordine, dà all'agente la capacità di operare nel workflow specifico dell'azienda, non in un generico mondo di codice.

Vale la pena dire perché custom batte quasi sempre il generico, perché è una domanda che ogni decisore si pone: esistono MCP server pronti, di terze parti, che si collegano a un database o a un servizio popolare in pochi minuti. Per un prototipo vanno benissimo. Per la produzione no, e la ragione è proprio la disciplina degli scope: un MCP server generico espone, per definizione, capacità generiche e larghe, perché deve servire tutti i casi d'uso di tutti i clienti. È il tool onnipotente travestito da comodità, con in più il problema della supply chain, perché stai dando a un componente di terzi accesso ai tuoi sistemi. Un server custom, invece, espone solo i tool che servono al tuo workflow specifico, ognuno stretto sul perimetro reale, e nessuno scope in eccesso che un attaccante possa sfruttare. Il costo di costruirlo è ripagato dal fatto che ciò che non hai esposto è esattamente ciò che non potrà mai essere abusato. In un mondo in cui l'agente legge e segue istruzioni, la superficie che non esiste è la difesa più solida che hai.

Il punto che chiude il discorso, e che vale per chi valuta se costruire queste integrazioni, è che la potenza e la sicurezza non sono in conflitto: sono la stessa decisione di design vista da due lati. Un tool ben progettato è insieme più utile (perché fa esattamente la cosa giusta) e più sicuro (perché non può fare nient'altro). La tentazione del tool onnipotente è la scorciatoia che sembra far risparmiare lavoro e che invece compra un rischio che pagherai con gli interessi. Costruire MCP server seri significa accettare di scrivere più tool, ognuno stretto, invece di pochi tool larghi, ed è esattamente questo investimento che separa un'integrazione di produzione da una demo. La domanda giusta da farsi davanti a ogni tool che stai per esporre non è "cosa può fare di utile per l'agente", è "cosa potrebbe fare di dannoso se l'agente venisse manipolato a usarlo", e progettare la risposta a quella seconda domanda dentro la forma del tool stesso è tutto il mestiere. Se vuoi integrare un agente di coding nei sistemi della tua azienda, con i tool giusti e il perimetro di sicurezza all'altezza, puoi usare il modulo di preventivo gratuito: sette domande, due minuti, e ti dico se il tuo caso rientra nel mio perimetro o se ti conviene un'altra figura.

Ultima modifica: