|
| 1 | + |
| 2 | + |
| 3 | +# Azure SQL MCP Server with Connector Namespace |
| 4 | + |
| 5 | +Deploy a hosted Azure SQL Model Context Protocol (MCP) server to [Azure Connector Namespace](https://learn.microsoft.com/azure/logic-apps/connector-namespace/connector-namespace-hosted-mcp). The sample provisions Azure SQL Database, exposes a `BlogPost` table through Data API Builder MCP, and configures managed identity access so MCP clients such as GitHub Copilot in Visual Studio Code can query the database. |
| 6 | + |
| 7 | +### Contents |
| 8 | + |
| 9 | +[About this sample](#about-this-sample)<br/> |
| 10 | +[Before you begin](#before-you-begin)<br/> |
| 11 | +[Run this sample](#run-this-sample)<br/> |
| 12 | +[Sample details](#sample-details)<br/> |
| 13 | +[Clean up](#clean-up)<br/> |
| 14 | +[Related links](#related-links)<br/> |
| 15 | + |
| 16 | +<a name=about-this-sample></a> |
| 17 | + |
| 18 | +## About this sample |
| 19 | + |
| 20 | +- **Applies to:** Azure SQL Database |
| 21 | +- **Key features:** Azure Connector Namespace, hosted MCP server, Data API Builder, managed identity, Application Insights |
| 22 | +- **Workload:** AI agent data access |
| 23 | +- **Programming Language:** Bicep, PowerShell, Bash, JSON |
| 24 | + |
| 25 | +This sample deploys a hosted `mcp-sql` server in Azure Connector Namespace. The hosted MCP server uses Data API Builder configuration to expose a SQL table through MCP tools. The SQL database is seeded with a `dbo.BlogPost` table containing links to Microsoft Learn and .NET Blog posts. For more background, see [Hosted MCP servers in Azure Connector Namespace](https://learn.microsoft.com/azure/logic-apps/connector-namespace/connector-namespace-hosted-mcp). |
| 26 | + |
| 27 | +<a name=before-you-begin></a> |
| 28 | + |
| 29 | +## Before you begin |
| 30 | + |
| 31 | +To run this sample, you need the following prerequisites. |
| 32 | + |
| 33 | +**Software prerequisites:** |
| 34 | + |
| 35 | +1. [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) (`az`) |
| 36 | +1. [Azure Developer CLI](https://learn.microsoft.com/azure/developer/azure-developer-cli/install-azd) (`azd`) |
| 37 | +1. PowerShell 7+ on Windows, or Bash on Linux/macOS |
| 38 | + |
| 39 | +**Azure prerequisites:** |
| 40 | + |
| 41 | +1. An Azure subscription with permissions to create resource groups and resources. |
| 42 | +1. Permission to create Azure SQL Database, Application Insights, Log Analytics workspace, and Connector Namespace resources. |
| 43 | +1. Permission to create an Azure SQL Microsoft Entra administrator for the signed-in user. |
| 44 | + |
| 45 | +<a name=run-this-sample></a> |
| 46 | + |
| 47 | +## Run this sample |
| 48 | + |
| 49 | +From this folder: |
| 50 | + |
| 51 | +```bash |
| 52 | +azd auth login |
| 53 | +azd init |
| 54 | +azd up |
| 55 | +``` |
| 56 | + |
| 57 | +#### `azd init` prompts |
| 58 | + |
| 59 | +When you run `azd init` for the first time, it detects the existing `azure.yaml` and Bicep templates: |
| 60 | + |
| 61 | +1. **"How do you want to initialize your app?"** — Select **Use code in the current directory**. |
| 62 | +2. **"Confirm and continue initializing this app"** — Press **Enter** to confirm the detected services. |
| 63 | +3. **"Enter a new environment name"** — Pick any name, for example `mcp-dev`. This name is used as a prefix for Azure resource names. |
| 64 | + |
| 65 | +You only need to run `azd init` once. Subsequent deployments only require `azd up`. |
| 66 | + |
| 67 | +#### `azd up` prompts |
| 68 | + |
| 69 | +When you run `azd up`, you are prompted for: |
| 70 | + |
| 71 | +- **Azure Subscription:** Select the Azure subscription to deploy to. |
| 72 | +- **Azure location:** Choose a supported region (e.g. `eastasia`, `westcentralus`). |
| 73 | +- **`deployerLoginName` infrastructure parameter:** Enter your Azure sign-in email or user principal name, for example `user@contoso.com`. If you don't know the value, run the following command in a different terminal instance and use the result: |
| 74 | + |
| 75 | + ```bash |
| 76 | + az account show --query user.name -o tsv |
| 77 | + ``` |
| 78 | +- **`connectorNamespaceIdentityType` infrastructure parameter:** Enter `SystemAssigned` for the default Connector Namespace managed identity, or `UserAssigned` to create and attach a user-assigned managed identity. |
| 79 | + |
| 80 | +The `deployerLoginName` value is used to create the Azure SQL server with Microsoft Entra-only authentication and set you as the SQL Entra admin. |
| 81 | + |
| 82 | +### Optional: use a user-assigned managed identity |
| 83 | + |
| 84 | +When `azd up` prompts for `connectorNamespaceIdentityType`, enter `UserAssigned` to test with a user-assigned managed identity. |
| 85 | + |
| 86 | +When set to `UserAssigned`, the template creates a user-assigned managed identity, attaches it to the Connector Namespace, passes its client ID to the hosted MCP server, and grants that identity access to Azure SQL. |
| 87 | + |
| 88 | +Choose the identity type before the first deployment. Connector Namespace doesn't allow changing attached user-assigned identities after the namespace is created. To switch between `SystemAssigned` and `UserAssigned`, create a new azd environment or run `azd down --purge` and deploy again. |
| 89 | + |
| 90 | +### Connect from Visual Studio Code |
| 91 | + |
| 92 | +After `azd up` completes, the MCP endpoint URL is printed. Add it to VS Code using the UI: |
| 93 | + |
| 94 | +1. In VS Code, open the Command Palette: |
| 95 | + - Windows/Linux: <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd> |
| 96 | + - macOS: <kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd> |
| 97 | +1. Run **MCP: Add Server**. |
| 98 | +1. Choose **HTTP** as the server type. |
| 99 | +1. Paste the MCP endpoint URL printed by `azd up`. |
| 100 | +1. Enter a server name, for example `sql-mcp`. |
| 101 | +1. Choose whether to save the server in user settings or workspace settings. |
| 102 | +1. Start the `sql-mcp` server when VS Code prompts you. |
| 103 | + |
| 104 | +VS Code prompts you to sign in with Microsoft. Then use Copilot Chat to query your database, for example: *"List the blog posts in the database."* |
| 105 | + |
| 106 | +<a name=sample-details></a> |
| 107 | + |
| 108 | +## Sample details |
| 109 | + |
| 110 | +### Architecture |
| 111 | + |
| 112 | +``` |
| 113 | +┌─────────────────────────────────────┐ |
| 114 | +│ Connector Namespace │ |
| 115 | +│ (Microsoft.Web/connectorGateways) │ |
| 116 | +│ │ |
| 117 | +│ ┌───────────────────────────────┐ │ |
| 118 | +│ │ Hosted SQL MCP Server │ │ |
| 119 | +│ │ (Data API Builder) │ │ |
| 120 | +│ │ │ │ |
| 121 | +│ │ MI ───► Azure SQL DB │ │ |
| 122 | +│ └───────────────────────────────┘ │ |
| 123 | +└─────────────────────────────────────┘ |
| 124 | + ▲ |
| 125 | + │ MCP (HTTP + SSE) |
| 126 | + │ |
| 127 | + VS Code / Copilot / MCP Client |
| 128 | +``` |
| 129 | + |
| 130 | +### Resources deployed |
| 131 | + |
| 132 | +| Resource | Purpose | |
| 133 | +|----------|---------| |
| 134 | +| **Resource Group** | Container for all deployed resources | |
| 135 | +| **Azure SQL Server** | Entra-only auth, with you as SQL admin | |
| 136 | +| **Azure SQL Database** | Basic SKU database with a `BlogPost` sample table used by the MCP server | |
| 137 | +| **SQL Firewall Rules** | Allows Azure services/resources, Azure Portal Query Editor, and your public IP for setup | |
| 138 | +| **Log Analytics Workspace** | Stores Application Insights telemetry | |
| 139 | +| **Application Insights** | Collects telemetry from the hosted MCP server | |
| 140 | +| **Connector Namespace** | Hosts MCP servers with system-assigned managed identity by default, or user-assigned managed identity when configured | |
| 141 | +| **Hosted SQL MCP Server** | `mcp-sql` server config on the namespace | |
| 142 | +| **MCP Access Policy** | Grants you access to invoke MCP tools | |
| 143 | + |
| 144 | +Resource names use the pattern `<type>-<environment-name>-<short-suffix>` where possible, for example `sql-mcp-dev-a1b2c3d4`. The suffix is deterministic for the subscription, environment name, and location so names are readable and stable across redeployments. |
| 145 | + |
| 146 | +### What `azd up` does |
| 147 | + |
| 148 | +| Step | Action | |
| 149 | +|------|--------| |
| 150 | +| **Provision** | Deploys Azure SQL, SQL firewall rules, Log Analytics, Application Insights, Connector Namespace, hosted `mcp-sql`, and MCP access policy. | |
| 151 | +| **Post-provision** | Allows your public IP through the SQL firewall, creates and seeds `dbo.BlogPost`, creates the Connector Namespace managed identity SQL user, grants SQL permissions, generates `dab-config.generated.json`, and prints the MCP endpoint plus Azure Portal resource group link. | |
| 152 | + |
| 153 | +The hosted MCP server receives: |
| 154 | + |
| 155 | +- the included `dab-config.json` as `properties.hostedMcpServer.configuration.configFile` |
| 156 | +- the generated SQL connection string as `SQL_CONNECTION_STRING` |
| 157 | +- the Application Insights connection string as `APPLICATIONINSIGHTS_CONNECTION_STRING` |
| 158 | +- `AZURE_CLIENT_ID` when the sample is configured to use a user-assigned managed identity |
| 159 | + |
| 160 | +No SQL or Application Insights connection string is checked in. |
| 161 | + |
| 162 | +This sample includes a ready-to-use `dab-config.json`. If you want to create or customize a Data API Builder configuration from scratch, install the DAB CLI and use it to generate a config file. For more information, see [Install the Data API Builder CLI](https://learn.microsoft.com/azure/data-api-builder/command-line/install). |
| 163 | + |
| 164 | +For details about the hosted MCP server resource model and supported server types, see [Hosted MCP servers in Azure Connector Namespace](https://learn.microsoft.com/azure/logic-apps/connector-namespace/connector-namespace-hosted-mcp). For a walkthrough focused on the SQL hosted MCP server, see [Hosted MCP server quickstart for SQL](https://learn.microsoft.com/azure/logic-apps/connector-namespace/hosted-mcp-quickstart?pivots=sql). |
| 165 | + |
| 166 | +### Inspect resources in Azure Portal |
| 167 | + |
| 168 | +After deployment, the post-provision output includes a link to the Azure resource group in the Azure Portal. Use that page to inspect the SQL server, Application Insights resource, Log Analytics workspace, Connector Namespace, and hosted MCP server. |
| 169 | + |
| 170 | +To allow additional users to connect to the MCP server: |
| 171 | + |
| 172 | +1. Open the deployed **Connector Namespace** resource in the Azure Portal. |
| 173 | +1. Open the hosted MCP server configuration, for example `sql-mcp`. |
| 174 | +1. Add an access policy for each additional user or group that should be allowed to invoke the MCP server. |
| 175 | + |
| 176 | +### Sample data |
| 177 | + |
| 178 | +The post-provision hook creates and seeds `dbo.BlogPost` with these entries: |
| 179 | + |
| 180 | +| Title | Source | |
| 181 | +|-------|--------| |
| 182 | +| Hosted MCP servers in Azure Connector Namespace | Microsoft Learn | |
| 183 | +| Durable Workflows in Microsoft Agent Framework | .NET Blog | |
| 184 | + |
| 185 | +### SQL firewall access |
| 186 | + |
| 187 | +The deployment configures two SQL firewall paths: |
| 188 | + |
| 189 | +| Rule | When | Purpose | |
| 190 | +|------|------|---------| |
| 191 | +| `AllowAzureServices` | During Bicep provisioning | Allows Azure services/resources, including Azure Portal Query Editor, to reach the SQL server. | |
| 192 | +| `AllowDeployerIp` | During post-provision | Detects your current public IP and allows your local machine to seed and query the database. | |
| 193 | + |
| 194 | +If SQL reports a different blocked client IP during post-provision, the script adds that IP and retries. |
| 195 | + |
| 196 | +<a name=clean-up></a> |
| 197 | + |
| 198 | +## Clean up |
| 199 | + |
| 200 | +Using azd: |
| 201 | + |
| 202 | +```bash |
| 203 | +azd down --purge |
| 204 | +``` |
| 205 | + |
| 206 | +Or with Azure CLI: |
| 207 | + |
| 208 | +```bash |
| 209 | +# Replace <environment-name> with your azd environment name. |
| 210 | +az group delete --name rg-<environment-name> --yes --no-wait |
| 211 | + |
| 212 | +# Optional: remove the subscription-scope deployment record. |
| 213 | +az deployment sub delete --name <environment-name> |
| 214 | +``` |
| 215 | + |
| 216 | +<a name=related-links></a> |
| 217 | + |
| 218 | +## Related links |
| 219 | + |
| 220 | +- [Hosted MCP servers in Azure Connector Namespace](https://learn.microsoft.com/azure/logic-apps/connector-namespace/connector-namespace-hosted-mcp) |
| 221 | +- [Hosted MCP server quickstart for SQL](https://learn.microsoft.com/azure/logic-apps/connector-namespace/hosted-mcp-quickstart?pivots=sql) |
| 222 | +- [Azure SQL MCP server support in Data API Builder](https://learn.microsoft.com/azure/data-api-builder/mcp/overview) |
| 223 | +- [Install the Data API Builder CLI](https://learn.microsoft.com/azure/data-api-builder/command-line/install) |
| 224 | +- [Connector Namespace overview](https://learn.microsoft.com/azure/logic-apps/connector-namespace/connector-namespace-overview) |
| 225 | +- [Azure Developer CLI](https://learn.microsoft.com/azure/developer/azure-developer-cli/) |
0 commit comments