14 KiB
Environment variables
Everything an operator can set for the MCP stack, in three parts:
- The stack’s
.env- what you write in.envnext tomcp-stack.compose.yml. Split into required and optional. - What the compose file
sets itself - do not put these in
.env. - Per-server
variables - only for starting one image by hand with
docker run, 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 |
Keep them. The images run as 10001:10001, and the dev-server’s two
volumes take their owner from the image, so another value leaves the
worker unable to write to them. Give
MCP_WORKSPACE_HOST_PATH to 10001:10001
instead. This file is read literally, no shell runs over it. |
Optional
Images
| Variable | Default | Meaning |
|---|---|---|
MCP_IMAGE_TAG |
the hash named in mcp-stack.compose.yml |
Which build of the five luciolelii/* images to run: a
commit hash of the mcps repository, or latest.
Bumping it is a deploy. |
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_INTERNAL_BUCKET_EXPIRE_DAYS |
7 |
Lifecycle rule set on an execution’s bucket when this server creates
it: objects are deleted that many days after they were written.
0 sets none. The empty bucket stays. Needs permission to
set a bucket lifecycle; if refused, the session still opens and a
warning is logged. |
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).
PostgreSQL MCP
| Variable | Default | Meaning |
|---|---|---|
POSTGRES_MCP_API_KEYS |
none, required | Bearer tokens, as for the other servers; at least 32 characters each. |
POSTGRES_MCP_INTERNAL_DATABASE_PREFIX |
exec_ |
Every internal-mode database, and its user, is
<prefix><execution id> with the id’s dashes as
underscores. Cannot be empty; at most 26 lowercase letters, digits or
_, starting with a letter. It is the boundary that keeps
the API key inside databases this server made. |
POSTGRES_MCP_ALLOWED_HOSTS |
empty | Comma-separated host names this server may connect to. The external mode is off while it is empty: the model could otherwise aim the server at any address it reaches. For the internal mode it is optional; when set, the platform’s PostgreSQL host has to be on it. |
POSTGRES_MCP_MAX_ROWS |
1000 |
Most rows one query returns, whatever the model asks. Ceiling 10000. |
POSTGRES_MCP_MAX_RESULT_BYTES |
1048576 (1 MiB) |
Most bytes of rows one statement returns; the rest is cut and the answer says so. Ceiling 16 MiB. |
POSTGRES_MCP_STATEMENT_TIMEOUT_MS |
30000 |
A statement running longer is stopped by the server. Ceiling 10 minutes. |
POSTGRES_MCP_MAX_CONNECTIONS_PER_SESSION |
4 |
External mode only. Ceiling 32. |
The internal PostgreSQL’s host and credentials are
not variables here: they are headers of the
postgres-mcp-internal entry in the workflow manager’s
catalog (x-postgres-host, x-postgres-port,
x-postgres-database, x-postgres-user,
x-postgres-password, x-postgres-sslmode, and
x-postgres-role-secret). The user has to be able to make
databases and users - CREATEDB and CREATEROLE,
and nothing more - and the secret, at least 32 characters, is what the
password of each execution’s own user is derived from. It has to
be the same as the executionRoleSecret of the workflow
manager’s own storages.json entry for that
PostgreSQL, and so does the prefix, or the storage nodes and
the models would not see the same database. The databases are dropped
when they are older than the entry’s
executionDatabaseExpireDays by the workflow manager, not by
this server.
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 an image by hand)
Only for docker run of one image, 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_INTERNAL_BUCKET_EXPIRE_DAYS |
7 |
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 |
PostgreSQL MCP
| Variable | Default | |
|---|---|---|
POSTGRES_MCP_API_KEYS |
none, required | |
POSTGRES_MCP_INTERNAL_DATABASE_PREFIX |
exec_ |
See above. |
POSTGRES_MCP_ALLOWED_HOSTS |
empty | See above: empty turns the external mode off. |
POSTGRES_MCP_MAX_ROWS |
1000 |
Ceiling 10000. |
POSTGRES_MCP_MAX_RESULT_BYTES |
1048576 |
Ceiling 16 MiB. |
POSTGRES_MCP_STATEMENT_TIMEOUT_MS |
30000 |
|
POSTGRES_MCP_MAX_CONNECTIONS_PER_SESSION |
4 |
Ceiling 32. |
POSTGRES_MCP_MAX_SESSIONS |
16 |
|
POSTGRES_MCP_SESSION_TTL_SECONDS |
1800 |
|
POSTGRES_MCP_REQUEST_MAX_BYTES |
1048576 |
HTTP body limit. |
POSTGRES_MCP_HOST / _PORT |
0.0.0.0 / 3000 |
|
POSTGRES_MCP_CORS_ORIGINS |
empty |