Files
docs/services/mcp-gateway.md
T
fkrebs 0600032b75 docs: migrate MCP gateway docs from mcp-gateway to Bifrost
- mcp-gateway.md: full rewrite for Bifrost at ai.nuclide.systems/mcp;
  29 clients / ~760 tools; VK auth; n8n+shepard blocked on
  streamable-HTTP; legacy gateway decommission checklist added
- connection-hosts.md: Bifrost at port 14003 is now ai.nuclide.systems;
  LiteLLM demoted to internal-only; mcp.nuclide.systems marked pending
  decommission; OIDC client 78c78998 flagged for removal

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 12:55:33 +02:00

155 lines
6.0 KiB
Markdown

# MCP Gateway — Bifrost (migrated 2026-05-26)
MCP servers are now aggregated by **Bifrost** at `https://ai.nuclide.systems/mcp`.
The legacy FastAPI DinD mcp-gateway (`mcp.nuclide.systems`) is pending decommission.
## Architecture
- **Stack**: `ai/bifrost/` on CT 104 — Bifrost LLM+MCP gateway, SQLite state at `data/config.db`.
- **Endpoint**: `https://ai.nuclide.systems/mcp` (Zoraxy → `192.168.1.40:14003`)
- **Auth**: Virtual Key (`sk-bf-` prefix) via `Authorization: Bearer <vk>`.
- **Client model**: Each upstream MCP server is a registered client in Bifrost (`auth_type=none`, `allow_on_all_virtual_keys=true`). Tools are auto-discovered and enabled via `tools_to_execute_json`.
- **Internal upstreams**: All child MCP containers run on the `ai-internal` Docker network at `http://<name>-mcp:8000/mcp` (streamable-HTTP) or as dedicated stacks.
## Virtual keys
| Name | Key prefix | Use |
|---|---|---|
| `claude-code` | `sk-bf-bfc19117-4c46-4d48-9b10-85d78b1ae2b3` | Claude Code + Claude.ai |
| `mcp-dev` | `sk-bf-279d3ecc-9031-41ff-a582-ecf3dca61d52` | Testing / dev |
## Server inventory (as of 2026-05-26)
**29 connected clients, ~760 tools total.**
| Client name | Upstream | Notes |
|---|---|---|
| `bluesky` | `http://ariel-mcp:8000/mcp` | |
| `coder` | `http://coder-mcp:8000/mcp` | |
| `comfyui` | `http://comfyui-mcp:8000/mcp` | Intel Arc image gen |
| `context7` | `http://mcp-context7:8000/mcp` | |
| `crawl4ai` | `http://mcp-crawl4ai:11235/mcp/sse` (SSE) | |
| `docling` | `http://docling-mcp:8000/mcp` | PDF→Markdown |
| `fetch` | `http://mcp-fetch:8000/mcp` | |
| `git` | `http://mcp-git:8000/mcp` | |
| `gitea` | `http://gitea-mcp:8000/mcp` | |
| `gitlab` | `http://mcp-gitlab:8000/mcp` | `GITLAB_API_URL=https://gitlab.dlr.de/api/v4` |
| `gotify` | `http://mcp-gotify:8000/mcp` | |
| `home_assistant` | `http://192.168.1.60:9583/private_ehnWeRl2G3De6NnbcN7teQ` | HA add-on; no TLS |
| `immich` | `http://mcp-immich:8000/mcp` | |
| `kroki` | `http://kroki-mcp:8000/mcp` | Diagram rendering |
| `markitdown` | `http://mcp-markitdown:8000/mcp` | |
| `memos` | `http://mcp-memos:8000/mcp` | |
| `nextcloud` | `http://mcp-nextcloud:8000/mcp` | |
| `ntfy` | `http://mcp-ntfy:8000/mcp` | |
| `obsidian` | `http://mcp-obsidian:8000/mcp` | Vault at Nextcloud/UNAS |
| `paper_search` | `http://mcp-paper-search:8000/mcp` | |
| `paperless` | `http://paperless-mcp:8000/mcp` | |
| `proxmox` | `http://mcp-proxmox:8000/mcp` | Read-only (`PVEAuditor`) |
| `searxng` | `http://mcp-searxng:8000/mcp` | |
| `sequential_thinking` | `http://mcp-sequential-thinking:8000/mcp` | |
| `time` | `http://mcp-time:8000/mcp` | |
| `unifi` | `http://mcp-unifi:8000/mcp` | |
| `upload_artifact` | `http://upload-artifact-mcp:8000/mcp` | S3 via Garage |
| `wikipedia` | `http://mcp-wikipedia-mcp:8000/mcp` | |
| `youtube_transcript` | `http://mcp-youtube-transcript:8000/mcp` | |
### Not yet connected
| Client | Reason |
|---|---|
| `n8n``https://n8n.nuclide.systems/mcp-server/http` | Streamable-HTTP transport: POST returns SSE stream, Bifrost HTTP client times out. |
| `shepard``https://shepard.nuclide.systems/v2/mcp` | Same streamable-HTTP issue. Bearer token stored in `/tmp/migrate_mcp_oauth.py`. |
## Client configuration
### Claude Code
Add to `~/.claude.json` or project `.mcp.json`:
```json
{
"mcpServers": {
"nuclide": {
"type": "http",
"url": "https://ai.nuclide.systems/mcp",
"headers": {
"Authorization": "Bearer sk-bf-bfc19117-4c46-4d48-9b10-85d78b1ae2b3"
}
}
}
}
```
### Claude.ai
Settings → Integrations → Add MCP server:
- URL: `https://ai.nuclide.systems/mcp`
- Header: `Authorization: Bearer sk-bf-279d3ecc-9031-41ff-a582-ecf3dca61d52`
## Ops
```bash
# On CT 104
cd /opt/stacks/ai/bifrost
docker compose up -d --force-recreate
docker logs bifrost -f
# Inspect config DB
sqlite3 data/config.db '.tables'
sqlite3 data/config.db 'SELECT name, auth_type, allow_on_all_virtual_keys FROM config_mcp_clients;'
# Count active tools via API
curl -s http://localhost:14003/mcp \
-H "Authorization: Bearer sk-bf-279d3ecc-9031-41ff-a582-ecf3dca61d52" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | python3 -m json.tool | grep '"name"' | wc -l
```
### Add a new MCP client
```bash
curl -s -X POST http://localhost:14003/api/mcp/client \
-H "Authorization: Bearer sk-tapirnase" \
-H "Content-Type: application/json" \
-d '{
"name": "<name>",
"connection_type": "http",
"connection_string": "http://<host>:8000/mcp",
"auth_type": "none",
"allow_on_all_virtual_keys": true
}'
```
Wait ~10 s for tool discovery, then enable tools via `PUT /api/mcp/client/<id>` with `tools_to_execute`.
See `/tmp/add_all_mcp_clients.py` on CT 104 for a complete example.
### Key requirements for tools to appear in `/mcp tools/list`
1. `auth_type=none` (not `per_user_oauth`)
2. `allow_on_all_virtual_keys=true`
3. `tools_to_execute_json` populated (tool names without client prefix)
4. VK must have `sk-bf-` prefix
## Legacy mcp-gateway (FastAPI / DinD)
**Status: pending decommission.** Container `mcp-gateway` still running at `192.168.1.40:8080` / `https://mcp.nuclide.systems`. Stack: `ai/mcp-gateway/`.
Before removing:
1. Confirm Zoraxy route `mcp.nuclide.systems` is no longer referenced anywhere (explicit user confirmation required before touching Zoraxy CT 108).
2. Stop container: rename compose file to `docker-compose.yml.disabled`, update `/opt/stacks/CLAUDE.md`.
3. Remove Pocket-ID client `e73bb7b9` (mcp-gateway) and `78c78998` (Claude MCP callback to mcp.nuclide.systems) after confirming no active tokens.
4. Remove Zoraxy route `mcp.nuclide.systems``192.168.1.40:8080`.
## Bifrost OIDC client (Pocket ID)
Used for `per_user_oauth` flows (not currently active — all clients use `auth_type=none`):
| Field | Value |
|---|---|
| Client ID | `ec0d15e6-e86d-49b0-ac12-cdfb5afc9086` |
| Authorize URL | `https://id.nuclide.systems/authorize` |
| Token URL | `https://id.nuclide.systems/api/oidc/token` |
| `mcp_external_client_url` | `https://ai.nuclide.systems` |