SynaMCPs
Fornece um gateway universal para ferramentas de IA corporativas, oferecendo armazenamento de conhecimento, controle de acesso e proxy de fontes externas de IA.
Documentação
Synamcps (SynaMCPs) — Gateway MCP + Armazenamento de Conhecimento
Synamcps é um servidor que fornece:
- Um servidor MCP para clientes de LLM (Cursor / Claude Desktop / Claude Code / etc.)
- Uma API HTTP para criar/buscar/ler itens de conhecimento
- Uma UI de Administração Web para gerenciar usuários/grupos/armazenamentos/tokens, visualizar status e fazer diagnósticos básicos
- Acesso baseado em token aos armazenamentos (tokens apenas restringem permissões), com ACL/RBAC, limite de taxa e uso/métricas
O servidor suporta múltiplos métodos de autenticação (OIDC/Keycloak/Google/Teleport Proxy JWT) e um login interno para a UI de Administração.
Início rápido (Docker Compose)
Pré-requisitos:
- Docker + Docker Compose
Execute:
cp .env.example .env
make compose-up
Abra:
- Login:
http://localhost:8080/login - UI de Administração:
http://localhost:8080/admin - Aplicativo do usuário:
http://localhost:8080/app - Endpoint MCP (streamable):
http://localhost:8080/mcp - API HTTP:
http://localhost:8080/api/*
Pare:
make compose-down
Execução local (sem Docker)
Pré-requisitos:
- Go 1.23+
- Postgres, Redis, S3/MinIO disponíveis (ou use Docker Compose como sua infraestrutura)
export CONFIG_PATH=configs/config.local.yaml
go run ./cmd/server
Recursos (visão geral)
Armazenamentos, ACL e tokens
- Armazenamento é uma entidade lógica vinculada a:
- registros no catálogo de metadados (Postgres)
- um prefixo S3 (
storage.S3Prefix) - escopo de busca (backend vetorial: pgvector/qdrant)
- Vínculos de ACL definem acesso de usuário/grupo a um armazenamento (leitura/escrita/admin/proprietário).
- Tokens de acesso:
- pertencem a um usuário (proprietário)
- não expandem permissões — eles restringem o acesso do proprietário (interseção entre a ACL do usuário e os escopos do token)
- podem restringir:
storageIds,maxMode(leitura/leitura_escrita),toolAllowlist, limites de taxa.
- Visibilidade de documentos (
personal/group/public) é aplicada além do acesso ao armazenamento: conseguir ler um armazenamento é necessário, mas não suficiente — um documentopersonalé visível apenas para seu proprietário, um documentogroupapenas para seu proprietário ou membros de seus grupos.
Itens de conhecimento
- Você pode adicionar um item como:
- Texto (via o padrão
POST /api/knowledge) - Arquivo (upload → conteúdo bruto armazenado no S3 → extração com melhor esforço → resumo+embeddings → item salvo no armazenamento)
- Link (download → conteúdo bruto armazenado no S3 → extração → resumo+embeddings → item salvo no armazenamento)
- Texto (via o padrão
- A ingestão de Link aceita apenas URLs
http/httpse recusa buscar endereços internos (loopback, link-local, incluindo metadados de nuvem169.254.169.254, e faixas privadas) — proteção SSRF que também se aplica a redirecionamentos.
MCP
- O MCP expõe um
tools/listdinâmico baseado no token bearer (apenas ferramentas/armazenamentos permitidos são visíveis). - Suporta transporte Streamable HTTP (
/mcp) e SSE legado opcional. - Os nomes das ferramentas MCP usam
_(underscore) para evitar filtragem/avisos em alguns clientes. - Proxy MCP: registre servidores MCP HTTP/SSE upstream na UI de Administração (aba
MCP Servers), descubra ferramentas/recursos/prompts, restrinja por ACL e escopos por token. Identificadores com proxy:- ferramentas/prompts:
{slug}__{upstream_name} - recursos:
syna-mcp/{slug}/{upstream_uri} - o
slugé gerado automaticamente a partir do nome do servidor (sem entrada manual).
- ferramentas/prompts:
- Segredos de autenticação upstream são armazenados criptografados no Postgres (
MCP_PROXY_SECRETS_KEYem.env).
Uso / Limite de taxa / Métricas
- Limite de taxa por token (minuto/hora/dia + rajada), aplicado tanto para chamadas MCP quanto para a API REST (
429 Too Many Requestsquando excedido). - Corpos de requisição são limitados por
limits.max_upload_bytes(413quando excedido). - Eventos de uso (e status/erros) podem ser gravados no Redis TimeSeries (quando habilitado).
/metricsexpõe métricas em formato Prometheus (valores de rótulos são sanitizados e a cardinalidade das séries é limitada).
UI de Administração Web
A UI de administração integrada (HTML renderizado no servidor) permite:
- Usuários / Grupos / Membros de grupos
- Armazenamentos + detalhes do armazenamento (ACL, chaves/tokens, lista de itens)
- Tokens + assistente MCP Connect + exclusão
- Adicionar item (Texto/Arquivo/Link)
- Busca (por token / por armazenamento)
- Status (Postgres/Redis/S3/LLMs + contadores de erros)
Os formulários selecionam entidades a partir de menus suspensos de nomes (armazenamentos/grupos/usuários/tokens/servidores MCP) com botões de atualização em vez de digitar IDs brutos. Slugs não são mais inseridos manualmente — um armazenamento usa seu id como slug padrão e um servidor MCP deriva um slug único a partir do seu nome.
Configuração
Config padrão: configs/config.example.yaml
Substituição: CONFIG_PATH=/path/to/config.yaml
Seções principais:
web.default_admin: nome de usuário/senha da UI de Administração (senha via referência de env)oauth.providers: provedores OIDC (issuer/audience/jwks_url; client_id opcional para login AS)oauth_as: Servidor de Autorização MCP OAuth 2.1 para Claude Desktop Connectorsteleport: Teleport Proxy JWT (issuer/audience)redis: sessões + uso/séries temporais (quando habilitado)s3: endpoint/bucket + limite de documentos grandesembedding,summarization: LLMs (provider/model/api/api_key_env_ref)vector_backend.active:pgvectorouqdrantmetadata_catalog.dsn: DSN do Postgresapi.allowed_origins: lista de permissão CORS estritausage: contabilidade e séries temporais, retenção, exportadores
Exemplo de .env para desenvolvimento local: .env.example.
API HTTP
Autenticação:
- cookieAuth: sessão da UI web (cookie
session_id) - bearerAuth:
Authorization: Bearer <token>
Códigos de erro comuns:
401— token/sessão ausente403— proibido (permissões insuficientes para o armazenamento/operação)404— não encontrado413— corpo da requisição excedelimits.max_upload_bytes422— requisição inválida429— limite de taxa excedido (limites por token)
API de Conhecimento
GET /api/knowledge
Lista itens com paginação e filtros.
Parâmetros de consulta:
page(int)pageSize(int)storageId(string) — limitar a um armazenamento específicosource(string) — correspondência exatasourceUrl(string)sourceUrlMode(exact|partial) —partialfunciona apenas quandosearch.filters.source_url.allow_partial_match=true
Resposta: models.PaginatedKnowledgeList (itens + total + hasNext + page/pageSize).
POST /api/knowledge
Cria um item a partir de texto.
Corpo:
{
"storageId": "storage-id-optional",
"title": "Runbook",
"text": "Long knowledge text...",
"mimeType": "text/plain",
"visibility": "personal",
"groupIds": [],
"source": "api",
"sourceUrl": "https://docs.example.com/runbook"
}
Observações:
- se
storageIdestiver vazio e o serviço de acesso estiver habilitado, o servidor usa/cria o armazenamento pessoal do usuário visibilityassume o padrãopersonalgroupIdsdeve ser um array (nãonull)
GET /api/knowledge/{docId}
Retorna um único documento.
DELETE /api/knowledge/{docId}
Exclui um documento (e os embeddings associados no armazenamento vetorial).
POST /api/knowledge/search
Busca baseada em embeddings.
Corpo:
{
"query": "kubernetes ingress timeout",
"topK": 10,
"filters": {
"storageId": "storage-id-optional",
"source": "api",
"sourceUrl": "https://...",
"sourceUrlMode": "exact"
}
}
Resposta: um array de resultados de busca (incluindo snippet/título/fonte/sourceUrl).
API de Ingestão (Arquivo/Link)
POST /api/knowledge/ingest/file (multipart)
Envia um arquivo como item:
- o conteúdo bruto é armazenado no S3
- a extração de texto com melhor esforço é realizada
- o pipeline produz resumo + embeddings
- o resultado final é salvo como um item de conhecimento normal
Campos multipart:
storageId(string, opcional)title(string, opcional)visibility(personal|group|public, opcional)source(string, opcional)sourceUrl(string, opcional)mimeType(string, opcional)file(obrigatório)
Exemplo:
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)
Baixa uma URL, armazena o conteúdo bruto no S3, extrai texto e salva um item.
Corpo:
{
"storageId": "storage-id-optional",
"title": "Optional title",
"url": "https://example.com/docs",
"visibility": "personal",
"source": "link"
}
API de Administração (/api/admin/*)
Todos os endpoints exigem autenticação (cookie ou bearer), e muitos exigem platform_admin.
Usuários
GET /api/admin/meGET /api/admin/users(platform_admin)POST /api/admin/users(platform_admin)GET /api/admin/users/{id}(admin ou o próprio usuário)PATCH /api/admin/users/{id}(admin ou o próprio usuário)POST /api/admin/users/{id}/password(admin ou o próprio usuário)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)
Armazenamentos
GET /api/admin/storages(armazenamentos disponíveis para o usuário atual)POST /api/admin/storagesDELETE /api/admin/storages/{id}(exigestorage.delete: proprietário/admin do armazenamento ou platform_admin)GET /api/admin/storages/{id}(detalhes do armazenamento: storage + acl + tokens; exige acesso de leitura)GET /api/admin/storages/{id}/acl(exigeacl.manage)PUT /api/admin/storages/{id}/acl(exigeacl.manage)
Tokens
Endpoints de mutação de tokens exigem que o chamador seja o proprietário do token ou platform_admin; GET /api/admin/tokens lista apenas os tokens do próprio chamador (platform_admin vê todos).
GET /api/admin/tokensPOST /api/admin/tokensDELETE /api/admin/tokens/{id}(proprietário/platform_admin)PATCH /api/admin/tokens/{id}/rate-limit(proprietário/platform_admin)POST /api/admin/tokens/{id}/revoke(proprietário/platform_admin)POST /api/admin/tokens/{id}/rotate(proprietário/platform_admin)PATCH /api/admin/tokens/{id}/mcp-scopes(proprietário/platform_admin)GET/POST /api/admin/tokens/{id}/connect-options(assistente para clientes MCP)
Uso / Status
GET /api/admin/usage/seriesGET /api/admin/usage/summaryGET /api/admin/status— status dos componentes + contadores de erros (Redis TimeSeries)
MCP
Transporte
- Streamable HTTP:
POST /mcp(JSON-RPC) +GET /mcp(stream SSE viaMcp-Session-Id) - SSE legado (se habilitado):
/sse+/messages
Fluxo mínimo (streamable)
- Obtenha um token bearer (OIDC/Teleport ou interno)
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":{}}'
- Salve
Mcp-Session-Iddos cabeçalhos/resposta (os clientes fazem isso automaticamente) - Abra o stream (o token bearer é obrigatório e deve corresponder ao proprietário da sessão):
curl -N http://localhost:8080/mcp \
-H "Authorization: Bearer $TOKEN" \
-H "Mcp-Session-Id: <session_id>"
GET /mcp e DELETE /mcp são autenticados; uma sessão só pode ser lida/encerrada pelo principal que a criou.
tools/list dinâmico
tools/list retorna apenas as ferramentas permitidas pelo token bearer atual e seus escopos de armazenamento.
tools/call
tools/call roteia chamadas para os métodos internos correspondentes (knowledge_* etc.).
MCP Connect (UI Web)
A UI de Administração (/admin) inclui uma página MCP Connect que gera:
- nome do arquivo de configuração
configBody(JSON)- instruções passo a passo
Você pode copiar configBody clicando nele.
Instalação e operações
Docker Compose
cp .env.example .env
make compose-up
Útil:
make compose-downmake seed-dev(se usado no seu ambiente)
Configuração e segredos
configs/config.example.yaml— exemplo de configuraçãoconfigs/config.local.yaml— configuração compose local (usada emdocker-compose.yml).env— segredos (senhas/chaves), exemplo em.env.example
CORS
api.allowed_origins é uma lista de permissão estrita. Origens desconhecidas são rejeitadas.
As rotas da UI Web (/, /login, /logout, /app*, /admin*) ignoram a verificação de origem.
Solução de problemas
- Origem não permitida:
- adicione a origem a
api.allowed_origins - certifique-se de abrir a UI Web via
/login(rotas web ignoram a verificação de origem)
- adicione a origem a
- Credenciais inválidas:
- verifique se
.envestá carregado (no compose ele é conectado viaenv_file: .env) - verifique
web.default_admin.password_env_ref
- verifique se
- Séries temporais não são criadas:
- você precisa de Redis com o módulo RedisTimeSeries (
TS.ADDdeve ser suportado) - ou desabilite
usage.redis_timeseries
- você precisa de Redis com o módulo RedisTimeSeries (
- Aviso de ferramentas MCP "filtradas":
- os nomes das ferramentas já usam
_em vez de.
- os nomes das ferramentas já usam
Documentação neste repositório
docs/marketing.md— visão geral do produto + cenários de RAG corporativo / pipeline agênticodocs/setup.md— instalação e execuçãodocs/api.md— endpoints básicos de conhecimentodocs/mcp-connection.md— conexão MCPdocs/auth-setup.md— provedores de autenticaçãodocs/openapi.yaml— stub OpenAPI de base