Skip to content

Commit 97342eb

Browse files
authored
Merge pull request Patrick-Ehimen#52 from bomanaps/debug/mcp
Fix MCP server: stderr logging, optional SQLite, runtime API key
2 parents 8b691d5 + 0fb527a commit 97342eb

8 files changed

Lines changed: 387 additions & 66 deletions

File tree

apps/mcp-server/src/config/env-loader.ts

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ export class EnvLoader {
8686
if (validLevels.includes(env.LOG_LEVEL)) {
8787
config.logLevel = env.LOG_LEVEL as any;
8888
} else {
89-
console.warn(`Invalid LOG_LEVEL: ${env.LOG_LEVEL}. Using default 'info'.`);
89+
process.stderr.write(
90+
`Warning: Invalid LOG_LEVEL: ${env.LOG_LEVEL}. Using default 'info'.\n`,
91+
);
9092
}
9193
}
9294

@@ -96,7 +98,9 @@ export class EnvLoader {
9698
if (!isNaN(size) && size > 0) {
9799
config.maxStorageSize = size;
98100
} else {
99-
console.warn(`Invalid MAX_STORAGE_SIZE: ${env.MAX_STORAGE_SIZE}. Using default.`);
101+
process.stderr.write(
102+
`Warning: Invalid MAX_STORAGE_SIZE: ${env.MAX_STORAGE_SIZE}. Using default.\n`,
103+
);
100104
}
101105
}
102106

@@ -110,7 +114,9 @@ export class EnvLoader {
110114
if (!isNaN(interval) && interval > 0) {
111115
config.metricsInterval = interval;
112116
} else {
113-
console.warn(`Invalid METRICS_INTERVAL: ${env.METRICS_INTERVAL}. Using default.`);
117+
process.stderr.write(
118+
`Warning: Invalid METRICS_INTERVAL: ${env.METRICS_INTERVAL}. Using default.\n`,
119+
);
114120
}
115121
}
116122

@@ -167,24 +173,19 @@ export class EnvLoader {
167173

168174
/**
169175
* Display current configuration (for debugging)
176+
* Uses stderr to avoid corrupting MCP stdio protocol on stdout
170177
*/
171178
static displayConfig(config: Partial<ServerConfig>): void {
172-
console.log("\n📋 Server Configuration:");
173-
console.log(" Name:", config.name || "default");
174-
console.log(" Version:", config.version || "default");
175-
console.log(" Log Level:", config.logLevel || "default");
176-
console.log(
177-
" Max Storage:",
178-
config.maxStorageSize ? `${(config.maxStorageSize / 1024 / 1024).toFixed(2)} MB` : "default",
179-
);
180-
console.log(
181-
" Metrics:",
182-
config.enableMetrics !== undefined ? config.enableMetrics : "default",
183-
);
184-
console.log(
185-
" Metrics Interval:",
186-
config.metricsInterval ? `${config.metricsInterval / 1000}s` : "default",
187-
);
188-
console.log("");
179+
const lines = [
180+
"\nServer Configuration:",
181+
` Name: ${config.name || "default"}`,
182+
` Version: ${config.version || "default"}`,
183+
` Log Level: ${config.logLevel || "default"}`,
184+
` Max Storage: ${config.maxStorageSize ? `${(config.maxStorageSize / 1024 / 1024).toFixed(2)} MB` : "default"}`,
185+
` Metrics: ${config.enableMetrics !== undefined ? config.enableMetrics : "default"}`,
186+
` Metrics Interval: ${config.metricsInterval ? `${config.metricsInterval / 1000}s` : "default"}`,
187+
"",
188+
];
189+
process.stderr.write(lines.join("\n") + "\n");
189190
}
190191
}

apps/mcp-server/src/config/server-config.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,34 @@ export interface ServerConfig {
2121
multiTenancy?: MultiTenancyConfig;
2222
}
2323

24+
/**
25+
* Get default auth config with API key read at runtime (not module load time)
26+
* This ensures environment variables set after module import are respected
27+
*/
28+
export function getDefaultAuthConfig(): AuthConfig {
29+
return {
30+
defaultApiKey: process.env.LIGHTHOUSE_API_KEY,
31+
enablePerRequestAuth: true,
32+
requireAuthentication: true,
33+
keyValidationCache: {
34+
enabled: true,
35+
maxSize: 1000,
36+
ttlSeconds: 300, // 5 minutes
37+
cleanupIntervalSeconds: 60,
38+
},
39+
rateLimiting: {
40+
enabled: true,
41+
requestsPerMinute: 60,
42+
burstLimit: 10,
43+
keyBasedLimiting: true,
44+
},
45+
};
46+
}
47+
48+
/**
49+
* Default auth config - reads API key at module load time for backward compatibility.
50+
* For runtime reading of env vars, use getDefaultAuthConfig() instead.
51+
*/
2452
export const DEFAULT_AUTH_CONFIG: AuthConfig = {
2553
defaultApiKey: process.env.LIGHTHOUSE_API_KEY,
2654
enablePerRequestAuth: true,
@@ -88,6 +116,28 @@ export const DEFAULT_MULTI_TENANCY_CONFIG: MultiTenancyConfig = {
88116
auditLogRetentionDays: 90,
89117
};
90118

119+
/**
120+
* Get default server config with API key read at runtime
121+
*/
122+
export function getDefaultServerConfig(): ServerConfig {
123+
return {
124+
name: "lighthouse-storage",
125+
version: "0.1.0",
126+
logLevel: "info",
127+
maxStorageSize: 1024 * 1024 * 1024, // 1GB
128+
enableMetrics: true,
129+
metricsInterval: 60000, // 1 minute
130+
lighthouseApiKey: process.env.LIGHTHOUSE_API_KEY,
131+
authentication: getDefaultAuthConfig(),
132+
performance: DEFAULT_PERFORMANCE_CONFIG,
133+
multiTenancy: DEFAULT_MULTI_TENANCY_CONFIG,
134+
};
135+
}
136+
137+
/**
138+
* Default server config - reads API key at module load time for backward compatibility.
139+
* For runtime reading of env vars, use getDefaultServerConfig() instead.
140+
*/
91141
export const DEFAULT_SERVER_CONFIG: ServerConfig = {
92142
name: "lighthouse-storage",
93143
version: "0.1.0",

apps/mcp-server/src/index.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,28 +118,31 @@ Examples:
118118

119119
// Handle graceful shutdown
120120
const shutdown = async () => {
121-
console.log("\nShutting down server...");
121+
// Use stderr to avoid corrupting MCP stdio protocol on stdout
122+
process.stderr.write("\nShutting down server...\n");
122123
try {
123124
await server.stop();
124125
process.exit(0);
125126
} catch (error) {
126-
console.error("Error during shutdown:", error);
127+
process.stderr.write(`Error during shutdown: ${error}\n`);
127128
process.exit(1);
128129
}
129130
};
130131

131132
process.on("SIGINT", shutdown);
132133
process.on("SIGTERM", shutdown);
133134
} catch (error) {
134-
console.error("Fatal error:", error);
135+
// Use stderr to avoid corrupting MCP stdio protocol on stdout
136+
process.stderr.write(`Fatal error: ${error}\n`);
135137
process.exit(1);
136138
}
137139
}
138140

139141
// Run main function if this is the entry point
140142
if (import.meta.url === `file://${process.argv[1]}`) {
141143
main().catch((error) => {
142-
console.error("Failed to start server:", error);
144+
// Use stderr to avoid corrupting MCP stdio protocol on stdout
145+
process.stderr.write(`Failed to start server: ${error}\n`);
143146
process.exit(1);
144147
});
145148
}

apps/mcp-server/src/server.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525
LighthouseGenerateKeyTool,
2626
LighthouseSetupAccessControlTool,
2727
} from "./tools/index.js";
28-
import { ServerConfig, DEFAULT_SERVER_CONFIG } from "./config/server-config.js";
28+
import { ServerConfig, getDefaultServerConfig } from "./config/server-config.js";
2929
import { AuthManager } from "./auth/AuthManager.js";
3030
import { LighthouseServiceFactory } from "./auth/LighthouseServiceFactory.js";
3131
import { RequestContext } from "./auth/RequestContext.js";
@@ -50,7 +50,8 @@ export class LighthouseMCPServer {
5050
datasetService?: MockDatasetService;
5151
},
5252
) {
53-
this.config = { ...DEFAULT_SERVER_CONFIG, ...config };
53+
// Use runtime config getter to ensure env vars are read at construction time
54+
this.config = { ...getDefaultServerConfig(), ...config };
5455

5556
// Initialize logger
5657
this.logger = Logger.getInstance({

0 commit comments

Comments
 (0)