# MS SQL Server MCP Server v3.0.0 ๐Ÿš€ **Model Context Protocol (MCP) server** for Microsoft SQL Server - compatible with Claude Desktop, Cursor, Windsurf and VS Code. [![CI](https://github.com/BYMCS/mssql-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/BYMCS/mssql-mcp/actions/workflows/ci.yml) [![npm version](https://img.shields.io/npm/v/mssql-mcp.svg)](https://www.npmjs.com/package/mssql-mcp) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) ## Standards Alignment - Protocol target: [MCP draft/latest spec](https://modelcontextprotocol.io/specification/draft/server/tools) - Transport spec: [Transports](https://modelcontextprotocol.io/specification/draft/basic/transports) - Security: [Security best practices](https://modelcontextprotocol.io/docs/tutorials/security/security_best_practices) - SDK: `@modelcontextprotocol/server` / `@modelcontextprotocol/client` / `@modelcontextprotocol/node` v2 (`2.0.0`), targeting the 2026-07-28 MCP spec - Requires Node.js >= 20 ## ๐Ÿš€ Quick Start ### 1. Install ```bash npm install -g mssql-mcp ``` ### 2. Configure IDE **Claude Desktop** (`claude_desktop_config.json`): ```json { "mcpServers": { "mssql": { "command": "npx", "args": ["-y", "mssql-mcp@latest"], "env": { "DB_SERVER": "your-server.com", "DB_DATABASE": "your-database", "DB_USER": "your-username", "DB_PASSWORD": "your-password", "DB_ENCRYPT": "true", "DB_TRUST_SERVER_CERTIFICATE": "true" } } } } ``` **Cursor/Windsurf/VS Code** (`.vscode/mcp.json`): ```json { "servers": { "mssql": { "command": "npx", "args": ["-y", "mssql-mcp@latest"], "env": { "DB_SERVER": "your-server.com", "DB_DATABASE": "your-database", "DB_USER": "your-username", "DB_PASSWORD": "your-password", "DB_ENCRYPT": "true", "DB_TRUST_SERVER_CERTIFICATE": "true" } } } } ``` **HTTP transport** (remote/hosted scenarios): ```json { "servers": { "mssql": { "type": "http", "url": "http://127.0.0.1:3001", "env": {} } } } ``` > Replace with your actual database credentials. Credentials are read from the **server environment only** โ€” never passed as tool parameters. ## ๏ฟฝ๏ฟฝ๏ธ Tool Catalog ### Primary tools (use these) | Tool | Read-only | Description | |------|-----------|-------------| | `mssql_connect_database` | No | Connect using env variables. Idempotent. | | `mssql_disconnect_database` | No | Close connection. Idempotent. | | `mssql_connection_status` | โœ… | Connection state and pool metrics | | `mssql_run_sql_query` | โš ๏ธ No | Execute arbitrary SQL. **May mutate data.** | | `mssql_list_schema_objects` | โœ… | List tables/views/procedures/functions with pagination | | `mssql_describe_table_columns` | โœ… | Column definitions for a table | | `mssql_read_table_rows` | โœ… | Paginated rows with projection and safe WHERE | | `mssql_execute_stored_procedure` | โš ๏ธ No | Execute a stored procedure | | `mssql_list_databases` | โœ… | List all databases on the instance | All data tools accept a `response_format` parameter (`"json"` | `"markdown"`, default `"json"`). Use `"markdown"` to get human-readable table output. ### Deprecated aliases (still registered for backward compatibility) These are the only alias tool names the server actually registers (in `src/tools/*.ts`). They behave the same as their replacement but are not documented in new integrations โ€” use the primary tool names above instead. | Old name | Use instead | |----------|-------------| | `mssql_execute_query` | `mssql_run_sql_query` | | `mssql_get_schema` | `mssql_list_schema_objects` | | `mssql_describe_table` | `mssql_describe_table_columns` | | `mssql_get_table_data` | `mssql_read_table_rows` | | `mssql_execute_procedure` | `mssql_execute_stored_procedure` | ## ๐ŸšŒ Transport Modes | Mode | Use when | |------|----------| | `stdio` (default) | Local IDE integration (Claude Desktop, Cursor, VS Code) | | `http` | Remote/hosted deployment, testing with MCP Inspector | ```bash # stdio (default) node dist/src/index.js # HTTP on 127.0.0.1:3001 MCP_TRANSPORT=http node dist/src/index.js # Custom HTTP host/port MCP_TRANSPORT=http MCP_HOST=0.0.0.0 MCP_PORT=8080 node dist/src/index.js ``` ## ๐Ÿ”ง Environment Variables ### Database connection | Variable | Required | Default | Description | |----------|----------|---------|-------------| | `DB_SERVER` | โœ… | โ€” | SQL Server hostname or IP | | `DB_DATABASE` | โŒ | โ€” | Database name | | `DB_USER` | โŒ | โ€” | Login username | | `DB_PASSWORD` | โŒ | โ€” | Login password | | `DB_PORT` | โŒ | 1433 | TCP port | | `DB_ENCRYPT` | โŒ | true | Enable TLS (required for Azure SQL) | | `DB_TRUST_SERVER_CERTIFICATE` | โŒ | false | Trust self-signed certs | | `DB_CONNECTION_TIMEOUT` | โŒ | 30000 | Connection timeout ms | | `DB_REQUEST_TIMEOUT` | โŒ | 30000 | Query timeout ms | ### Transport | Variable | Default | Description | |----------|---------|-------------| | `MCP_TRANSPORT` | `stdio` | `stdio` or `http` | | `MCP_HOST` | `127.0.0.1` | HTTP bind address | | `MCP_PORT` | `3001` | HTTP port | ## ๐Ÿ”’ Security Model - **No credential parameters**: All connection settings come from environment variables only. Tool inputs cannot override connection config. - **Identifier validation**: Schema, table, and procedure names are validated against a safe identifier pattern before interpolation into SQL. - **Parameterized queries**: All user-supplied values (WHERE clause values, column values) must be passed as named parameters via `@paramName` โ€” never embedded in query strings. - **Origin and Host validation**: HTTP transport validates both the `Origin` and `Host` headers against an allowlist (localhost, `[::1]`, and the configured bind host by default), guarding against DNS rebinding. - **SQL risk labeling**: `run_sql_query` and `execute_stored_procedure` are explicitly labeled as non-read-only and open-world. ### โš ๏ธ SQL Risk Notes `run_sql_query` accepts arbitrary SQL including DDL and DML. To minimize risk: - Use a least-privilege SQL login (SELECT-only where possible) - Never run the server with a `sysadmin` or `sa` account - Consider network firewall rules to limit what the server can reach ## ๐Ÿ“„ Pagination All list tools return a `pagination` object: ```json { "count": 20, "limit": 20, "offset": 0, "has_more": true, "next_offset": 20, "total_count": 150 } ``` Default page size: **20 rows**. Maximum: **200 rows**. Results are also truncated if the serialized payload exceeds 100KB, with a `truncation_message` explaining how many rows were dropped. ## ๐Ÿ—๏ธ Architecture ``` src/ index.ts โ† bootstrap (env, transport selection) server.ts โ† createServer() factory constants.ts โ† limits, defaults, protocol strings config.ts โ† env parsing types.ts โ† shared TypeScript interfaces db/ connection.ts โ† connection pool singleton validators.ts โ† SQL identifier validation query-builders.ts โ† safe parameterized query construction tools/ โ† one file per tool group resources/ โ† MCP resource handlers transports/ โ† stdio and HTTP transports utils/ errors.ts โ† error normalization helpers format.ts โ† JSON formatting, payload truncation markdown.ts โ† markdown table/list rendering helpers pagination.ts โ† pagination metadata helpers ``` ## ๐Ÿงช Inspector Smoke Test ```bash npx @modelcontextprotocol/inspector ``` Expected: - stdio server connects - Tool list renders with all tools - `mssql_connection_status` returns JSON without a connection - `mssql_connect_database` works when env variables are set ## ๐Ÿ”จ Development ```bash npm install cp .env.example .env # fill in your test DB credentials npm run typecheck # type check only npm run build # compile TypeScript npm test # run unit tests npm run ci # typecheck + build + test ``` ## License [MIT](LICENSE) ยฉ BYMCS