DEV Community

René Nijkamp
René Nijkamp

Posted on • Originally published at itsrene.nl

Azure APIM MCP Automation: The Bridging Problem

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

Diagram

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:

  1. Source of truth for MCP exposure (which APIs become tools?)
  2. Review gates for tool quality (are descriptions agent-friendly?)
  3. Approval workflows for changes (who decides what gets exposed?)
  4. Audit trail for MCP operations (what changed and when?)
  5. 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
Enter fullscreen mode Exit fullscreen mode

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.

Diagram

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-enabled get 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.

Diagram

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.

Diagram

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:

  1. OpenAPI spec is single source of truth (no config duplication)
  2. Standard API deployment unchanged (MCP is an overlay, not replacement)
  3. Governed by flags (explicit opt-in via x-mcp-enabled)
  4. Easy to remove (when ASO adds MCP support)
  5. 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
Enter fullscreen mode Exit fullscreen mode

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: []
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

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}
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

AI agent sees this: "I can onboard customers, verify identities, open accounts, transfer money—I understand the business intent."

Why This Matters for MCP

Diagram

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

Diagram

Three paths forward:

  1. APIs already functional? Add MCP flags, deploy
  2. APIs refactorable? Transform technical → functional first
  3. 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...
Enter fullscreen mode Exit fullscreen mode

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]
Enter fullscreen mode Exit fullscreen mode

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?
Enter fullscreen mode Exit fullscreen mode

Functional approach (single call):

POST /customers/onboard (everything happens atomically)
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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-enabled flags
  • 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
Enter fullscreen mode Exit fullscreen mode

Not:

# Imperative commands that modify state
az apim mcp create --name ...
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

No cowboy deployments. Every change goes through review.

Rollback Capability

Git tags for deployments:

git tag deploy-20260112-103000
Enter fullscreen mode Exit fullscreen mode

Rollback = checkout previous tag:

git checkout deploy-20260112-100000
./deploy.sh  # Re-applies previous state
Enter fullscreen mode Exit fullscreen mode

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:

Diagram

Plugin would:

  1. Scan OpenAPI spec for x-mcp-enabled flags
  2. Generate standard ASO API CRD (existing behavior)
  3. Generate MCP overlay as Kubernetes Job (new behavior)
  4. Job runs as ArgoCD PostSync hook
  5. 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
Enter fullscreen mode Exit fullscreen mode

What we'd need:

  • type: mcp support (currently only http, soap, websocket)
  • mcpConfiguration section for tool control
  • Respect for x-mcp-enabled flags in OpenAPI specs
  • Policy application for MCP servers

Migration path:

  1. ASO releases MCP CRDs
  2. We update our plugin to generate MCP CRDs instead of overlay Jobs
  3. Bump plugin version in parent POM
  4. Redeploy APIs (ASO reconciles to MCP type)
  5. Delete overlay Job charts
  6. 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:

  1. Governance is more critical than automation

    AI agents reading descriptions = extra eyes on every change

  2. API quality matters more than ever

    Don't MCP-ify garbage APIs expecting good agent behavior

  3. GitOps principles apply

    Source control, review gates, rollback capability

  4. Custom bridging is temporary

    Build with removal in mind (ASO will eventually catch up)

  5. 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


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)