Azure APIM MCP Automation: The Bridging Problem
In Part 3, we tackled observability. Now let's talk about the automation elephant in the room.
Azure APIM MCP is in preview. And here's what that means for Infrastructure as Code:
- No ARM template support
- No Bicep support
- No Terraform provider support
- No Azure Service Operator (ASO) support
Here's the reality: You can't use standard IaC tooling. You're either clicking through the Azure Portal manually, or you're building custom automation.
But before you rush to build REST API scripts, let's talk about why this problem matters and what it means for your architecture.
Why This Is Different
It's Not Just About Automation
Most IaC gaps are annoying but straightforward: write some REST API calls, wrap them in a script, deploy via pipeline. Done.
MCP is different. And here's why:
AI agents read your API descriptions. Those descriptions become tool definitions that LLMs use to decide when and how to invoke your APIs. A poorly written description? The agent misunderstands. A misleading summary? The agent calls the wrong endpoint. A missing security note? The agent leaks data.
This is a governance problem disguised as an automation problem.
The Real Risks
Without proper governance:
- No review of tool descriptions before AI agents see them
- No validation of API quality before MCP exposure
- No control over which operations become agent-accessible tools
- No audit trail of what got exposed and when
This isn't Terraform failing to deploy a VM. This is giving AI agents access to your business logic without proper oversight.
The Governance-First Approach
What We Need
Before worrying about automation tooling, we need:
- Source of truth for MCP exposure (which APIs become tools?)
- Review gates for tool quality (are descriptions agent-friendly?)
- Approval workflows for changes (who decides what gets exposed?)
- Audit trail for MCP operations (what changed and when?)
- Rollback capability (can we undo a bad exposure?)
This is GitOps territory. Not because of Kubernetes or Helm charts, but because we need:
- Version control for configuration
- Pull request reviews before changes
- Approval gates for production
- History of who changed what
OpenAPI as Configuration
Here's the pattern: OpenAPI specifications become your configuration files.
paths:
/users/{userId}/profile:
get:
operationId: getUserProfile
summary: "Retrieve user profile information"
description: "Get comprehensive profile data for the authenticated user including preferences, settings, and basic account information. This tool respects user privacy and only returns data the user has permission to access."
x-mcp-enabled: true # Governance flag
parameters:
- name: userId
in: path
required: true
description: "User identifier - must match authenticated user"
schema:
type: string
That x-mcp-enabled: true flag is governance metadata, not just a technical toggle. It says:
- Someone reviewed this operation's description
- Someone decided AI agents should have access
- Someone validated the security model
- Someone approved this for MCP exposure
No flag = no MCP exposure. Simple as that.
Conceptual Bridging Approaches
Let's talk about how to bridge the IaC gap until ASO catches up.
Full disclosure: These are patterns we're exploring, not battle-tested solutions. They're based on months of working with APIM MCP and years of GitOps experience, but consider them architectural ideas rather than production-ready implementations.
Pattern 1: Centralized Automation Repository
Concept: Single repository that polls APIM instances, detects APIs with x-mcp-enabled flags, and applies MCP overlays.
Characteristics:
- Separation of concerns: Standard API deployment unchanged
- Non-invasive: Overlay runs externally, doesn't touch existing workflows
- Easy removal: When ASO adds MCP support, delete the overlay repo
-
Governance preserved: Only APIs with
x-mcp-enabledget converted
Trade-offs:
- Eventual consistency (polling-based, not real-time)
- Requires cross-subscription credentials for multi-tenant scenarios
- Centralized monitoring but distributed execution
Pattern 2: Event-Driven Kubernetes Jobs
Concept: ArgoCD PostSync hooks that detect MCP-enabled APIs after deployment and apply conversion.
Characteristics:
- Event-driven: Conversion happens immediately after API deployment
- Kubernetes-native: Fits existing ArgoCD workflows
- Per-cluster isolated: Each cluster handles its own APIM instance
Trade-offs:
- Embeds workaround in Helm charts (harder to remove cleanly)
- Requires RBAC setup for Kubernetes service accounts
- Debugging in pod logs vs centralized logging
Pattern 3: Build-Time Generation
Concept: Maven plugin or build tool generates two outputs: standard API spec + MCP overlay config.
Characteristics:
- Zero operational overhead: Automatic for all builds
- Fits existing workflows: Maven → Helm → ArgoCD
- Centralized logic: One plugin, all APIs benefit
Trade-offs:
- Requires modifying build tooling (parent POM, plugins)
- Longer development time upfront
- Still needs Azure credentials in Kubernetes
What These Patterns Have in Common
All three approaches share critical principles:
- OpenAPI spec is single source of truth (no config duplication)
- Standard API deployment unchanged (MCP is an overlay, not replacement)
-
Governed by flags (explicit opt-in via
x-mcp-enabled) - Easy to remove (when ASO adds MCP support)
- Support full CRUD (create, update, delete MCP exposure)
Which one is right? Depends on your organization:
- Centralized control + multi-tenant? Pattern 1
- Kubernetes-native + per-cluster isolation? Pattern 2
- Minimal operational overhead? Pattern 3
The Governance Framework
Let's break down what governance actually means for MCP exposure.
Review Workflow
Typical approval flow:
Developer → OpenAPI with x-mcp-enabled → Pull Request →
Domain Review → Security Review → Principal Architect →
Merge → Automated Deployment → MCP Server Live
What gets reviewed:
| Aspect | Review Focus | Risk if Skipped |
|---|---|---|
| Description Quality | Is it clear for AI agents? | Misunderstood intent, wrong API calls |
| Security Model | Auth requirements documented? | Unauthorized access, data leaks |
| Data Exposure | Sensitive data clearly marked? | Privacy violations, compliance gaps |
| Operation Safety | Read-only vs write operations? | Accidental data modification |
| Rate Limiting | Appropriate throttling? | Resource exhaustion, DoS |
Tool Quality Standards
Bare minimum for MCP-enabled operations:
# BAD: Too vague for AI agents
get:
summary: "Get user"
x-mcp-enabled: true
# GOOD: Clear, actionable, with constraints
get:
summary: "Retrieve user profile information"
description: |
Get comprehensive profile data for the authenticated user including
preferences, settings, and basic account information.
**Authentication required**: User can only access their own profile.
**Data privacy**: Returns only non-sensitive user data.
**Rate limit**: 100 requests per minute.
x-mcp-enabled: true
security:
- BearerAuth: []
Why this matters: AI agents rely on descriptions to understand:
- What the tool does
- When to use it
- What data it returns
- What permissions are needed
Poor descriptions = poor agent behavior.
CODEOWNERS for MCP
Enforce review requirements:
# In your Git repository
/apis/customer-management/ @customer-team @security-team
/apis/payment-processing/ @payment-team @compliance-team @security-team
/apis/public-data/ @platform-team
# Any file with x-mcp-enabled requires principal architect
**/openapi*.yaml @principal-architect
This enforces:
- Domain experts review their APIs
- Security team sees all MCP-enabled operations
- Principal architect has final approval
Audit Trail
Git as audit trail:
{
"commit": "abc123",
"author": "developer@org.com",
"timestamp": "2026-01-12T10:30:00Z",
"changes": [
{
"file": "apis/customer-management/openapi.yaml",
"operation": "/users/{userId}/profile",
"change": "Added x-mcp-enabled: true",
"reviewers": ["security-team", "principal-architect"],
"approved_at": "2026-01-12T11:00:00Z"
}
]
}
Every MCP exposure change lives in Git history. Who changed what, when, and who approved it.
API Quality Prerequisites
Here's an uncomfortable truth: You can't sprinkle MCP on top of a shitty API landscape and expect good results.
What Makes an API "MCP-Ready"?
Not every API should become an MCP tool. Consider:
| Characteristic | MCP-Ready | Not MCP-Ready |
|---|---|---|
| Documentation | Clear, complete, agent-friendly | Sparse, outdated, human-only |
| Stability | Versioned, stable contract | Frequent breaking changes |
| Error Handling | Structured error responses | Generic 500s, no details |
| Security Model | Well-defined auth/authz | Ad-hoc permissions |
| Performance | Reliable response times | Intermittent timeouts |
| Idempotency | Safe retry behavior | Side effects on retry |
AI agents are unforgiving consumers. They won't debug your API, they won't file tickets, they'll just fail spectacularly.
The Functional vs Technical API Problem
Here's the hill I'm willing to die on: AI agents need functional APIs, not technical APIs.
Technical APIs (what most orgs have):
# CRUD operations, database-centric
POST /api/v1/customers
GET /api/v1/customers/{id}
PUT /api/v1/customers/{id}
DELETE /api/v1/customers/{id}
POST /api/v1/accounts
GET /api/v1/accounts/{id}
PUT /api/v1/accounts/{id}
AI agent sees this: "I have create, read, update, delete... but what am I actually doing for the user?"
Functional APIs (what agents need):
# Business capabilities, intent-driven
POST /customers/onboard
- "Onboard a new customer with KYC verification"
POST /customers/{id}/verify-identity
- "Verify customer identity using government documents"
POST /accounts/open
- "Open a new bank account for verified customer"
POST /payments/transfer
- "Transfer money between accounts with fraud checks"
AI agent sees this: "I can onboard customers, verify identities, open accounts, transfer money—I understand the business intent."
Why This Matters for MCP
With technical APIs:
- Agent must orchestrate multiple low-level operations
- No transaction boundaries (what if step 3 fails?)
- Business rules scattered across agent logic
- High risk of incorrect sequences
With functional APIs:
- Single API call expresses business intent
- Transaction handled by backend
- Business rules centralized in API
- Lower risk, easier to audit
The Refactoring Question
Three paths forward:
- APIs already functional? Add MCP flags, deploy
- APIs refactorable? Transform technical → functional first
- APIs beyond hope? Build new functional APIs from scratch
Don't expose CRUD endpoints to AI agents expecting them to orchestrate business logic. That's a production incident waiting to happen.
Real-World Examples
Bad API (technical, don't MCP-ify this):
/api/customers:
post:
summary: "Create customer"
description: "Insert customer record into database"
requestBody:
content:
application/json:
schema:
type: object
properties:
firstName: string
lastName: string
email: string
# 50 more fields...
AI agent sees this: "I can create a customer record, but what about KYC? Compliance checks? Account setup? Am I supposed to call other APIs? Which ones?"
Good API (functional, MCP-ready):
/customers/onboard:
post:
summary: "Onboard new customer with full verification"
description: |
Complete customer onboarding process including:
- Identity verification (government ID + liveness check)
- KYC/AML compliance screening
- Risk assessment
- Welcome email and account activation
**Business rules enforced:**
- Customer must be 18+ years old
- Must pass identity verification
- Must clear compliance screening
- Duplicate detection performed automatically
**What happens on success:**
- Customer record created with verified status
- Welcome email sent
- Customer can proceed to account opening
**Authentication required:** Staff or authorized system only
**Rate limit:** 10 requests per minute
x-mcp-enabled: true
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [firstName, lastName, dateOfBirth, governmentId]
properties:
firstName:
type: string
description: "Customer's legal first name"
lastName:
type: string
description: "Customer's legal last name"
dateOfBirth:
type: string
format: date
description: "Date of birth (must be 18+ years ago)"
governmentId:
type: object
description: "Government-issued identification"
required: [type, number, issuingCountry]
properties:
type:
type: string
enum: [passport, drivers_license, national_id]
number:
type: string
issuingCountry:
type: string
responses:
'201':
description: "Customer onboarded successfully"
content:
application/json:
schema:
type: object
properties:
customerId:
type: string
description: "Unique customer identifier"
verificationStatus:
type: string
enum: [verified, pending_review]
nextSteps:
type: array
items:
type: string
example: ["Open savings account", "Apply for credit card"]
'400':
description: "Invalid input or failed verification"
content:
application/json:
schema:
type: object
properties:
error:
type: string
reason:
type: string
enum: [underage, failed_identity_check, failed_compliance, duplicate_customer]
AI agent sees this: "Crystal clear. This onboards a customer, handles verification, enforces business rules, tells me what happens next. I know exactly when to use this and what data I need."
Why Technical APIs Fail with AI Agents
Problem 1: Orchestration burden
Technical approach (agent must figure out):
1. POST /customers (create record)
2. POST /kyc-checks (verify identity)
3. GET /kyc-checks/{id} (wait for result)
4. POST /compliance-screenings (AML check)
5. GET /compliance-screenings/{id} (wait for result)
6. PUT /customers/{id} (update status to verified)
7. POST /emails (send welcome email)
What if step 4 fails? What if step 6 fails but step 7 succeeds?
Functional approach (single call):
POST /customers/onboard (everything happens atomically)
Problem 2: Business rule discovery
Technical API says: "Here's a database table, figure it out"
Functional API says: "Here's the business process, I'll enforce the rules"
Problem 3: Error semantics
Technical API: 400 Bad Request (what went wrong?)
Functional API: 400 Bad Request - reason: "failed_identity_check" (ah, identity verification failed)
This isn't just API design pedantry. This is the difference between agents that work and agents that cause production incidents.
GitOps Principles for MCP
Let's talk about what "GitOps" actually means in this context.
Single Source of Truth
Everything in Git:
- OpenAPI specifications with
x-mcp-enabledflags - APIM policy templates
- Security configurations
- Access control lists
Nothing in Azure Portal. If it's not in Git, it doesn't exist.
Declarative Configuration
What we want:
# This operation should be an MCP tool
x-mcp-enabled: true
Not:
# Imperative commands that modify state
az apim mcp create --name ...
The bridge automation reads declarative config and reconciles Azure state.
Review Before Merge
Feature Branch → Pull Request → Automated Validation →
Human Review → Approval → Merge to Main → Automated Deployment
No cowboy deployments. Every change goes through review.
Rollback Capability
Git tags for deployments:
git tag deploy-20260112-103000
Rollback = checkout previous tag:
git checkout deploy-20260112-100000
./deploy.sh # Re-applies previous state
Observability
Track what automation does:
- What APIs were scanned?
- Which operations had
x-mcp-enabled? - What MCP servers were created/updated/deleted?
- Any failures or errors?
Pipeline logs become your audit trail.
Our Exploration: What We're Testing
Full transparency: We're in the exploration phase. Here's what we're considering for Grand Central.
Option We're Leaning Toward
Maven plugin extension that generates MCP overlay configs during build.
Why this appeals:
- Fits our existing OpenAPI → Maven → Helm → ArgoCD workflow
- Zero operational overhead once deployed
- Centralized logic (one plugin, all APIs benefit)
- Easy removal when ASO adds MCP support
How it would work:
Plugin would:
- Scan OpenAPI spec for
x-mcp-enabledflags - Generate standard ASO API CRD (existing behavior)
- Generate MCP overlay as Kubernetes Job (new behavior)
- Job runs as ArgoCD PostSync hook
- Job calls Azure REST API to convert API to MCP type
Why Not the Alternatives?
Centralized polling approach:
- Requires cross-subscription service principal
- Eventual consistency (polling lag)
- Extra infrastructure to maintain
Per-customer workflows:
- Deployment overhead (one repo per customer installation)
- Configuration drift risk
- Harder to update/remove
Our context: Multi-tenant platform with dozens of APIM instances, standardized bootstrap configuration across all of them. Maven plugin fits our existing patterns.
What We Haven't Solved Yet
Kubernetes RBAC:
- How do Jobs get Azure credentials?
- Managed Identity? Service account with federated identity?
- Per-cluster or shared credentials?
Error handling:
- Job fails to convert API to MCP. Now what?
- Does ArgoCD deployment fail? Or continue?
- How do we surface MCP conversion errors to developers?
Testing strategy:
- How do we validate MCP overlays in dev before production?
- Can we preview what tools would be exposed?
- Dry-run mode for the conversion?
Removal path:
- When ASO adds MCP support, how do we migrate?
- Do we update the plugin to generate ASO MCP CRDs instead of Jobs?
- Phased rollout or big-bang cutover?
These are open questions. We're working through them.
Decision Framework: When to Build vs Wait
Not every organization should build custom automation. Let's break down the decision.
Build Custom Bridging If:
- You have scale (multiple APIM instances, lots of APIs)
- You have GitOps maturity (already using IaC, review processes)
- You have time (2-4 weeks for design + implementation + testing)
- You have appetite (willing to maintain bridge until ASO catches up)
- You need governance (AI agents accessing business-critical APIs)
Wait for ASO If:
- Small scale (1-2 APIM instances, handful of APIs)
- Portal management is fine (low change frequency)
- Prototyping phase (not production-critical yet)
- No GitOps (not using IaC for other Azure resources)
- Resource constrained (can't invest dev time in tooling)
Our Context
Why we're building:
- Dozens of APIM instances across customer installations
- Hundreds of APIs, growing fast
- Existing GitOps workflows (OpenAPI → Maven → ArgoCD)
- Banking platform (governance non-negotiable)
- Multi-tenant isolation requirements
Manual Portal management doesn't scale at our size.
What ASO Support Would Look Like
Microsoft hasn't announced a timeline, but here's what we expect:
CRD Structure (Hypothetical)
apiVersion: apimanagement.azure.com/v1api20260501
kind: API
metadata:
name: customer-api
namespace: default
spec:
owner:
name: apim-instance
displayName: "Customer Management API"
type: mcp # MCP type support
path: customer-mcp
serviceUrl: https://backend.example.com
protocols:
- https
apiVersion: v1
mcpConfiguration: # MCP-specific config
enableToolDiscovery: true
mcpTools:
- operationId: getUserProfile
enabled: true
- operationId: updateUserProfile
enabled: true
What we'd need:
-
type: mcpsupport (currently onlyhttp,soap,websocket) -
mcpConfigurationsection for tool control - Respect for
x-mcp-enabledflags in OpenAPI specs - Policy application for MCP servers
Migration path:
- ASO releases MCP CRDs
- We update our plugin to generate MCP CRDs instead of overlay Jobs
- Bump plugin version in parent POM
- Redeploy APIs (ASO reconciles to MCP type)
- Delete overlay Job charts
- Done
If ASO doesn't support x-mcp-enabled flags: We'd need to maintain the plugin logic anyway, just targeting CRDs instead of REST API.
Advocacy: Push Microsoft
Here's the thing: Microsoft responds to feedback. If nobody asks for MCP IaC support, it stays low priority.
What You Can Do
File GitHub issues:
- Azure/azure-service-operator: Request MCP CRD support
- Azure/azure-rest-api-specs: Request stable MCP API version
- Azure/bicep: Request MCP resource types
Engage on Azure forums:
- Azure feedback portal: Vote for IaC support
- Azure APIM team: Share your use case
Show demand: The more organizations ask, the higher priority it becomes.
We're doing our part. We've already escalated to Microsoft's APIM team. They're aware of the need. But they need to see community demand.
Conclusion: The Architect's Lens
Let's zoom out and look at this from an architecture perspective.
What This Series Covered
- Part 1: MCP preview realities (what works, what's broken, when to use it)
-
Part 2: Security hardening (fixing
/tools/list, subscription validation) - Part 3: Observability (audit logging without performance hits)
- Part 4 (this post): Automation bridging (governance-first approach)
Key Takeaways
MCP on Azure APIM is powerful but immature. You can run it in production, but:
Governance is more critical than automation
AI agents reading descriptions = extra eyes on every changeAPI quality matters more than ever
Don't MCP-ify garbage APIs expecting good agent behaviorGitOps principles apply
Source control, review gates, rollback capabilityCustom bridging is temporary
Build with removal in mind (ASO will eventually catch up)Not every org should build
Weigh scale, maturity, and resources before committing
Where We Are
At Grand Central: Exploring Maven plugin approach for our multi-tenant scale. Governance framework designed. API quality assessment in progress. Not deployed yet.
Being honest: These are ideas we're testing, not battle-tested solutions. We're sharing our thinking because maybe it helps you avoid pitfalls.
What's Next
For us: Prototype the Maven plugin, test in dev environment, validate governance workflows, iterate based on learnings.
For you: Assess your context. Do you need custom bridging? Can you wait for ASO? What's your governance story?
For Microsoft: Keep pushing them. File issues. Share use cases. Show demand.
Resources
- Azure Service Operator: https://github.com/Azure/azure-service-operator
- APIM REST API: https://learn.microsoft.com/rest/api/apimanagement/
- MCP Specification: https://modelcontextprotocol.io/
- OpenAPI Extension: x-mcp-enabled pattern (community convention)
I'm a Product Architect at Backbase, where I design integration platforms for global banks. The patterns in this series come from real production implementations at enterprise scale, filtered through the lens of "what would I want to know if I were you?" Views are my own.
Building custom MCP automation? Running into governance challenges? Let's talk—drop a comment or connect on LinkedIn.
Top comments (0)