Configuration: env vars, YAML files, secrets
ToolMesh is configured entirely via environment variables and YAML files.
Environment Variables
Section titled “Environment Variables”MCP Server
Section titled “MCP Server”| Variable | Default | Description |
|---|---|---|
TOOLMESH_PORT | 8123 | Host port (Docker mapping; internally always 8080) |
TOOLMESH_TRANSPORT | http | Transport: http or stdio |
TOOLMESH_CORS_ORIGINS | (empty) | Allowed CORS origins |
TOOLMESH_AUTH_PASSWORD | (empty) | Single-user OAuth password |
TOOLMESH_API_KEY | (empty) | Static API key |
| Variable | Default | Description |
|---|---|---|
AUDIT_STORE | log | log (slog) or sqlite |
AUDIT_RETENTION_DAYS | 90 | Retention for SQLite store |
Authorization
Section titled “Authorization”| Variable | Default | Description |
|---|---|---|
OPENFGA_API_URL | http://localhost:8080 | OpenFGA API endpoint. In Docker Compose use http://openfga:8080 (set in .env). |
OPENFGA_STORE_ID | (empty) | OpenFGA store ID (set by ./config/openfga/setup.sh) |
OPENFGA_MODE | bypass | bypass (no authz, dev only) or restrict (enforced, recommended for production) |
Timeouts
Section titled “Timeouts”| Variable | Default | Description |
|---|---|---|
TOOLMESH_MCP_TIMEOUT | 120 | HTTP client timeout for MCP backends (seconds) |
TOOLMESH_EXEC_TIMEOUT | 120 | Tool execution timeout (seconds) |
Logging
Section titled “Logging”| Variable | Default | Description |
|---|---|---|
LOG_LEVEL | debug / info | Log verbosity |
LOG_FORMAT | json | json or text |
DEBUG_BACKENDS | (empty) | Comma-separated backend names for debug logging |
DEBUG_FILE | (empty) | Path to debug log file |
Security warning: Debug logging may capture full request/response payloads including sensitive data. Never enable
DEBUG_BACKENDSorDEBUG_FILEin production environments.
Telemetry
Section titled “Telemetry”ToolMesh reports anonymous, aggregated usage statistics to https://tmc.dunkel.cloud/v1/telemetry once every 24 hours.
| Variable | Default | Description |
|---|---|---|
DO_NOT_SEND_ANONYMOUS_STATISTICS | (empty) | Set to yes to stop sending. Counters keep accumulating locally. |
TELEMETRY_INTERVAL | 24h | Send interval as a Go duration (1h, 30m) — intended for testing |
Each entry in a report carries exactly five fields:
dadl_hash— content hash of the DADL file the calls went throughcall_count/error_count— successful and failed calls since the last reportversion— the ToolMesh versionmcp_server_count— number of configured MCP server backends
Tool arguments, responses, credentials, backend URLs, hostnames and user identifiers are never collected, and there is no persistent install ID. The DADL hash identifies the connector definition rather than the deployment — everyone running the same DADL reports the same value. As with any HTTP request, the receiving endpoint does see the sender’s IP address.
To opt out:
DO_NOT_SEND_ANONYMOUS_STATISTICS=yesCredentials
Section titled “Credentials”Credentials are set as env vars with CREDENTIAL_ prefix:
CREDENTIAL_GITHUB_TOKEN=ghp_xxxxxCREDENTIAL_STRIPE_KEY=sk_live_xxxxxCREDENTIAL_MEMORIZER_API_KEY=sk-mem-xxxxxConfiguration Files
Section titled “Configuration Files”backends.yaml
Section titled “backends.yaml”Defines which backends ToolMesh connects to:
backends: # MCP backend - name: memorizer transport: http url: "https://memorizer.example.com/mcp" api_key_env: "MEMORIZER_API_KEY"
# REST backend via DADL - name: github transport: rest dadl: /app/dadl/github.dadl url: "https://api.github.com"Tools are automatically exposed with a backend prefix (e.g., memorizer_retrieve_knowledge, github_list_repos).
users.yaml
Section titled “users.yaml”Multi-user configuration for OAuth:
users: - username: alice password: "$2a$12$..." company: acme plan: pro roles: [admin]apikeys.yaml
Section titled “apikeys.yaml”API key definitions:
keys: - key_hash: "$2a$12$..." username: ci-bot company: acme plan: standard roles: [read] caller_id: github-actionscaller-classes.yaml
Section titled “caller-classes.yaml”Maps caller IDs to trust classes:
classes: trusted: - claude-code - claude-desktop standard: - partner-* # Everything else → "untrusted"