🚀 Model Context Protocol (MCP) server for Microsoft SQL Server - compatible with Claude Desktop, Cursor, Windsurf and VS Code.
- Protocol target: MCP draft/latest spec
- Transport spec: Transports
- Security: Security best practices
- SDK:
@modelcontextprotocol/server/@modelcontextprotocol/client/@modelcontextprotocol/nodev2 (2.0.0), targeting the 2026-07-28 MCP spec - Requires Node.js >= 20
npm install -g mssql-mcpClaude Desktop (claude_desktop_config.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):
{
"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):
{
"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 | 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 |
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 |
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.
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 |
| Mode | Use when |
|---|---|
stdio (default) |
Local IDE integration (Claude Desktop, Cursor, VS Code) |
http |
Remote/hosted deployment, testing with MCP Inspector |
# 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| 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 |
| Variable | Default | Description |
|---|---|---|
MCP_TRANSPORT |
stdio |
stdio or http |
MCP_HOST |
127.0.0.1 |
HTTP bind address |
MCP_PORT |
3001 |
HTTP port |
- 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
OriginandHostheaders against an allowlist (localhost,[::1], and the configured bind host by default), guarding against DNS rebinding. - SQL risk labeling:
run_sql_queryandexecute_stored_procedureare explicitly labeled as non-read-only and open-world.
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
sysadminorsaaccount - Consider network firewall rules to limit what the server can reach
All list tools return a pagination object:
{
"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.
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
npx @modelcontextprotocol/inspectorExpected:
- stdio server connects
- Tool list renders with all tools
mssql_connection_statusreturns JSON without a connectionmssql_connect_databaseworks when env variables are set
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 + testMIT © BYMCS