Configuration System
Seed uses a centralized, environment-based configuration system that consolidates all settings in a single location. Configuration is loaded from environment variables with sensible defaults.
Overview
The configuration system provides:
- Centralized Configuration: All settings in
src/config/index.ts - Environment-Based: Values loaded from environment variables
- Typed and Validated: TypeScript interfaces with runtime validation
- Modular Structure: Separate files for different concerns
- Sensible Defaults: Works out-of-the-box for development
Configuration Structure
src/config/
├── index.ts # Main configuration export
├── oidc.ts # OIDC/OAuth settings
├── cors.ts # CORS configuration
└── dcr.ts # Dynamic Client Registration settingsMain Configuration
File: src/config/index.ts
export const config = {
// Server Configuration
port: parseInt(process.env.PORT ?? "3000", 10),
baseUrl: process.env.BASE_URL ?? "",
authRequired: process.env.AUTH_REQUIRED !== "false",
// Server Metadata
server: {
name: "seed",
version: "0.1.3", // From package.json
},
// Module Configurations
cors: corsConfig,
dcr: dcrConfig,
oidc: oidcConfig,
};Server Settings
| Variable | Type | Default | Description |
|---|---|---|---|
PORT | number | 3000 | HTTP server port |
BASE_URL | string | "" | Public base URL for OAuth redirects |
AUTH_REQUIRED | boolean | true | Enable/disable authentication globally |
Example:
PORT=8080
BASE_URL=https://seed.example.com
AUTH_REQUIRED=trueOIDC Configuration
File: src/config/oidc.ts
export const oidcConfig = {
issuer: process.env.OIDC_ISSUER ?? "",
audience: process.env.OIDC_AUDIENCE ?? "",
tokenUrl: process.env.OAUTH_TOKEN_URL ?? "",
authorizationUrl: process.env.OAUTH_AUTHORIZATION_URL ?? "",
jwksUrl: process.env.OIDC_JWKS_URL ?? "",
jwks: {
cacheTtlMs: 60 * 60 * 1000, // 1 hour
refreshBeforeExpiryMs: 5 * 60 * 1000, // 5 minutes
},
};OIDC Settings
| Variable | Required | Description |
|---|---|---|
OIDC_ISSUER | Yes | Identity provider issuer URL (e.g., https://auth.example.com/application/o/my-app/) |
OIDC_AUDIENCE | Yes | Client ID for JWT audience validation (also used as static IdP client) |
OAUTH_TOKEN_URL | Yes | OAuth token endpoint URL |
OAUTH_AUTHORIZATION_URL | Yes | OAuth authorization endpoint URL |
OIDC_JWKS_URL | No | JWKS endpoint URL (auto-discovered from issuer if not provided) |
Example:
OIDC_ISSUER=https://auth.example.com/application/o/my-app/
OIDC_AUDIENCE=my-client-id
OAUTH_TOKEN_URL=https://auth.example.com/application/o/token/
OAUTH_AUTHORIZATION_URL=https://auth.example.com/application/o/authorize/
# OIDC_JWKS_URL is optional, will be discovered from OIDC_ISSUERJWKS Settings
Hardcoded Configuration:
jwks: {
cacheTtlMs: 3600000, // 1 hour cache
refreshBeforeExpiryMs: 300000, // Refresh 5 minutes before expiry
}These settings control JWKS caching behavior and cannot be changed via environment variables.
CORS Configuration
File: src/config/cors.ts
export const corsConfig = {
origin: [
/^http:\/\/localhost(:\d+)?$/, // http://localhost:*
"https://claude.ai", // Claude web app
/^https:\/\/.*\.anthropic\.com$/, // Anthropic domains
...(process.env.CORS_EXTRA_ORIGINS?.split(",") || []),
],
credentials: true,
allowedHeaders: [
"Content-Type",
"Accept",
"Authorization",
"Mcp-Session-Id",
"Last-Event-ID",
],
exposedHeaders: [
"Content-Type",
"Mcp-Session-Id",
],
};CORS Settings
| Variable | Type | Default | Description |
|---|---|---|---|
CORS_EXTRA_ORIGINS | string | "" | Comma-separated list of additional allowed origins |
Default Allowed Origins:
http://localhost:*(any port) - For local developmenthttps://claude.ai- Claude web applicationhttps://*.anthropic.com- Any Anthropic subdomain
Example:
CORS_EXTRA_ORIGINS=https://app1.example.com,https://app2.example.comCORS Headers
Allowed Request Headers:
Content-Type: For JSON requestsAccept: Content negotiationAuthorization: Bearer tokensMcp-Session-Id: MCP session trackingLast-Event-ID: Server-sent events (future use)
Exposed Response Headers:
Content-Type: Response formatMcp-Session-Id: Session identifier
Dynamic Client Registration Configuration
File: src/config/dcr.ts
export const dcrConfig = {
redisUrl: process.env.REDIS_URL ?? "redis://redis:6379",
clientTtlSeconds: parseInt(process.env.DCR_CLIENT_TTL ?? "2592000", 10),
keyPrefix: "dcr:client:",
clientIdPrefix: "seed-",
maxRedirectUris: 10,
rateLimit: {
windowMs: parseInt(process.env.DCR_RATE_LIMIT_WINDOW_MS ?? "3600000", 10),
maxRequests: parseInt(process.env.DCR_RATE_LIMIT_MAX ?? "10", 10),
},
};DCR Settings
| Variable | Type | Default | Description |
|---|---|---|---|
REDIS_URL | string | redis://redis:6379 | Redis connection URL |
DCR_CLIENT_TTL | number | 2592000 | Client TTL in seconds (30 days) |
DCR_RATE_LIMIT_WINDOW_MS | number | 3600000 | Rate limit window in milliseconds (1 hour) |
DCR_RATE_LIMIT_MAX | number | 10 | Max registrations per window |
Example:
REDIS_URL=redis://redis.example.com:6379
DCR_CLIENT_TTL=604800 # 7 days
DCR_RATE_LIMIT_WINDOW_MS=1800000 # 30 minutes
DCR_RATE_LIMIT_MAX=5 # 5 registrations per windowHardcoded DCR Settings
These settings are not configurable via environment:
- keyPrefix:
"dcr:client:"- Redis key prefix for clients - clientIdPrefix:
"seed-"- Prefix for generated client IDs - maxRedirectUris:
10- Maximum redirect URIs per client
Environment File Template
.env.example
# Server Configuration
PORT=3000
BASE_URL=https://seed.example.com
AUTH_REQUIRED=true
# OIDC Configuration (Required)
OIDC_ISSUER=https://auth.example.com/application/o/my-app/
OIDC_AUDIENCE=my-client-id
OAUTH_TOKEN_URL=https://auth.example.com/application/o/token/
OAUTH_AUTHORIZATION_URL=https://auth.example.com/application/o/authorize/
# OIDC Configuration (Optional)
OIDC_JWKS_URL=https://auth.example.com/application/o/my-app/jwks/
# Redis Configuration
REDIS_URL=redis://redis:6379
# Dynamic Client Registration
DCR_CLIENT_TTL=2592000 # 30 days
DCR_RATE_LIMIT_WINDOW_MS=3600000 # 1 hour
DCR_RATE_LIMIT_MAX=10
# CORS Configuration (Optional)
CORS_EXTRA_ORIGINS=https://app1.example.com,https://app2.example.comConfiguration Loading
Loading Order
- Environment variables: Loaded from process.env
- Default values: Used if environment variable not set
- Type conversion: Strings parsed to numbers/booleans as needed
- Validation: Runtime checks for required values
Type Conversion
String to Number:
parseInt(process.env.PORT ?? "3000", 10)String to Boolean:
process.env.AUTH_REQUIRED !== "false" // true unless explicitly "false"String to Array:
process.env.CORS_EXTRA_ORIGINS?.split(",") || []Configuration Validation
Required Variables
When AUTH_REQUIRED=true, the following must be set:
OIDC_ISSUERorOIDC_JWKS_URLOIDC_AUDIENCEOAUTH_TOKEN_URLOAUTH_AUTHORIZATION_URL
Validation Logic:
// In src/services/jwks.ts
if (config.authRequired && !config.oidc.issuer && !config.oidc.jwksUrl) {
throw new Error(
"OIDC_ISSUER or OIDC_JWKS_URL must be configured when AUTH_REQUIRED=true"
);
}URL Validation
OAuth endpoints must be valid URLs:
try {
new URL(config.oidc.tokenUrl);
new URL(config.oidc.authorizationUrl);
} catch (error) {
throw new Error("Invalid OAuth endpoint URL");
}Configuration Best Practices
Development
Minimal configuration for local development:
# Disable authentication for testing
AUTH_REQUIRED=false
# Use default port
PORT=3000
# No OIDC required when auth disabledTesting
Configuration for automated tests:
# Disable auth for unit tests
AUTH_REQUIRED=false
# Use test Redis instance
REDIS_URL=redis://localhost:6379
# Short TTLs for faster test execution
DCR_CLIENT_TTL=60Production
Production-ready configuration:
# Always require authentication
AUTH_REQUIRED=true
# Set public base URL
BASE_URL=https://seed.example.com
# Use production IdP
OIDC_ISSUER=https://auth.example.com/application/o/my-app/
OIDC_AUDIENCE=production-client-id
OAUTH_TOKEN_URL=https://auth.example.com/application/o/token/
OAUTH_AUTHORIZATION_URL=https://auth.example.com/application/o/authorize/
# Use production Redis
REDIS_URL=redis://redis.prod:6379
# Standard 30-day client TTL
DCR_CLIENT_TTL=2592000
# Rate limiting
DCR_RATE_LIMIT_WINDOW_MS=3600000
DCR_RATE_LIMIT_MAX=10Configuration Security
Sensitive Values
The following should be kept secret:
REDIS_URL(if it contains credentials)- IdP endpoints (may reveal internal infrastructure)
Not sensitive (can be public):
PORTBASE_URLOIDC_ISSUER(public OIDC metadata)OIDC_AUDIENCE(client ID, not a secret)
Environment Variable Storage
Recommended practices:
- Use
.envfiles for local development (add to.gitignore) - Use Docker secrets for containerized deployments
- Use Kubernetes ConfigMaps/Secrets for k8s
- Use cloud provider secret management (AWS Secrets Manager, etc.)
Default Value Security
All defaults are safe:
- No hardcoded credentials
- Localhost-only for development
- Authentication enabled by default
- Secure CORS origins
Docker Configuration
docker-compose.yml
version: '3.8'
services:
seed:
image: seed-mcp-server
environment:
- PORT=3000
- BASE_URL=https://seed.example.com
- AUTH_REQUIRED=true
- OIDC_ISSUER=${OIDC_ISSUER}
- OIDC_AUDIENCE=${OIDC_AUDIENCE}
- OAUTH_TOKEN_URL=${OAUTH_TOKEN_URL}
- OAUTH_AUTHORIZATION_URL=${OAUTH_AUTHORIZATION_URL}
- REDIS_URL=redis://redis:6379
ports:
- "3000:3000"
depends_on:
- redis
redis:
image: redis:7-alpine
ports:
- "6379:6379"Environment File
# .env (for docker-compose)
OIDC_ISSUER=https://auth.example.com/application/o/my-app/
OIDC_AUDIENCE=my-client-id
OAUTH_TOKEN_URL=https://auth.example.com/application/o/token/
OAUTH_AUTHORIZATION_URL=https://auth.example.com/application/o/authorize/Configuration Access
In Application Code
import { config } from "./config/index.js";
// Access server settings
const port = config.port;
const baseUrl = config.baseUrl;
// Access OIDC settings
const issuer = config.oidc.issuer;
const audience = config.oidc.audience;
// Access DCR settings
const redisUrl = config.dcr.redisUrl;
const clientTtl = config.dcr.clientTtlSeconds;
// Access CORS settings
const allowedOrigins = config.cors.origin;TypeScript Types
interface Config {
port: number;
baseUrl: string;
authRequired: boolean;
server: {
name: string;
version: string;
};
cors: CorsConfig;
dcr: DcrConfig;
oidc: OidcConfig;
}Troubleshooting
Common Issues
Issue: "OIDC_ISSUER must be configured"
- Solution: Set
OIDC_ISSUERor disable auth withAUTH_REQUIRED=false
Issue: Redis connection refused
- Solution: Verify
REDIS_URLpoints to running Redis instance
Issue: CORS errors in browser
- Solution: Add origin to
CORS_EXTRA_ORIGINS
Issue: JWT validation fails
- Solution: Verify
OIDC_ISSUERandOIDC_AUDIENCEmatch IdP configuration
Implementation Files
- Main Config:
src/config/index.ts - OIDC Config:
src/config/oidc.ts - CORS Config:
src/config/cors.ts - DCR Config:
src/config/dcr.ts - Environment Template:
.env.example
Related Documentation
- Authentication Flow - OIDC configuration usage
- OAuth 2.1 Implementation - OAuth endpoint configuration
- Session Management - Redis configuration
- MCP Server Design - Server metadata configuration