# MCP servers The image ships three [MCP](https://modelcontextprotocol.io/) servers for Claude Code, all speaking stdio: | Server | Name in `/mcp` | What it gives Claude | Source | | --- | --- | --- | --- | | Gitea | `gitea` | Repos, issues, PRs, releases on your Gitea instance | [gitea/gitea-mcp](https://gitea.com/gitea/gitea-mcp) (official, latest release binary) | | n8n | `n8n` | n8n node documentation, plus workflow creation/management when the API env vars are set | [czlonkowski/n8n-mcp](https://github.com/czlonkowski/n8n-mcp) (npm) | | InvokeAI | `invokeai` | Text-to-image, img2img, and upscaling against your InvokeAI instance | [coinstax/invokeai-mcp-server](https://github.com/coinstax/invokeai-mcp-server) (PyPI) | ## How install and registration are split The Dockerfile only *installs* the servers (`/usr/local/bin/n8n-mcp`, `/usr/local/bin/gitea-mcp`, and a `uv` tool venv for InvokeAI). *Registration* happens in `files/entrypoint.sh` on every container start, via `claude mcp add --scope user`. It has to work that way: user-scope MCP config lives in `~/.claude.json`, which [`claudaris start`](claudaris.md#start) bind-mounts from the host — so anything registered at build time would be shadowed by the mounted file. The runtime registration writes into the mounted file instead, which also means it persists across rebuilds like the login does. Registration is guarded per server: a server that's already present is left alone, so hand edits to its config survive restarts. The flip side is that a server deleted with `claude mcp remove` comes back on the next container start — to change one permanently, edit its entry rather than removing it. ## Pointing the servers at your instances The servers read their URLs and tokens from the environment Claude Code runs in (Claude Code passes its environment through to stdio MCP servers). Set them in your host-persisted aliases file, `$DATA_DIR/home/bash_aliases`, where a commented template already exists at the bottom: ```bash export GITEA_HOST='https://gitea.example.com' export GITEA_ACCESS_TOKEN='...' export N8N_API_URL='https://n8n.example.com' # optional: enables workflow management tools export N8N_API_KEY='...' export INVOKEAI_BASE_URL='http://invokeai.example.com:9090' ``` Then start a new shell (or `source ~/.bashrc`) and launch `claude`. Because the file lives on the host, tokens never end up in the image or the repo. If your `bash_aliases` was seeded before the MCP servers existed, copy the template block from `files/bash_aliases`. Notes: - **URLs must be reachable from inside the container.** `127.0.0.1` means the container itself, not the host. Use the host's LAN address or service hostname. - **Gitea:** create the token in Gitea under *Settings → Applications → Generate New Token*. - **n8n:** without `N8N_API_URL`/`N8N_API_KEY` the server still works as a node-documentation reference; the API pair unlocks creating and managing workflows. Create the key in n8n under *Settings → n8n API*. - **InvokeAI:** defaults to `http://127.0.0.1:9090` if unset. Upstream hardcodes that URL; the Dockerfile patches the package so `INVOKEAI_BASE_URL` is honored (and the build fails loudly if a future upstream release breaks the patch). Registration uses `python -m invokeai_mcp_server` because the package's console script is broken upstream. ## Checking it works Inside the container: ```bash claude mcp list # all three should show as configured ``` Or in a Claude Code session, run `/mcp` to see connection status, and try something like *"list my Gitea repos"*. A server whose env vars are unset will show as failed/erroring until you set them — the other servers are unaffected.