diff --git a/MssqlMcp/Node/README.md b/MssqlMcp/Node/README.md index 3f7e687..c72e1a6 100644 --- a/MssqlMcp/Node/README.md +++ b/MssqlMcp/Node/README.md @@ -142,11 +142,38 @@ This server leverages the Model Context Protocol (MCP), a versatile framework th - **SERVER_NAME**: Your MSSQL Database server name (e.g., `my-server.database.windows.net`) - **DATABASE_NAME**: Your database name +- **AUTHENTICATION_TYPE**: Authentication method to use. Options: + - `"entra"` - Use Microsoft Entra ID (Azure AD) authentication with interactive browser login (default) + - `"sql"` - Use SQL Server authentication with username/password +- **SQL_USER**: (Required when `AUTHENTICATION_TYPE` is `"sql"`) SQL Server username +- **SQL_PASSWORD**: (Required when `AUTHENTICATION_TYPE` is `"sql"`) SQL Server password - **READONLY**: Set to `"true"` to restrict to read-only operations, `"false"` for full access - **Path**: Update the path in `args` to point to your actual project location. - **CONNECTION_TIMEOUT**: (Optional) Connection timeout in seconds. Defaults to `30` if not set. - **TRUST_SERVER_CERTIFICATE**: (Optional) Set to `"true"` to trust self-signed server certificates (useful for development or when connecting to servers with self-signed certs). Defaults to `"false"`. +### Example: SQL Server Authentication + +```json +{ + "mcpServers": { + "mssql": { + "command": "node", + "args": ["C:/path/to/your/Node/dist/index.js"], + "env": { + "SERVER_NAME": "your-server-name", + "DATABASE_NAME": "your-database-name", + "AUTHENTICATION_TYPE": "sql", + "SQL_USER": "your_username", + "SQL_PASSWORD": "your_password", + "TRUST_SERVER_CERTIFICATE": "true", + "READONLY": "true" + } + } + } +} +``` + ## Sample Configurations You can find sample configuration files in the `src/samples/` folder: diff --git a/MssqlMcp/Node/src/index.ts b/MssqlMcp/Node/src/index.ts index 8dc1f30..c41197e 100644 --- a/MssqlMcp/Node/src/index.ts +++ b/MssqlMcp/Node/src/index.ts @@ -24,22 +24,62 @@ import { DescribeTableTool } from "./tools/DescribeTableTool.js"; // MSSQL Database connection configuration // const credential = new DefaultAzureCredential(); +// Authentication types +type AuthenticationType = 'sql' | 'entra'; + // Globals for connection and token reuse let globalSqlPool: sql.ConnectionPool | null = null; let globalAccessToken: string | null = null; let globalTokenExpiresOn: Date | null = null; -// Function to create SQL config with fresh access token, returns token and expiry -export async function createSqlConfig(): Promise<{ config: sql.config, token: string, expiresOn: Date }> { +// Get authentication type from environment variable (defaults to 'entra' for backward compatibility) +function getAuthenticationType(): AuthenticationType { + const authType = process.env.AUTHENTICATION_TYPE?.toLowerCase(); + if (authType === 'sql') return 'sql'; + if (authType === 'entra') return 'entra'; + // Default to 'entra' for backward compatibility + return 'entra'; +} + +// Function to create SQL config - supports both SQL auth and Entra ID auth +export async function createSqlConfig(): Promise<{ config: sql.config, token: string | null, expiresOn: Date | null }> { + const trustServerCertificate = process.env.TRUST_SERVER_CERTIFICATE?.toLowerCase() === 'true'; + const connectionTimeout = process.env.CONNECTION_TIMEOUT ? parseInt(process.env.CONNECTION_TIMEOUT, 10) : 30; + const authType = getAuthenticationType(); + + if (authType === 'sql') { + // Use SQL Server authentication (username/password) + const sqlUser = process.env.SQL_USER; + const sqlPassword = process.env.SQL_PASSWORD; + + if (!sqlUser || !sqlPassword) { + throw new Error('SQL authentication requires SQL_USER and SQL_PASSWORD environment variables'); + } + + return { + config: { + server: process.env.SERVER_NAME!, + database: process.env.DATABASE_NAME!, + user: sqlUser, + password: sqlPassword, + options: { + encrypt: true, + trustServerCertificate + }, + connectionTimeout: connectionTimeout * 1000, // convert seconds to milliseconds + }, + token: null, + expiresOn: null + }; + } + + // Use Entra ID (Azure AD) authentication const credential = new InteractiveBrowserCredential({ redirectUri: 'http://localhost' // disableAutomaticAuthentication : true }); const accessToken = await credential.getToken('https://database.windows.net/.default'); - const trustServerCertificate = process.env.TRUST_SERVER_CERTIFICATE?.toLowerCase() === 'true'; - const connectionTimeout = process.env.CONNECTION_TIMEOUT ? parseInt(process.env.CONNECTION_TIMEOUT, 10) : 30; - return { config: { server: process.env.SERVER_NAME!, @@ -164,8 +204,16 @@ runServer().catch((error) => { // Connect to SQL only when handling a request async function ensureSqlConnection() { - // If we have a pool and it's connected, and the token is still valid, reuse it + const authType = getAuthenticationType(); + + // If using SQL auth, just check if pool is connected (no token expiry to worry about) + if (authType === 'sql' && globalSqlPool && globalSqlPool.connected) { + return; + } + + // If using Entra ID auth, check if pool is connected and token is still valid if ( + authType === 'entra' && globalSqlPool && globalSqlPool.connected && globalAccessToken && @@ -175,7 +223,7 @@ async function ensureSqlConnection() { return; } - // Otherwise, get a new token and reconnect + // Otherwise, get config (and new token if using Entra ID) and reconnect const { config, token, expiresOn } = await createSqlConfig(); globalAccessToken = token; globalTokenExpiresOn = expiresOn; diff --git a/MssqlMcp/Node/src/samples/claude_desktop_config.json b/MssqlMcp/Node/src/samples/claude_desktop_config.json index 5f2c0fa..8714389 100644 --- a/MssqlMcp/Node/src/samples/claude_desktop_config.json +++ b/MssqlMcp/Node/src/samples/claude_desktop_config.json @@ -6,6 +6,7 @@ "env": { "SERVER_NAME": "your-server-name.database.windows.net", "DATABASE_NAME": "your-database-name", + "AUTHENTICATION_TYPE": "entra", "READONLY": "false" } } diff --git a/MssqlMcp/Node/src/samples/vscode_agent_config.json b/MssqlMcp/Node/src/samples/vscode_agent_config.json index a8f91ff..85cfe24 100644 --- a/MssqlMcp/Node/src/samples/vscode_agent_config.json +++ b/MssqlMcp/Node/src/samples/vscode_agent_config.json @@ -8,6 +8,7 @@ "env": { "SERVER_NAME": "your-server-name.database.windows.net", "DATABASE_NAME": "your-database-name", + "AUTHENTICATION_TYPE": "entra", "READONLY": "false" } }