Claude dentro de sistemas reales
MCP connectors
Dos formas de dejar que Claude opere un negocio con exactamente los permisos de la persona que lo usa, y nada más.
- Rol
- Único autor
- Período
- oct. 2026
- Estado
- Ambos en producción
- Código
- Privado
- herramientas de Snup, 5 de escritura
- 17
- pruebas del conector de Snup
- 85
- herramientas de Maquila
- 66
- tablas de Maquila con RLS
- 25 de 25
- MCP
- OAuth 2.1
- PKCE
- Elixir
- Phoenix
- Next.js
- Supabase
- Postgres RLS
01 Contexto
Por qué existe
Operar un negocio desde Claude solo sirve si el modelo no puede hacer más que la persona que está detrás. En Snup, el acceso de administrador era un solo interruptor que abría todos los endpoints de administración, y la operación del día a día, como revisar postulaciones o investigar un cobro, muchas veces iba directo a la base de datos, sin revisar permisos y sin registro de auditoría. El riesgo que el diseño nombra primero es que un agente escriba en producción algo que nadie pidió.
Maquila, una app de operaciones para un negocio familiar, tiene la forma opuesta: dos o tres personas de confianza, registro abierto y agentes de más de un proveedor. Ahí no basta con haber iniciado sesión, y las mismas reglas tienen que valer para la app web, la app de escritorio, el servidor MCP y las llamadas directas a la API.
Los dos conectores responden la misma pregunta en lugares distintos. Snup revisa en la aplicación los permisos concedidos y convierte cada escritura en una operación de dos pasos. Maquila lleva el límite a la base de datos, así que la consulta de un agente corre como la persona.
02 Arquitectura
Cómo funciona
El conector de Snup está integrado en la app Phoenix y llama a los mismos módulos de dominio que el panel de administración. Snup es su propio servidor OAuth 2.1: Claude lo descubre a partir de un 401, se registra de forma dinámica y el administrador da su consentimiento en una página donde elige qué puede hacer esta conexión. El diagrama sigue una llamada.
-
Conexión y consentimiento
Claude lee los metadatos del recurso protegido y del servidor de autorización, se registra y abre la página de consentimiento con PKCE. El administrador entra con su sesión normal y elige las herramientas por área, si se permiten escrituras, si se ven los datos de contacto y cuánto dura la conexión.
-
Controlar cada solicitud
Un plug revisa el interruptor de la funcionalidad, el origen y el bearer token, y luego resuelve un
Principal. También vuelve a comprobar que la persona siga siendo administrador. Los tokens personales de Claude Code y el OAuth de claude.ai se resuelven en el mismoPrincipal, así que las herramientas, los límites y la auditoría nunca necesitan saber cuál se usó. -
Escribir toma dos llamadas
Las herramientas de escritura usan
dry_run: truepor defecto y devuelven una vista previa del antes y el después, los efectos secundarios y un token firmado sobre la persona, la credencial, la herramienta y un hash de los argumentos, válido por cinco minutos. Aplicar la escritura requiere los mismos argumentos, ese token y un motivo no vacío. -
Auditoría, siempre
Cada llamada escribe una fila: lecturas, rechazos, llamadas frenadas por el límite de uso, vistas previas y escrituras, con el actor, la credencial, el cliente, los argumentos y el motivo. El resultado en sí nunca se guarda.
-
Maquila: la consulta corre como la persona
Supabase Auth hace de servidor OAuth. Cada herramienta arma un cliente de base de datos que lleva el token del propio usuario, así que la seguridad a nivel de fila, los privilegios por columna y los triggers de protección se aplican al agente exactamente como en la app. Una consulta de permisos existe solo para devolver un rechazo amable.
-
Maquila: la base de datos sabe que es un agente
Una función SQL lee el cliente OAuth desde el token. Eso hace posible un interruptor por persona que deja editar en la app pero solo leer a través de un agente, y desconectar un agente termina sus sesiones de inmediato.
03 Decisiones
Las decisiones que le dieron forma
-
Decisión 01
Integrar el conector en Snup y llamar al código de dominio del propio panel
- Elegí
- Un endpoint MCP dentro de la app Phoenix, que llama a los mismos módulos que el panel de administración.
- En vez de
- Un servicio MCP aparte que llame a la API de administración por HTTP, lo que exige reenviar tokens (la especificación de MCP lo prohíbe) o una credencial de servicio que pierde la identidad de la persona.
- Porque
- Un solo lugar para permisos y auditoría y, de regalo, las validaciones y los efectos secundarios del panel.
- Costo
- Primero hubo que sacar lógica de los controladores hacia módulos de dominio, y el conector comparte el proceso y el pool de base de datos de la app.
-
Decisión 02
Que Snup sea su propio servidor OAuth
- Elegí
- PKCE, registro dinámico contra una lista cerrada de URIs de redirección, access tokens de una hora y refresh tokens que rotan en cada uso; reutilizar uno ya rotado revoca toda la conexión. Solo se guardan hashes.
- En vez de
- El proveedor de identidad que ya existía, con una audiencia por ambiente, que se probó primero: con él falló agregar el conector desde un teléfono.
- Porque
- El conector tenía que funcionar desde todos los clientes de Claude, y el proveedor se interponía entre el administrador y el consentimiento que el diseño necesitaba.
- Costo
- Código de seguridad a mi cargo: PKCE, rotación, detección de reutilización y revocación, cubiertos por 29 pruebas.
-
Decisión 03
Que cada persona elija sus permisos, y postergar los roles
- Elegí
- Una lista de herramientas permitidas por credencial, más interruptores para escrituras y datos de contacto, intersectada con seguir siendo administrador. Las herramientas que devuelven datos bancarios empiezan desactivadas.
- En vez de
- Scopes gruesos de lectura y escritura, y claims de rol en los tokens, donde quitar un rol no afecta a los tokens ya emitidos.
- Porque
- Salió en días, y los permisos se ven y se pueden revocar por conexión.
- Costo
- Todavía no hay roles de mínimo privilegio: cualquier administrador puede darle a su propia conexión cualquier herramienta.
-
Decisión 04
Imponer en el servidor las escrituras en dos pasos, sin estado
- Elegí
- Un token de confirmación firmado, atado a la llamada exacta y que no se guarda en ninguna parte. El flujo en dos pasos vive en el servidor, no en cada herramienta, así que una herramienta nueva no puede olvidarlo.
- En vez de
- Confiar en que el cliente muestre una confirmación para las herramientas destructivas.
- Porque
- Los clientes difieren en lo que le preguntan al usuario, y una regla en el servidor vale para todos.
- Costo
- Dos viajes de ida y vuelta por escritura. El token queda atado a los argumentos, no a los datos, así que las escrituras de dominio son compare-and-set y reportan el desfase si el registro cambió entremedio.
-
Decisión 05
Poner la autorización de Maquila en la base de datos
- Elegí
- Seguridad a nivel de fila por área y nivel de acceso en todas las tablas, columnas de costo legibles solo a través de funciones, triggers de protección y políticas restrictivas por empresa.
- En vez de
- Validaciones por herramienta en TypeScript, que podrían desalinearse entre la app web, la app de escritorio, el servidor MCP y las llamadas directas a la API.
- Porque
- Un agente no puede ver más que su humano porque la consulta corre como ese humano.
- Costo
- Una consulta extra en cada llamada,
select *falla en las tablas con columnas de costo y las reglas viven en SQL. Ahí, la confirmación antes de escribir es una instrucción del servidor, no un paso impuesto.
04 Lo interesante
Vale la pena mirarlo de cerca
-
El token de confirmación está atado a la llamada exacta
Sus claims son la persona, la credencial, la herramienta y un hash de los argumentos que no depende de su orden. Si cambia cualquier argumento, ya no coincide; a los cinco minutos, expira. No se guarda nada, así que no hay nada que limpiar.
-
El texto que escriben los usuarios llega marcado como no confiable
Cada campo de texto libre escrito por un usuario, como una reseña o un mensaje de soporte, llega al modelo envuelto como no confiable y con un largo máximo. Sumado a la regla de la vista previa, un texto inyectado puede, en el peor caso, producir una vista previa que nadie confirma.
-
La seguridad a nivel de fila es el límite del agente
En Maquila, la propia base de datos impone lo que ve un agente, y aun así puede distinguir el tráfico de un agente del de la app. Revocar un agente termina sus sesiones de inmediato, porque cada llamada vuelve a validar el token.
-
Papel que un agente puede leer
Las hojas de producción impresas de Maquila llevan un código simple en cada fila para que un agente pueda leer una foto de la hoja ya llenada y registrar el trabajo. Un trigger de la base de datos rechaza totales mayores que la cantidad pedida.
05 Hecho con agentes
Cómo encajan los agentes
Los dos conectores existen para que los agentes hagan trabajo real: aprobar postulaciones, hacer seguimiento de pagos pendientes, registrar producción a partir de una foto. A los dos también los construyeron agentes, y los nueve commits del conector de Snup y los siete del servidor MCP de Maquila tienen a Claude como coautor.
El conector de Snup se diseñó primero en documentos. Un brief de planificación sin código, un ADR y dos enmiendas que recortaron el alcance llegaron antes de los dos briefs de implementación, cada uno con un checklist y un plan de pruebas. La versión con tokens personales entró en un solo commit de unas cinco mil líneas con sus pruebas, y OAuth llegó el mismo día.
El archivo de reglas de Maquila funciona como el manual de operación del agente: seguridad a nivel de fila en todas las tablas, vistas que corren con los permisos de quien las consulta y un plan corto antes de cualquier cambio. El servidor MCP pasó de 35 a 66 herramientas en seis días bajo esas reglas.