Construir o MCP para ERP se resume a quatro decisões. Exponha transações, não tabelas: uma ferramenta deve ser algo que uma pessoa poderia fazer no sistema, como criar uma fatura ou registrar um pagamento, com as regras de negócio dentro dela. Nomeie e descreva cada ferramenta para o modelo que lerá a lista, com as restrições que ele deve respeitar na descrição, em vez de na documentação que ele nunca verá. Deixe a identidade OAuth em cada solicitação decidir quais ferramentas são listadas e se cada chamada é executada. E projete cada gravação para que uma nova tentativa, uma recusa ou uma pergunta sejam seguras, porque um modelo produzirá todas as três.
O transporte, a descoberta e o login são especificados e qualquer SDK os gerencia. O valor do servidor está nessas quatro decisões, e um sistema de negócios que as acerta pode ser operado pelo Claude, ChatGPT ou qualquer outro cliente sem que esse cliente saiba nada sobre isso.
Comece pela transação, não pela tabela
O primeiro instinto ao expor um ERP é gerar uma ferramenta por tabela com criar, ler, atualizar e excluir em cada uma. Isso produz uma lista grande e uniforme que um modelo lida mal, porque a regra de negócio de que uma fatura precisa de uma taxa de imposto em cada linha, ou que o estoque não pode ser despachado antes de ser reservado, não está em lugar algum que o modelo possa ver. Exponha as ações em vez disso. Um teste útil é se uma pessoa poderia descrever a ferramenta como algo que fez hoje: levantou uma fatura, registrou um pagamento, moveu um negócio, adiou uma cobrança. Cada uma delas carrega suas regras, valida suas entradas e retorna um resultado legível.
Junto com as ações, adicione um pequeno número de ferramentas de resumo que respondam às perguntas que um modelo faz antes de agir. Uma chamada que retorna o perfil de uma conta, saúde, itens abertos e histórico recente economiza quatro chamadas para o modelo e vários milhares de tokens de contexto, e torna a próxima ação melhor informada. O Sois chama essas ferramentas de examinador; examinarContato e obterResumoContábil são dois. Mantenha a superfície total em vista também: o Claude Code limita a saída de um servidor por chamada por padrão, e tanto Claude quanto OpenAI oferecem carregamento diferido ou busca de ferramentas para listas grandes, então um servidor com várias centenas de ferramentas deve retorná-las em uma ordem determinística (a especificação pede isso para que os clientes possam armazenar em cache) e deve filtrar por função antes de listar.
Nomeando ferramentas para que um modelo escolha a correta
A especificação limita nomes levemente: de um a 128 caracteres, letras, dígitos, sublinhado, hífen e ponto, sensível a maiúsculas e minúsculas, exclusivo dentro do servidor. Tudo o mais é convenção, e a convenção que funciona é um verbo seguido pelo substantivo de negócios em um caso consistente, com os mesmos verbos significando as mesmas coisas em todos os lugares. Um modelo escolhendo entre buscarFaturas, obterFatura e criar fatura está escolhendo entre uma lista, um registro e uma gravação, e aprende esse padrão uma vez para todo o servidor.
| Fraco | Melhor | Por quê |
|---|---|---|
fatura | criar fatura | Um substantivo sozinho não diz se lê ou grava; um cliente não pode anotá-lo e um modelo não pode classificá-lo em relação a seus irmãos. |
faturaCriarV2Final | criar fatura | Versão e status pertencem ao servidor, não ao nome. Nomes que mudam quebram listas de ferramentas em cache e caches de prompt. |
fazerContabilidade | registrarPagamento, enviarLembretesDeFatura | Um catch-all com um argumento de modo oculta a transação. Um nome por transação permite que o cliente aplique confirmação por ferramenta. |
obter_fatura e obterContato misto | Um caso em todo lugar | Agregando clientes prefixando nomes pelo servidor; a consistência dentro de um servidor é do que o modelo depende. |
A descrição carrega o resto: quando usar a ferramenta, quando não usar, e qualquer regra que o modelo deve respeitar antes de chamá-la.
As descrições são lidas por um modelo sob pressão para agir, então escreva-as como instruções. Declare o que a ferramenta faz na primeira frase, depois as condições. Se uma ferramenta irmã for a escolha certa para um pedido próximo, diga isso pelo nome. Se um campo deve ser definido para que o resultado seja correto, diga isso em MAIÚSCULAS se necessário; a ferramenta de fatura da Sois informa ao modelo que a taxa de imposto deve ser definida em cada linha e que as taxas exatas vêm de listTaxTypes, porque uma fatura sem IVA é um fracasso pior do que uma chamada recusada. Inclua um exemplo de chamada. Tudo que o modelo precisa para chamar a ferramenta corretamente deve estar na ferramenta, porque ele nunca abrirá sua documentação.
Uma definição de ferramenta de exemplo
Esta é uma ferramenta de fatura da Sois como um cliente a recebe de tools/list, reduzido aos campos que importam, com anotações e um esquema de saída adicionados na forma que a especificação atual define. Mostra o padrão: um nome verbo-substantivo, uma descrição instrucional, um esquema cujas descrições de propriedades fazem a prevenção de erros do modelo, e dicas que um cliente pode usar para decidir se deve confirmar.
{
"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
}
}As anotações dizem: isso grava, apenas adiciona (um rascunho), chamá-lo duas vezes cria dois rascunhos e não toca em nada fora do sistema. Os clientes devem tratar as anotações como não confiáveis, a menos que o servidor seja confiável, portanto, são dicas para o comportamento de confirmação, não um substituto para as próprias verificações do servidor.
Três escolhas nessa definição são deliberadas. O resultado retorna um identificador que o modelo deve carregar para dentro de sendInvoice e registrarPagamento, que é a maneira recomendada pela especificação para relacionar chamadas agora que os servidores não mantêm estado de sessão. A ferramenta cria um rascunho, não uma fatura publicada, então a gravação é aditiva e uma pessoa ou uma ferramenta de aprovação separada a finaliza. E o esquema de saída significa que uma integração pode ler o número e o total como dados, enquanto o modelo lê o mesmo resultado como texto.
Limitando ferramentas ao usuário
Sobre HTTP, o chamador chega com um token de acesso OAuth vinculado ao seu servidor, e esse token identifica uma pessoa. A especificação permite que o resultado de tools/list variar de acordo com as credenciais na solicitação, então a primeira decisão de escopo é filtrar a lista pelo papel daquela pessoa antes de retorná-la: um usuário de armazém não recebe aprovar faturaA lista não deve variar por conexão ou como um efeito colateral de outras chamadas, apenas por autorização, o que a torna armazenável em cache.
A segunda decisão é verificar novamente na execução. Um cliente pode enviar qualquer chamada que desejar, e um modelo pode ser manipulado por texto em um resultado de ferramenta para tentar um. Resolva o usuário a partir do token em cada chamada, verifique a permissão que a ferramenta requer e recuse com um erro de execução da ferramenta que o modelo pode ler. Mantenha os escopos OAuth amplos (Sois emite escopos de leitura, escrita e offline) e deixe os próprios papéis do ERP serem a fronteira detalhada, porque esses papéis já existem, já são mantidos e já significam algo para o negócio. Atribua cada chamada à pessoa no log com seus argumentos e resultado, para que o trabalho de um agente seja revisável exatamente como o de uma pessoa.
- Token chegaValide a assinatura e que o público seja este servidor, conforme exige a RFC 8707; rejeite qualquer outra coisa com 401.
- Resolva a pessoaMapeie o token a um usuário no espaço de trabalho e carregue seu papel e aplicativos instalados.
- Filtrar a listaRetorne apenas as ferramentas que esse papel pode usar, em uma ordem estável, da lista de ferramentas.
- Verifique a chamadaNa chamada de ferramentas, verifique a permissão novamente e recuse com isError se estiver faltando; nada será executado.
- Executar e registrarExecute a transação, meça-a se seu próprio agente fez o raciocínio e escreva a chamada no log de auditoria sob essa pessoa.
Gerenciando gravações
Um modelo que recebe um resultado ambíguo fará uma nova chamada, e um que recebe um erro tentará uma entrada corrigida. Projete para isso. Escritas que criam devem retornar um identificador e, quando possível, aceitar uma chave de idempotência ou uma chave natural para que uma repetição seja detectada. Escritas que mudam de estado devem ser explícitas sobre a transição que realizam e recusar aquelas impossíveis com uma razão legível: registrar um pagamento contra uma fatura anulada é um isError resultado dizendo isso, não uma operação silenciosa e não um rastreamento de pilha. Nunca deixe uma escrita parcial; se uma ferramenta de múltiplas etapas não puder ser concluída, reverta e relate.
- Prefira rascunhos e aprovações. Faça a criação aditiva (um rascunho) e dê à finalização sua própria ferramenta com sua própria permissão, para que o passo destrutivo seja aquele que um cliente confirma e um papel controla.
- Marque ferramentas destrutivas. Definir
destructiveHintsobre anulações e exclusões e diga isso na descrição; Claude e ChatGPT usam esses sinais ao decidir perguntar antes de chamar. - Pergunte em vez de adivinhar. Quando uma chamada precisa de uma decisão que a ferramenta não pode tomar, retorne um resultado que requer entrada com um pedido de elicitação; o cliente faz a pergunta à pessoa e tenta a chamada novamente com a resposta.
- Limite o raio de impacto. Limite a taxa por conexão, defina um teto de gastos por integração onde seu próprio agente faz raciocínio, e valide cada entrada no lado do servidor, independentemente do esquema, porque o esquema é uma orientação para o modelo, não uma imposição.
Testando a interface com um cliente real
O inspetor do MCP irá exercer tools/list e tools/call e percorrer o fluxo OAuth. O verdadeiro teste é um modelo. Conecte Claude como um conector personalizado, ou ChatGPT em modo de desenvolvedor, faça login como um usuário com um papel restrito e peça um resultado rotineiro que precise de três ou quatro ferramentas. Observe quais ferramentas ele escolhe e por quê; uma escolha errada é quase sempre um problema de descrição. Em seguida, faça login como um usuário sem uma das permissões e confirme que a execução para na chamada correta com uma razão que o modelo repete.
É assim que o servidor do espaço de trabalho Sois é construído e verificado: transações como ferramentas, descrições instrucionais, uma lista filtrada por papel, uma segunda verificação em cada chamada, rascunhos antes das aprovações e um registro que uma pessoa pode ler. Desenvolvedores que constroem aplicativos para o marketplace publicam ferramentas na mesma lista sob as mesmas regras, de modo que um aplicativo é operável por qualquer agente no momento em que é instalado. O padrão não é específico de um produto; qualquer ERP que o adote se torna algo que um agente pode executar.
Perguntas que as pessoas fazem
Quantas ferramentas um servidor ERP MCP deve expor?
Quantas transações valem a pena automatizar, filtradas por usuário para que cada chamador veja um conjunto funcional. Vários centenas é normal para um sistema completo; o que importa é que a lista seja estável, filtrada por papel e organizada por verbos consistentes para que o modelo possa classificar os candidatos.
Devo usar escopos OAuth para permissões detalhadas?
Use escopos amplos para a conexão e os próprios papéis do ERP para a delimitação detalhada, verificados em cada chamada. Os papéis já existem e são mantidos pela empresa; um esquema de escopo paralelo se afastaria deles.
Como uma gravação deve se comportar se o modelo a chamar duas vezes?
Ou detecte a repetição por meio de uma chave de idempotência ou natural e retorne o registro existente, ou faça a gravação aditiva e claramente relatada para que o duplicado seja visível. Nunca falhe silenciosamente e nunca deixe uma gravação parcial.
As anotações de ferramentas são aplicadas pelo cliente?
Não. Elas são dicas, e a especificação diz aos clientes para tratá-las como não confiáveis, a menos que o servidor seja confiável. Os clientes as usam para escolher o comportamento de confirmação; as próprias verificações de permissão e validação do servidor são o que previne danos.
- Especificação do Protocolo de Contexto do Modelo (2026-07-28): ferramentas nomes de ferramentas, esquemas, anotações, resultados estruturados, tratamento de erros e a orientação de manipulação com estado
- Especificação do Protocolo de Contexto do Modelo: autorização validação de público de token, desafios de escopo e o modelo de autorização por solicitação
- OpenAI Apps SDK: construa um servidor MCP como o ChatGPT usa readOnlyHint, destructiveHint e openWorldHint para o comportamento de confirmação
- Documentação do Sois: o servidor MCP do espaço de trabalho a referência da ferramenta da qual o exemplo é extraído, filtragem de papéis, limites e códigos de erro
Este artigo é revisado quando os produtos que descreve mudam. Próxima revisão agendada: 4 de dezembro de 2026.
