Skip to content

Commit bfa649e

Browse files
committed
feat(config): add MCP initialization config handling and prioritization (#12)
Introduce a handler extracting configuration from MCP client info during initialization, enabling dynamic config setup based on client-provided data. Update configuration loader to prioritize MCP init config over environment variables and other sources, ensuring runtime flexibility and seamless integration with MCP clients. Add comprehensive tests verifying MCP config precedence, boolean parsing, nested config handling, and hostname extraction.
1 parent 30c72ed commit bfa649e

26 files changed

Lines changed: 1767 additions & 324 deletions

Dockerfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ COPY --from=builder /app/dist ./dist
2626

2727
# Default environment
2828
ENV TRANSPORT_MODE=http
29+
ENV LOKALISE_API_KEY=YOUR_LOKALISE_API_KEY_HERE
30+
ENV LOKALISE_API_HOSTNAME=https://api.stage.lokalise.cloud/api2/
31+
ENV DEBUG=true
32+
ENV MCP_SERVER_MODE=true
33+
ENV NODE_ENV=production
34+
2935
EXPOSE 3000
3036

3137
CMD ["node", "dist/index.js"]

docs/CONFIGURATION.md

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
# Configuration Management
2+
3+
## Overview
4+
5+
The Lokalise MCP server uses a centralized configuration management system that provides:
6+
- **Single entry point** for all configuration access
7+
- **Strong typing** with TypeScript and Zod validation
8+
- **Priority-based** configuration loading from multiple sources
9+
- **Environment-specific** configuration support
10+
11+
## Configuration Priority
12+
13+
Configuration values are loaded from multiple sources with the following priority (highest to lowest):
14+
15+
1. **HTTP Query Parameters** (Smithery) - Passed via query strings
16+
2. **MCP Initialization Config** - From clientInfo during MCP initialization
17+
3. **Environment Variables** - Direct process.env values
18+
4. **`.env` File** - Project root .env file
19+
5. **Global Config File** - `~/.mcp/configs.json`
20+
21+
Higher priority sources override lower priority ones.
22+
23+
## Usage
24+
25+
### Import the Config Utility
26+
27+
```typescript
28+
import { config } from "./shared/utils/config.util.js";
29+
```
30+
31+
### Load Configuration
32+
33+
Configuration is automatically loaded when first accessed, but can be explicitly loaded:
34+
35+
```typescript
36+
config.load(); // Called automatically in main entry point
37+
```
38+
39+
### Access Configuration Values
40+
41+
All configuration access should go through typed getter methods:
42+
43+
```typescript
44+
// Core configuration
45+
const apiKey = config.getLokaliseApiKey(); // Required, throws if not set
46+
const apiHost = config.getLokaliseApiHostname(); // With default fallback
47+
48+
// Server configuration
49+
const transportMode = config.getTransportMode(); // "stdio" | "http"
50+
const port = config.getPort(); // Default: 3000
51+
52+
// Debug configuration
53+
const isDebug = config.isDebugEnabled(); // boolean
54+
const debugPattern = config.getDebugPattern(); // string | undefined
55+
56+
// Environment detection
57+
const isTest = config.isTestEnvironment(); // Detects test environment
58+
const isMcpServer = config.isMcpServerMode(); // MCP server vs CLI mode
59+
const nodeEnv = config.getNodeEnv(); // "development" | "test" | "production"
60+
```
61+
62+
### Set Configuration from Different Sources
63+
64+
```typescript
65+
// Set HTTP query configuration (highest priority)
66+
config.setHttpQueryConfig({
67+
LOKALISE_API_KEY: "key_from_query",
68+
debug_mode: true
69+
});
70+
71+
// Set MCP initialization configuration
72+
config.setMcpInitConfig({
73+
LOKALISE_API_KEY: "key_from_mcp",
74+
DEBUG: false
75+
});
76+
```
77+
78+
### Validate Configuration
79+
80+
```typescript
81+
const validation = config.validate();
82+
if (!validation.valid) {
83+
console.error("Configuration errors:", validation.errors);
84+
}
85+
```
86+
87+
## Environment Variables
88+
89+
The following environment variables are supported:
90+
91+
| Variable | Type | Required | Default | Description |
92+
|----------|------|----------|---------|-------------|
93+
| `LOKALISE_API_KEY` | string | Yes | - | Your Lokalise API token |
94+
| `LOKALISE_API_HOSTNAME` | string | No | `https://api.lokalise.com/api2/` | Custom Lokalise API endpoint |
95+
| `TRANSPORT_MODE` | string | No | `stdio` | Transport mode: `stdio` or `http` |
96+
| `PORT` | number | No | `3000` | HTTP server port (only for HTTP transport) |
97+
| `DEBUG` | boolean/string | No | `false` | Debug mode or pattern for selective logging |
98+
| `NODE_ENV` | string | No | - | Node environment: `development`, `test`, `production` |
99+
| `MCP_SERVER_MODE` | boolean | No | `false` | Indicates if running as MCP server |
100+
101+
## Configuration Files
102+
103+
### `.env` File
104+
105+
Create a `.env` file in the project root:
106+
107+
```env
108+
LOKALISE_API_KEY=your_api_key_here
109+
LOKALISE_API_HOSTNAME=https://api.lokalise.com/api2/
110+
TRANSPORT_MODE=http
111+
PORT=3000
112+
DEBUG=true
113+
```
114+
115+
### Global Config File
116+
117+
Create `~/.mcp/configs.json` for global configuration:
118+
119+
```json
120+
{
121+
"lokalise-mcp": {
122+
"environments": {
123+
"LOKALISE_API_KEY": "your_global_api_key",
124+
"LOKALISE_API_HOSTNAME": "https://api.lokalise.com/api2/"
125+
}
126+
}
127+
}
128+
```
129+
130+
## Debug Configuration
131+
132+
The `DEBUG` environment variable supports multiple formats:
133+
134+
- `true` or `1` - Enable all debug logging
135+
- `false` or `0` - Disable debug logging
136+
- Pattern string - Enable selective logging (e.g., `"controllers/*,services/*"`)
137+
138+
Examples:
139+
```bash
140+
DEBUG=true # Enable all debug
141+
DEBUG=controllers/* # Debug only controllers
142+
DEBUG=services/*,utils/* # Debug services and utils
143+
```
144+
145+
## Type Safety
146+
147+
All configuration is strongly typed using Zod schemas:
148+
149+
```typescript
150+
// Configuration schema is defined in src/shared/schemas/config.schema.ts
151+
export const RuntimeConfigSchema = z.object({
152+
LOKALISE_API_KEY: z.string().min(1, "LOKALISE_API_KEY is required"),
153+
LOKALISE_API_HOSTNAME: z.string().url().default("https://api.lokalise.com/api2/"),
154+
TRANSPORT_MODE: z.enum(["stdio", "http"]).default("stdio"),
155+
PORT: z.number().int().min(1).max(65535).default(3000),
156+
DEBUG: z.union([z.boolean(), z.string()]).default(false),
157+
// ... other fields
158+
});
159+
```
160+
161+
## Best Practices
162+
163+
1. **Never access `process.env` directly** - Always use the config utility
164+
2. **Use typed getter methods** - Avoid generic `config.get()` when possible
165+
3. **Handle configuration errors early** - Validate configuration at startup
166+
4. **Use appropriate defaults** - Provide sensible defaults for optional values
167+
5. **Document required variables** - Clearly indicate which variables are required
168+
169+
## Migration Guide
170+
171+
If you're updating code that previously used `process.env` directly:
172+
173+
```typescript
174+
// ❌ Old way - direct process.env access
175+
const apiKey = process.env.LOKALISE_API_KEY;
176+
const isTest = process.env.NODE_ENV === "test";
177+
178+
// ✅ New way - through config utility
179+
import { config } from "./shared/utils/config.util.js";
180+
const apiKey = config.getLokaliseApiKey();
181+
const isTest = config.isTestEnvironment();
182+
```
183+
184+
## Exceptions
185+
186+
The following cases legitimately use `process.env` directly:
187+
188+
1. **Logger utility** - To avoid circular dependencies
189+
2. **Test utilities** - When spawning child processes or manipulating test environment
190+
3. **Build scripts** - Scripts that run outside the main application context
191+
192+
## Smithery Integration
193+
194+
For Smithery deployments, configuration can be passed via HTTP query parameters:
195+
196+
```
197+
GET /mcp?LOKALISE_API_KEY=key&debug_mode=true
198+
```
199+
200+
These query parameters have the highest priority and will override all other configuration sources.

0 commit comments

Comments
 (0)