Document every environment variable of the MCP stack
One place for what an operator can set, split the way an operator needs it: the stack's .env as required, required-in-practice and optional; what the compose file fixes itself and .env cannot override; and the per-server variables for starting a server by hand, which the stack does not forward. "Required" here means the service refuses to start or the stack is unusable without it - Compose itself only substitutes an empty string and warns. That was checked against each server's startup code, not assumed: the API keys, the worker token, the dev-server command allowlist and the browser's allowed origins all fail at start when empty. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
aa3f51b4ed
commit
921d54cb06
|
|
@ -0,0 +1,191 @@
|
|||
# Environment variables
|
||||
|
||||
Everything an operator can set for the MCP stack, in three parts:
|
||||
|
||||
1. [The stack's `.env`](#1-the-stacks-env) - what you write in `.env` next to `mcp-stack.compose.yml`.
|
||||
Split into **required** and **optional**.
|
||||
2. [What the compose file sets itself](#2-what-the-compose-file-sets-itself) - do not put these in `.env`.
|
||||
3. [Per-server variables](#3-per-server-variables-running-a-server-by-hand) - only for starting one
|
||||
server outside Compose.
|
||||
|
||||
`mcp-stack.env.example` is the template: `cp mcp-stack.env.example .env`. `.env` is ignored by git
|
||||
and holds secrets, so it stays on the machine that runs the stack.
|
||||
|
||||
> Compose substitutes an unset variable with an empty string and only warns. A "required" variable
|
||||
> below is one whose absence makes the service refuse to start or the stack unusable - not one
|
||||
> Compose itself rejects.
|
||||
|
||||
## 1. The stack's `.env`
|
||||
|
||||
### Required
|
||||
|
||||
| Variable | What it is | Notes |
|
||||
|---|---|---|
|
||||
| `CODING_AGENT_MCP_API_KEYS` | Bearer tokens that may call the coding-agent MCP. Comma-separated, optionally `subject=token`. | Each token at least 32 characters. The server refuses to start with none. This is the `key` in the node's catalog entry. |
|
||||
| `DEV_SERVER_MCP_API_KEYS` | Same, for the dev-server MCP. | Use a different token from the other servers. |
|
||||
| `BROWSER_MCP_API_KEYS` | Same, for the browser MCP. | |
|
||||
| `MINIO_MCP_API_KEYS` | Same, for the MinIO MCP. | |
|
||||
| `DEV_SERVER_WORKER_TOKEN` | Shared secret between `dev-server-mcp` and `dev-server-worker`. | At least 32 characters; both refuse to start otherwise. Never leaves the stack, so it is not a catalog value. |
|
||||
| `MCP_WORKSPACE_HOST_PATH` | Absolute path of the host directory mounted as `/workspace`. | Bind-mount source, so empty fails. A dedicated project directory - never a home directory or `/`. |
|
||||
|
||||
Generate a token with `openssl rand -hex 32`.
|
||||
|
||||
### Required in practice
|
||||
|
||||
| Variable | Default | Why |
|
||||
|---|---|---|
|
||||
| `MCP_UID`, `MCP_GID` | `10001` / `10001` | Must be the numeric owner of `MCP_WORKSPACE_HOST_PATH`, or the containers cannot write to it. Write what `id -u` and `id -g` print: this file is read literally, no shell runs over it. |
|
||||
|
||||
### Optional
|
||||
|
||||
**MinIO MCP**
|
||||
|
||||
| Variable | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `MINIO_MCP_INTERNAL_BUCKET_PREFIX` | `exec-` | Every internal-mode bucket is `<prefix><execution id>`. Cannot be empty; at most 27 lowercase letters, digits or `-`. It is the boundary that keeps the API key inside buckets this server made. |
|
||||
| `MINIO_MCP_ALLOWED_ENDPOINTS` | empty (any) | Comma-separated S3 origins, e.g. `https://s3.example.org`. **Set it on an exposed server.** It applies to both modes, so the internal MinIO's endpoint must be on it. |
|
||||
| `MINIO_MCP_DEFAULT_REGION` | `us-east-1` | Region when a session names none. |
|
||||
| `MINIO_MCP_MAX_OBJECT_BYTES` | `1048576` (1 MiB) | Limit for one read and one write. Ceiling 32 MiB. |
|
||||
| `MINIO_MCP_MAX_CONNECTIONS_PER_SESSION` | `8` | External mode only. Ceiling 64. |
|
||||
|
||||
The internal MinIO's endpoint and keys are **not** variables here: they are headers of the
|
||||
`minio-mcp-internal` entry in the workflow manager's catalog (`x-minio-endpoint`,
|
||||
`x-minio-access-key`, `x-minio-secret-key`, optionally `x-minio-region`).
|
||||
|
||||
**Dev server**
|
||||
|
||||
| Variable | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `DEV_SERVER_SERVICES_CONFIG` | `./dev-server-mcp/services.example.json` | The services a caller may start. Copy `services.example.json` and edit the copy. Mounted read-only. |
|
||||
| `DEV_SERVER_ALLOWED_COMMANDS` | `node,npm,python3,./mvnw` | What a service may run. `npx` is left out on purpose: it runs an arbitrary package by name. |
|
||||
| `DEV_SERVER_PORT_RANGE` | `5200-5219` | Ports given to per-execution instances. Keep aligned with `BROWSER_MCP_ALLOWED_ORIGINS`. |
|
||||
| `DEV_SERVER_MAX_INSTANCES` | `4` | Concurrent instances. Size by memory: two frontend builds saturate the worker's 2 GB. |
|
||||
| `DEV_SERVER_MAX_WORKSPACE_BYTES` | `536870912` (512 MiB) | Largest workspace copied for an instance. |
|
||||
| `DEV_SERVER_IDLE_TIMEOUT_SECONDS` | `7200` | Idle time after which an instance is stopped (its copy is kept). |
|
||||
| `DEV_SERVER_MAX_LIFETIME_SECONDS` | `86400` | Absolute lifetime; then everything, copy included, is discarded. |
|
||||
| `DEV_SERVER_PREVIEW_BASE_URL` | empty | Public address a person opens a preview at. Empty means no preview proxy and no preview links. |
|
||||
| `DEV_SERVER_PREVIEW_PORT` | `4500` | Port of the preview proxy inside the worker. |
|
||||
| `DEV_SERVER_EGRESS_PROXY` | `http://egress-proxy:3128` | The only route out the worker has, for installs. |
|
||||
| `DEV_SERVER_NO_PROXY` | `localhost,127.0.0.1,dev-server-worker` | Hosts that bypass that proxy. |
|
||||
|
||||
**Browser**
|
||||
|
||||
| Variable | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `BROWSER_MCP_ALLOWED_ORIGINS` | `http://dev-server-worker:5173,http://dev-server-worker:5200-5219` | Origins the browser may open, exact match. Keep the range aligned with `DEV_SERVER_PORT_RANGE`, or a preview looks like a broken app. |
|
||||
| `BROWSER_MCP_MAX_SESSIONS` | `8` | Concurrent browser sessions. |
|
||||
|
||||
**Published ports** (all on loopback, `127.0.0.1`)
|
||||
|
||||
| Variable | Default | |
|
||||
|---|---|---|
|
||||
| `MCP_GATEWAY_PORT` | `3100` | One port serving every server by path (`/coding-agent/`, `/dev-server/`, `/browser/`, `/minio/`). What the catalog expects. |
|
||||
| `CODING_AGENT_MCP_PORT` | `3101` | Per-server ports, kept for clients configured before the gateway. |
|
||||
| `DEV_SERVER_MCP_PORT` | `3102` | |
|
||||
| `BROWSER_MCP_PORT` | `3103` | |
|
||||
| `MINIO_MCP_PORT` | `3104` | |
|
||||
|
||||
**Dedicated VM** (with the overlay `mcp-stack.vm.compose.yml`)
|
||||
|
||||
| Variable | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `MCP_GATEWAY_CADDYFILE` | `./mcp-stack.Caddyfile` | Set to `./mcp-stack.vm.Caddyfile` on the VM: it serves HTTPS. |
|
||||
| `MCP_SITE_ADDRESS` | `:3100` | The public host name Caddy gets a certificate for, e.g. `mcp-stack.example.org`. Required with the VM Caddyfile. |
|
||||
| `MCP_TLS_CONTACT` | empty | Contact e-mail for the certificate authority. Set it on the VM. |
|
||||
| `MCP_BIND_ADDRESS` | `0.0.0.0` | Address ports 80 and 443 bind to. |
|
||||
|
||||
## 2. What the compose file sets itself
|
||||
|
||||
Fixed in `mcp-stack.compose.yml`. They are not read from `.env`, and overriding them there has no
|
||||
effect.
|
||||
|
||||
| Variable | Set on | Value |
|
||||
|---|---|---|
|
||||
| `CODING_AGENT_MCP_EXECUTION_BACKEND` | coding-agent-mcp | `disabled`, so no command-running tool is offered. |
|
||||
| `DEV_SERVER_WORKER_URL` | dev-server-mcp | `http://dev-server-worker:4000` |
|
||||
| `DEV_SERVER_CONFIG` | dev-server-worker | `/config/services.json` |
|
||||
| `DEV_SERVER_WORKSPACE_ROOT` | dev-server-worker | `/workspace` |
|
||||
| `DEV_SERVER_INSTANCES_ROOT`, `DEV_SERVER_INSTANCE_HOME`, `DEV_SERVER_NPM_CACHE` | dev-server-worker | volumes `/instances`, `/instances/.shared-home`, `/npm-cache` |
|
||||
|
||||
Container paths, user ids of the browser (`1000:1000`), memory and CPU limits are fixed in the file
|
||||
too.
|
||||
|
||||
## 3. Per-server variables (running a server by hand)
|
||||
|
||||
Only for `node src/index.js` and similar, outside Compose. The stack does not forward these, so they
|
||||
cannot be set through `.env`. Defaults shown are the ones in the code.
|
||||
|
||||
### coding-agent-mcp
|
||||
|
||||
| Variable | Default | |
|
||||
|---|---|---|
|
||||
| `CODING_AGENT_MCP_API_KEYS` | none, **required** over HTTP | Also read from `MCP_API_KEYS` when unset. |
|
||||
| `CODING_AGENT_MCP_ROOTS` | the working directory | Workspace root(s), when no `--root` flag is given. |
|
||||
| `CODING_AGENT_MCP_EXECUTION_BACKEND` | `local` on stdio, `disabled` on HTTP | Whether command execution is offered. |
|
||||
| `CODING_AGENT_MCP_CORS_ORIGINS` | empty | Comma-separated browser origins allowed. |
|
||||
| `CODING_AGENT_MCP_AUDIT_LOG` | none | Path of an audit log file. |
|
||||
| `MCP_DEBUG_REQUESTS` | off | `1`/`true`/`yes`/`on` logs requests. Leave it off in production. |
|
||||
|
||||
### dev-server-mcp
|
||||
|
||||
| Variable | Default | |
|
||||
|---|---|---|
|
||||
| `DEV_SERVER_MCP_API_KEYS` | none, **required** | |
|
||||
| `DEV_SERVER_WORKER_TOKEN` | none, **required** | At least 32 characters. |
|
||||
| `DEV_SERVER_WORKER_URL` | `http://dev-server-worker:4000` | |
|
||||
| `DEV_SERVER_MCP_HOST` / `_PORT` | `0.0.0.0` / `3000` | |
|
||||
| `DEV_SERVER_MCP_MAX_SESSIONS` | `64` | |
|
||||
| `DEV_SERVER_MCP_SESSION_TTL_SECONDS` | `1800` | |
|
||||
| `DEV_SERVER_MCP_CORS_ORIGINS` | empty | |
|
||||
|
||||
### dev-server-worker
|
||||
|
||||
| Variable | Default | |
|
||||
|---|---|---|
|
||||
| `DEV_SERVER_WORKER_TOKEN` | none, **required** | At least 32 characters. |
|
||||
| `DEV_SERVER_CONFIG` | `/config/services.json` | The services file. |
|
||||
| `DEV_SERVER_WORKSPACE_ROOT` | `/workspace` | |
|
||||
| `DEV_SERVER_ALLOWED_COMMANDS` | none, **required** | The worker refuses to start with it empty, and every service's `command` must be on it. |
|
||||
| `DEV_SERVER_INSTANCES_ROOT` | none | Where per-execution copies live. |
|
||||
| `DEV_SERVER_INSTANCE_HOME` | `/tmp/dev-server` | |
|
||||
| `DEV_SERVER_NPM_CACHE` | none | |
|
||||
| `DEV_SERVER_NPM_REGISTRY` | none | Registry override. |
|
||||
| `DEV_SERVER_PORT_RANGE` | `5200-5219` | Ports for instances: a rising range above 1023. |
|
||||
| `DEV_SERVER_MAX_INSTANCES` | `4` | |
|
||||
| `DEV_SERVER_MAX_WORKSPACE_BYTES` / `_ENTRIES` | 512 MiB / `20000` | |
|
||||
| `DEV_SERVER_IDLE_TIMEOUT_SECONDS` / `_MAX_LIFETIME_SECONDS` | `7200` / `86400` | |
|
||||
| `DEV_SERVER_EGRESS_PROXY` / `_NO_PROXY` | none | Proxy for installs. |
|
||||
| `DEV_SERVER_PREVIEW_BASE_URL` | none | |
|
||||
| `DEV_SERVER_PREVIEW_HOST` / `_PORT` | `0.0.0.0` / `4500` | |
|
||||
| `DEV_SERVER_CHILD_PATH` | `/opt/java/openjdk/bin:/usr/local/bin:/usr/bin:/bin` | `PATH` of started services. |
|
||||
| `JAVA_HOME` | none | Passed to started services. |
|
||||
| `DEV_SERVER_WORKER_HOST` / `_PORT` | `0.0.0.0` / `4000` | |
|
||||
| `DEV_SERVER_WORKER_REQUEST_TIMEOUT_MS` | `620000` | |
|
||||
|
||||
### browser-mcp
|
||||
|
||||
| Variable | Default | |
|
||||
|---|---|---|
|
||||
| `BROWSER_MCP_API_KEYS` | none, **required** | |
|
||||
| `BROWSER_MCP_ALLOWED_ORIGINS` | none, **required** | The server refuses to start with it empty. Exact origins, plus ranges such as `http://host:5200-5219`. |
|
||||
| `BROWSER_MCP_MAX_SESSIONS` | `16` | |
|
||||
| `BROWSER_MCP_DEFAULT_TIMEOUT_MS` | `15000` | |
|
||||
| `BROWSER_MCP_HOST` / `_PORT` | `0.0.0.0` / `3000` | |
|
||||
| `BROWSER_MCP_SESSION_TTL_SECONDS` | `1800` | |
|
||||
| `BROWSER_MCP_CORS_ORIGINS` | empty | |
|
||||
|
||||
### minio-mcp
|
||||
|
||||
| Variable | Default | |
|
||||
|---|---|---|
|
||||
| `MINIO_MCP_API_KEYS` | none, **required** | |
|
||||
| `MINIO_MCP_INTERNAL_BUCKET_PREFIX` | `exec-` | See above. |
|
||||
| `MINIO_MCP_ALLOWED_ENDPOINTS` | empty (any) | |
|
||||
| `MINIO_MCP_DEFAULT_REGION` | `us-east-1` | |
|
||||
| `MINIO_MCP_MAX_OBJECT_BYTES` | `1048576` | Ceiling 32 MiB. |
|
||||
| `MINIO_MCP_MAX_CONNECTIONS_PER_SESSION` | `8` | Ceiling 64. |
|
||||
| `MINIO_MCP_MAX_SESSIONS` | `32` | |
|
||||
| `MINIO_MCP_SESSION_TTL_SECONDS` | `1800` | |
|
||||
| `MINIO_MCP_REQUEST_MAX_BYTES` | derived from `MAX_OBJECT_BYTES` | HTTP body limit; base64 adds a third. |
|
||||
| `MINIO_MCP_HOST` / `_PORT` | `0.0.0.0` / `3000` | |
|
||||
| `MINIO_MCP_CORS_ORIGINS` | empty | |
|
||||
|
|
@ -12,7 +12,7 @@ The MCP client orchestrates them; servers do not share MCP sessions or credentia
|
|||
|
||||
## Start
|
||||
|
||||
1. Copy `mcp-stack.env.example` to `.env` and replace every token with an independent random value.
|
||||
1. Copy `mcp-stack.env.example` to `.env` and replace every token with an independent random value. Every variable, required or optional, is documented in [ENVIRONMENT.md](ENVIRONMENT.md).
|
||||
2. Set `MCP_WORKSPACE_HOST_PATH` to one dedicated project directory.
|
||||
3. Copy and edit `dev-server-mcp/services.example.json`. It ships four worked service definitions: a shared Vite tree, and per-execution ones for Node, Java (through the project's own `./mvnw`) and Python.
|
||||
Keep `BROWSER_MCP_ALLOWED_ORIGINS` aligned with `DEV_SERVER_PORT_RANGE`: the browser reaches a preview only on a port that range covers.
|
||||
|
|
|
|||
Loading…
Reference in New Issue