Overview

Headless gateway and Docker

docker pull ghcr.io/btsouth/toolport-gateway:latest
mkdir -p data
cp data/registry.json.example data/registry.json
cp docker-compose.example.yml docker-compose.yml
# create .env with at least TOOLPORT_HTTP_TOKEN=...
docker compose up -d

Image defaults: TOOLPORT_HTTP_HOST=0.0.0.0, TOOLPORT_REGISTRY=/data/registry.json, port 8765, volume /data. The image runs as user toolport (uid 10001).

export TOOLPORT_HTTP_HOST=0.0.0.0
export TOOLPORT_HTTP_TOKEN="$(openssl rand -hex 24)"
export TOOLPORT_REGISTRY=/path/to/registry.json
toolport-gateway --http 8765

From source, compiling inside Docker:

docker build -f Dockerfile.source -t toolport-gateway .

Or build the binary on the host, then the runtime image:

cargo build --release --bin toolport-gateway --manifest-path src-tauri/Cargo.toml --no-default-features
cp src-tauri/target/release/toolport-gateway toolport-gateway-bin
docker build -t toolport-gateway .

Point an MCP client at http://host:8765/mcp, or Open WebUI at http://host:8765 with the token as its API key.

Secrets without a keychain#

Put secrets in .env with the TOOLPORT_SECRET_ prefix:

TOOLPORT_HTTP_TOKEN=replace-me
TOOLPORT_SECRET_STRIPE_SECRET_KEY=sk_live_...

Or set TOOLPORT_SECRET_KEY and use the encrypted secrets.enc vault. The full order is in Configuration.

Stdio servers need their runtimes (node/npx, uv) in the image. Remote MCP servers need nothing extra.

Production checklist#

Network and auth
  • Bearer token with at least 24 bytes of entropy, or scoped httpClients[].
  • Firewall the port; do not publish :8765 to the internet without a reverse proxy.
  • Terminate TLS in front: the gateway speaks plain HTTP.
  • The gateway allows 10 seconds for headers and 30 for the body, then returns 408. Keep proxy deadlines at least as strict.
Secrets and registry
  • Use TOOLPORT_SECRET_KEY with secrets.enc, or TOOLPORT_SECRET_<KEY> env vars.
  • Keep .env at mode 600 and never commit it.
  • Persist /data/registry.json on a volume and back it up before upgrades. A corrupt file is quarantined, not wiped.
  • Set humanApproval: false: without the desktop approval broker, gated tools fail closed.
Runtime
  • Browser OAuth needs the desktop app. Use API keys or pre-vaulted secrets.
  • The first npx/uvx connect can take up to about 2 minutes while the package downloads.
  • Pin the image by digest or version tag in production.

Updated

Was this page helpful?