Construir MCP para ERP se reduce a cuatro decisiones. Exponer transacciones, no tablas: una herramienta debe ser algo que una persona podría hacer en el sistema, como crear una factura o registrar un pago, con las reglas de negocio dentro de ella. Nombra y describe cada herramienta para el modelo que leerá la lista, con las restricciones que debe respetar en la descripción en lugar de en la documentación que nunca verá. Deja que la identidad de OAuth en cada solicitud decida tanto qué herramientas se enumeran como si cada llamada se ejecuta. Y diseña cada escritura de tal manera que un reintento, una negativa o una pregunta sea segura, porque un modelo producirá las tres.
El transporte, descubrimiento e inicio de sesión están especificados y cualquier SDK los maneja. El valor del servidor radica en esas cuatro decisiones, y un sistema empresarial que las acierte es operable por Claude, ChatGPT o cualquier otro cliente sin que ese cliente sepa nada al respecto.
Comienza desde la transacción, no desde la tabla
El primer instinto al exponer un ERP es generar una herramienta por tabla con crear, leer, actualizar y eliminar en cada una. Esto produce una lista grande y uniforme que un modelo maneja mal, porque la regla de negocio de que una factura necesita una tasa de impuesto en cada línea, o que el stock no puede ser despachado antes de ser reservado, no está en ningún lugar que el modelo pueda ver. Exponer las acciones en su lugar. Una prueba útil es si una persona podría describir la herramienta como algo que hizo hoy: levantar una factura, registrar un pago, mover un trato, posponer un seguimiento. Cada una de esas lleva sus reglas, valida sus entradas y devuelve un resultado legible.
Junto a las acciones, añade un pequeño número de herramientas de resumen que respondan a las preguntas que un modelo hace antes de actuar. Una llamada que devuelve el perfil de una cuenta, salud, elementos abiertos e historia reciente ahorra al modelo cuatro llamadas y varios miles de tokens de contexto, y hace que la siguiente acción esté mejor informada. Sois llama a estas herramientas examinadoras; examinarContacto y obtenerResumenContable son dos. Mantén también en vista la superficie total: Claude Code limita la salida de un servidor por llamada de forma predeterminada, y tanto Claude como OpenAI ofrecen carga diferida o búsqueda de herramientas para listas grandes, por lo que un servidor con varios cientos de herramientas debería devolverlas en un orden determinista (la especificación lo solicita para que los clientes puedan almacenar en caché) y debería filtrar por rol antes de listar.
Nombrar herramientas para que un modelo elija la correcta
La especificación restringe los nombres ligeramente: uno de hasta 128 caracteres, letras, dígitos, guion bajo, guion y punto, sensible a mayúsculas y minúsculas, único dentro del servidor. Todo lo demás es convención, y la convención que funciona es un verbo seguido del sustantivo comercial en un caso consistente, con los mismos verbos significando lo mismo en todas partes. Un modelo eligiendo entre buscarFacturas, obtenerFactura y crear factura está eligiendo entre una lista, un registro y una escritura, y aprende ese patrón una vez para todo el servidor.
| Débil | Mejor | Por qué |
|---|---|---|
factura | crear factura | Un sustantivo solo no indica si lee o escribe; un cliente no puede anotarlo y un modelo no puede clasificarlo frente a sus hermanos. |
facturaCrearV2Final | crear factura | La versión y el estado pertenecen al servidor, no al nombre. Los nombres que cambian rompen las listas de herramientas en caché y los cachés de solicitudes. |
hacerContabilidad | registrarPago, enviarRecordatoriosDeFactura | Un catch-all con un argumento de modo oculta la transacción. Un nombre por transacción permite al cliente aplicar confirmación por herramienta. |
obtener_factura y obtenerContacto mezclado | Un caso en todo | Los clientes agregados prefijan nombres por servidor; la consistencia dentro de un servidor es de lo que depende el modelo. |
La descripción lleva el resto: cuándo usar la herramienta, cuándo no, y cualquier regla que el modelo debe respetar antes de llamarla.
Las descripciones son leídas por un modelo bajo presión para actuar, así que escríbelas como instrucciones. Indica lo que la herramienta hace en la primera oración, luego las condiciones. Si una herramienta hermana es la elección correcta para una solicitud cercana, dilo por nombre. Si un campo debe establecerse para que el resultado sea correcto, dilo en mayúsculas si es necesario; la herramienta de facturación de Sois le dice al modelo que la tasa de impuesto debe establecerse en cada línea y que las tasas exactas provienen de , porque la descripción de la herramienta de facturación dice que la tasa de impuesto debe establecerse en cada línea y que las tasas exactas del espacio de trabajo provienen de esa llamada; un modelo lee descripciones, y una buena descripción evita que una factura se envíe sin IVA. Creó la factura con una línea, cantidad doce, a la tasa establecida en los términos del cliente, y recibió el identificador y número de la nueva factura en el resultado. Pasó ese identificador a, porque una factura sin IVA es un fracaso peor que una llamada rechazada. Incluye un ejemplo de llamada. Todo lo que el modelo necesita para llamar a la herramienta correctamente debe estar en la herramienta, porque nunca abrirá tu documentación.
Una definición de herramienta de ejemplo
Esta es una herramienta de facturación de Sois tal como la recibe un cliente de tools/list, recortado a los campos que importan, con anotaciones y un esquema de salida añadido en la forma que define la especificación actual. Muestra el patrón: un nombre verbo-sustantivo, una descripción instructiva, un esquema cuyas descripciones de propiedades previenen errores del modelo, y sugerencias que un cliente puede usar para decidir si 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
}
}Las anotaciones dicen: esto escribe, solo agrega (un borrador), llamarlo dos veces crea dos borradores y no toca nada fuera del sistema. Los clientes deben tratar las anotaciones como no confiables a menos que el servidor sea confiable, por lo que son pistas para el comportamiento de confirmación, no un sustituto de las propias verificaciones del servidor.
Tres elecciones en esa definición son deliberadas. El resultado devuelve un identificador que el modelo debe llevar a , que adjunta el PDF y lo envía por correo electrónico, y finalmente a y registrarPago, que es la forma recomendada por la especificación para relacionar llamadas ahora que los servidores no mantienen estado de sesión. La herramienta crea un borrador, no una factura publicada, por lo que la escritura es aditiva y una persona o una herramienta de aprobación separada la finaliza. Y el esquema de salida significa que una integración puede leer el número y el total como datos, mientras que el modelo lee el mismo resultado como texto.
Definir herramientas para el usuario
A través de HTTP, el llamador llega con un token de acceso OAuth vinculado a tu servidor, y ese token identifica a una persona. La especificación permite que el resultado de tools/list variará según las credenciales en la solicitud, por lo que la primera decisión de alcance es filtrar la lista según el rol de esa persona antes de devolverla: un usuario de almacén no recibe aprobar facturaLa lista no debe variar por conexión o como un efecto secundario de otras llamadas, solo por autorización, lo que la hace almacenable en caché.
La segunda decisión es verificar nuevamente en la ejecución. Un cliente puede enviar cualquier llamada que desee, y un modelo puede ser manipulado por texto en un resultado de herramienta para intentar uno. Resuelve al usuario a partir del token en cada llamada, verifica el permiso que requiere la herramienta y rechaza con un error de ejecución de herramienta que el modelo puede leer. Mantén los alcances de OAuth amplios (Sois emite alcances de lectura, escritura y fuera de línea) y deja que los propios roles del ERP sean el límite detallado, porque esos roles ya existen, ya se mantienen y ya significan algo para el negocio. Atribuye cada llamada a la persona en el registro con sus argumentos y resultado, para que el trabajo de un agente sea revisable exactamente como lo es el de una persona.
- El token llegaValida la firma y que el público sea este servidor, como lo requiere la RFC 8707; rechaza cualquier otra cosa con 401.
- Resolver a la personaAsocia el token a un usuario en el espacio de trabajo y carga su rol y aplicaciones instaladas.
- Filtra la listaDevuelve solo las herramientas que ese rol puede usar, en un orden estable, de tools/list.
- Verifica la llamadaEn tools/call, verifica el permiso nuevamente y rechaza con isError si falta; nada se ejecuta.
- Ejecuta y registraEjecuta la transacción, mídela si tu propio agente hizo el razonamiento, y escribe la llamada en el registro de auditoría bajo esa persona.
Manejo de escrituras
Un modelo que recibe un resultado ambiguo volverá a llamar, y uno que recibe un error intentará una entrada corregida. Diseña para eso. Las escrituras que crean deben devolver un identificador y, cuando sea posible, aceptar una clave de idempotencia o una clave natural para que se detecte una repetición. Las escrituras que cambian de estado deben ser explícitas sobre la transición que realizan y rechazar las imposibles con una razón legible: registrar un pago contra una factura anulada es un isError resultado que lo indique, no un no-op silencioso y no un rastreo de pila. Nunca dejes una escritura parcial; si una herramienta de múltiples pasos no puede completarse, revierte y reporta.
- Prefiere borradores y aprobaciones. Haz que la creación sea aditiva (un borrador) y da a la finalización su propia herramienta con su propio permiso, de modo que el paso destructivo sea el que un cliente confirma y un rol controla.
- Marca las herramientas destructivas. Establecer
destructiveHintsobre anulaciones y eliminaciones y decirlo en la descripción; Claude y ChatGPT utilizan tales señales al decidir preguntar antes de llamar. - Pregunta en lugar de adivinar. Cuando una llamada necesita una decisión que la herramienta no puede tomar, devuelve un resultado que requiere entrada con una solicitud de elicitar; el cliente plantea la pregunta a la persona y vuelve a intentar la llamada con la respuesta.
- Limita el radio de impacto. Limita la tasa por conexión, establece un límite de gasto por integración donde tu propio agente realiza razonamientos, y valida cada entrada del lado del servidor independientemente del esquema, porque el esquema es una recomendación para el modelo, no una imposición.
Probar la superficie con un cliente real
El inspector de MCP ejercerá tools/list y tools/call y seguir el flujo de OAuth. La verdadera prueba es un modelo. Conecta Claude como un conector personalizado, o ChatGPT en modo desarrollador, inicia sesión como un usuario con un rol limitado y pide un resultado rutinario que necesite tres o cuatro herramientas. Observa qué herramientas elige y por qué; una elección incorrecta es casi siempre un problema de descripción. Luego inicia sesión como un usuario sin uno de los permisos y confirma que la ejecución se detiene en la llamada correcta con una razón que el modelo repite.
Así es como se construye y verifica el servidor del espacio de trabajo de Sois: transacciones como herramientas, descripciones instructivas, una lista filtrada por rol, una segunda verificación en cada llamada, borradores antes de las aprobaciones y un registro que una persona puede leer. Los desarrolladores que crean aplicaciones para el mercado publican herramientas en la misma lista bajo las mismas reglas, por lo que una aplicación es operable por cualquier agente en el momento en que se instala. El patrón no es específico de un producto; cualquier ERP que lo adopte se convierte en algo que un agente puede ejecutar.
Preguntas que la gente hace
¿Cuántas herramientas debería exponer un servidor ERP MCP?
Tantas como transacciones valga la pena automatizar, filtradas por usuario para que cada llamador vea un conjunto funcional. Varios cientos es normal para un sistema completo; lo que importa es que la lista sea estable, filtrada por rol y organizada por verbos consistentes para que el modelo pueda clasificar candidatos.
¿Debería usar ámbitos de OAuth para permisos detallados?
Utilice ámbitos amplios para la conexión y los propios roles del ERP para el límite detallado, verificado en cada llamada. Los roles ya existen y son mantenidos por el negocio; un esquema de ámbito paralelo se desviaría de ellos.
¿Cómo debería comportarse una escritura si el modelo la llama dos veces?
Detecte la repetición a través de una clave de idempotencia o natural y devuelva el registro existente, o haga que la escritura sea aditiva y claramente reportada para que el duplicado sea visible. Nunca falle en silencio y nunca deje una escritura parcial.
¿Las anotaciones de herramientas son impuestas por el cliente?
No. Son indicios, y la especificación indica a los clientes que las traten como no confiables a menos que el servidor sea confiable. Los clientes las utilizan para elegir el comportamiento de confirmación; las propias verificaciones de permisos y validación del servidor son las que previenen daños.
- Especificación del Protocolo de Contexto del Modelo (2026-07-28): herramientas nombres de herramientas, esquemas, anotaciones, resultados estructurados, manejo de errores y la guía de manejo con estado
- Especificación del Protocolo de Contexto del Modelo: autorización validación de audiencia de token, desafíos de ámbito y el modelo de autorización por solicitud
- OpenAI Apps SDK: construya un servidor MCP cómo ChatGPT utiliza readOnlyHint, destructiveHint y openWorldHint para el comportamiento de confirmación
- documentación de Sois: el servidor MCP del espacio de trabajo la referencia de la herramienta de la que se extrae el ejemplo, filtrado de roles, límites y códigos de error
Este artículo se revisa cuando cambian los productos que describe. Próxima revisión programada: 4 de diciembre de 2026.
