Skip to content

MCP Servers

AKKO ships two Model Context Protocol (MCP) servers that let LLM agents (Claude Desktop, Cursor, VS Code, Continue, LibreChat) talk to the platform natively — while every byte and every model stays inside your cluster.

Service-reference page (image, env vars, health): Services / MCP Servers. This page focuses on capabilities, security model and integration.

Why MCP on AKKO

Model Context Protocol is Anthropic's open standard for connecting LLMs to tools and resources through a JSON-RPC-like interface. AKKO is one of the only open-source sovereign platforms that exposes its SQL engine and its data catalog through MCP, with Keycloak-enforced authentication and OPA-enforced authorization — no SaaS MCP gateway needed.

  • Sovereign — both servers run inside the akko namespace; traffic never leaves the cluster unless your agent lives outside (Ingress-exposed with TLS).
  • Sovereign models too — tools like akko_ai_sentiment call the local Trino AI plugin, which routes to Ollama. No OpenAI.
  • Governed — every tool call is authenticated (Keycloak JWT or service token) and authorized (Trino/OpenMetadata RBAC + OPA).
  • Observable — every call emits a span in Tempo and a structured log line in Loki.

Architecture

flowchart LR
    subgraph Agents[AI agents]
        CLAUDE[Claude Desktop]
        CURSOR[Cursor / VS Code]
        LIB[LibreChat / Continue]
    end
    subgraph Edge[Edge]
        TR[Traefik<br/>TLS + OIDC]
    end
    subgraph Servers[AKKO MCP servers]
        MCT[MCP Trino<br/>8 tools]
        MCO[MCP OpenMetadata<br/>catalog + lineage]
    end
    subgraph Plane[Data plane]
        TRI[Trino 480<br/>+ ai_* plugin]
        OM[OpenMetadata]
        AIS[AI Service<br/>FastAPI]
        OLL[Ollama]
    end
    CLAUDE & CURSOR & LIB --> TR
    TR --> MCT
    TR --> MCO
    MCT --> TRI
    MCT --> AIS
    AIS --> OLL
    MCO --> OM

Both servers are deployed as standard Kubernetes Deployments with 2 replicas, exposed through Traefik at:

  • https://mcp-trino.<domain>/sse
  • https://mcp-openmetadata.<domain>/sse

TLS is terminated by the shared akko-tls secret. Only GET and POST are allowed at the Ingress level.

MCP Trino — 8 Tools

Enables agents to discover data, run SELECTs safely, and invoke sovereign AI functions.

Tool Signature Purpose
list_catalogs() List Trino catalogs (iceberg, postgresql, tpch, …)
list_schemas(catalog) (catalog: str) List schemas in a catalog
list_tables(catalog, schema) (catalog, schema) List tables in a schema
describe_table(catalog, schema, table) (catalog, schema, table) Return column types, nullability, comments
execute_query(sql) (sql: str) Read-only SELECT, max 100 rows, 30 s timeout
akko_ai_sentiment(text) (text: str) Local sentiment via Trino AI plugin → Ollama
akko_ai_summarize(text) (text: str) Local summarization via Trino AI plugin
akko_ai_ask(question, context?) (question: str, context?: str) Free-form question with optional context

Security model

  • Read-only by default — the server parses the SQL with sqlglot and rejects anything that is not a single SELECT / WITH / UNION / EXCEPT / INTERSECT.
  • Keyword denylistINSERT, UPDATE, DELETE, DROP, CREATE, ALTER, GRANT, REVOKE are rejected a second time.
  • Identity forwarding — the caller's Keycloak JWT (or a delegated service token) is forwarded as X-Trino-User; OPA policies apply end-to-end.
  • Hard limitsTRINO_MAX_ROWS=100, TRINO_TIMEOUT_S=30. Adjustable in values, but any agent config > 1000 rows requires akko-admin.
  • AI sub-toolsakko_ai_sentiment/akko_ai_summarize/akko_ai_ask call SELECT akko_ai_sentiment(?) via Trino; the Trino AI plugin enforces its own rate limits per user.

MCP OpenMetadata — 5 Tools

Enables agents to find datasets, explore lineage, and reference the business glossary.

Tool Signature Purpose
search_datasets(query) (query: str) Full-text search across the OpenMetadata catalog
get_table_metadata(fqn) (fqn: str) Return schema, tags, owners, description for an FQN
get_lineage(fqn, hops=3) (fqn: str, hops: int) Upstream / downstream lineage (max hops)
list_glossary_terms() Enumerate business glossary entries
list_dashboards() Superset dashboards registered in OpenMetadata

Security model

  • Read-only — the server uses a scoped JWT that only has the catalog:view and lineage:view permissions in OpenMetadata.
  • Service JWT stored in the Kubernetes Secret akko-mcp-om and injected at startup. Rotate via kubectl delete secret akko-mcp-om && helm upgrade.
  • No impersonation — MCP OpenMetadata does not forward the caller identity; OpenMetadata lineage is considered public metadata within the platform. PII column tags remain visible; actual PII values are served by Trino only.

Configuration

Helm values (helm/akko/values.yaml)

akko-mcp:
  trino:
    enabled: true
    image: akko-mcp-trino:2026.03
    ingress:
      host: mcp-federation.akko.local
    env:
      TRINO_HOST: akko-trino
      TRINO_PORT: "8080"
      TRINO_USER: mcp-trino
      TRINO_READ_ONLY: "true"
      TRINO_MAX_ROWS: "100"
      TRINO_TIMEOUT_S: "30"
  openmetadata:
    enabled: true
    image: akko-mcp-openmetadata:2026.03
    ingress:
      host: mcp-catalog.akko.local
    env:
      OPENMETADATA_HOST: openmetadata
      OPENMETADATA_PORT: "8585"
    envFromSecret: akko-mcp-om

Claude Desktop — ~/Library/Application Support/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "akko-trino": {
      "url": "https://mcp-federation.akko.local/sse"
    },
    "akko-openmetadata": {
      "url": "https://mcp-catalog.akko.local/sse"
    }
  }
}

Cursor / Continue / VS Code

All three use the same url field; see their respective docs for the exact config file.

Local development without Ingress

kubectl port-forward -n akko svc/akko-akko-mcp-trino 3000:3000
kubectl port-forward -n akko svc/akko-akko-mcp-openmetadata 3001:3000
# Then point the agent at http://localhost:3000/sse and :3001/sse

RBAC

Role MCP Trino execute_query MCP Trino ai_* MCP OpenMetadata all tools
akko-admin yes (rows capped) yes yes
akko-engineer yes yes yes
akko-analyst yes (OPA masks PII) yes yes
akko-user yes (OPA masks PII) yes (subset) yes
akko-viewer yes (row filters apply) no yes

Token forwarding only works if the agent is behind Traefik with OIDC. When using a raw kubectl port-forward, the MCP server falls back to its service identity (mcp-trino in group.txt), which is mapped to a restricted analyst profile.

Observability

  • Tempo — every tool call is a span: service name akko-mcp-trino or akko-mcp-openmetadata, attributes include tool.name, trino.sql.hash, user.id.
  • Loki — structured JSON lines with app=akko-mcp-trino, fields tool, user, latency_ms, status.
  • Prometheus — counters and histograms:
akko_mcp_tool_calls_total{server, tool, status}
akko_mcp_tool_duration_seconds{server, tool}
akko_mcp_trino_rows_returned{user}

A Grafana dashboard AKKO / MCP Servers ships with p95 latency, top tools, error rate and per-user activity.

Troubleshooting

Symptom Likely cause Fix
Claude Desktop shows "tool not available" Agent cached an old schema Restart Claude Desktop fully
403 on every call OIDC cookie expired Re-login to Traefik via the redirect; or rotate the service token for headless agents
execute_query returns 0 rows on a table that exists OPA row filter applies for the role Run the same query as akko-admin in Trino CLI; check OPA logs
Lineage empty for a known FQN OpenMetadata not yet ingested Trigger openmetadata_ingest_dag in Airflow
SSE connection drops every 30 s Traefik timeout too low Set spec.defaultTimeout=3600s on the IngressRoute