Files
2026-07-14 21:01:46 +00:00

3.9 KiB

MCP servers

The image ships three MCP 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 (official, latest release binary)
n8n n8n n8n node documentation, plus workflow creation/management when the API env vars are set czlonkowski/n8n-mcp (npm)
InvokeAI invokeai Text-to-image, img2img, and upscaling against your InvokeAI instance 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 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:

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:

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". Note that a server whose env vars are unset still connects — the servers only read them when a tool is actually called — so a green /mcp status doesn't prove the configuration is right. Tool calls failing (or Gitea answering about gitea.com instead of your instance, its built-in default) is the symptom of missing/wrong env vars.