Chapter 9 Β· Integrate & Ship
Azure Deployment
Ship the server to Azure with one script. Bicep provisions everything, the image is built in ACR, and APIM fronts the app. You choose App Service or Container Apps.
π― What you'll be able to do
- Run the deployment script for App Service or Container Apps
- Identify the Azure resources each Bicep file creates
- Understand the APIM policy and replace its placeholder IP ranges
- Choose between App Service and Container Apps
Primary deployment command
From the project root:
az login
.\scripts\deploy.ps1 `
-ResourceGroup rg-jira-mcp `
-Location eastus `
-Acr myacr `
-PublisherEmail you@example.comThe script:
- Creates the resource group.
- Builds the image in Azure Container Registry.
- Deploys Azure resources with Bicep.
- Prints the MCP endpoint.
- Prints the connector host.
Use Container Apps instead of App Service with the -Hosting switch:
.\scripts\deploy.ps1 `
-ResourceGroup rg-jira-mcp `
-Location eastus `
-Acr myacr `
-PublisherEmail you@example.com `
-Hosting ContainerAppsDeployment topology
App Service deployment resources
infra\\main.bicep creates:
| Resource | Purpose |
|---|---|
| Log Analytics workspace | Stores logs. |
| Application Insights | App telemetry. |
| Key Vault | Gateway secret. |
| Linux App Service plan | Hosts the container. |
| Linux Web App | Runs the MCP container. |
| Autoscale setting | Scales the App Service plan. |
| API Management | Public gateway. |
| APIM named value | Secret reference to Key Vault. |
| APIM API and operation | Exposes /jira-mcp/mcp. |
| APIM policy | Security and routing policy. |
Container Apps deployment resources
infra\\containerapp.bicep creates:
| Resource | Purpose |
|---|---|
| User-assigned managed identity | Pulls the ACR image and reads the Key Vault secret. |
| Log Analytics workspace | Container logs. |
| Application Insights | App telemetry. |
| Key Vault | Gateway secret. |
| Container Apps environment | Hosting environment. |
| Container App | Runs the MCP container. |
| API Management | Public gateway. |
| APIM policy | Security and routing. |
APIM policy & IP ranges
The policy in infra\\apim-policy.xml restricts origins via CORS, includes placeholder IP allow-list ranges, rate limits and applies a daily quota by IP, requires an Authorization header, injects X-Gateway-Token, adds hardening headers, and deletes sensitive headers on error paths.
<address-range from="REPLACE_START_IP" to="REPLACE_END_IP" />Find the service tag ranges for your region:
az network list-service-tags --location eastus `
--query "values[?name=='AzureConnectors.EastUS'].properties.addressPrefixes" -o jsonApp Service vs Container Apps
β App Service β choose when
- You want a familiar web-app hosting model
- You value built-in health checks and simple ops
β Container Apps β choose when
- You want container-native scaling and revisions
- You want HTTP-concurrency-based scaling
β Concept check
Deployment succeeds, the app's own /healthz works, but calls through APIM fail. The APIM policy still has REPLACE_START_IP. What's happening?
π Chapter summary
deploy.ps1creates the resource group, builds the image in ACR, deploys Bicep, and prints the MCP endpoint and connector host.- Both hosting options put APIM in front and use a Key Vault-backed gateway secret.
- Replace placeholder IP ranges in the APIM policy with connector egress / service tags before production.