Files
claudaris/docs/mcp.md
T
2026-07-14 20:47:29 +00:00

79 lines
3.6 KiB
Markdown

# 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.