Security 27 Sep 2026 · 5 min read

MCP servers for the Microsoft stack: SQL Server, Azure and Active Directory

Microsoft’s three MCP servers split the stack by layer, and the split has surprises: the Azure one’s SQL tools never read a row, the SQL one never lets the model write SQL, and on-premises Active Directory gets none.

MR mcprush team · The people who run the gateway

Look for an MCP server for SQL Server, Azure or Active Directory and you find dozens of near-identical repositories. Microsoft’s own answer is three servers, one per layer, and a gap: SQL MCP Server for rows in SQL Server and Azure SQL, Azure MCP Server for Azure resources, Microsoft MCP Server for Enterprise for read-only questions about Entra ID, and nothing for on-premises Active Directory. Here is what each reaches, what fills the gaps, and how to connect them read-only. Excel has its own Excel MCP server guide.

One official server per layer and an empty fourth column. The line under each box is what it will not do.One official server per layer and an empty fourth column. The line under each box is what it will not do.
One official server per layer and an empty fourth column. The line under each box is what it will not do.

SQL Server and Azure SQL: Microsoft’s SQL MCP Server

Microsoft’s MCP server for SQL Server ships inside Data API builder (DAB), its open-source .NET tool for APIs over a database: DAB 1.7 or later, with 2.0 generally available and Microsoft.DataApiBuilder 2.0.12 the stable NuGet release. It speaks stdio and Streamable HTTP, and it never turns the model’s sentence into SQL. The model picks a tool and an entity you configured; DAB writes the T-SQL. There is no DDL.

dotnet tool install --global Microsoft.DataApiBuilder # needs the .NET 8 runtime (the tool targets net8.0) dab init --database-type mssql --connection-string "@env('MSSQL_CONNECTION_STRING')" --host-mode Development --config dab-config.json dab add Products --source dbo.Products --permissions "anonymous:read" --description "Products with stock and price" dab configure --runtime.mcp.enabled true # write tools off, for every role dab configure --runtime.mcp.dml-tools.create-record false dab configure --runtime.mcp.dml-tools.update-record false dab configure --runtime.mcp.dml-tools.delete-record false
Microsoft’s quickstart, plus the switches that remove write tools from the tool list whatever the roles allow.
{ "servers": { "sql-mcp-server": { "type": "stdio", "command": "dab", "args": ["start", "--mcp-stdio", "role:anonymous", "--loglevel", "error", "--config", "${workspaceFolder}/dab-config.json"] } } }
Microsoft’s stdio entry for .vscode/mcp.json. The role after --mcp-stdio is the one the agent acts as.

The model sees up to seven tools: describe_entities, read_records, aggregate_records, execute_entity for stored procedures, and create, update and delete, filtered by role. read_records reads one table or view per call, so joins need a view or a procedure. Over HTTP, a config made by DAB 2.0’s dab init uses the Unauthenticated provider, so every request runs as anonymous and anyone who reaches /mcp gets that role. Over stdio DAB switches to the Simulator provider and acts as the role named after --mcp-stdio. Keep anonymous at read, and switch to the EntraId provider or put a gateway in front.

Community MCP servers for SQL Server, and what guards their writes

ServerInstallWhat guards the writes
DBHub (Bytebase)npm @bytebase/dbhubreadonly = true on execute_sql in dbhub.toml; there is no CLI flag
MSSQL MCP Readernpm @connorbritain/mssql-mcp-readerA read-only package; writes ship as separate packages
SqlAugurNuGet tool SqlAugurSELECT and WITH only, parsed with Microsoft’s T-SQL parser
MCP SQL Server (alyiox, not Microsoft)NuGet Alyio.McpMssqlNo write tool until a profile sets AllowWrite, which defaults to false
dbatools MCPnpm dbatools-mcp-serverSafe mode: changes need confirm: true
SqlServer.Rules (ErikEJ)NuGet tool ErikEJ.DacFX.TSQLAnalyzer.CliNever connects: it lints T-SQL scripts
sqlglassPyPI sqlglassRead-only execution
Unlike SQL MCP Server, most of these let the model write its own SELECT. More in the catalogue.

Azure MCP Server: it manages Azure SQL, it does not query it

The official Azure MCP Server ships as npm @azure/mcp, NuGet Azure.Mcp, PyPI msmcp-azure, a VS Code extension and a Docker image. Check the version first: npm’s latest tag points at a 3.0.0 beta (3.0.0-beta.47 as of 27 September 2026), so the @azure/mcp@latest in Microsoft’s own README installs a beta. The stable release is 2.0.5.

# stable, read-only, and only the services this job needs npx -y @azure/mcp@2.0.5 server start --read-only --namespace sql --namespace monitor
--read-only filters the tool list to read-only operations; --namespace hides the rest of Azure.

Namespace mode, one tool per service, is the default so VS Code stays under its 128-tool limit; the VS Code extension has azureMcp.readOnly and azureMcp.enabledServices for the same flags. The surprise: the sql namespace is control plane. It creates and deletes servers and databases, renames and updates databases, lists elastic pools and Entra admins, and adds or removes firewall rules. None of it queries a table.

Two servers with SQL in their tool names. Ask the left one for last week’s orders and you get a list of databases.Two servers with SQL in their tool names. Ask the left one for last week’s orders and you get a list of databases.
Two servers with SQL in their tool names. Ask the left one for last week’s orders and you get a list of databases.

It acts as you, trying local credentials from environment variables through the Azure CLI to a browser sign-in, and can do what that identity’s Azure roles allow. Tools that return secrets or change resources ask for consent first (elicitation) unless someone passes --dangerously-disable-elicitation, and telemetry is on until AZURE_MCP_COLLECT_TELEMETRY=false. See its listing, and the remote Microsoft Learn MCP server for documentation.

Active Directory and Entra ID: one official MCP server, in preview

For the cloud directory there is Microsoft MCP Server for Enterprise, remote, at https://mcp.svc.cloud.microsoft/enterprise. It is in public preview, read-only and delegated-only: it acts as the signed-in user, within their roles and consented scopes, and never app-only. Three tools turn a question into Microsoft Graph reads about users, groups, apps, devices and reports; every scope, such as MCP.User.Read.All, is a read. Sign-in is delegated OAuth, the arrangement covered in our authentication guide.

# once per tenant, as Application Administrator or Cloud Application Administrator Install-Module Microsoft.Entra.Beta -Force -AllowClobber # 1.0.13 or later Connect-Entra -Scopes 'Application.ReadWrite.All', 'Directory.Read.All', 'DelegatedPermissionGrant.ReadWrite.All' Grant-EntraBetaMCPServerPermission -ApplicationName VisualStudioCode // then, in .vscode/mcp.json { "servers": { "entra": { "type": "http", "url": "https://mcp.svc.cloud.microsoft/enterprise" } } }
Provisioned once per tenant. A custom client needs its own app registration with MCP.* scopes and admin consent.

It needs no extra licence, though the data keeps its own (PIM data needs Entra ID P2 or ID Governance), and 100 calls a minute per user on top of Graph throttling. Calls appear in Graph activity logs under app ID e8c77dc2-69b3-43f4-bc51-3213c9d915b4; the server can be disabled, not deleted. Here is its listing. Three community servers cover what it does not:

  • Lokka (@merill/lokka): one tool for any Microsoft Graph or Azure Resource Manager call, writes included when permissions allow. Community-built, not Microsoft’s.
  • entraadm (entraadm-mcp): read-only triage of sign-in and audit logs that can also run app-only, which the Enterprise server cannot.
  • Entra Permissions (@mjendza/entra-permissions-mcp): Graph permission reference data with no tenant access, handy for picking the smallest permission.

On-premises Active Directory Domain Services has no official MCP server. Microsoft’s MCP catalogue lists none. Community LDAP servers exist, a few of them MIT-licensed, most young and unvetted; none is in our catalogue, and we would not hand one a domain credential. The supported route is Entra: sync users and groups with Entra Connect Sync or Entra Cloud Sync, which Microsoft calls “the future of synchronization”, and read them through the Enterprise server. From a Windows machine, on-premises AD is reachable through the Active Directory PowerShell module or WinRM; MCP on Windows covers that route.

The route that exists today. The dashed line is the one people search for.The route that exists today. The dashed line is the one people search for.
The route that exists today. The dashed line is the one people search for.

Connecting them safely: a separate identity, read-only twice

A read-only switch is a promise the server makes, and a release can change it: in 3.0.0-beta.44, Azure MCP Server moved its MySQL and PostgreSQL query tools from read-only to destructive, leaving the database permissions to decide. Permissions are enforced by SQL Server, Azure or Entra whatever the server does. So lock both: the identity and the switch.

The switch hides write tools from the model; the permission refuses the write if one gets through.The switch hides write tools from the model; the permission refuses the write if one gets through.
The switch hides write tools from the model; the permission refuses the write if one gets through.
-- Azure SQL, run by an Entra identity with ALTER ANY USER CREATE USER [mcp-reporting-reader] FROM EXTERNAL PROVIDER; -- same name as the agent's managed identity CREATE ROLE mcp_read; GRANT SELECT ON SCHEMA :: reporting TO mcp_read; ALTER ROLE mcp_read ADD MEMBER [mcp-reporting-reader];
A role rather than a user, and narrower than db_datareader, which reads every user table and view. Outside Azure, use a login made for the agent.
  • An identity per agent, never a person’s: a managed identity on Azure (Authentication=Active Directory Managed Identity), elsewhere a service principal with a certificate. Active Directory Password is deprecated.
  • Roles that stop at metadata: Azure’s Reader sees resources, not data; Key Vault Reader sees secret metadata, not values. The Azure RBAC skill helps find the least-privileged role.
  • Secrets out of the config: DAB reads @env('…'), or @akv('…') from Key Vault; other local servers take keys in env, not args (where each client keeps them). Keep .env and .akv out of git.
  • Nothing on a public address: stdio answers only its client, HTTP answers the network. The trade-off, and what to check before installing.

Problems, causes and fixes

ProblemCauseFix
@azure/mcp@latest installed a betanpm’s latest is a 3.0.0 betaPin @azure/mcp@2.0.5
Azure MCP Server returns no rowsIts sql namespace is control planeSQL MCP Server or a community server
delete_record is in the tool listDML tools start enableddab configure --runtime.mcp.dml-tools.delete-record false
Custom DAB roles never apply; anyone can call /mcpUnder the default Unauthenticated provider, everything runs as anonymousSwitch to the EntraId provider, or put a gateway in front
The Enterprise server rejects an app-only tokenIt supports delegated permissions onlySign in as a user
Browse more: SQL Server, Azure and Entra in the catalogue.

Three servers, three layers, one gap, and one rule under all of them: the agent’s own identity can only read, and the server’s switch is the second lock, not the first.