MetaMCP Environment Variables: Production Best Practices and Security Guide
Store secrets in Docker or Kubernetes secret stores, reference them using ${VAR} syntax in MCP server configurations, set NODE_ENV=production, and validate required variables at startup to secure MetaMCP production deployments.
MetaMCP, an open-source Docker-based service from the metatool-ai/metamcp repository, manages STDIO MCP servers as child processes. Properly configuring MetaMCP environment variables in production requires understanding how the container merges host environment variables with server-specific configurations while keeping sensitive credentials out of source control.
Understanding MetaMCP's Environment Variable Architecture
How MetaMCP Inherits Environment Variables
When MetaMCP spawns a STDIO MCP server, it constructs the child process environment by merging three sources. According to the source code in apps/backend/src/lib/stdio-transport/process-managed-transport.ts, the getDefaultEnvironment() function (lines 94-115) combines the container's current process environment with a safe-inheritance whitelist and any explicit env map defined in the server configuration.
The Default Safe-Inheritance List
The DEFAULT_INHERITED_ENV_VARS array (lines 49-91 in process-managed-transport.ts) defines which host environment variables MetaMCP safely passes to child processes by default. This whitelist prevents leaking unrelated host information, such as user home directories or shell histories, into MCP server containers. You should avoid adding arbitrary host variables to this list unless specifically required by your MCP servers.
Production Configuration Best Practices for MetaMCP
Keep Secrets Out of Source Control
Store actual secret values only in the container's runtime environment using Docker --env-file, Docker Secrets, Kubernetes Secrets, or CI/CD secret stores. As documented in the README (lines 102-124), MetaMCP resolves ${VAR} references at runtime from the container's environment and never writes expanded values to the MCP JSON configuration file.
Use ${VAR} Syntax for Dynamic Values
Reference environment variables in your MCP server definitions using the ${VAR} syntax. For example, configure API_KEY=${OPENAI_API_KEY} in your server JSON configuration. This approach, shown in the README's Environment Variable References section (lines 112-118), keeps secrets out of version-controlled JSON files while allowing the same configuration to be reused across development, staging, and production environments.
Set NODE_ENV=production Explicitly
Add ENV NODE_ENV=production in your Dockerfile or docker-compose file. The repository's example.env file (line 1) demonstrates this setting, and the Dockerfile (line 18) sets NEXT_TELEMETRY_DISABLED=1 for production builds. Many internal code branches, such as OAuth utilities, guard production-only behavior behind this flag (process.env.NODE_ENV === "production" as seen in lines 70-78 of the README analysis).
Validate Required Variables at Startup
Implement a bootstrap validation script that checks for critical environment variables before MetaMCP starts. This prevents the service from running with partial configuration. The script should verify variables such as APP_URL, DATABASE_URL, and any OIDC credentials, exiting with a clear error message if any are missing.
Implementing Secure MetaMCP Deployments
Docker Compose Configuration Example
For production deployments, use Docker Compose with an external environment file. The repository's docker-compose.yml demonstrates this pattern, separating runtime secrets from the container image.
services:
metamcp:
image: ghcr.io/metatool-ai/metamcp:latest
env_file:
- .env # Runtime secrets, never committed
environment:
- NODE_ENV=production # Force production mode
ports:
- "8080:8080"
MCP Server Definition with Environment References
Configure your MCP servers to reference environment variables rather than hard-coding secrets. This JSON configuration can be safely committed to source control.
{
"OpenAI": {
"type": "STDIO",
"command": "uvx",
"args": ["mcp-openai"],
"env": {
"API_KEY": "${OPENAI_API_KEY}",
"BASE_URL": "https://api.openai.com/v1"
}
}
}
Bootstrap Validation Script
Add a TypeScript validation script to your deployment to ensure all required MetaMCP environment variables are present before startup.
// src/bootstrap.ts
const required = [
"APP_URL",
"DATABASE_URL",
"OPENAI_API_KEY",
"OIDC_CLIENT_ID",
"OIDC_CLIENT_SECRET",
];
for (const key of required) {
if (!process.env[key]) {
console.error(`Missing required environment variable: ${key}`);
process.exit(1);
}
}
console.log("All required environment variables are present");
Execute this script before starting the main application: node src/bootstrap.js && npm start.
Summary
- Store secrets in Docker or Kubernetes secret stores, never in source control or MCP JSON configuration files.
- Use the
${VAR}syntax in MCP server definitions to reference container environment variables at runtime. - Set
NODE_ENV=productionexplicitly in your Dockerfile or docker-compose configuration. - Validate required MetaMCP environment variables at startup using a bootstrap script to fail fast on misconfiguration.
- Rely on the built-in
DEFAULT_INHERITED_ENV_VARSwhitelist inprocess-managed-transport.tsto prevent leaking host environment variables to child processes.
Frequently Asked Questions
How does MetaMCP handle environment variable inheritance?
MetaMCP merges the container's process environment with a safe-inheritance whitelist (DEFAULT_INHERITED_ENV_VARS in apps/backend/src/lib/stdio-transport/process-managed-transport.ts) and any explicit env map defined in the server configuration. This ensures child MCP server processes receive only necessary variables without exposing unrelated host environment data.
What is the recommended way to store secrets for MetaMCP?
Store secrets in the container's runtime environment using Docker --env-file, Docker Secrets, Kubernetes Secrets, or CI/CD secret stores. Never commit actual values to source control. Reference these secrets in your MCP JSON configuration using the ${VAR} syntax, which MetaMCP resolves at runtime without writing values to disk.
Should I use turbo.json globalEnv for production deployments?
No. The globalEnv array in turbo.json is designed for local development with Turborepo and should not be relied upon for production. According to the repository documentation, production deployments should inject environment variables directly via Docker or Kubernetes secret stores rather than through the Turborepo configuration.
How do I validate that all required MetaMCP environment variables are set?
Implement a bootstrap validation script that checks for critical variables such as APP_URL, DATABASE_URL, and OIDC credentials before starting the MetaMCP service. If any required variables are missing, the script should exit with a clear error message. This "fail fast" approach prevents the service from running with partial configuration and makes deployment issues immediately obvious.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →