Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions deploy/azure/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Deploy MongoDB MCP Server on Azure Container Apps

## Overview
This directory contains an Azure Bicep template (`bicep/main.bicep`) and supporting parameter files for deploying the infrastructure required to run the MongoDB MCP (Model Context Protocol) server. Use this guide to prepare prerequisites, select the appropriate parameter file, and run the deployment end-to-end.

## Prerequisites
- Azure CLI (2.55.0 or later) installed and signed in (`az login`).
- Azure subscription with permissions to deploy the required resources.
- MongoDB MCP server container image available in dockerhub registry (mongodb/mongodb-mcp-server:latest).

## Parameter Files
Two sample parameter files are provided to help you tailor deployments:

- `bicep/params.json`: Baseline configuration that deploys the MongoDB MCP server with authentication disabled or using default settings. Use this when testing in development environments or when external authentication is not required.
- `bicep/paramsWithAuthEnabled.json`: Extends the baseline deployment and enables Microsoft Entra ID (Azure AD) authentication using managed identity and client application IDs. Use this when you want the server protected with Azure AD authentication via managed identity.

> **Tip:** Update the image reference, secrets, networking, and any other environment-specific values in the chosen parameter file before deployment.
## Deploy the Bicep Template
1. **Set common variables (PowerShell example):**
```powershell
$location = "eastus"
$resourceGroup = "mongodb-mcp-demo-rg"
$templateFile = "bicep/main.bicep"
$parameterFile = "bicep/params.json" # or bicep/paramsWithAuthEnabled.json
```

2. **Create the resource group (if it does not exist):**
```powershell
az group create --name $resourceGroup --location $location
```

3. **Validate the deployment (optional but recommended):**
```powershell
az deployment group what-if \
--resource-group $resourceGroup \
--template-file $templateFile \
--parameters @$parameterFile
```

4. **Run the deployment:**
```powershell
az deployment group create \
--resource-group $resourceGroup \
--template-file $templateFile \
--parameters @$parameterFile
```

5. **Monitor outputs:** Review the deployment outputs and logs for connection endpoints, credential references, or other values needed to complete integration.

## Post-Deployment Checklist
- Confirm the container instance or orchestration target pulled the correct MongoDB MCP image from your dockerhub.
- Verify networking rules (firewalls, VNet integrations, etc.) allow intended clients to reach the server endpoint.
- If using the auth-enabled parameters, validate that credentials/secrets are stored securely (Key Vault, managed identity) and tested end-to-end.
- Document any additional operational steps (scaling, logging, maintenance) based on your environment requirements.

## Updating the Deployment
To apply changes:
1. Update the parameter file or `main.bicep` as needed.
2. Re-run the `az deployment group create` command with the same resource group.
3. Use `az deployment group what-if` to preview differences before applying them.

## Cleanup
Remove the deployed resources when no longer needed:

```powershell
az group delete --name $resourceGroup --yes --no-wait
```

> **Reminder:** Deleting the resource group removes all resources inside it. Ensure any persistent data or backups are retained elsewhere before running the cleanup command.
212 changes: 212 additions & 0 deletions deploy/azure/bicep/main.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
@description('Name of the Container Apps Environment. Leave blank to create a new one.')
param containerAppEnvName string = ''

@description('Location of resources')
param location string = resourceGroup().location

@description('Name of the Container App')
param containerAppName string = 'mongo-mcp-server-app'

@description('Docker image to deploy')
param containerImage string = 'mongodb/mongodb-mcp-server:latest'

@description('Container CPU (vCPU) as string. Allowed: 0.25 - 2.0 in 0.25 increments')
@allowed([
'0.25'
'0.5'
'0.75'
'1.0'
'1.25'
'1.5'
'1.75'
'2.0'
])
param containerCpu string = '1.0'

// Convert CPU string to number (Bicep lacks float type; json() parses to number)
var containerCpuNumber = json(containerCpu)

@description('Container Memory (GB)')
@allowed([
'0.5Gi'
'1Gi'
'2Gi'
'4Gi'
])
param containerMemory string = '2Gi'

@description('Container App Environment Variables')
param appEnvironmentVars object = {
MDB_MCP_READ_ONLY: 'true' // set to 'false' to enable write operations
MDB_MCP_HTTP_PORT: '8080'
MDB_MCP_HTTP_HOST: '::'
MDB_MCP_TRANSPORT: 'http'
MDB_MCP_LOGGERS: 'disk,mcp,stderr'
MDB_MCP_LOG_PATH: '/tmp/mongodb-mcp'
}

@description('Authentication mode toggle for the Container App. NOAUTH disables platform auth; MicrosoftMIBasedAuth enables Azure AD auth and enforces 401 for unauthenticated requests.')
@allowed([
'NOAUTH'
'MicrosoftMIBasedAuth'
])
param authMode string = 'NOAUTH'

@description('Azure AD Application (client) ID used when authMode is MicrosoftMIBasedAuth. Leave blank for NOAUTH.')
param authClientId string = ''

@description('Issuer URL (OpenID issuer) when authMode is MicrosoftMIBasedAuth. Example: https://login.microsoftonline.com/<tenant-id>/v2.0 or https://sts.windows.net/<tenant-id>/v2.0')
param authIssuerUrl string = ''

@description('Azure AD Tenant ID (GUID) used when authMode is MicrosoftMIBasedAuth. Provided separately to avoid hard-coded cloud endpoints in template logic.')
param authTenantId string = ''

@description('Optional array of allowed client application IDs. If empty, all applications are allowed (not recommended).')
param authAllowedClientApps array = []

@secure()
@description('MongoDB Connection String')
param mdbConnectionString string

// Create Container App Environment if not provided
resource containerAppEnv 'Microsoft.App/managedEnvironments@2024-02-02-preview' = if (empty(containerAppEnvName)) {
name: 'mcp-env-${uniqueString(resourceGroup().id)}'
location: location
properties: {}
}

// Get the Container App Environment resource ID (either existing or newly created)
var envResourceId = empty(containerAppEnvName)
? containerAppEnv.id
: resourceId('Microsoft.App/managedEnvironments', containerAppEnvName)

// Build environment variables array
var envVarsArray = [
for item in items(appEnvironmentVars): {
name: item.key
value: string(item.value)
}
]

// Additional environment variables injected when MicrosoftMIBasedAuth is enabled (merged after user-provided vars so user can override if desired)
var authEnvVars = authMode == 'MicrosoftMIBasedAuth'
? concat([
{
name: 'MDB_MCP_HTTP_AUTH_MODE'
value: 'azure-managed-identity'
}
{
// Tenant ID of the Azure AD tenant
name: 'MDB_MCP_AZURE_MANAGED_IDENTITY_TENANT_ID'
value: authTenantId
}
{
// Client ID of the Azure AD App representing your container app
name: 'MDB_MCP_AZURE_MANAGED_IDENTITY_CLIENT_ID'
value: authClientId
}
], length(authAllowedClientApps) > 0 ? [
{
// Comma-separated list of allowed Client App IDs for access
// (only listed Client Apps are allowed if client apps specified)
name: 'MDB_MCP_AZURE_MANAGED_IDENTITY_ALLOWED_APP_IDS'
value: join(authAllowedClientApps, ',')
}
] : [])
: [
{
name: 'MDB_MCP_HTTP_AUTH_MODE'
value: 'none'
}
]

// Deploy Container App
resource containerApp 'Microsoft.App/containerApps@2024-02-02-preview' = {
name: containerAppName
location: location
identity: {
type: 'SystemAssigned'
}
properties: {
managedEnvironmentId: envResourceId
configuration: {
ingress: {
external: true
targetPort: int(appEnvironmentVars.MDB_MCP_HTTP_PORT)
transport: 'auto'
}
secrets: [
{
name: 'mdb-mcp-connection-string'
value: mdbConnectionString
}
]
}
template: {
containers: [
{
name: 'mcpserver'
image: containerImage
resources: {
cpu: containerCpuNumber
memory: containerMemory
}
env: concat(
envVarsArray,
authEnvVars,
[
{
name: 'MDB_MCP_CONNECTION_STRING'
secretRef: 'mdb-mcp-connection-string'
}
]
)
}
]
scale: {
minReplicas: 1
maxReplicas: 1
rules: [] // disables autoscaling
}
}
}
}

// Container App Authentication (child resource) - only deployed when MicrosoftMIBasedAuth selected
resource containerAppAuth 'Microsoft.App/containerApps/authConfigs@2024-10-02-preview' = if (authMode == 'MicrosoftMIBasedAuth') {
name: 'current'
parent: containerApp
properties: {
platform: {
enabled: true
// runtimeVersion optional
}
globalValidation: {
unauthenticatedClientAction: 'Return401'
redirectToProvider: 'azureActiveDirectory'
}
identityProviders: {
azureActiveDirectory: {
enabled: true
registration: {
clientId: authClientId
openIdIssuer: authIssuerUrl
}
validation: {
allowedAudiences: [
authClientId
]
// defaultAuthorizationPolicy allows restriction to specific client applications
defaultAuthorizationPolicy: length(authAllowedClientApps) > 0 ? {
allowedApplications: authAllowedClientApps
} : null
jwtClaimChecks: length(authAllowedClientApps) > 0 ? {
allowedClientApplications: authAllowedClientApps
} : null
}
}
}
}
}

output containerAppUrl string = containerApp.properties.configuration.ingress.fqdn
22 changes: 22 additions & 0 deletions deploy/azure/bicep/params.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"containerImage": { "value": "mongodb/mongodb-mcp-server:latest" },
"containerCpu": { "value": "1.0" },
"containerMemory": { "value": "2Gi" },
"appEnvironmentVars": {
"value": {
"MDB_MCP_READ_ONLY": "false",
"MDB_MCP_HTTP_PORT": "8080",
"MDB_MCP_HTTP_HOST": "::",
"MDB_MCP_TRANSPORT": "http",
"MDB_MCP_LOGGERS": "disk,mcp,stderr",
"MDB_MCP_LOG_PATH": "/tmp/mongodb-mcp",
"MDB_MCP_DISABLED_TOOLS": "explain,export,atlas-create-access-list,atlas-create-db-user,drop-database,drop-collection,delete-many"
}
},
"authMode": { "value": "NOAUTH" },
"mdbConnectionString": { "value": "<MONGODB_CONNECTION_STRING>" }
}
}
29 changes: 29 additions & 0 deletions deploy/azure/bicep/paramsWithAuthEnabled.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"containerAppEnvName": { "value": "container-app-env" },
"containerAppName": { "value": "mongo-mcp-server-app-with-auth" },
"containerImage": { "value": "mongodb/mongodb-mcp-server:latest" },
"containerCpu": { "value": "1.0" },
"containerMemory": { "value": "2Gi" },
"appEnvironmentVars": {
"value": {
"MDB_MCP_READ_ONLY": "false",
"MDB_MCP_HTTP_PORT": "8080",
"MDB_MCP_HTTP_HOST": "::",
"MDB_MCP_TRANSPORT": "http",
"MDB_MCP_LOGGERS": "disk,mcp,stderr",
"MDB_MCP_LOG_PATH": "/tmp/mongodb-mcp",
"MDB_MCP_DISABLED_TOOLS": "explain,export,atlas-create-access-list,atlas-create-db-user,drop-database,drop-collection,delete-many"
}
},
"mdbConnectionString": { "value": "<MONGODB_CONNECTION_STRING>" },

"authMode": { "value": "MicrosoftMIBasedAuth" },
"authClientId": { "value": "<AUTH_CLIENT_ID>" },
"authIssuerUrl": { "value": "<AUTH_ISSUER_URL>" },
"authTenantId": { "value": "<AUTH_TENANT_ID>" },
"authAllowedClientApps": { "value": ["<AUTH_ALLOWED_CLIENT_APP_1>","<AUTH_ALLOWED_CLIENT_APP_2>"] }
}
}
Loading