Skip to content

Commit a5902fe

Browse files
committed
Add health checks
1 parent 2234cb6 commit a5902fe

File tree

10 files changed

+76
-8
lines changed

10 files changed

+76
-8
lines changed

azure.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,22 @@
33
name: python-mcp-demo
44
metadata:
55
6+
67
services:
7-
# Not using remoteBuild due to private endpoint usage
88
server:
99
project: .
1010
language: docker
1111
host: containerapp
1212
docker:
13+
remoteBuild: true
1314
path: ./servers/Dockerfile
1415
context: .
1516
agent:
1617
project: .
1718
language: docker
1819
host: containerapp
1920
docker:
21+
remoteBuild: true
2022
path: ./agents/Dockerfile
2123
context: .
2224
hooks:

infra/agent.bicep

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ module app 'core/host/container-app-upsert.bicep' = {
4848
name: 'MCP_SERVER_URL'
4949
value: mcpServerUrl
5050
}
51+
{
52+
name: 'RUNNING_IN_PRODUCTION'
53+
value: 'true'
54+
}
5155
]
5256
}
5357
}

infra/core/host/container-app-upsert.bicep

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ param containerCpuCoreCount string = '0.5'
4040
@description('Memory allocated to a single container instance, e.g. 1Gi')
4141
param containerMemory string = '1.0Gi'
4242

43+
@description('Health probes for the container')
44+
param probes array = []
45+
4346
resource existingApp 'Microsoft.App/containerApps@2025-01-01' existing = if (exists) {
4447
name: name
4548
}
@@ -67,6 +70,7 @@ module app 'container-app.bicep' = {
6770
env: env
6871
imageName: exists ? existingApp.properties.template.containers[0].image : ''
6972
targetPort: targetPort
73+
probes: probes
7074
}
7175
}
7276

infra/core/host/container-app.bicep

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ param containerCpuCoreCount string = '0.5'
4040
@description('Memory allocated to a single container instance, e.g. 1Gi')
4141
param containerMemory string = '1.0Gi'
4242

43+
@description('Health probes for the container')
44+
param probes array = []
45+
4346
resource userIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = {
4447
name: identityName
4548
}
@@ -102,6 +105,7 @@ resource app 'Microsoft.App/containerApps@2025-01-01' = {
102105
cpu: json(containerCpuCoreCount)
103106
memory: containerMemory
104107
}
108+
probes: probes
105109
}
106110
]
107111
scale: {

infra/core/host/container-apps-environment.bicep

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,21 @@ module containerAppsEnvironment 'br/public:avm/res/app/managed-environment:0.11.
2626
location: location
2727
tags: tags
2828
zoneRedundant: false
29-
publicNetworkAccess: 'Enabled'
29+
publicNetworkAccess: usePrivateIngress ? 'Disabled' : 'Enabled'
30+
workloadProfiles: usePrivateIngress
31+
? [
32+
{
33+
name: 'Consumption'
34+
workloadProfileType: 'Consumption'
35+
}
36+
{
37+
name: 'Warm'
38+
workloadProfileType: 'D4'
39+
minimumCount: 1
40+
maximumCount: 3
41+
}
42+
]
43+
: []
3044
appLogsConfiguration: useLogging
3145
? {
3246
destination: 'log-analytics'

infra/core/host/container-registry.bicep

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ param encryption object = {
1010
status: 'disabled'
1111
}
1212
param networkRuleBypassOptions string = 'AzureServices'
13-
param publicNetworkAccess string = useVnet ? 'Disabled' : 'Enabled' // Public network access is disabled if VNet integration is enabled
13+
param publicNetworkAccess string = 'Enabled' // Keep public access enabled for pushing images from local machine
1414
param useVnet bool = false // Determines if VNet integration is enabled
1515
param sku object = {
1616
name: useVnet ? 'Premium' : 'Standard' // Use Premium if VNet is required, otherwise Standard

infra/main.bicep

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ module logAnalyticsWorkspace 'br/public:avm/res/operational-insights/workspace:0
152152
skuName: 'PerGB2018'
153153
dataRetention: 30
154154
publicNetworkAccessForIngestion: useVnet ? 'Disabled' : 'Enabled'
155-
publicNetworkAccessForQuery: useVnet ? 'Disabled' : 'Enabled'
155+
publicNetworkAccessForQuery: 'Enabled' // Keep public query access for debugging - change to 'Disabled' for more security
156156
useResourcePermissions: true
157157
}
158158
}
@@ -540,7 +540,7 @@ module monitorPrivateLinkScope 'br/public:avm/res/insights/private-link-scope:0.
540540
tags: tags
541541
accessModeSettings: {
542542
ingestionAccessMode: 'PrivateOnly'
543-
queryAccessMode: 'PrivateOnly'
543+
queryAccessMode: 'Open' // Allow public queries for debugging - change to 'PrivateOnly' for more security
544544
}
545545
scopedResources: [
546546
{

infra/main.parameters.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@
2020
"usePrivateIngress": {
2121
"value": "${USE_PRIVATE_INGRESS=false}"
2222
},
23-
"acaExists": {
24-
"value": "${SERVICE_ACA_RESOURCE_EXISTS=false}"
23+
"serverExists": {
24+
"value": "${SERVICE_SERVER_RESOURCE_EXISTS=false}"
25+
},
26+
"agentExists": {
27+
"value": "${SERVICE_AGENT_RESOURCE_EXISTS=false}"
2528
}
2629
}
27-
}
30+
}

infra/server.bicep

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,37 @@ module app 'core/host/container-app-upsert.bicep' = {
6060
}
6161
]
6262
targetPort: 8000
63+
probes: [
64+
{
65+
type: 'Startup'
66+
httpGet: {
67+
path: '/health'
68+
port: 8000
69+
}
70+
initialDelaySeconds: 3
71+
periodSeconds: 3
72+
failureThreshold: 30
73+
}
74+
{
75+
type: 'Readiness'
76+
httpGet: {
77+
path: '/health'
78+
port: 8000
79+
}
80+
initialDelaySeconds: 5
81+
periodSeconds: 5
82+
failureThreshold: 3
83+
}
84+
{
85+
type: 'Liveness'
86+
httpGet: {
87+
path: '/health'
88+
port: 8000
89+
}
90+
periodSeconds: 10
91+
failureThreshold: 3
92+
}
93+
]
6394
}
6495
}
6596

servers/deployed_mcp.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from azure.identity.aio import DefaultAzureCredential, ManagedIdentityCredential
1010
from dotenv import load_dotenv
1111
from fastmcp import FastMCP
12+
from starlette.responses import JSONResponse
1213

1314
load_dotenv(override=True)
1415

@@ -39,6 +40,11 @@
3940
mcp = FastMCP("Expenses Tracker")
4041

4142

43+
@mcp.custom_route("/health", methods=["GET"])
44+
async def health_check(request):
45+
return JSONResponse({"status": "healthy", "service": "mcp-server"})
46+
47+
4248
class PaymentMethod(Enum):
4349
AMEX = "amex"
4450
VISA = "visa"

0 commit comments

Comments
 (0)