MCP — Claude Desktop / ChatGPT integration
Wire Atrium's tool catalog into any MCP-aware AI host. Same tools as the in-app /admin/ai agent, role-tier-filtered per caller, hosted-confirmation contract for mutations, full audit.
Atrium speaks the Model Context Protocol so any MCP-aware host (Claude Desktop, ChatGPT Connectors, Cursor, custom agents) can list and call Atrium tools directly. The endpoint reuses the agent's tool catalog, filtered per caller's role.
Endpoint: POST https://atrium.ommax-intelligence.de/api/mcp — JSON-RPC 2.0 over HTTP.
Auth: Authorization: Bearer atr_live_<token> (same Atrium API key as everywhere else).
Quick start — /admin/mcp
The in-app tutorial page does the boring parts for you:
- Sign in to Atrium → your avatar menu (top right) → MCP setup. Admins also have it as a tab in the admin nav; both land on
/admin/mcp, which every signed-in user may open. The/adminprefix is a naming quirk, same as/admin/api-keys. - Mint key for MCP — one click. Token is shown ONCE and is auto-pasted into the Claude Desktop config block + ChatGPT header snippet below it. The key inherits your current Atrium role at every call.
- Copy the Claude Desktop config (or the ChatGPT instructions) and follow the per-host setup below.
- The page also lists, in real time, the exact tool surface your host will see — driven by the same
tools/listcall the host will make.
Why we built this
The choice we explicitly made: don't replace the in-app agent, share its catalog. A typed-tool layer (with confirm-flow, audit log, RBAC, structured I/O) is the security architecture; MCP is "the same surface, addressable from elsewhere". An MCP server without typed tools would lose the confirm gate, granular audit, and LLM ergonomics — those properties are what we wanted to preserve.
The hand-rolled implementation is ~250 LOC (no SDK). MCP's HTTP transport is plain JSON-RPC 2.0 with three meaningful methods (initialize, tools/list, tools/call); a 200kb SDK would have added more weight than value.
Role-tiered catalog
Each tool declares a minRole. The MCP server filters tools/list per caller. RBAC is re-checked at tools/call time so a name discovered out-of-band can't bypass the catalog.
| Caller's role | Sees | Practical use |
|---|---|---|
user (default) | list_apps, get_app, list_my_groups, request_app_access | Self-service: "what apps exist", "which groups am I in", "request access to X" |
admin | All of the above + group/app curation, search_users, action / secret listings, runtime health, Zitadel URL discovery | Day-to-day directory management |
super_admin | Everything — incl. set_app_public, mint_api_key, Zitadel target / signing-key tools | Sensitive infra |
See AI agent for the full catalog.
Mutations are open — host confirms
Unlike the first MCP cut (read-only), the current endpoint does allow mutate tools. Justification: every MCP-aware client (Claude Desktop, ChatGPT) renders a per-tool-call approval prompt before execution, so the host IS the confirm UX. We additionally write AtriumAiAuditLog rows tagged conversationId = "mcp:<apiKeyId>" so MCP-driven calls show up alongside in-app activity.
If you don't trust your host's confirm UX, use a user-tier API key — only request_app_access is mutating at that tier, and it goes to a PENDING queue an admin reviews on /admin/access-requests anyway.
Wire into Claude Desktop
Claude Desktop loads MCP servers from ~/Library/Application Support/Claude/claude_desktop_config.json on macOS (or %APPDATA%\Claude\claude_desktop_config.json on Windows). Merge this in, swap the placeholder for your token, then quit + relaunch Claude Desktop:
{
"mcpServers": {
"atrium": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://atrium.ommax-intelligence.de/api/mcp",
"--header",
"Authorization:Bearer atr_live_YOUR_KEY_HERE"
]
}
}
}
mcp-remote is a small shim — Claude Desktop's built-in transport is stdio, the shim bridges to a remote HTTP endpoint and injects the auth header. No manual install (npx fetches it).
Wire into ChatGPT
ChatGPT Connectors (Plus / Team / Enterprise required):
- Settings → Connectors → Add MCP server.
- URL:
https://atrium.ommax-intelligence.de/api/mcp. - Authentication: Custom header, value:
Authorization: Bearer atr_live_YOUR_KEY_HERE. - Save. ChatGPT probes
tools/listand surfaces Atrium tools when you @-mention the connector.
Audit + observability
- Per-call audit:
AtriumAiAuditLogrow on everytools/call, withconversationId = "mcp:<apiKeyId>". Same kind of row the in-app agent writes — filterable by source. - Per-key usage: the existing
AtriumApiKeyUseaudit applies./admin/api-keysshows last-used timestamps + per-key call paths. - Role drift: if you remove someone's
atrium:adminrole in Zitadel, their MCP key catalogs down to user-tier on next call automatically (the role check is evaluated against the liverolesSnapshot, not the key creation snapshot).
Limitations / honest caveats
- No SSE push. The endpoint is request/response only. We don't emit
notifications/tools/list_changedwhen the catalog evolves; hosts re-probe on connect, which is enough for the catalog churn we actually have (occasional new tools, never within a session). - Plunk credit cost when
ATRIUM_EMAIL_BCCis set. If a tool fires an email trigger (e.g. agent grants someone a role → ROLE_GRANTED notification), the BCC mechanism doubles the Plunk send count. Intended for the test phase only. - An unscoped API key inherits its creator's roles via
rolesSnapshotonAtriumUser, with a legacy super-admin fallback when that snapshot is empty (users who haven't signed in since the column was added). Scoped keys have landed and are a different model: they carry no roles at all, and/api/mcprejects them outright, because a catalog tiered by "no roles" would be meaningless. The legacy fallback is slated for removal, not something to build on. See API keys. tools/list_changednotification isn't emitted; if you add a new tool, restart Claude Desktop to pick it up.- Read-only-mode flag isn't exposed — the catalog is what determines mutate availability. If you want a hard read-only key for an integration, mint it from a regular-
useraccount; the user-tier catalog has no destructive tools (onlyrequest_app_access, which routes through admin approval).