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.
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.
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{
"servers": {
"sql-mcp-server": {
"type": "stdio",
"command": "dab",
"args": ["start", "--mcp-stdio", "role:anonymous", "--loglevel", "error",
"--config", "${workspaceFolder}/dab-config.json"]
}
}
}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
| Server | Install | What guards the writes |
|---|---|---|
| DBHub (Bytebase) | npm @bytebase/dbhub | readonly = true on execute_sql in dbhub.toml; there is no CLI flag |
| MSSQL MCP Reader | npm @connorbritain/mssql-mcp-reader | A read-only package; writes ship as separate packages |
| SqlAugur | NuGet tool SqlAugur | SELECT and WITH only, parsed with Microsoft’s T-SQL parser |
| MCP SQL Server (alyiox, not Microsoft) | NuGet Alyio.McpMssql | No write tool until a profile sets AllowWrite, which defaults to false |
| dbatools MCP | npm dbatools-mcp-server | Safe mode: changes need confirm: true |
| SqlServer.Rules (ErikEJ) | NuGet tool ErikEJ.DacFX.TSQLAnalyzer.Cli | Never connects: it lints T-SQL scripts |
| sqlglass | PyPI sqlglass | Read-only execution |
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 monitorNamespace 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.
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" }
}
}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.
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.
-- 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];- 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
| Problem | Cause | Fix |
|---|---|---|
| @azure/mcp@latest installed a beta | npm’s latest is a 3.0.0 beta | Pin @azure/mcp@2.0.5 |
| Azure MCP Server returns no rows | Its sql namespace is control plane | SQL MCP Server or a community server |
| delete_record is in the tool list | DML tools start enabled | dab configure --runtime.mcp.dml-tools.delete-record false |
| Custom DAB roles never apply; anyone can call /mcp | Under the default Unauthenticated provider, everything runs as anonymous | Switch to the EntraId provider, or put a gateway in front |
| The Enterprise server rejects an app-only token | It supports delegated permissions only | Sign in as a user |
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.