Skip to main content
Gli strumenti personalizzati estendono l’Agent SDK permettendoti di definire le tue funzioni che Claude può chiamare durante una conversazione. Utilizzando il server MCP in-process dell’SDK, puoi dare a Claude accesso a database, API esterne, logica specifica del dominio o qualsiasi altra capacità di cui la tua applicazione ha bisogno.

Riferimento rapido

Creare uno strumento personalizzato

Uno strumento è definito da quattro parti, passate come argomenti al helper tool() in TypeScript o al decoratore @tool in Python:
  • Nome: un identificatore univoco che Claude utilizza per chiamare lo strumento.
  • Descrizione: cosa fa lo strumento. Claude legge questo per decidere quando chiamarlo.
  • Schema di input: gli argomenti che Claude deve fornire. In TypeScript questo è sempre uno schema Zod, e gli args del handler sono tipizzati automaticamente da esso. In Python questo è un dict che mappa nomi a tipi, come {"latitude": float}, che l’SDK converte in JSON Schema per voi. Il decoratore Python accetta anche un dict completo di JSON Schema direttamente quando avete bisogno di enum, intervalli, campi opzionali o oggetti annidati.
  • Handler: la funzione asincrona che viene eseguita quando Claude chiama lo strumento. Riceve gli argomenti convalidati e deve restituire un oggetto con:
    • content (obbligatorio): un array di blocchi di risultato, ciascuno con un type di "text", "image", "audio", "resource" o "resource_link". Vedere Return images and resources per i blocchi non testuali.
    • structuredContent (opzionale): un oggetto JSON che contiene il risultato come dati leggibili da macchina, restituito insieme a content. Vedere Return structured data.
    • isError (opzionale): impostare su true per segnalare un errore dello strumento in modo che Claude possa reagire. Vedere Handle errors.
Dopo aver definito uno strumento, avvolgetelo in un server con createSdkMcpServer (TypeScript) o create_sdk_mcp_server (Python). Il server viene eseguito in-process all’interno della vostra applicazione, non come processo separato.

Esempio di strumento meteo

Questo esempio definisce uno strumento get_temperature e lo avvolge in un server MCP. Configura solo lo strumento; per passarlo a query e eseguirlo, vedere Call a custom tool di seguito.
Vedere il riferimento TypeScript tool() o il riferimento Python @tool per i dettagli completi dei parametri, inclusi i formati di input JSON Schema e la struttura del valore di ritorno.
Per rendere un parametro opzionale: in TypeScript, aggiungete .default() al campo Zod. In Python, lo schema dict tratta ogni chiave come obbligatoria, quindi omettete il parametro dallo schema, menzionatelo nella stringa di descrizione e leggetelo con args.get() nel handler. Lo strumento get_precipitation_chance di seguito mostra entrambi i modelli.

Chiamare uno strumento personalizzato

Passate il server MCP che avete creato a query tramite l’opzione mcpServers. La chiave in mcpServers diventa il segmento {server_name} nel nome completamente qualificato di ogni strumento: mcp__{server_name}__{tool_name}. Elencate quel nome in allowedTools in modo che lo strumento venga eseguito senza un prompt di autorizzazione. Questi snippet riutilizzano il weatherServer dall’esempio precedente per chiedere a Claude qual è il meteo in una posizione specifica.
Combinate questo snippet con le definizioni di strumento e server dall’esempio di strumento meteo in un unico file, quindi eseguitelo con python weather.py per Python o npx tsx weather.ts per TypeScript. Claude chiama get_temperature e lo script stampa una risposta su una riga con la temperatura attuale a San Francisco.

Aggiungere più strumenti

Un server contiene tutti gli strumenti che elencate nel suo array tools. Con più di uno strumento su un server, potete elencare ciascuno in allowedTools individualmente o utilizzare il wildcard mcp__weather__* per coprire ogni strumento che il server espone. L’esempio di seguito definisce un secondo strumento, get_precipitation_chance, e sostituisce la definizione di weatherServer dall’esempio di strumento meteo con una che elenca entrambi gli strumenti nell’array.
Tool search è abilitato per impostazione predefinita e rinvia gli strumenti SDK MCP: Claude vede il nome di ogni strumento in un elenco compatto e carica il suo schema completo su richiesta. Con la ricerca degli strumenti disabilitata, ogni strumento in questo array consuma spazio della finestra di contesto ad ogni turno. In TypeScript, passate alwaysLoad: true nell’argomento extras di tool() o nelle opzioni di createSdkMcpServer() per mantenere lo schema completo di uno strumento nel prompt iniziale.

Aggiungere annotazioni di strumento

Le annotazioni di strumento sono metadati opzionali che descrivono il comportamento di uno strumento. Passateli come quinto argomento al helper tool() in TypeScript o tramite l’argomento della parola chiave annotations per il decoratore @tool in Python. Tutti i campi di suggerimento sono booleani. Le annotazioni sono metadati, non applicazione. Uno strumento contrassegnato con readOnlyHint: true può comunque scrivere su disco se è quello che fa il handler. Mantenete l’annotazione accurata rispetto al handler. Questo esempio aggiunge readOnlyHint allo strumento get_temperature dall’esempio di strumento meteo.
Vedere ToolAnnotations nel riferimento TypeScript o Python.

Controllare l’accesso ai tool

L’esempio di tool meteo ha registrato un server e ha elencato i tool in allowedTools. Questa sezione illustra come limitare l’accesso quando si hanno più tool o si desidera limitare i tool integrati. Per informazioni su come vengono costruiti i nomi dei tool, vedere Chiamare un tool personalizzato.

Configurare i tool consentiti

L’opzione tools e gli elenchi consentiti/non consentiti influiscono su due livelli: la disponibilità, che controlla se un tool appare nel contesto di Claude, e il permesso, che controlla se una chiamata viene approvata una volta che Claude la tenta. tools e le voci disallowedTools con nome semplice modificano la disponibilità. allowedTools e le regole disallowedTools con ambito modificano il permesso. Se si nomina uno dei tool di tracciamento delle attività in allowedTools, Claude Code opta anche la sessione. Per rimuovere completamente un tool integrato, omettetelo da tools o elencate il suo nome semplice in disallowedTools (Python: disallowed_tools); entrambi mantengono il tool fuori dal contesto in modo che Claude non lo tenti mai. Una regola disallowedTools con ambito blocca le chiamate corrispondenti ma lascia il tool visibile, quindi Claude potrebbe sprecare un turno tentandolo. Vedere Configurare i permessi per l’ordine di valutazione completo.

Gestire gli errori

Un errore del handler non interrompe il ciclo dell’agente. Il server MCP in-process dell’SDK cattura le eccezioni non gestite e le restituisce come risultati di errore, quindi il modo in cui segnalate un errore determina ciò che Claude legge, non se la query fallisce: In entrambi i casi Claude può riprovare, provare uno strumento diverso o spiegare il fallimento. Catturate gli errori voi stessi quando il messaggio di eccezione grezzo non è sufficiente per Claude per agire. L’esempio seguente cattura due tipi di fallimenti all’interno del handler e compone il messaggio di errore che Claude legge. Uno stato HTTP non-200 viene catturato dalla risposta e restituito come risultato di errore. Un errore di rete o JSON non valido viene catturato dal try/except (Python) o try/catch (TypeScript) circostante e anch’esso restituito come risultato di errore. In entrambi i casi Claude riceve un messaggio che descrive il fallimento invece di una stringa di eccezione nuda.

Restituire immagini e risorse

L’array content in un risultato di tool accetta blocchi text, image, audio, resource e resource_link. È possibile mescolarli nella stessa risposta. In TypeScript, l’SDK salva i blocchi audio su disco e Claude riceve un blocco di testo con il percorso del file salvato; in Python, l’SDK elimina i blocchi audio dal risultato del tool e registra un avviso. Claude riceve ogni blocco di collegamento a risorse come un blocco di testo contenente il nome, l’URI e la descrizione del collegamento. In TypeScript, l’applicazione riceve anche i collegamenti stessi come resourceLinks sul tool_use_result del messaggio dell’utente; in Python, l’SDK li appiattisce a testo prima che la CLI veda il risultato, quindi la chiave Python resourceLinks non viene mai prodotta per i tool in-process.

Immagini

Un blocco immagine contiene i byte dell’immagine inline, codificati in base64. Non esiste un campo URL. Per restituire un’immagine che si trova in un URL, recuperarla nel gestore, leggere i byte della risposta e codificarli in base64 prima di restituirli. Il risultato viene elaborato come input visivo.

Risorse

Un blocco risorsa incorpora un pezzo di contenuto identificato da un URI. L’URI è un’etichetta per Claude a cui fare riferimento; il contenuto effettivo si trova nel campo text o blob del blocco. Utilizzare questa opzione quando il tool produce qualcosa che ha senso affrontare per nome in seguito, come un file generato o un record da un sistema esterno. Questo esempio mostra un blocco risorsa restituito dall’interno di un gestore di tool. L’URI file:///tmp/report.md è un’etichetta a cui Claude può fare riferimento in seguito; l’SDK non legge da quel percorso.
Queste forme di blocco provengono dal tipo MCP CallToolResult. Consultare la specifica MCP per la definizione completa.

Restituire dati strutturati

structuredContent è un oggetto JSON opzionale sul risultato, separato dall’array content. Utilizzarlo per restituire valori grezzi che Claude può leggere come campi esatti invece di analizzarli da una stringa di testo o da un’immagine. Quando structuredContent è impostato, Claude riceve il JSON più eventuali blocchi di immagine o risorsa da content. I blocchi di testo in content non vengono inoltrati, poiché si presume che duplichino i dati strutturati. L’esempio seguente renderizza un grafico come blocco di immagine e restituisce i punti dati dietro di esso in structuredContent dallo stesso handler. Nel frammento, chartPngBuffer è un Buffer che contiene i byte PNG renderizzati.
TypeScript
Il decoratore Python @tool inoltra solo content e is_error dal dizionario di ritorno dell’handler. Per restituire structuredContent da Python, eseguire un server MCP standalone invece di un server SDK in-process.

Esempio: convertitore di unità

Questo strumento converte valori tra unità di lunghezza, temperatura e peso. Un utente può chiedere “converti 100 chilometri in miglia” o “quanto sono 72°F in Celsius”, e Claude sceglie il tipo di unità e le unità corrette dalla richiesta. Dimostra due pattern:
  • Schemi enum: unit_type è vincolato a un insieme fisso di valori. In TypeScript, usa z.enum(). In Python, lo schema dict non supporta gli enum, quindi è richiesto lo schema JSON completo.
  • Gestione dell’input non supportato: quando una coppia di conversione non viene trovata, il gestore restituisce isError: true in modo che Claude possa dire all’utente cosa è andato storto piuttosto che trattare un fallimento come un risultato normale.
Una volta definito il server, passalo a query nello stesso modo dell’esempio meteo. Questo esempio invia tre prompt diversi in un ciclo per mostrare lo stesso strumento che gestisce diversi tipi di unità. Per ogni risposta, ispeziona gli oggetti AssistantMessage (che contengono le chiamate di strumento che Claude ha effettuato durante quel turno) e stampa ogni ToolUseBlock prima di stampare il testo finale di ResultMessage. Questo ti permette di vedere quando Claude sta usando lo strumento rispetto a quando sta rispondendo dalle sue conoscenze. Poiché tool search è attivato per impostazione predefinita, l’output può includere anche una chiamata ToolSearch mentre Claude carica lo schema dello strumento differito.

Passaggi successivi

È possibile combinare i modelli su questa pagina nello stesso server: un singolo server può contenere uno strumento di database, uno strumento gateway API e un renderer di immagini uno accanto all’altro. Da qui:
  • Se il vostro server cresce fino a dozzine di strumenti, consultate tool search per rinviare il caricamento fino a quando Claude non ne avrà bisogno.
  • Per connettersi a server MCP esterni (filesystem, GitHub, Slack) invece di costruire i vostri, consultate Connect MCP servers.
  • Per controllare quali strumenti vengono eseguiti automaticamente rispetto a quelli che richiedono approvazione, consultate Configure permissions.