Labsco
alyiox logo

SQL Server MCP

β˜… 7

from alyiox

A read-only Model Context Protocol (MCP) server for Microsoft SQL Server, enabling safe metadata discovery and parameterized SELECT queries.

πŸ”₯πŸ”₯πŸ”₯πŸ”₯βœ“ VerifiedFreeQuick setup

MCP SQL Server Tool

A read-only Model Context Protocol (MCP) server for Microsoft SQL Server that supports metadata discovery, parameterized queries, and query analysis, with profile-based configuration and strict no-DML/DDL enforcement.

Requirements: .NET 8.0 or later runtime (the tool targets net8.0 and net10.0), SQL Server, and a connection string. Building from source requires the .NET 10.0 SDK.

Tools and resources

All tools accept an optional profile; when omitted, the default profile is used.

Tools

ToolDescriptionKey params
list_profilesList configured connection profiles. Call first when picking a non-default profile.β€”
get_server_propertiesGet server properties and execution limits (timeouts, row caps, guardrails).profile
list_objectsList catalog metadata. kind=catalog: databases; schema: schemas; relation: tables/views; routine: procedures/functions. catalog omitted β†’ active catalog (ignored for kind=catalog). schema omission depends on kind.kind, profile, catalog, schema
get_objectGet metadata for one relation or routine. Use list_objects to resolve names. Returns empty detail payloads if includes is null.kind, name, profile, catalog, schema, includes
run_queryExecute read-only T-SQL SELECT; only SELECT allowed (no DML/DDL). Returns results as CSV in the data field (inline) or a snapshot resource URI when snapshot=true. Inline limit: 500 rows (hard ceiling 1000). Snapshot limit: 10 000 rows. Prefer analyze_query for plan tuning.sql, profile, catalog, parameters, snapshot
analyze_queryAnalyze execution plan for a read-only SELECT. Returns compact JSON summary (cost, operators, cardinality, warnings, indexes, waits, stats). Fetch full XML from plan_uri; does not return result rows.sql, profile, catalog, parameters, estimated
  • kind β€” catalog, schema, relation, or routine. For get_object, only relation or routine.
  • includes β€” Array of detail sections: columns, indexes, constraints (relations only), definition (routines only).

Resources

URI templateDescription
mssql://profilesList configured connection profiles. Same data as list_profiles.
mssql://server-properties?{profile}Get server properties and execution limits. Same data as get_server_properties.
mssql://objects?{kind,profile,catalog,schema}List catalog metadata. Schema omission behavior matches list_objects.
mssql://objects/{kind}/{name}{?profile,catalog,schema,includes}Get metadata for one relation or routine. includes is required.
mssql://plans/{id}Retrieve full XML execution plan by ID from analyze_query; entries expire after 7 days.
mssql://snapshots/{id}Retrieve full query result as CSV by ID from run_query (snapshot=true); entries expire after 1 day.

Resources mirror their corresponding tools and return JSON (except mssql://plans/{id} which returns XML and mssql://snapshots/{id} which returns CSV).

Security

Read-only (SELECT only); parameterized @paramName. Use environment variables or user-secrets for connection stringsβ€”never commit secrets.

MCP host examples

Snippets for common MCP clients. Replace the connection string with your own; ensure dotnet is on your PATH. The env block is not required if the connection string is already set via appsettings.json or environment variables.

Cursor

{
  "mcpServers": {
    "mssql": {
      "command": "dotnet",
      "args": ["dnx", "Alyio.McpMssql", "--prerelease", "--yes"],
      "env": {
        "MCPMSSQL_CONNECTION_STRING": "Server=127.0.0.1;User ID=sa;Password=<YourStrong@Passw0rd>;Encrypt=True;TrustServerCertificate=True;"
      }
    }
  }
}

Gemini

{
  "mcpServers": {
    "mssql": {
      "command": "dotnet",
      "args": ["dnx", "Alyio.McpMssql", "--prerelease", "--yes"],
      "env": {
        "MCPMSSQL_CONNECTION_STRING": "Server=127.0.0.1;User ID=sa;Password=<YourStrong@Passw0rd>;Encrypt=True;TrustServerCertificate=True;"
      }
    }
  }
}

Codex

[mcp_servers.mssql]
command = "dotnet"
args = ["dnx", "Alyio.McpMssql", "--prerelease", "--yes"]
[mcp_servers.mssql.env]
MCPMSSQL_CONNECTION_STRING = "Server=127.0.0.1;User ID=sa;Password=<YourStrong@Passw0rd>;Encrypt=True;TrustServerCertificate=True;"

Open Code

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "mssql": {
      "type": "local",
      "enabled": true,
      "command": ["dotnet", "dnx", "Alyio.McpMssql", "--prerelease", "--yes"],
      "environment": {
        "MCPMSSQL_CONNECTION_STRING": "Server=127.0.0.1;User ID=sa;Password=<YourStrong@Passw0rd>;Encrypt=True;TrustServerCertificate=True;"
      }
    }
  }
}

Claude Code

{
  "mcpServers": {
    "mssql": {
      "command": "dotnet",
      "args": ["dnx", "Alyio.McpMssql", "--prerelease", "--yes"],
      "env": {
        "MCPMSSQL_CONNECTION_STRING": "Server=127.0.0.1;User ID=sa;Password=<YourStrong@Passw0rd>;Encrypt=True;TrustServerCertificate=True;"
      }
    }
  }
}

GitHub Copilot

{
  "inputs": [],
  "servers": {
    "mssql": {
      "type": "stdio",
      "command": "dotnet",
      "args": ["dnx", "Alyio.McpMssql", "--prerelease", "--yes"],
      "env": {
        "MCPMSSQL_CONNECTION_STRING": "Server=127.0.0.1;User ID=sa;Password=<YourStrong@Passw0rd>;Encrypt=True;TrustServerCertificate=True;"
      }
    }
  }
}

Integration tests

Tests use a real SQL Server and the default profile (MCPMSSQL_CONNECTION_STRING from environment variables or user-secrets). The suite expects a database named McpMssqlTest: the connection string must include Initial Catalog=McpMssqlTest. The test infrastructure creates, seeds, and drops this database. Set the secret for the test project:

dotnet user-secrets set "MCPMSSQL_CONNECTION_STRING" \
  "Server=localhost,1433;User ID=sa;Password=...;TrustServerCertificate=True;Encrypt=True;Initial Catalog=McpMssqlTest;" \
  --project test/Alyio.McpMssql.Tests

One framework at a time. The single McpMssqlTest database is shared by every test, and the fixtures drop and recreate it on initialization. Within one test process this is safe β€” the SqlServer collection disables parallelization. Across processes it is not: the test project targets both net8.0 and net10.0, and dotnet test runs the two framework modules in parallel, so they race on that one database. There is no cross-process locking, so run a single framework at a time:

dotnet test --framework net8.0
dotnet test --framework net10.0

CI does the same, iterating over TARGET_FRAMEWORKS sequentially.

Why this instead of Data API Builder?

Data API Builder (DAB) is a full REST/GraphQL API with CRUD and auth. This project is a small, read-only MCP server for agents: stdio, parameterized SELECT only, minimal surface. Choose this for agent workflows and low operational overhead; choose DAB for CRUD, REST/GraphQL, and rich policies.