The ConfigPlugin provides typed environment variable access for your FrontMCP servers. It automatically loads .env and .env.local files, and exposes configuration via this.config in all execution contexts.
Built-in Feature
ConfigPlugin is built into the SDK - no separate installation required. Just import and use:
import { ConfigPlugin } from ' @frontmcp/sdk ' ;
Why Use ConfigPlugin?
Typed Access Type-safe environment variable access with getRequired(), getNumber(), getBoolean()
Auto-Loading Automatically loads .env and .env.local files with proper precedence
Schema Validation Optional Zod schema validation for fail-fast configuration errors
DI Integration Access via this.config in tools, resources, prompts, and other contexts
Quick Start
1. Create your .env files
# .env - Base configuration (committed to git)
DATABASE_URL = postgres://localhost:5432/myapp
API_TIMEOUT = 30000
DEBUG = false
# .env.local - Local overrides (gitignored)
DATABASE_URL = postgres://localhost:5432/myapp_dev
DEBUG = true
2. Add ConfigPlugin to your server
import { FrontMcp , App , ConfigPlugin } from ' @frontmcp/sdk ' ;
@ App ({
name : ' my-app ' ,
plugins : [
ConfigPlugin . init ({
basePath : __dirname , // Directory containing .env files
loadEnv : true , // Load .env files (default: true)
populateProcessEnv : true , // Set process.env values (default: true)
}),
],
tools : [ MyTool ],
})
class MyApp {}
@ FrontMcp ({
info : { name : ' My Server ' , version : ' 1.0.0 ' },
apps : [ MyApp ],
})
export default class Server {}
import { Tool , ToolContext } from ' @frontmcp/sdk ' ;
import { z } from ' zod ' ;
@ Tool ({
name : ' connect-db ' ,
description : ' Connect to the database ' ,
inputSchema : z . object ({}),
})
export default class ConnectDbTool extends ToolContext {
async execute () {
// Get required config (throws if missing)
const dbUrl = this . config . getRequired ( ' DATABASE_URL ' );
// Get with default value
const timeout = this . config . getNumber ( ' API_TIMEOUT ' , 5000 );
// Check existence
const isDebug = this . config . getBoolean ( ' DEBUG ' , false );
return { connected : true , debug : isDebug };
}
}
Configuration Options
Configure the plugin when initializing:
ConfigPlugin . init ({
basePath : __dirname , // Base directory for resolving paths
envPath : ' .env ' , // Path to base env file (default: '.env')
localEnvPath : ' .env.local ' , // Path to local override file (default: '.env.local')
loadEnv : true , // Whether to load .env files (default: true)
populateProcessEnv : true , // Whether to set process.env (default: true)
schema : envSchema , // Optional Zod schema for validation
})
Base directory for resolving relative .env paths. Required for file loading.
Path to the base environment file, relative to basePath.
localEnvPath
string
default: "'.env.local'"
Path to the local override file, relative to basePath. Values in this file override the base file.
Whether to load .env files. Set to false if you only want to read from process.env.
Whether to set loaded values into process.env. Does not override existing values.
Optional Zod schema to validate the configuration. Throws ConfigValidationError if validation fails.
ConfigService API
Access configuration values via this.config in any execution context:
get(key, defaultValue?)
Get a configuration value with optional default:
// Returns string | undefined
const apiKey = this . config . get ( ' API_KEY ' );
// Returns string (uses default if not found)
const region = this . config . get ( ' AWS_REGION ' , ' us-east-1 ' );
getRequired(key)
Get a required configuration value. Throws ConfigMissingError if not found:
// Throws ConfigMissingError if DATABASE_URL is not set
const dbUrl = this . config . getRequired ( ' DATABASE_URL ' );
has(key)
Check if a configuration key exists:
if ( this . config . has ( ' OPTIONAL_FEATURE ' )) {
// Enable optional feature
}
getAll()
Get all configuration values as a record:
const allConfig = this . config . getAll ();
console . log ( Object . keys ( allConfig ). length , ' config values loaded ' );
getNumber(key, defaultValue?)
Parse a configuration value as a number:
// Returns NaN if not found or not a number
const port = this . config . getNumber ( ' PORT ' );
// Returns 3000 if PORT is not set
const port = this . config . getNumber ( ' PORT ' , 3000 );
getBoolean(key, defaultValue?)
Parse a configuration value as a boolean:
// Returns true for 'true', '1', 'yes', 'on' (case-insensitive)
const debug = this . config . getBoolean ( ' DEBUG ' , false );
Schema Validation
Define a Zod schema to validate your configuration at startup:
import { z } from ' zod ' ;
import { ConfigPlugin } from ' @frontmcp/sdk ' ;
const envSchema = z . object ({
DATABASE_URL : z . string (). url (),
API_KEY : z . string (). min ( 10 ),
PORT : z . coerce . number (). default ( 3000 ),
DEBUG : z . coerce . boolean (). default ( false ),
});
ConfigPlugin . init ({
basePath : __dirname ,
schema : envSchema ,
})
When schema validation is enabled, missing or invalid values will throw ConfigValidationError during server startup, preventing the server from running with invalid configuration.
File Loading Behavior
Precedence Rules
Base file (.env) is loaded first
Local file (.env.local) overrides base values
Existing process.env values are not overwritten
Supported Syntax
# Comments start with #
DATABASE_URL = postgres://localhost:5432/myapp
# Quoted values (single or double quotes)
API_KEY = " secret-key-with-spaces "
MESSAGE = ' Hello, World! '
# Empty values
EMPTY_VAR =
# Escape sequences in double quotes
MULTILINE = " line1\nline2\ttabbed "
Add .env.local to your .gitignore file to keep local secrets out of version control.
CLI Integration
The frontmcp dev command automatically loads .env files before starting your server:
# Automatically loads .env and .env.local from current directory
frontmcp dev
# Your server starts with environment variables already set
The CLI loads environment files before spawning your server process, so process.env values are available immediately.
Error Handling
ConfigMissingError
Thrown when getRequired() is called for a missing key:
import { ConfigMissingError } from ' @frontmcp/sdk ' ;
try {
const secret = this . config . getRequired ( ' MISSING_KEY ' );
} catch ( error ) {
if ( error instanceof ConfigMissingError ) {
console . error ( ` Missing config: ${ error . key } ` );
}
}
ConfigValidationError
Thrown when schema validation fails:
// At server startup, if DATABASE_URL is invalid:
// ConfigValidationError: Configuration validation failed
// - DATABASE_URL: Invalid url
Complete Example
import { FrontMcp , App , Tool , ToolContext , ConfigPlugin } from ' @frontmcp/sdk ' ;
import { z } from ' zod ' ;
// Define configuration schema
const envSchema = z . object ({
DATABASE_URL : z . string (). url (),
API_KEY : z . string (),
PORT : z . coerce . number (). default ( 3000 ),
DEBUG : z . coerce . boolean (). default ( false ),
CACHE_TTL : z . coerce . number (). default ( 3600 ),
});
// Tool that uses configuration
@ Tool ({
name : ' get-config-info ' ,
description : ' Get current configuration status ' ,
inputSchema : z . object ({}),
})
class GetConfigInfoTool extends ToolContext {
async execute () {
return {
debug : this . config . getBoolean ( ' DEBUG ' ),
port : this . config . getNumber ( ' PORT ' ),
cacheTtl : this . config . getNumber ( ' CACHE_TTL ' , 3600 ),
hasApiKey : this . config . has ( ' API_KEY ' ),
};
}
}
@ App ({
name : ' config-demo ' ,
plugins : [
ConfigPlugin . init ({
basePath : __dirname ,
schema : envSchema ,
}),
],
tools : [ GetConfigInfoTool ],
})
class ConfigDemoApp {}
@ FrontMcp ({
info : { name : ' Config Demo Server ' , version : ' 1.0.0 ' },
apps : [ ConfigDemoApp ],
http : { port : 3000 },
})
export default class Server {}
Links & Resources
Source Code View the ConfigPlugin source code
Providers Guide Learn about dependency injection and providers
Plugins Overview Learn about the FrontMCP plugin system
Demo Application See ConfigPlugin in action with real examples