From 4f29a92f01db228595806121f8c1d72968dcca8d Mon Sep 17 00:00:00 2001 From: mnmldr Date: Tue, 9 Dec 2025 15:50:37 +0000 Subject: [PATCH 1/2] Add SQL_ENCRYPT env flags and keep MCP stdio JSON-clean --- src/node/README.md | 2 ++ src/node/src/config/EnvironmentManager.ts | 24 ++++++++++++++++------- src/node/src/index.ts | 5 +++++ 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/node/README.md b/src/node/README.md index c5661e0..02d02ff 100644 --- a/src/node/README.md +++ b/src/node/README.md @@ -59,6 +59,8 @@ npm install -g @connorbritain/mssql-mcp-server@latest | `DATABASE_NAME` | Yes | Target database | | `SQL_AUTH_MODE` | | `sql`, `windows`, or `aad` (default: `aad`) | | `SQL_USERNAME` / `SQL_PASSWORD` | | Required for `sql`/`windows` modes | +| `SQL_ENCRYPT` | | `true`/`false` (default: `true`). Azure SQL / Synapse require encryption. | +| `TRUST_SERVER_CERTIFICATE` | | `true`/`false` (default: `false`) | | `READONLY` | | `true` disables write tools | | `ENVIRONMENTS_CONFIG_PATH` | | Multi-environment JSON config | | `SCRIPTS_PATH` | | Named SQL scripts directory | diff --git a/src/node/src/config/EnvironmentManager.ts b/src/node/src/config/EnvironmentManager.ts index bff990d..30a3697 100644 --- a/src/node/src/config/EnvironmentManager.ts +++ b/src/node/src/config/EnvironmentManager.ts @@ -17,6 +17,7 @@ export interface EnvironmentConfig { username?: string; password?: string; domain?: string; + encrypt?: boolean; trustServerCertificate?: boolean; connectionTimeout?: number; @@ -80,6 +81,14 @@ function resolveSecretsInConfig>(config: T): T { return resolved; } +const parseBool = (value: string | undefined, defaultValue: boolean): boolean => { + if (value === undefined) return defaultValue; + const normalized = value.toString().trim().toLowerCase(); + if (["true", "1", "yes"].includes(normalized)) return true; + if (["false", "0", "no"].includes(normalized)) return false; + return defaultValue; +}; + export class EnvironmentManager { private readonly environments: Map; private defaultEnvironment?: string; @@ -118,7 +127,7 @@ export class EnvironmentManager { this.environments.set(resolvedEnv.name, resolvedEnv); } - console.log(`Loaded ${this.environments.size} environment(s) from ${resolvedPath}`); + console.error(`Loaded ${this.environments.size} environment(s) from ${resolvedPath}`); } catch (error) { console.error(`Failed to load environment config: ${error}`); this.loadFromEnvVars(); @@ -144,7 +153,8 @@ export class EnvironmentManager { username: process.env.SQL_USERNAME, password: process.env.SQL_PASSWORD, domain: process.env.SQL_DOMAIN, - trustServerCertificate: process.env.TRUST_SERVER_CERTIFICATE?.toLowerCase() === "true", + encrypt: parseBool(process.env.SQL_ENCRYPT ?? process.env.ENCRYPT, true), + trustServerCertificate: parseBool(process.env.TRUST_SERVER_CERTIFICATE, false), connectionTimeout: process.env.CONNECTION_TIMEOUT ? parseInt(process.env.CONNECTION_TIMEOUT, 10) : 30, @@ -153,7 +163,7 @@ export class EnvironmentManager { this.environments.set("default", defaultEnv); this.defaultEnvironment = "default"; - console.log("Loaded default environment from environment variables"); + console.error("Loaded default environment from environment variables"); } getEnvironment(name?: string): EnvironmentConfig { @@ -318,7 +328,7 @@ export class EnvironmentManager { user: env.username, password: env.password, options: { - encrypt: false, + encrypt: env.encrypt ?? true, trustServerCertificate: env.trustServerCertificate ?? false, }, }, @@ -336,7 +346,7 @@ export class EnvironmentManager { config: { ...baseConfig, options: { - encrypt: false, + encrypt: env.encrypt ?? true, trustServerCertificate: env.trustServerCertificate ?? false, }, authentication: { @@ -365,7 +375,7 @@ export class EnvironmentManager { config: { ...baseConfig, options: { - encrypt: true, + encrypt: env.encrypt ?? true, trustServerCertificate: env.trustServerCertificate ?? false, }, authentication: { @@ -385,7 +395,7 @@ export class EnvironmentManager { for (const [name, { pool }] of this.connections.entries()) { if (pool.connected) { await pool.close(); - console.log(`Closed connection for environment '${name}'`); + console.error(`Closed connection for environment '${name}'`); } } this.connections.clear(); diff --git a/src/node/src/index.ts b/src/node/src/index.ts index 977d386..7c1b18f 100644 --- a/src/node/src/index.ts +++ b/src/node/src/index.ts @@ -1,6 +1,11 @@ #!/usr/bin/env node // External imports +// Keep MCP stdio JSON clean by sending logs to stderr +const origError = console.error.bind(console); +console.log = origError; +console.info = origError; +console.warn = origError; import { Buffer } from "node:buffer"; import * as dotenv from "dotenv"; import sql from "mssql"; From 25b92f6e27f06a7e9e6afe78b32bed7fe31cbbac Mon Sep 17 00:00:00 2001 From: mnmldr Date: Tue, 9 Dec 2025 15:57:40 +0000 Subject: [PATCH 2/2] Keep log level, rely on stderr routing for MCP stdio --- src/node/src/config/EnvironmentManager.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/node/src/config/EnvironmentManager.ts b/src/node/src/config/EnvironmentManager.ts index 30a3697..7771e3b 100644 --- a/src/node/src/config/EnvironmentManager.ts +++ b/src/node/src/config/EnvironmentManager.ts @@ -127,7 +127,7 @@ export class EnvironmentManager { this.environments.set(resolvedEnv.name, resolvedEnv); } - console.error(`Loaded ${this.environments.size} environment(s) from ${resolvedPath}`); + console.log(`Loaded ${this.environments.size} environment(s) from ${resolvedPath}`); } catch (error) { console.error(`Failed to load environment config: ${error}`); this.loadFromEnvVars(); @@ -163,7 +163,7 @@ export class EnvironmentManager { this.environments.set("default", defaultEnv); this.defaultEnvironment = "default"; - console.error("Loaded default environment from environment variables"); + console.log("Loaded default environment from environment variables"); } getEnvironment(name?: string): EnvironmentConfig { @@ -395,7 +395,7 @@ export class EnvironmentManager { for (const [name, { pool }] of this.connections.entries()) { if (pool.connected) { await pool.close(); - console.error(`Closed connection for environment '${name}'`); + console.log(`Closed connection for environment '${name}'`); } } this.connections.clear();