← SCRAM AI Lab
Exponer Bind ERP via Model Context Protocol en vez de un wrapper API por cliente. Una capa, varios LLMs (Claude, Cursor, GPT) hablando con el mismo ERP. Rate limits y Redis incluido.
May 21, 2026
4 lecturas
Cuando en SCRAM decidimos que Claude tenía que hablar directamente con Bind ERP — para que el equipo pudiera preguntar por clientes, facturas e inventario sin abrir tres pestañas — la respuesta fácil habría sido un backend NestJS con endpoints REST/GraphQL custom por consumidor. La respuesta correcta fue un MCP server: una capa que cualquier cliente AI (Claude Desktop, Cursor, ChatGPT con conector, agentes propios) consume con el mismo schema. Un servidor, múltiples consumidores, cero código por cliente nuevo. Hoy el mismo servidor sirve a tres equipos internos y a dos integraciones externas sin que tocáramos una línea entre uno y otro.
// scram-bind-mcp/src/tools.ts
export const TOOLS = [
{
name: 'bind_search_customers',
description: 'Busca clientes en Bind ERP por nombre, RFC o email',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', minLength: 2 },
limit: { type: 'number', default: 10, maximum: 50 },
},
required: ['query'],
},
},
{
name: 'bind_get_invoice_status',
description: 'Obtiene el status de una factura por serie/folio',
inputSchema: {
type: 'object',
properties: {
serie: { type: 'string' },
folio: { type: 'string' },
},
required: ['serie', 'folio'],
},
},
{
name: 'bind_get_inventory',
description: 'Consulta inventario por SKU o almacén',
inputSchema: {
type: 'object',
properties: {
sku: { type: 'string' },
almacen_id: { type: 'string' },
},
},
},
];
Bind acepta ~30 requests por minuto antes de empezar a tirar 429. Un solo agente AI haciendo "dame los 50 clientes con factura vencida y sus últimos 3 pedidos" puede quemar el budget en segundos. Solución que probamos en producción: Redis como cache con TTL 5 minutos sobre todas las queries de lectura.
async function callBind(endpoint: string, params: any) {
const cacheKey = `bind:${endpoint}:${hash(params)}`;
const cached = await redis.get(cacheKey);
if (cached) return JSON.parse(cached);
await rateLimiter.acquire(); // token bucket 30/min
const res = await fetch(`${BIND_API}/${endpoint}`, {
headers: { Authorization: `Bearer ${BIND_TOKEN}` },
body: JSON.stringify(params),
});
const data = await res.json();
await redis.setex(cacheKey, 300, JSON.stringify(data));
return data;
}
Para queries de escritura (crear pedido, actualizar inventario) no cacheamos pero sí pasamos por el rate limiter y agregamos un retry con backoff cuando llega 429.
Listamos arriba lectura. Para escritura, el MCP solo expone tools idempotentes y de bajo blast radius:
La regla operativa que mantenemos sin excepciones: cualquier acción con consecuencia fiscal o financiera requiere confirmación humana en UI separada. El agente puede preparar la factura y mostrar el preview, pero el "timbrar" es un click humano. No es desconfianza al modelo; es compliance básico para SAT.
Node 20 + @modelcontextprotocol/sdk, expuesto vía stdio para Claude Desktop y vía HTTP/SSE para clientes web. Corre en Docker sobre nuestro e2-standard-4 con soft limits (reservation 256MB, sin hard limits — la regla de la casa). Logs estructurados a Loki con label mcp_server=scram-bind y session_id por cliente AI. Métricas a Prometheus: latencia por tool, hits de cache, rate-limit acquisitions.
La pregunta para la siguiente iteración: ¿deberían las tools del MCP server ser generadas desde el catálogo de endpoints de Bind, o curadas a mano? Spoiler: a mano hasta que tengas más de 40 tools. Generación automática multiplica las herramientas que el modelo tiene que filtrar y degrada la precisión.
Artículos relacionados
RPA REPSE/IMSS con Playwright + undetected-chromedriver
Los portales SAT/IMSS detectan headless browsers. Combinación ganadora: undetected-chromedriver para Python + Playwright para flow control. 2captcha y nunca almacenar credenciales del cliente.
Migración Mautic → CRM propio sin downtime
Patrón dual-write durante 30 días, backfill batch de 10K contactos por batch, redirect 301 al final. 47K contactos migrados en 6h sin interrumpir capturas.
INEGI BIE/DENUE para context grounding
Inyectar datos reales de INEGI (16M series económicas, 5M empresas geolocalizadas) como context grounding mejora respuestas de LLM sobre mercado mexicano. MCP tool definition y patrón de detection.