Skip to main content
Glama

Fabric MCP Agent

by yingkiat
azure-pipelines.yml13.5 kB
# Azure DevOps CI/CD Pipeline for Fabric MCP Agent # Builds Docker image and deploys to Azure Container Apps with Key Vault integration trigger: branches: include: - main - dev paths: exclude: - README.md - docs/ - .gitignore variables: - name: imageRepository value: 'fabric-mcp-agent' - name: dockerfilePath value: '$(Build.SourcesDirectory)/Dockerfile' - name: tag value: '$(Build.BuildId)' - name: resourceGroup value: 'M3-RG-ALZ-DWHS-ALYTICS-D-1' - name: containerAppName value: 'fabric-mcp-agent' - name: keyVaultName value: 'itapackeyvault' - name: keyVaultUrl value: 'https://itapackeyvault.vault.azure.net/' - group: ServicePrincipal # ✅ variable group now correctly inside variables list stages: - stage: Build displayName: Build and Push Docker Image (ACR Tasks) jobs: - job: Build displayName: Build pool: vmImage: ubuntu-latest steps: - task: AzureCLI@2 displayName: Build & push image with ACR Tasks inputs: azureSubscription: 'Azure-ServiceConnection' # ARM service connection scriptType: bash scriptLocation: inlineScript inlineScript: | set -euo pipefail REGISTRY_NAME="itapacdataacr" REPO_NAME="$(imageRepository)" TAG="$(tag)" IMAGE_FQN="${REGISTRY_NAME}.azurecr.io/${REPO_NAME}:${TAG}" echo "🔧 Using ACR Tasks to build ${IMAGE_FQN}" az acr build \ --registry "${REGISTRY_NAME}" \ --image "${REPO_NAME}:${TAG}" \ --file "$(dockerfilePath)" \ "$(Build.SourcesDirectory)" echo "🔁 Tagging image as :latest" az acr repository delete --name "${REGISTRY_NAME}" --image "${REPO_NAME}:latest" --yes >/dev/null 2>&1 || true az acr import \ --name "${REGISTRY_NAME}" \ --source "${REGISTRY_NAME}.azurecr.io/${REPO_NAME}:${TAG}" \ --image "${REPO_NAME}:latest" \ --registry "${REGISTRY_NAME}" echo "✅ Build & push complete: ${IMAGE_FQN}" - stage: Deploy displayName: Deploy to Azure Container Apps dependsOn: Build condition: succeeded() jobs: - deployment: Deploy displayName: Deploy pool: vmImage: ubuntu-latest environment: 'production' strategy: runOnce: deploy: steps: - task: AzureCLI@2 displayName: Login with Service Principal inputs: azureSubscription: 'Azure-ServiceConnection' scriptType: 'bash' scriptLocation: 'inlineScript' inlineScript: | az login --service-principal \ --username "$(AZURE_CLIENT_ID)" \ --password "$(AZURE_SECRET)" \ --tenant "$(AZURE_TENANT_ID)" echo "✅ Authenticated with Service Principal" - task: AzureCLI@2 displayName: Deploy to Azure Container Apps inputs: azureSubscription: 'Azure-ServiceConnection' scriptType: 'bash' scriptLocation: 'inlineScript' inlineScript: | echo "🚀 Starting Azure Container Apps deployment..." FULL_IMAGE_NAME="itapacdataacr.azurecr.io/$(imageRepository):latest" LOCATION="southeastasia" ENVIRONMENT_NAME="$(containerAppName)-env" ACR_SERVER="itapacdataacr.azurecr.io" ACR_USERNAME="itapacdataacr" ACR_PASSWORD=$(az keyvault secret show \ --vault-name "$(keyVaultName)" \ --name "itapacdataacr" \ --query "value" -o tsv) echo "🔑 Retrieved ACR credentials from Key Vault" echo "Image: $FULL_IMAGE_NAME" echo "Resource Group: $(resourceGroup)" echo "Container App: $(containerAppName)" echo "Key Vault: $(keyVaultUrl)" az extension add --name containerapp --upgrade --yes az provider register --namespace Microsoft.App --wait az provider register --namespace Microsoft.OperationalInsights --wait if ! az keyvault show --name "$(keyVaultName)" --resource-group "$(resourceGroup)" &>/dev/null; then echo "❌ Key Vault $(keyVaultName) not found in resource group $(resourceGroup)" exit 1 fi echo "✅ Key Vault $(keyVaultName) found" # Check environment status and handle failed states ENV_STATE="" if az containerapp env show --name "$ENVIRONMENT_NAME" --resource-group "$(resourceGroup)" &>/dev/null; then ENV_STATE=$(az containerapp env show --name "$ENVIRONMENT_NAME" --resource-group "$(resourceGroup)" --query "properties.provisioningState" -o tsv) echo "Existing environment state: $ENV_STATE" if [[ "$ENV_STATE" == "ScheduledForDelete" || "$ENV_STATE" == "Failed" ]]; then echo "Environment in bad state ($ENV_STATE), deleting..." az containerapp env delete --name "$ENVIRONMENT_NAME" --resource-group "$(resourceGroup)" --yes # Wait for deletion to complete echo "Waiting for environment deletion..." for i in {1..20}; do if ! az containerapp env show --name "$ENVIRONMENT_NAME" --resource-group "$(resourceGroup)" &>/dev/null; then echo "✅ Environment deleted successfully" break fi echo "Waiting for deletion... ($i/20)" sleep 15 done ENV_STATE="" fi fi if [[ "$ENV_STATE" != "Succeeded" ]]; then echo "Creating Container Apps environment..." az containerapp env create \ --name "$ENVIRONMENT_NAME" \ --resource-group "$(resourceGroup)" \ --location "$LOCATION" echo "Waiting for environment to be fully provisioned..." # Wait for environment to be ready for i in {1..30}; do if az containerapp env show --name "$ENVIRONMENT_NAME" --resource-group "$(resourceGroup)" --query "properties.provisioningState" -o tsv | grep -q "Succeeded"; then echo "✅ Environment provisioned successfully" break fi echo "Waiting for environment... ($i/30)" sleep 10 done # Final check ENV_STATE=$(az containerapp env show --name "$ENVIRONMENT_NAME" --resource-group "$(resourceGroup)" --query "properties.provisioningState" -o tsv) if [ "$ENV_STATE" != "Succeeded" ]; then echo "❌ Environment provisioning failed. State: $ENV_STATE" exit 1 fi fi # First, create/update the Container App if az containerapp show --name "$(containerAppName)" --resource-group "$(resourceGroup)" &>/dev/null; then echo "Updating existing Container App..." az containerapp update \ --name "$(containerAppName)" \ --resource-group "$(resourceGroup)" \ --image "$FULL_IMAGE_NAME" \ --registry-server "$ACR_SERVER" \ --registry-username "$ACR_USERNAME" \ --registry-password "$ACR_PASSWORD" else echo "Creating new Container App..." az containerapp create \ --name "$(containerAppName)" \ --resource-group "$(resourceGroup)" \ --environment "$ENVIRONMENT_NAME" \ --image "$FULL_IMAGE_NAME" \ --registry-server "$ACR_SERVER" \ --registry-username "$ACR_USERNAME" \ --registry-password "$ACR_PASSWORD" \ --target-port 8000 \ --ingress external \ --min-replicas 1 \ --max-replicas 3 \ --cpu 1.0 \ --memory 2.0Gi fi # Verify Container App was created successfully if ! az containerapp show --name "$(containerAppName)" --resource-group "$(resourceGroup)" &>/dev/null; then echo "❌ Container App creation failed" exit 1 fi echo "✅ Container App created/updated successfully" echo "🔐 Configuring secrets from Key Vault using Service Principal..." # Retrieve secrets directly from Key Vault using Service Principal access AZURE_OPENAI_KEY=$(az keyvault secret show --vault-name "$(keyVaultName)" --name "azureopenaikey" --query "value" -o tsv) AZURE_OPENAI_ENDPOINT=$(az keyvault secret show --vault-name "$(keyVaultName)" --name "azureopenaiendpoint" --query "value" -o tsv) AZURE_OPENAI_DEPLOYMENT=$(az keyvault secret show --vault-name "$(keyVaultName)" --name "azureopenaideployment" --query "value" -o tsv) AZURE_CLIENT_ID=$(az keyvault secret show --vault-name "$(keyVaultName)" --name "azureclientid" --query "value" -o tsv) AZURE_CLIENT_SECRET=$(az keyvault secret show --vault-name "$(keyVaultName)" --name "azureclientsecret" --query "value" -o tsv) AZURE_TENANT_ID=$(az keyvault secret show --vault-name "$(keyVaultName)" --name "azuretenantid" --query "value" -o tsv) FABRIC_SQL_SERVER=$(az keyvault secret show --vault-name "$(keyVaultName)" --name "fabricsqlserver" --query "value" -o tsv) FABRIC_SQL_DATABASE=$(az keyvault secret show --vault-name "$(keyVaultName)" --name "fabricsqldatabase" --query "value" -o tsv) echo "✅ Retrieved all secrets from Key Vault" # Set secrets as static values in Container App az containerapp secret set \ --name "$(containerAppName)" \ --resource-group "$(resourceGroup)" \ --secrets \ azure-openai-key="$AZURE_OPENAI_KEY" \ azure-openai-endpoint="$AZURE_OPENAI_ENDPOINT" \ azure-openai-deployment="$AZURE_OPENAI_DEPLOYMENT" \ azure-client-id="$AZURE_CLIENT_ID" \ azure-client-secret="$AZURE_CLIENT_SECRET" \ azure-tenant-id="$AZURE_TENANT_ID" \ fabric-sql-server="$FABRIC_SQL_SERVER" \ fabric-sql-database="$FABRIC_SQL_DATABASE" echo "✅ Secrets configured successfully" # Set environment variables to reference the secrets (no KEY_VAULT_URL to force env var mode) az containerapp update \ --name "$(containerAppName)" \ --resource-group "$(resourceGroup)" \ --set-env-vars \ AZURE_OPENAI_KEY="secretref:azure-openai-key" \ AZURE_OPENAI_ENDPOINT="secretref:azure-openai-endpoint" \ AZURE_OPENAI_DEPLOYMENT="secretref:azure-openai-deployment" \ AZURE_CLIENT_ID="secretref:azure-client-id" \ AZURE_CLIENT_SECRET="secretref:azure-client-secret" \ AZURE_TENANT_ID="secretref:azure-tenant-id" \ FABRIC_SQL_SERVER="secretref:fabric-sql-server" \ FABRIC_SQL_DATABASE="secretref:fabric-sql-database" APP_URL=$(az containerapp show --name "$(containerAppName)" --resource-group "$(resourceGroup)" --query "properties.configuration.ingress.fqdn" -o tsv) echo "✅ Deployment complete!" echo "App URL: https://$APP_URL" - task: AzureCLI@2 displayName: Test Deployment inputs: azureSubscription: 'Azure-ServiceConnection' scriptType: 'bash' scriptLocation: 'inlineScript' inlineScript: | echo "🧪 Testing deployment..." APP_URL=$(az containerapp show --name "$(containerAppName)" --resource-group "$(resourceGroup)" --query "properties.configuration.ingress.fqdn" -o tsv) echo "Waiting for app to be ready..." sleep 30 if curl -f "https://$APP_URL/list_tools" > /dev/null 2>&1; then echo "✅ Health check passed" echo "🌐 App URL: https://$APP_URL" echo "🔗 Test endpoints:" echo " - https://$APP_URL/list_tools" echo " - https://$APP_URL" else echo "❌ Health check failed" echo "Check Container App logs for details" fi

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/yingkiat/mcp_fabric_server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server