MS SQL Server MCP Server
# MS SQL Server MCP Server v2.3.6
๐ **Model Context Protocol (MCP) server** for Microsoft SQL Server - compatible with Claude Desktop, Cursor, Windsurf and VS Code.
[](https://github.com/BYMCS/mssql-mcp/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/mssql-mcp)
[](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/sdk` pinned to `1.28.0`
## ๐ 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 work for backward compatibility)
| Old name | Use instead |
|----------|-------------|
| `connect_database` | `mssql_connect_database` |
| `disconnect_database` | `mssql_disconnect_database` |
| `connection_status` | `mssql_connection_status` |
| `execute_query` | `mssql_run_sql_query` |
| `run_sql_query` | `mssql_run_sql_query` |
| `get_schema` | `mssql_list_schema_objects` |
| `list_schema_objects` | `mssql_list_schema_objects` |
| `describe_table` | `mssql_describe_table_columns` |
| `describe_table_columns` | `mssql_describe_table_columns` |
| `get_table_data` | `mssql_read_table_rows` |
| `read_table_rows` | `mssql_read_table_rows` |
| `execute_procedure` | `mssql_execute_stored_procedure` |
| `execute_stored_procedure` | `mssql_execute_stored_procedure` |
| `list_databases` | `mssql_list_databases` |
## ๐ 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 validation**: HTTP transport validates `Origin` header and only allows localhost by default.
- **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
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
TDQS
Scored across 14 tools
Several tools are duplicates with different names (e.g., mssql_get_table_data vs mssql_read_table_rows, mssql_execute_query vs mssql_run_sql_query). Descriptions clearly mark deprecated aliases, reducing confusion, but the presence of both still creates ambiguity about which to use.
Tool names follow a mssql_ prefix but use inconsistent verb patterns: connect/disconnect, get/run/execute/list/describe/read. The deprecated aliases introduce further inconsistency (e.g., get_table_data vs read_table_rows, execute_procedure vs execute_stored_procedure). No uniform verb_noun convention.
14 tools is within the acceptable range, but 5 are deprecated aliases, inflating the count and adding redundancy. The unique tool set is about 9, which is well-scoped. Slightly heavier than needed but not excessive.
The server covers core SQL Server operations: connection management, arbitrary query execution, table reads, schema listing, column descriptions, stored procedures, and database listing. Arbitrary SQL covers writes, so no major dead ends. Minor gaps include no transaction control or bulk operation tools.