Read-only MCP for Microsoft SQL Server: metadata discovery, parameterized SELECT, plans.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
π‘ Paste into ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows)
A read-only-by-default Model Context Protocol (MCP) server for Microsoft SQL Server that supports metadata discovery, parameterized queries, and query analysis, with profile-based configuration. The query tools enforce SELECT-only (no DML/DDL); an optional run_command tool can execute arbitrary write T-SQL, but only on profiles that explicitly opt in via AllowWrite (locked off by default).
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.
Set MCPMSSQL_CONNECTION_STRING and run the server in one of these ways:
Use --prerelease for pre-release builds.
All settings use the MCPMSSQL prefix. Flat environment variables (e.g. MCPMSSQL_CONNECTION_STRING) are the straightforward way to configure the default profile when you have a single connection. For multiple profiles, the user-scoped appsettings.json file is recommended.
Single connection: Configure via environment variables.
Multiple connections: Use the user-scoped appsettings.json file (recommended). Env vars also work via .NET host conventions (MCPMSSQL__PROFILES__<NAME>__CONNECTIONSTRING, etc.).
~/.config/mcp-mssql/appsettings.json%USERPROFILE%\.config\mcp-mssql\appsettings.jsonExample (appsettings.json):
Local development: Store the connection string in user-secrets, then run with DOTNET_ENVIRONMENT=Development so secrets load.
Azure SQL / Microsoft Entra ID: This MCP server uses Microsoft.Data.SqlClient, which supports Microsoft Entra (Azure AD) authentication. Set the Authentication property in the connection string to a supported mode (e.g. Active Directory Default, Active Directory Managed Identity, or Active Directory Interactive) when connecting to Azure SQL. See Connect to Azure SQL with Microsoft Entra authentication and SqlClient for all modes and details.
All tools accept an optional profile; when omitted, the default profile is used.
Tools
| Tool | Description | Key params |
|---|---|---|
list_profiles | List configured connection profiles. Call first when picking a non-default profile. | β |
get_server_properties | Get server properties and execution limits (timeouts, row caps, guardrails). | profile |
list_objects | List 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_object | Get 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_query | Execute 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_query | Analyze 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 |
run_command | Execute write T-SQL (DDL/DML). Rejected unless the target profile sets AllowWrite=true (off by default). Caller manages transactions. Returns rows_affected (β1 for DDL) and server messages. Marked destructive; intended for human-supervised use. | sql, profile, catalog, parameters |
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 template | Description |
|---|---|
mssql://profiles | List 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).
The query tools (run_query, analyze_query) are read-only (SELECT only) and use parameterized @paramName binding. Use environment variables or user-secrets for connection stringsβnever commit secrets.
Writes are opt-in. The run_command tool executes arbitrary T-SQL. It is rejected unless the target profile sets AllowWrite=true, which defaults to false, so existing deployments stay read-only with no change. The tool is always advertised and rejects at call time on locked profiles.
AllowWrite is a soft, application-level guard, not a security boundary β it constrains this server, not the database. For a genuine read-only guarantee, connect with a login restricted to db_datareader, and keep write-enabled profiles pointed at credentials scoped to only what they need. run_command is marked destructive via MCP tool annotations so hosts can gate it behind confirmation, but honor those annotations at the host's discretion.
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.
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:
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:
CI does the same, iterating over TARGET_FRAMEWORKS sequentially.
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.
Open issues or PRs; follow existing style and add tests where appropriate.
MIT. See LICENSE.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/microsoft-sql-server)<a href="https://allmcps.com/mcp/microsoft-sql-server"><img src="https://allmcps.com/api/badge/microsoft-sql-server?style=directory" alt="Microsoft SQL Server on AllMCPs" /></a>