SynaMCPs MCP Server

कॉर्पोरेट AI टूल्स के लिए एक सार्वभौमिक गेटवे प्रदान करता है, जो ज्ञान भंडारण, पहुँच नियंत्रण और बाहरी AI स्रोतों की प्रॉक्सी सेवा प्रदान करता है।

दस्तावेज़

Synamcps (SynaMCPs) — MCP + Knowledge Storage Gateway

Synamcps is a server that provides:

  • An MCP server for LLM clients (Cursor / Claude Desktop / Claude Code / etc.)
  • An HTTP API to create/search/read knowledge items
  • A Web Admin UI to manage users/groups/storages/tokens, view status, and do basic diagnostics
  • Token-based access to storages (tokens only narrow permissions), with ACL/RBAC, rate limiting, and usage/metrics

The server supports multiple auth methods (OIDC/Keycloak/Google/Teleport Proxy JWT) and an internal login for the Admin UI.


Quick start (Docker Compose)

Requirements:

  • Docker + Docker Compose

Run:

cp .env.example .env
make compose-up

Open:

  • Web UI: http://localhost:8080/login
  • MCP endpoint (streamable): http://localhost:8080/mcp
  • HTTP API: http://localhost:8080/api/*

Stop:

make compose-down

Local run (without Docker)

Requirements:

  • Go 1.23+
  • Postgres, Redis, S3/MinIO available (or use Docker Compose as your infrastructure)
export CONFIG_PATH=configs/config.local.yaml
go run ./cmd/server

Features (high level)

Storages, ACL and tokens

  • Storage is a logical entity tied to:
    • records in the metadata catalog (Postgres)
    • an S3 prefix (storage.S3Prefix)
    • search scoping (vector backend: pgvector/qdrant)
  • ACL bindings define user/group access to a storage (read/write/admin/owner).
  • Access tokens:
    • belong to a user (owner)
    • do not expand permissions — they narrow the owner's access (intersection of user ACL and token scopes)
    • can restrict: storageIds, maxMode (read/read_write), toolAllowlist, rate limits.
  • Document visibility (personal/group/public) is enforced on top of storage access: being able to read a storage is necessary but not sufficient — a personal document is visible only to its owner, a group document only to its owner or members of its groups.

Knowledge items

  • You can add an item as:
    • Text (via the standard POST /api/knowledge)
    • File (upload → raw stored to S3 → best-effort extraction → summary+embeddings → item saved to storage)
    • Link (download → raw stored to S3 → extraction → summary+embeddings → item saved to storage)
  • Link ingestion only accepts http/https URLs and refuses to fetch internal addresses (loopback, link-local incl. cloud metadata 169.254.169.254, and private ranges) — SSRF protection that also applies across redirects.

MCP

  • MCP exposes a dynamic tools/list based on the bearer token (only allowed tools/storages are visible).
  • Supports Streamable HTTP transport (/mcp) and optional legacy SSE.
  • MCP tool names use _ (underscore) to avoid filtering/warnings in some clients.
  • MCP proxy: register upstream HTTP/SSE MCP servers in Admin UI (MCP Servers tab), discover tools/resources/prompts, restrict by ACL and per-token scopes. Proxied identifiers:
    • tools/prompts: {slug}__{upstream_name}
    • resources: syna-mcp/{slug}/{upstream_uri}
    • the slug is generated automatically from the server name (no manual entry).
  • Upstream auth secrets are stored encrypted in Postgres (MCP_PROXY_SECRETS_KEY in .env).

Usage / Rate limit / Metrics

  • Rate limiting per token (minute/hour/day + burst), enforced for both MCP calls and the REST API (429 Too Many Requests when exceeded).
  • Request bodies are capped by limits.max_upload_bytes (413 when exceeded).
  • Usage events (and status/errors) can be written to Redis TimeSeries (when enabled).
  • /metrics exposes Prometheus-format metrics (label values are sanitized and series cardinality is bounded).

Web Admin UI

The built-in admin UI (server-rendered HTML) lets you:

  • Users / Groups / Group members
  • Storages + Storage details (ACL, keys/tokens, items list)
  • Tokens + MCP Connect wizard + delete
  • Add item (Text/File/Link)
  • Search (by token / by storage)
  • Status (Postgres/Redis/S3/LLMs + error counters)

Forms pick entities from name dropdowns (storages/groups/users/tokens/MCP servers) with refresh buttons instead of typing raw IDs. Slugs are no longer entered by hand — a storage defaults its slug to its id and an MCP server derives a unique slug from its name.


Configuration

Default config: configs/config.example.yaml
Override: CONFIG_PATH=/path/to/config.yaml

Key sections:

  • web.default_admin: Admin UI username/password (password via env ref)
  • oauth.providers: OIDC providers (issuer/audience/jwks_url)
  • teleport: Teleport Proxy JWT (issuer/audience)
  • redis: sessions + usage/time-series (when enabled)
  • s3: endpoint/bucket + large document threshold
  • embedding, summarization: LLMs (provider/model/api/api_key_env_ref)
  • vector_backend.active: pgvector or qdrant
  • metadata_catalog.dsn: Postgres DSN
  • api.allowed_origins: strict CORS allowlist
  • usage: accounting and time series, retention, exporters

Example .env for local development: .env.example.


HTTP API

Authentication:

  • cookieAuth: web UI session (session_id cookie)
  • bearerAuth: Authorization: Bearer <token>

Common error codes:

  • 401 — missing token/session
  • 403 — forbidden (insufficient permissions for the storage/operation)
  • 404 — not found
  • 413 — request body exceeds limits.max_upload_bytes
  • 422 — invalid request
  • 429 — rate limit exceeded (per-token limits)

Knowledge API

GET /api/knowledge

List items with pagination and filters.

Query params:

  • page (int)
  • pageSize (int)
  • storageId (string) — limit to a specific storage
  • source (string) — exact match
  • sourceUrl (string)
  • sourceUrlMode (exact | partial) — partial works only when search.filters.source_url.allow_partial_match=true

Response: models.PaginatedKnowledgeList (items + total + hasNext + page/pageSize).

POST /api/knowledge

Create an item from text.

Body:

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

Notes:

  • if storageId is empty and access-service is enabled, the server uses/creates the user's personal storage
  • visibility defaults to personal
  • groupIds must be an array (not null)

GET /api/knowledge/{docId}

Return a single document.

DELETE /api/knowledge/{docId}

Delete a document (and associated embeddings in the vector store).

POST /api/knowledge/search

Embedding-based search.

Body:

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

Response: an array of search hits (including snippet/title/source/sourceUrl).

Ingest API (File/Link)

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

Upload a file as an item:

  • raw content is stored in S3
  • best-effort text extraction is performed
  • the pipeline produces summary + embeddings
  • the final result is saved as a normal knowledge item

Multipart fields:

  • storageId (string, optional)
  • title (string, optional)
  • visibility (personal|group|public, optional)
  • source (string, optional)
  • sourceUrl (string, optional)
  • mimeType (string, optional)
  • file (required)

Example:

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)

Downloads a URL, stores raw content to S3, extracts text, and saves an item.

Body:

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

Admin API (/api/admin/*)

All endpoints require authentication (cookie or bearer), and many require platform_admin.

Users

  • GET /api/admin/me
  • GET /api/admin/users (platform_admin)
  • POST /api/admin/users (platform_admin)
  • GET /api/admin/users/{id} (admin или сам пользователь)
  • PATCH /api/admin/users/{id} (admin или сам пользователь)
  • POST /api/admin/users/{id}/password (admin или сам пользователь)
  • DELETE /api/admin/users/{id} (platform_admin)

Groups

  • 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)

Storages

  • GET /api/admin/storages (storages available to the current user)
  • POST /api/admin/storages
  • DELETE /api/admin/storages/{id} (requires storage.delete: storage owner/admin or platform_admin)
  • GET /api/admin/storages/{id} (storage details: storage + acl + tokens; requires read access)
  • GET /api/admin/storages/{id}/acl (requires acl.manage)
  • PUT /api/admin/storages/{id}/acl (requires acl.manage)

Tokens

Mutating token endpoints require the caller to be the token owner or platform_admin; GET /api/admin/tokens lists only the caller's own tokens (platform_admin sees all).

  • GET /api/admin/tokens
  • POST /api/admin/tokens
  • DELETE /api/admin/tokens/{id} (owner/platform_admin)
  • PATCH /api/admin/tokens/{id}/rate-limit (owner/platform_admin)
  • POST /api/admin/tokens/{id}/revoke (owner/platform_admin)
  • POST /api/admin/tokens/{id}/rotate (owner/platform_admin)
  • PATCH /api/admin/tokens/{id}/mcp-scopes (owner/platform_admin)
  • GET/POST /api/admin/tokens/{id}/connect-options (wizard for MCP clients)

Usage / Status

  • GET /api/admin/usage/series
  • GET /api/admin/usage/summary
  • GET /api/admin/status — component status + error counters (Redis TimeSeries)

MCP

Transport

  • Streamable HTTP: POST /mcp (JSON-RPC) + GET /mcp (SSE stream по Mcp-Session-Id)
  • Legacy SSE (если включено): /sse + /messages

Minimal flow (streamable)

  1. Obtain a bearer token (OIDC/Teleport/or internal)
  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. Save Mcp-Session-Id from headers/response (clients do this automatically)
  2. Open the stream (the bearer token is required and must match the session owner):
curl -N http://localhost:8080/mcp \
  -H "Authorization: Bearer $TOKEN" \
  -H "Mcp-Session-Id: <session_id>"

GET /mcp and DELETE /mcp are authenticated; a session can only be read/closed by the principal that created it.

Dynamic tools/list

tools/list returns only the tools allowed by the current bearer token and its storage scopes.

tools/call

tools/call routes calls to the corresponding internal methods (knowledge_* etc.).

MCP Connect (Web UI)

The Admin UI includes an MCP Connect page that generates:

  • config file name
  • configBody (JSON)
  • step-by-step instructions

You can copy configBody by clicking it.


Installation and operations

Docker Compose

cp .env.example .env
make compose-up

Helpful:

  • make compose-down
  • make seed-dev (if used in your environment)

Config and secrets

  • configs/config.example.yaml — example config
  • configs/config.local.yaml — local compose config (used in docker-compose.yml)
  • .env — secrets (passwords/keys), example in .env.example

CORS

api.allowed_origins is a strict allowlist. Unknown origins are rejected. Web UI routes (/, /login, /logout, /app*) bypass the origin check.


Troubleshooting

  • Origin not allowed:
    • add the origin to api.allowed_origins
    • make sure you open the Web UI via /login (web routes bypass origin-check)
  • Invalid credentials:
    • verify .env is loaded (in compose it is wired via env_file: .env)
    • verify web.default_admin.password_env_ref
  • Time series are not created:
    • you need Redis with the RedisTimeSeries module (TS.ADD must be supported)
    • or disable usage.redis_timeseries
  • MCP tools “filtered out” warning:
    • tool names already use _ instead of .

Documentation in this repo

  • docs/marketing.md — product overview + corporate RAG / agentic pipeline scenarios
  • docs/setup.md — installation and run
  • docs/api.md — basic knowledge endpoints
  • docs/mcp-connection.md — MCP connection
  • docs/auth-setup.md — auth providers
  • docs/openapi.yaml — baseline OpenAPI stub