Skip to main content
Glama
AshwathDAzur

sqlserver

by AshwathDAzur

MCP SQL Server Server

A Model Context Protocol (MCP) server that provides tools to interact with SQL Server databases. This server allows Cursor and other MCP clients to query, analyze, and manage SQL Server data intelligently.

Features

  • Execute SQL Queries: Run SELECT queries safely to retrieve data

  • List Tables: Discover all tables in the database

  • Get Table Schema: Inspect table structure, columns, and data types

  • Get Table Statistics: View row counts and column information

  • Insert Data: Add new records to tables

  • Update Data: Modify existing records

Related MCP server: Python MSSQL MCP Server

Prerequisites

  • Node.js v22.14.0 or higher

  • Docker version 28.3.3 or higher

  • SQL Server running in Docker (or access to an existing SQL Server instance)

Step-by-Step Setup Guide

Step 1: Install Dependencies

npm install

This will install all required packages including:

  • @modelcontextprotocol/sdk - MCP SDK for building the server

  • mssql - SQL Server driver for Node.js

  • typescript - TypeScript compiler

  • tsx - TypeScript execution environment

Step 2: Start SQL Server with Docker

The project includes a docker-compose.yml file that will automatically:

  • Start SQL Server 2022

  • Create the SampleDB database

  • Create sample tables (Customers, Products, Orders, OrderItems)

  • Insert sample data

Start the SQL Server container:

docker-compose up -d

Verify the container is running:

docker ps

You should see a container named mcp-sqlserver running.

Wait for initialization: The database initialization script runs automatically. You can check the logs:

docker logs mcp-sqlserver

Note: The default password is YourStrong@Passw0rd. If you need to change it, update both docker-compose.yml and .env files.

Step 3: Configure Environment Variables

Copy the example environment file:

copy .env.example .env

Edit .env and ensure the connection details match your Docker setup:

SQL_SERVER_HOST=localhost
SQL_SERVER_PORT=1433
SQL_SERVER_DATABASE=SampleDB
SQL_SERVER_USER=sa
SQL_SERVER_PASSWORD=YourStrong@Passw0rd
SQL_SERVER_ENCRYPT=false

Step 4: Build the MCP Server

Compile the TypeScript code:

npm run build

This creates the dist/ directory with the compiled JavaScript.

Step 5: Test the MCP Server

You can test the server manually to ensure it works:

npm start

The server will start and listen on stdio (standard input/output). Press Ctrl+C to stop.

Step 6: Configure Cursor IDE

To use this MCP server in Cursor, you need to add it to Cursor's MCP configuration.

Option A: Using Cursor Settings UI

  1. Open Cursor IDE

  2. Go to Settings (Ctrl+,)

  3. Search for "MCP" or "Model Context Protocol"

  4. Click on "MCP Servers" or "Add MCP Server"

  5. Add a new server with these settings:

    • Name: sqlserver

    • Command: node

    • Args: ["dist/index.js"]

    • Working Directory: C:\OrgProjects\SkillUps\ModelContextProtocol (or your actual project path)

    • Environment Variables:

      • SQL_SERVER_HOST=localhost

      • SQL_SERVER_PORT=1433

      • SQL_SERVER_DATABASE=SampleDB

      • SQL_SERVER_USER=sa

      • SQL_SERVER_PASSWORD=YourStrong@Passw0rd

      • SQL_SERVER_ENCRYPT=false

Option B: Using Configuration File (Windows)

  1. Navigate to Cursor's configuration directory:

    %APPDATA%\Cursor\User\globalStorage\saoudrizwan.claude-dev\settings\
  2. Edit or create cline_mcp_settings.json and add:

{
  "mcpServers": {
    "sqlserver": {
      "command": "node",
      "args": ["C:\\\\OrgProjects\\\\SkillUps\\\\ModelContextProtocol\\\\dist\\\\index.js"],
      "env": {
        "SQL_SERVER_HOST": "localhost",
        "SQL_SERVER_PORT": "1433",
        "SQL_SERVER_DATABASE": "SampleDB",
        "SQL_SERVER_USER": "sa",
        "SQL_SERVER_PASSWORD": "YourStrong@Passw0rd",
        "SQL_SERVER_ENCRYPT": "false"
      }
    }
  }
}

Important: Replace C:\\OrgProjects\\SkillUps\\ModelContextProtocol with your actual project path.

  1. Restart Cursor IDE for changes to take effect.

Step 7: Verify MCP Server in Cursor

  1. Restart Cursor after adding the configuration

  2. Open a chat in Cursor

  3. Try asking questions like:

    • "List all tables in the database"

    • "Show me the schema of the Customers table"

    • "Get statistics for the Products table"

    • "Run a query to show all customers"

    • "Show me customers from New York"

The AI should now be able to use the MCP tools to interact with your SQL Server database!

Available MCP Tools

1. execute_query

Execute a SELECT query to retrieve data.

Example:

{
  "query": "SELECT TOP 10 * FROM Customers"
}

2. list_tables

List all tables in the database.

Example:

{}

3. get_table_schema

Get the schema of a specific table.

Example:

{
  "tableName": "Customers"
}

4. get_table_stats

Get statistics about a table (row count, columns).

Example:

{
  "tableName": "Products"
}

5. execute_insert

Insert a new record into a table.

Example:

{
  "tableName": "Customers",
  "data": {
    "FirstName": "John",
    "LastName": "Doe",
    "Email": "john.doe@example.com",
    "City": "Seattle"
  }
}

6. execute_update

Update existing records in a table.

Example:

{
  "tableName": "Customers",
  "data": {
    "City": "Portland"
  },
  "where": {
    "CustomerID": 1
  }
}

Sample Database Schema

The initialization script creates a sample e-commerce database with:

  • Customers: Customer information

  • Products: Product catalog

  • Orders: Customer orders

  • OrderItems: Order line items

Development

Run in Development Mode

npm run dev

This uses tsx watch to automatically recompile on file changes.

Project Structure

.
├── src/
│   └── index.ts          # Main MCP server implementation
├── dist/                 # Compiled JavaScript (generated)
├── init-db/              # SQL initialization scripts
│   └── 01-init-sample-db.sql
├── docker-compose.yml    # Docker setup for SQL Server
├── package.json          # Node.js dependencies
├── tsconfig.json         # TypeScript configuration
└── README.md             # This file

Troubleshooting

SQL Server Connection Issues

  1. Check if SQL Server is running:

    docker ps
  2. Check SQL Server logs:

    docker logs mcp-sqlserver
  3. Verify connection details in .env match your Docker setup

  4. Test connection manually:

    docker exec -it mcp-sqlserver /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P YourStrong@Passw0rd -Q "SELECT @@VERSION"

MCP Server Not Appearing in Cursor

  1. Verify the path in the configuration is correct and absolute

  2. Check that the build succeeded: npm run build

  3. Ensure the server starts without errors: npm start

  4. Restart Cursor after configuration changes

  5. Check Cursor's developer console for MCP-related errors

Permission Issues

  • Ensure SQL Server credentials are correct

  • Verify the database exists and is accessible

  • Check that the SA password matches in both docker-compose.yml and .env

Security Notes

  • Never commit .env files to version control

  • The execute_query tool only allows SELECT queries for security

  • Use strong passwords in production

  • Consider using environment-specific configurations

Next Steps

  • Explore the sample data using natural language queries in Cursor

  • Try asking complex questions that require joins

  • Add more tables or modify the schema as needed

  • Extend the MCP server with additional tools for your use case

License

MIT

Available Tools

6 tools
execute_insertA

Insert data into a table. Returns the inserted row ID if available.

ParametersJSON Schema
NameRequiredDescriptionDefault
dataYesObject with column names as keys and values to insert
tableNameYesName of the table to insert into

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the transparency burden. It discloses a behavioral trait: the function returns the inserted row ID 'if available,' hinting at possible unavailability. However, it does not state side effects (e.g., data mutation), permission needs, or error conditions, leaving gaps for a write operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences, front-loading the core action. Every word contributes: 'Insert data into a table' states the function, and the second sentence provides a useful return detail. No redundancy or fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with a clear schema, the description covers the action and return value. However, with no output schema, it omits when the row ID might be unavailable and gives no hint about constraints or error behavior. It is close to complete but lacks a few contextual edges.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the parameters are already well documented. The description adds no extra meaning beyond the schema—it doesn't explain how the 'data' object should be structured or any special tableName considerations. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Insert data into a table.' This clearly distinguishes the tool from siblings like execute_query and execute_update by focusing on the insert operation. Adding the return behavior ('Returns the inserted row ID if available') further clarifies purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus alternatives. It does not mention when to prefer insert over update/query, nor does it state conditions like table existence or constraint requirements. The description only states what the tool does, not when to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

execute_queryA

Execute a SQL query and return results. Use for SELECT queries to retrieve data.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesThe SQL query to execute (SELECT only)

TDQS

A3.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions executing a query and returning results, and says 'Use for SELECT queries', which implies a read-only nature, but does not explicitly state that it cannot modify data, nor does it mention side effects, permissions, or return format specifics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short sentences with no unnecessary words. It conveys the primary purpose and usage context succinctly, earning a perfect score for conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (one parameter, no output schema), the description is adequate: it explains the action, the return of results, and the applicable query type. It lacks a few details like explicit read-only assurance, but overall it is sufficiently complete for straightforward usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 100% parameter description coverage with 'The SQL query to execute (SELECT only)'. The description adds no significant semantic meaning beyond what the schema already provides, though it does reinforce the SELECT-only constraint. Baseline of 3 is appropriate given full schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool executes SQL queries and returns results, specifically for SELECT queries to retrieve data. This distinctly separates it from siblings like execute_insert and execute_update, which handle mutations, and from metadata tools like list_tables.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance to use this tool for SELECT queries, clearly indicating the appropriate use case. It does not explicitly mention alternatives or exclusions, but the intended context is strongly implied, making it effective.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

execute_updateB

Update data in a table. Returns the number of affected rows.

ParametersJSON Schema
NameRequiredDescriptionDefault
dataYesObject with column names as keys and new values
whereYesObject with column names as keys and values for WHERE clause
tableNameYesName of the table to update

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden of behavioral disclosure. It mentions the return value (affected rows) but does not explicitly warn about irreversible data modification, permission requirements, or that updates are limited to rows matching the WHERE clause. Minimal risk information is provided.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise: one sentence with two clauses. Every word earns its place, and the return value is front-loaded, making it easy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is adequate for a simple update command but lacks explicit emphasis on the WHERE-clause filtering, which is crucial for safe usage. Since the where parameter is required, the description could clarify that only matching rows are updated, but the schema conveys this. With no annotations or output schema, the description is serviceable but leaves some context implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema covers all three parameters with descriptions, so the baseline is 3. The tool description does not add extra parameter-level meaning beyond what the schema offers; it only provides the return behavior, which is not parameter-specific.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states 'Update data in a table' with a specific verb and resource, clearly distinguishing it from siblings like execute_query and execute_insert. The purpose is unambiguous and immediately understandable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives. There is no mention of prerequisites, exclusions, or comparison with execute_insert or execute_query, leaving the agent to infer usage from the name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_table_schemaA

Get the schema/structure of a table including column names, types, and constraints

ParametersJSON Schema
NameRequiredDescriptionDefault
tableNameYesName of the table to get schema for

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden for behavioral disclosure. It implies a read-only operation via 'Get', but it doesn't explicitly address permissions, error conditions, or side effects. However, the tool is simple and the omission isn't critical, so it stays at a baseline adequate level.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence with no filler. It efficiently conveys the tool's purpose and key output details without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description explains what the tool returns (columns, types, constraints) and has a single clearly described parameter. Without an output schema or annotations, this is sufficient, though slightly more detail about error handling or return format could be useful.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema fully describes the tableName parameter (100% coverage), so the description does not add meaning beyond what is already provided. The description's mention of schema contents relates to the return value, not the parameter, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves a table's schema/structure, specifying the included elements (column names, types, constraints). This distinguishes it from sibling tools like list_tables or get_table_stats, which have different purposes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use the tool (when you need a table's schema), but it doesn't explicitly mention alternatives or exclusions. It could have indicated use cases for sibling tools, but the context is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_table_statsB

Get statistics about a table including row count and column information

ParametersJSON Schema
NameRequiredDescriptionDefault
tableNameYesName of the table to get statistics for

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It transparently indicates the tool is a read-only data retrieval (get statistics), but it omits details such as whether column information covers data types, nullable flags, or other schema details, and does not mention performance implications or failure modes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, concise sentence that front-loads the verb and resource. It wastes no words and clearly communicates the core function.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With one simple parameter and no output schema, the description provides the key outputs (row count, column information) but omits potential additional statistics and error behavior. It is functional but leaves some ambiguity about the exact return structure.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents the tableName parameter. The description adds 'including row count and column information' which loosely maps to the output, but it does not add new meaning to the parameter itself beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool 'gets statistics' about a table, naming the specific resource and outputs (row count, column information). It is a specific verb+resource combination, but it does not explicitly distinguish itself from siblings like get_table_schema or execute_query, which could also retrieve related data.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is given on when to use this tool over alternatives such as execute_query or get_table_schema. The description implies usage for retrieving table statistics, but it does not state exclusions or comparison with siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_tablesA

List all tables in the database

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. 'List all tables' clearly indicates a read-only enumeration, but it does not disclose potential performance implications, whether system tables are included, or any other behavioral nuances. This is adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, simple sentence of six words that precisely states the tool's function. It is front-loaded and contains no filler, earning a perfect score for conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter list operation with no output schema and no annotations, the description gives the essential purpose. However, it does not specify the return format (e.g., an array of table names) or whether the list is ordered or filtered. A brief note about the output would improve completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so there is no parameter information to convey. The baseline of 4 applies because the description needs to add nothing beyond the schema, which is empty.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb 'List' and clearly identifies the resource as 'tables in the database'. This distinguishes it from siblings like execute_query and get_table_schema, which operate on query results or individual table schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool is for enumerating database tables, which provides clear context for when to use it. It does not explicitly exclude alternatives or mention siblings, but the purpose is self-evident in a database toolset.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 6 tool updatesv1.0.0
    • First observedexecute_insert
    • First observedexecute_query
    • First observedexecute_update
    • First observedget_table_schema
    • First observedget_table_stats
    • First observedlist_tables

TDQS

A3.6/5.0

Scored across 6 tools

Disambiguation5/5

Each tool targets a distinct action: SELECT retrieval, listing tables, schema inspection, statistics, inserts, and updates. There is no overlap between query, DML, and metadata operations, making selection straightforward.

Naming Consistency3/5

Naming mixes execute_query/execute_insert/execute_update with list_tables and get_table_schema/get_table_stats. The pattern is not uniform (execute_ vs list_ vs get_table_), though it remains readable and predictable within subgroups.

Tool Count5/5

Six tools is a well-scoped set for a SQL server, covering query, data modification, and metadata needs without excessive surface area.

Completeness2/5

The toolset covers SELECT, INSERT, UPDATE, and metadata, but lacks a DELETE operation, DDL support (CREATE/ALTER/DROP), and transaction control. These are significant gaps that will hinder common database workflows.

Maintenance

ActivityInactive
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    A Model Context Protocol server that enables AI assistants (Cursor, Windsurf, Claude Code) to interact with Microsoft SQL Server databases by providing connectivity through environment-configurable connections.
    8
    494
    8
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables Language Models to interact with Microsoft SQL Server databases by inspecting table schemas, executing SQL queries, and reading table data through a standardized Model Context Protocol interface.
    27
    -
  • F
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to query SQL Server databases and retrieve schema information securely through the Model Context Protocol.
    2
    -