SynaMCPs

Proporciona una puerta de enlace universal para herramientas de IA corporativas, ofreciendo almacenamiento de conocimiento, control de acceso y proxy de fuentes de IA externas.

Documentación

Synamcps (SynaMCPs) — Puerta de enlace de MCP + Almacenamiento de Conocimiento

Synamcps es un servidor que proporciona:

  • Un servidor MCP para clientes LLM (Cursor / Claude Desktop / Claude Code / etc.)
  • Una API HTTP para crear/buscar/leer elementos de conocimiento
  • Una interfaz de administración web para gestionar usuarios/grupos/almacenamientos/tokens, ver estado y realizar diagnósticos básicos
  • Acceso a almacenamientos basado en tokens (los tokens solo restringen permisos), con ACL/RBAC, limitación de velocidad y uso/métricas

El servidor admite múltiples métodos de autenticación (OIDC/Keycloak/Google/Teleport Proxy JWT) y un inicio de sesión interno para la interfaz de administración.


Inicio rápido (Docker Compose)

Requisitos:

  • Docker + Docker Compose

Ejecutar:

cp .env.example .env
make compose-up

Abrir:

  • Inicio de sesión: http://localhost:8080/login
  • Interfaz de administración: http://localhost:8080/admin
  • Aplicación de usuario: http://localhost:8080/app
  • Endpoint MCP (transmisible): http://localhost:8080/mcp
  • API HTTP: http://localhost:8080/api/*

Detener:

make compose-down

Ejecución local (sin Docker)

Requisitos:

  • Go 1.23+
  • Postgres, Redis, S3/MinIO disponibles (o usar Docker Compose como infraestructura)
export CONFIG_PATH=configs/config.local.yaml
go run ./cmd/server

Características (nivel alto)

Almacenamientos, ACL y tokens

  • Almacenamiento es una entidad lógica vinculada a:
    • registros en el catálogo de metadatos (Postgres)
    • un prefijo S3 (storage.S3Prefix)
    • alcance de búsqueda (backend vectorial: pgvector/qdrant)
  • Vinculaciones ACL definen el acceso de usuario/grupo a un almacenamiento (lectura/escritura/administración/propietario).
  • Tokens de acceso:
    • pertenecen a un usuario (propietario)
    • no amplían permisos — solo restringen el acceso del propietario (intersección de ACL de usuario y alcances del token)
    • pueden restringir: storageIds, maxMode (lectura/lectura_escritura), toolAllowlist, límites de velocidad.
  • Visibilidad de documentos (personal/group/public) se aplica además del acceso al almacenamiento: poder leer un almacenamiento es necesario pero no suficiente — un documento personal es visible solo para su propietario, un documento group solo para su propietario o miembros de sus grupos.

Elementos de conocimiento

  • Puede agregar un elemento como:
    • Texto (mediante el estándar POST /api/knowledge)
    • Archivo (subir → contenido sin procesar almacenado en S3 → extracción de mejor esfuerzo → resumen+incrustaciones → elemento guardado en el almacenamiento)
    • Enlace (descargar → contenido sin procesar almacenado en S3 → extracción → resumen+incrustaciones → elemento guardado en el almacenamiento)
  • La ingesta de enlaces solo acepta URLs http/https y se niega a obtener direcciones internas (loopback, link-local incl. metadatos de nube 169.254.169.254, y rangos privados) — protección SSRF que también se aplica a través de redirecciones.

MCP

  • MCP expone un tools/list dinámico basado en el token portador (solo se muestran herramientas/almacenamientos permitidos).
  • Admite transporte HTTP transmisible (/mcp) y SSE heredado opcional.
  • Los nombres de herramientas MCP usan _ (guion bajo) para evitar filtrados/avisos en algunos clientes.
  • Proxy MCP: registre servidores MCP HTTP/SSE ascendentes en la interfaz de administración (pestaña MCP Servers), descubra herramientas/recursos/indicaciones, restrinja por ACL y alcances por token. Identificadores proxy:
    • herramientas/indicaciones: {slug}__{upstream_name}
    • recursos: syna-mcp/{slug}/{upstream_uri}
    • el slug se genera automáticamente a partir del nombre del servidor (sin entrada manual).
  • Los secretos de autenticación ascendentes se almacenan cifrados en Postgres (MCP_PROXY_SECRETS_KEY en .env).

Uso / Límite de velocidad / Métricas

  • Limitación de velocidad por token (minuto/hora/día + ráfaga), aplicada tanto para llamadas MCP como para la API REST (429 Too Many Requests cuando se excede).
  • Los cuerpos de solicitud están limitados por limits.max_upload_bytes (413 cuando se excede).
  • Los eventos de uso (y estado/errores) pueden escribirse en Redis TimeSeries (cuando está habilitado).
  • /metrics expone métricas en formato Prometheus (los valores de etiquetas se sanean y la cardinalidad de series está limitada).

Interfaz de administración web

La interfaz de administración integrada (HTML renderizado en servidor) le permite:

  • Usuarios / Grupos / Miembros de grupo
  • Almacenamientos + detalles de almacenamiento (ACL, claves/tokens, lista de elementos)
  • Tokens + asistente de conexión MCP + eliminar
  • Agregar elemento (Texto/Archivo/Enlace)
  • Búsqueda (por token / por almacenamiento)
  • Estado (Postgres/Redis/S3/LLMs + contadores de errores)

Los formularios seleccionan entidades de listas desplegables de nombres (almacenamientos/grupos/usuarios/tokens/servidores MCP) con botones de actualización en lugar de escribir IDs sin procesar. Los slugs ya no se ingresan manualmente — un almacenamiento establece su slug por defecto a su id y un servidor MCP deriva un slug único de su nombre.


Configuración

Configuración predeterminada: configs/config.example.yaml
Anulación: CONFIG_PATH=/path/to/config.yaml

Secciones clave:

  • web.default_admin: nombre de usuario/contraseña de la interfaz de administración (contraseña mediante referencia de entorno)
  • oauth.providers: proveedores OIDC (emisor/audiencia/jwks_url; client_id opcional para inicio de sesión AS)
  • oauth_as: servidor de autorización MCP OAuth 2.1 para conectores de Claude Desktop
  • teleport: Teleport Proxy JWT (emisor/audiencia)
  • redis: sesiones + uso/series temporales (cuando está habilitado)
  • s3: endpoint/contenedor + umbral de documentos grandes
  • embedding, summarization: LLMs (proveedor/modelo/api/api_key_env_ref)
  • vector_backend.active: pgvector o qdrant
  • metadata_catalog.dsn: DSN de Postgres
  • api.allowed_origins: lista de permitidos CORS estricta
  • usage: contabilidad y series temporales, retención, exportadores

Ejemplo .env para desarrollo local: .env.example.


API HTTP

Autenticación:

  • cookieAuth: sesión de interfaz web (cookie session_id)
  • bearerAuth: Authorization: Bearer <token>

Códigos de error comunes:

  • 401 — token/sesión faltante
  • 403 — prohibido (permisos insuficientes para el almacenamiento/operación)
  • 404 — no encontrado
  • 413 — el cuerpo de la solicitud excede limits.max_upload_bytes
  • 422 — solicitud no válida
  • 429 — límite de velocidad excedido (límites por token)

API de conocimiento

GET /api/knowledge

Listar elementos con paginación y filtros.

Parámetros de consulta:

  • page (int)
  • pageSize (int)
  • storageId (cadena) — limitar a un almacenamiento específico
  • source (cadena) — coincidencia exacta
  • sourceUrl (cadena)
  • sourceUrlMode (exact | partial) — partial funciona solo cuando search.filters.source_url.allow_partial_match=true

Respuesta: models.PaginatedKnowledgeList (elementos + total + hasNext + página/tamañoDePágina).

POST /api/knowledge

Crear un elemento a partir de texto.

Cuerpo:

{
  "storageId": "storage-id-optional",
  "title": "Runbook",
  "text": "Long knowledge text...",
  "mimeType": "text/plain",
  "visibility": "personal",
  "groupIds": [],
  "source": "api",
  "sourceUrl": "https://docs.example.com/runbook"
}

Notas:

  • si storageId está vacío y el servicio de acceso está habilitado, el servidor usa/crea el almacenamiento personal del usuario
  • visibility por defecto es personal
  • groupIds debe ser una matriz (no null)

GET /api/knowledge/{docId}

Devolver un documento individual.

DELETE /api/knowledge/{docId}

Eliminar un documento (y las incrustaciones asociadas en el almacén vectorial).

POST /api/knowledge/search

Búsqueda basada en incrustaciones.

Cuerpo:

{
  "query": "kubernetes ingress timeout",
  "topK": 10,
  "filters": {
    "storageId": "storage-id-optional",
    "source": "api",
    "sourceUrl": "https://...",
    "sourceUrlMode": "exact"
  }
}

Respuesta: una matriz de resultados de búsqueda (incluyendo fragmento/título/fuente/URL de fuente).

API de ingesta (Archivo/Enlace)

POST /api/knowledge/ingest/file (multipart)

Subir un archivo como elemento:

  • el contenido sin procesar se almacena en S3
  • se realiza extracción de texto de mejor esfuerzo
  • el proceso produce resumen + incrustaciones
  • el resultado final se guarda como un elemento de conocimiento normal

Campos multipart:

  • storageId (cadena, opcional)
  • title (cadena, opcional)
  • visibility (personal|group|public, opcional)
  • source (cadena, opcional)
  • sourceUrl (cadena, opcional)
  • mimeType (cadena, opcional)
  • file (obligatorio)

Ejemplo:

curl -X POST http://localhost:8080/api/knowledge/ingest/file \
  -H "Authorization: Bearer $TOKEN" \
  -F "storageId=..." \
  -F "title=Spec" \
  -F "visibility=personal" \
  -F "file=@./spec.txt"

POST /api/knowledge/ingest/link (json)

Descarga una URL, almacena el contenido sin procesar en S3, extrae texto y guarda un elemento.

Cuerpo:

{
  "storageId": "storage-id-optional",
  "title": "Optional title",
  "url": "https://example.com/docs",
  "visibility": "personal",
  "source": "link"
}

API de administración (/api/admin/*)

Todos los endpoints requieren autenticación (cookie o bearer), y muchos requieren platform_admin.

Usuarios

  • GET /api/admin/me
  • GET /api/admin/users (platform_admin)
  • POST /api/admin/users (platform_admin)
  • GET /api/admin/users/{id} (admin o el propio usuario)
  • PATCH /api/admin/users/{id} (admin o el propio usuario)
  • POST /api/admin/users/{id}/password (admin o el propio usuario)
  • DELETE /api/admin/users/{id} (platform_admin)

Grupos

  • GET /api/admin/groups (platform_admin)
  • POST /api/admin/groups (platform_admin)
  • DELETE /api/admin/groups/{id} (platform_admin)
  • GET /api/admin/groups/{id}/members (platform_admin)
  • PUT /api/admin/groups/{id}/members/{userId} (platform_admin)
  • DELETE /api/admin/groups/{id}/members/{userId} (platform_admin)

Almacenamientos

  • GET /api/admin/storages (almacenamientos disponibles para el usuario actual)
  • POST /api/admin/storages
  • DELETE /api/admin/storages/{id} (requiere storage.delete: propietario/administrador del almacenamiento o platform_admin)
  • GET /api/admin/storages/{id} (detalles del almacenamiento: almacenamiento + acl + tokens; requiere acceso de lectura)
  • GET /api/admin/storages/{id}/acl (requiere acl.manage)
  • PUT /api/admin/storages/{id}/acl (requiere acl.manage)

Tokens

Los endpoints de mutación de tokens requieren que el llamante sea el propietario del token o platform_admin; GET /api/admin/tokens lista solo los tokens del propio llamante (platform_admin ve todos).

  • GET /api/admin/tokens
  • POST /api/admin/tokens
  • DELETE /api/admin/tokens/{id} (propietario/platform_admin)
  • PATCH /api/admin/tokens/{id}/rate-limit (propietario/platform_admin)
  • POST /api/admin/tokens/{id}/revoke (propietario/platform_admin)
  • POST /api/admin/tokens/{id}/rotate (propietario/platform_admin)
  • PATCH /api/admin/tokens/{id}/mcp-scopes (propietario/platform_admin)
  • GET/POST /api/admin/tokens/{id}/connect-options (asistente para clientes MCP)

Uso / Estado

  • GET /api/admin/usage/series
  • GET /api/admin/usage/summary
  • GET /api/admin/status — estado de componentes + contadores de errores (Redis TimeSeries)

MCP

Transporte

  • HTTP transmisible: POST /mcp (JSON-RPC) + GET /mcp (flujo SSE por Mcp-Session-Id)
  • SSE heredado (si está habilitado): /sse + /messages

Flujo mínimo (transmisible)

  1. Obtener un token portador (OIDC/Teleport o interno)
  2. initialize:
curl -X POST http://localhost:8080/mcp \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":"1","method":"initialize","params":{}}'
  1. Guardar Mcp-Session-Id de los encabezados/respuesta (los clientes lo hacen automáticamente)
  2. Abrir el flujo (el token portador es obligatorio y debe coincidir con el propietario de la sesión):
curl -N http://localhost:8080/mcp \
  -H "Authorization: Bearer $TOKEN" \
  -H "Mcp-Session-Id: <session_id>"

GET /mcp y DELETE /mcp están autenticados; una sesión solo puede ser leída/cerrada por el principal que la creó.

Herramientas dinámicas/lista

tools/list devuelve solo las herramientas permitidas por el token portador actual y sus alcances de almacenamiento.

herramientas/llamada

tools/call enruta llamadas a los métodos internos correspondientes (knowledge_* etc.).

Conexión MCP (interfaz web)

La interfaz de administración (/admin) incluye una página de Conexión MCP que genera:

  • nombre de archivo de configuración
  • configBody (JSON)
  • instrucciones paso a paso

Puede copiar configBody haciendo clic en él.


Instalación y operaciones

Docker Compose

cp .env.example .env
make compose-up

Útil:

  • make compose-down
  • make seed-dev (si se usa en su entorno)

Configuración y secretos

  • configs/config.example.yaml — configuración de ejemplo
  • configs/config.local.yaml — configuración de compose local (usada en docker-compose.yml)
  • .env — secretos (contraseñas/claves), ejemplo en .env.example

CORS

api.allowed_origins es una lista de permitidos estricta. Los orígenes desconocidos se rechazan. Las rutas de la interfaz web (/, /login, /logout, /app*, /admin*) omiten la verificación de origen.


Solución de problemas

  • Origen no permitido:
    • agregue el origen a api.allowed_origins
    • asegúrese de abrir la interfaz web mediante /login (las rutas web omiten la verificación de origen)
  • Credenciales no válidas:
    • verifique que .env esté cargado (en compose está conectado mediante env_file: .env)
    • verifique web.default_admin.password_env_ref
  • Las series temporales no se crean:
    • necesita Redis con el módulo RedisTimeSeries (TS.ADD debe ser compatible)
    • o deshabilite usage.redis_timeseries
  • Aviso de herramientas MCP "filtradas":
    • los nombres de herramientas ya usan _ en lugar de .

Documentación en este repositorio

  • docs/marketing.md — descripción general del producto + escenarios de RAG corporativo / proceso agéntico
  • docs/setup.md — instalación y ejecución
  • docs/api.md — endpoints básicos de conocimiento
  • docs/mcp-connection.md — conexión MCP
  • docs/auth-setup.md — proveedores de autenticación
  • docs/openapi.yaml — stub OpenAPI de referencia