Per le aziende Per le imprese Soluzioni App Prezzi Sviluppatori Blog Documentazione Avvia uno spazio di lavoro
Blog / MCP per software aziendale

MCP per ERP: una guida pratica

Una guida per i costruttori. Presuppone che tu abbia letto la specifica o l'articolo complementare su cosa sia un server ERP MCP e si concentra sulle decisioni che la specifica lascia a te: quali azioni pubblicare, come chiamarle, come l'identità del chiamante raggiunge ogni chiamata e cosa dovrebbe fare una scrittura quando un modello la riprova. Lo strumento di esempio è reale.

7 minuti di letturaAggiornato 4 settembre 2026Ingegneria Sois, il team che costruisce la piattaforma

Un banco da lavoro in un piccolo studio di ingegneria: cassetti per parti etichettati, uno schema stampato sotto una clip, un laptop chiuso e una lampada da saldatura spenta.
Risposta breve

Costruire MCP per ERP si riduce a quattro decisioni. Esporre le transazioni, non le tabelle: uno strumento dovrebbe essere qualcosa che una persona potrebbe fare nel sistema, come creare una fattura o registrare un pagamento, con le regole aziendali al suo interno. Nomina e descrivi ogni strumento per il modello che leggerà l'elenco, con i vincoli che deve rispettare nella descrizione piuttosto che nella documentazione che non vedrà mai. Lascia che l'identità OAuth in ogni richiesta decida sia quali strumenti sono elencati sia se ogni chiamata viene eseguita. E progetta ogni scrittura in modo che un tentativo, un rifiuto o una domanda siano sicuri, perché un modello produrrà tutti e tre.

Il trasporto, la scoperta e l'accesso sono specificati e qualsiasi SDK li gestisce. Il valore del server risiede in quelle quattro decisioni, e un sistema aziendale che le gestisce correttamente è utilizzabile da Claude, ChatGPT o qualsiasi altro cliente senza che quel cliente sappia nulla al riguardo.

Inizia dalla transazione, non dalla tabella

Il primo istinto quando si espone un ERP è generare uno strumento per tabella con crea, leggi, aggiorna ed elimina su ciascuno. Produce un elenco grande e uniforme che un modello gestisce male, perché la regola aziendale che una fattura ha bisogno di un'aliquota fiscale su ogni riga, o che le scorte non possono essere spedite prima di essere riservate, non è visibile al modello. Esporre le azioni invece. Un test utile è se una persona potrebbe descrivere lo strumento come qualcosa che ha fatto oggi: ha emesso una fattura, ha registrato un pagamento, ha spostato un affare, ha rimandato un sollecito. Ognuno di questi porta le proprie regole, convalida i propri input e restituisce un risultato leggibile.

Insieme alle azioni, aggiungi un numero ridotto di strumenti di riepilogo che rispondono alle domande che un modello pone prima di agire. Una chiamata che restituisce il profilo di un account, la salute, gli elementi aperti e la cronologia recente risparmia al modello quattro chiamate e diverse migliaia di token di contesto, e rende la prossima azione meglio informata. Sois chiama questi strumenti esaminatori; esaminareContatto e ottenereRiepilogoContabile sono due. Tieni presente anche la superficie totale: Claude Code limita l'output di un server per chiamata per impostazione predefinita, e sia Claude che OpenAI offrono caricamento differito o ricerca di strumenti per grandi elenchi, quindi un server con diverse centinaia di strumenti dovrebbe restituirli in un ordine deterministico (la specifica richiede questo affinché i clienti possano memorizzare nella cache) e dovrebbe filtrare per ruolo prima di elencarli.

Nomina gli strumenti affinché un modello scelga quello giusto

La specifica limita i nomi in modo leggero: uno fino a 128 caratteri, lettere, numeri, underscore, trattino e punto, sensibile al maiuscolo/minuscolo, unico all'interno del server. Tutto il resto è convenzione, e la convenzione che funziona è un verbo seguito dal sostantivo commerciale in un caso coerente, con gli stessi verbi che significano le stesse cose ovunque. Un modello che sceglie tra cercaFatture, ottenereFattura e crea fattura sta scegliendo tra un elenco, un record e una scrittura, e apprende quel modello una volta per l'intero server.

DeboleMeglioPerché
fatturacrea fatturaUn sostantivo da solo non indica se legge o scrive; un client non può annotarlo e un modello non può classificarlo rispetto ai suoi simili.
fatturaCreaV2Finalecrea fatturaVersione e stato appartengono al server, non al nome. I nomi che cambiano rompono le liste degli strumenti memorizzate nella cache e le cache dei prompt.
fare contabilitàregistraPagamento, inviaPromemoriaFattureUn catch-all con un argomento di modalità nasconde la transazione. Un nome per transazione consente al cliente di applicare la conferma per strumento.
ottieni_fattura e ottieniContatto mistoUn caso in tuttoAggregando i nomi dei clienti con un prefisso dal server; la coerenza all'interno di un server è ciò su cui si basa il modello.

La descrizione porta il resto: quando utilizzare lo strumento, quando non farlo e qualsiasi regola che il modello deve rispettare prima di chiamarlo.

Le descrizioni sono lette da un modello sotto pressione per agire, quindi scrivile come istruzioni. Indica cosa fa lo strumento nella prima frase, poi le condizioni. Se uno strumento simile è la scelta giusta per una richiesta vicina, dillo per nome. Se un campo deve essere impostato affinché il risultato sia corretto, dillo in maiuscolo se necessario; lo strumento di fatturazione di Sois dice al modello che l'aliquota fiscale deve essere impostata su ogni riga e che le aliquote esatte provengono da , perché la descrizione dello strumento di fatturazione dice che l'aliquota fiscale deve essere impostata su ogni riga e che le aliquote esatte del workspace provengono da quella chiamata; un modello legge le descrizioni, e una buona descrizione impedisce che una fattura venga inviata senza IVA. Ha creato la fattura con una riga, quantità dodici, all'aliquota prevista nei termini del cliente, e ha ricevuto l'identificatore e il numero della nuova fattura nel risultato. Ha passato quell'identificatore a, because an invoice with no VAT is a worse failure than a refused call. Include one example call. Everything the model needs to call the tool correctly should be in the tool, because it will never open your documentation.

Una definizione di strumento di esempio

Questo è uno strumento di fatturazione di Sois come lo riceve un cliente da tools/list, ridotto ai campi che contano, con annotazioni e uno schema di output aggiunto nella forma definita dalla specifica attuale. Mostra il modello: un nome verbo-sostantivo, una descrizione istruttiva, uno schema le cui descrizioni delle proprietà prevengono gli errori del modello e suggerimenti che un cliente può utilizzare per decidere se confermare.

{
  "name": "createInvoice",
  "title": "Create invoice",
  "description": "Create a new invoice of any type and return the draft with its auto-generated number. TAX: set tax_rate on each line (for example 20 for 20% VAT); call listTaxTypes for this workspace's exact rates. If the user says 'plus VAT' you MUST set tax_rate or the invoice goes out with no VAT. To email the result use sendInvoice. Example: createInvoice({ type: \"sales_invoice\", contact_id: \"uuid\", currency: \"GBP\", lines: [{ description: \"Consulting\", quantity: 10, unit_price: 150 }] })",
  "inputSchema": {
    "type": "object",
    "properties": {
      "type": { "type": "string", "description": "sales_invoice, purchase_invoice, sales_credit_note or purchase_credit_note" },
      "contact_id": { "type": "string", "description": "Contact UUID (bill-to for sales, bill-from for purchases)" },
      "currency": { "type": "string", "description": "ISO code, for example GBP. Uses the workspace default if omitted" },
      "invoice_date": { "type": "string", "description": "ISO date. Defaults to today" },
      "reference": { "type": "string" },
      "lines": {
        "type": "array",
        "description": "Line items. Every line MUST carry the numeric unit_price the user asked for",
        "items": {
          "type": "object",
          "properties": {
            "description": { "type": "string" },
            "quantity": { "type": "number", "description": "Defaults to 1" },
            "unit_price": { "type": "number", "description": "NUMBER only: no currency symbols, no thousands separators. Use the exact amount stated; never guess or round" },
            "tax_rate": { "type": "number" },
            "discount_percent": { "type": "number" }
          },
          "required": ["description", "unit_price"]
        }
      }
    },
    "required": ["type"]
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "invoice_id": { "type": "string" },
      "number": { "type": "string" },
      "status": { "type": "string" },
      "total": { "type": "number" }
    },
    "required": ["invoice_id", "number", "status"]
  },
  "annotations": {
    "readOnlyHint": false,
    "destructiveHint": false,
    "idempotentHint": false,
    "openWorldHint": false
  }
}

Le annotazioni dicono: questo scrive, aggiunge solo (una bozza), chiamarlo due volte crea due bozze e non tocca nulla al di fuori del sistema. I clienti devono trattare le annotazioni come non affidabili a meno che il server non sia affidabile, quindi sono suggerimenti per il comportamento di conferma, non un sostituto dei controlli del server.

Tre scelte in quella definizione sono deliberate. Il risultato restituisce un identificatore che il modello deve portare in , che allega il PDF e lo invia via email, e infine a e registraPagamento, che è il modo raccomandato dalla specifica per relazionare le chiamate ora che i server non mantengono lo stato di sessione. Lo strumento crea una bozza, non una fattura pubblicata, quindi la scrittura è additiva e una persona o uno strumento di approvazione separato la finalizza. E lo schema di output significa che un'integrazione può leggere il numero e il totale come dati mentre il modello legge lo stesso risultato come testo.

Definisci gli strumenti per l'utente

Attraverso HTTP, il chiamante arriva con un token di accesso OAuth legato al tuo server, e quel token identifica una persona. La specifica consente il risultato di tools/list variare in base alle credenziali nella richiesta, quindi la prima decisione di ambito è filtrare l'elenco in base al ruolo di quella persona prima di restituirlo: un utente del magazzino non riceve approvaFatturaLa lista non deve variare per connessione o come effetto collaterale di altre chiamate, solo per autorizzazione, il che la rende memorizzabile.

La seconda decisione è controllare di nuovo all'esecuzione. Un cliente può inviare qualsiasi chiamata desideri e un modello può essere manipolato tramite testo in un risultato dello strumento per provare uno. Risolvi l'utente dal token ad ogni chiamata, controlla il permesso richiesto dallo strumento e rifiuta con un errore di esecuzione dello strumento che il modello può leggere. Mantieni gli ambiti OAuth generali (Sois emette ambiti di lettura, scrittura e offline) e lascia che i ruoli dell'ERP siano il confine dettagliato, perché quei ruoli esistono già, sono già mantenuti e significano già qualcosa per l'azienda. Attribuisci ogni chiamata alla persona nel log con i suoi argomenti e risultati, in modo che il lavoro di un agente sia revisionabile esattamente come quello di una persona.

  1. Il token arrivaConvalida la firma e che il destinatario sia questo server, come richiesto dalla RFC 8707; rifiuta qualsiasi altra cosa con 401.
  2. Risolvere la personaMappa il token a un utente nello spazio di lavoro e carica il suo ruolo e le app installate.
  3. Filtra l'elencoRestituisci solo gli strumenti che quel ruolo può utilizzare, in un ordine stabile, da tools/list.
  4. Controlla la chiamataSu tools/call, controlla di nuovo il permesso e rifiuta con isError se manca; nulla viene eseguito.
  5. Esegui e registraEsegui la transazione, misurala se il tuo agente ha fatto il ragionamento e scrivi la chiamata nel registro delle verifiche sotto quella persona.

Gestione delle scritture

Un modello che riceve un risultato ambiguo chiamerà di nuovo, e uno che riceve un errore proverà un input corretto. Progetta per questo. Le scritture che creano dovrebbero restituire un handle e, dove possibile, accettare una chiave di idempotenza o una chiave naturale in modo che una ripetizione venga rilevata. Le scritture che cambiano stato dovrebbero essere esplicite riguardo alla transizione che eseguono e rifiutare quelle impossibili con una motivazione leggibile: registrare un pagamento contro una fattura annullata è un isError risultato che lo dice, non un silenzioso no-op e non un stack trace. Non lasciare mai una scrittura parziale; se uno strumento a più fasi non può completare, annulla e riporta.

  • Preferisci bozze e approvazioni. Rendi la creazione additiva (una bozza) e dai alla finalizzazione il suo strumento con il proprio permesso, in modo che il passaggio distruttivo sia quello che un cliente conferma e un ruolo controlla.
  • Contrassegna gli strumenti distruttivi. Imposta destructiveHint sui vuoti e le eliminazioni e dirlo nella descrizione; Claude e ChatGPT utilizzano entrambi tali segnali quando decidono di chiedere prima di chiamare.
  • Chiedi piuttosto che indovinare. Quando una chiamata necessita di una decisione che lo strumento non può prendere, restituisci un risultato che richiede input con una richiesta di elicitation; il cliente pone la domanda alla persona e ripete la chiamata con la risposta.
  • Limita il raggio d'azione. Limita la velocità per connessione, fissa un limite di spesa per integrazione dove il tuo stesso agente fa ragionamenti e valida ogni input lato server indipendentemente dallo schema, perché lo schema è un consiglio per il modello, non un'applicazione.

Testare la superficie con un cliente reale

L'ispettore MCP eserciterà tools/list e tools/call e seguire il flusso OAuth. Il vero test è un modello. Collega Claude come connettore personalizzato, o ChatGPT in modalità sviluppatore, accedi come utente con un ruolo ristretto e chiedi un risultato di routine che necessita di tre o quattro strumenti. Osserva quali strumenti sceglie e perché; una scelta sbagliata è quasi sempre un problema di descrizione. Poi accedi come utente senza uno dei permessi e conferma che l'esecuzione si ferma alla chiamata giusta con una ragione che il modello ripete.

Questo è come il server del workspace Sois è costruito e controllato: transazioni come strumenti, descrizioni istruttive, un elenco filtrato per ruolo, un secondo controllo su ogni chiamata, bozze prima delle approvazioni e un registro che una persona può leggere. Gli sviluppatori che costruiscono app per il marketplace pubblicano strumenti nello stesso elenco secondo le stesse regole, quindi un'app è operabile da qualsiasi agente nel momento in cui viene installata. Il modello non è specifico per un prodotto; qualsiasi ERP che lo adotta diventa qualcosa che un agente può eseguire.

Domande che le persone pongono

Quanti strumenti dovrebbe esporre un server ERP MCP?

Tanti quanti sono le transazioni che vale la pena automatizzare, filtrate per utente in modo che ogni chiamante veda un insieme funzionante. Diverse centinaia è normale per un sistema completo; ciò che conta è che l'elenco sia stabile, filtrato per ruolo e organizzato da verbi coerenti in modo che il modello possa classificare i candidati.

Dovrei usare gli ambiti OAuth per permessi dettagliati?

Usa ambiti generali per la connessione e i ruoli propri dell'ERP per il confine dettagliato, controllato ad ogni chiamata. I ruoli esistono già e sono mantenuti dall'azienda; uno schema di ambiti paralleli si allontanerebbe da essi.

Come dovrebbe comportarsi una scrittura se il modello la chiama due volte?

O rileva la ripetizione tramite un'idempotenza o una chiave naturale e restituisci il record esistente, oppure rendi la scrittura additiva e chiaramente riportata in modo che il duplicato sia visibile. Non fallire mai silenziosamente e non lasciare mai una scrittura parziale.

Le annotazioni degli strumenti sono imposte dal client?

No. Sono suggerimenti, e la specifica dice ai client di considerarli non attendibili a meno che il server non sia fidato. I client li usano per scegliere il comportamento di conferma; i controlli di autorizzazione e validazione del server sono ciò che previene danni.

Fonti
  1. Specifiche del Model Context Protocol (2026-07-28): strumenti nomi degli strumenti, schemi, annotazioni, risultati strutturati, gestione degli errori e indicazioni sul gestore a stato
  2. specifica del Model Context Protocol: autorizzazione validazione del pubblico del token, sfide sugli ambiti e modello di autorizzazione per richiesta
  3. OpenAI Apps SDK: costruisci un server MCP come ChatGPT utilizza readOnlyHint, destructiveHint e openWorldHint per il comportamento di conferma
  4. Documentazione Sois: il server MCP dello spazio di lavoro il riferimento dello strumento da cui è tratto l'esempio, filtraggio dei ruoli, limiti e codici di errore

Questo articolo viene revisionato quando i prodotti che descrive cambiano. Prossima revisione programmata: 4 dicembre 2026.

Inizia

Costruisci su Sois.

Collega il tuo agente agli strumenti di costruzione, descrivi l'app, convalidala, pubblicala e guadagna dall'uso.

  • Inizia gratis
  • Porta il tuo agente
  • Nessun vincolo con il fornitore