Weldon Web

Exposing enterprise APIs as MCP servers through Azure APIM

#azure#apim#mcp#ai

AI agents call tools using Model Context Protocol. When you deploy agents in front of your enterprise systems, your current REST APIs must speak MCP — or some agent must speak MCP.

Over the course of a couple of weeks, I set up an actual reference architecture for this on Azure with API Management serving as the front door. This post is about architecture and why. More in-depth write-ups to follow in upcoming weeks: gotchas, platform limitations, the Claude Code workflow that created it.

Why not a dedicated AI gateway if that's the case?If that is the case, why not a dedicated AI gateway?

Long version: your enterprise already has an API gateway. It is already able to process auth, rate limiting, audit, key rotation, network isolation, observability. It has been approved by your security team.

It's significantly less change to add MCP as another protocol it speaks than to set up an alternate “AI gateway” stack that does all the same governance stuff poorly, worse compliance posture and an entirely different procurement discussion.

But some AI gateway products actually offer truly new features: semantic guardrails, model routing and prompt caching. Fine. Those can sit on the side. This is the heart of the governance layer that needs to be solved and should not be made again.

If you're using Azure, then the answer is APIM.

The two patterns

Depending on the API, there are two ways to expose MCP which you will likely want to do both.

REST-as-MCP is a pattern whereby APIM generates a standard XML inbound policy and Liquid template to transform JSON-RPC payloads to the native REST calls of an existing REST API. You (the developer) choose to make which operations MCP tools, APIM translates the protocol, and your backend service remains unchanged. Best for APIs that you have and are not interested in changing — common enterprise integration applications.

You already have (or create) an MCP server dedicated to your use — in my case. Put APIM in front of NET 9 service — for auth, rate limiting and observability. When the tools require logic that is not easily expressible as a clean REST endpoint, or you want to separate the "agent surface" from the "system of record.

Both are employed during real deployments. Stable CRUD APIs get exposed via Pattern 1. A Pattern 2 server is anything which requires orchestration, session state, or composition across multiple backends.

What sits where

At the front of the APIM: The Entra ID token validation for tool calls feature (with context propagation to the backend through On-Behalf-Of flow) has been introduced.The feature of validating access tokens was introduced for tool calls, with context propagation to the backend via On-Behalf-Of flow.

  • Rate limiting per session or per consumer
  • Application Insights for audit logging. Isolating a network using Private Endpoints Attach Policy fragments for the cross-cutting concerns

The .NET MCP server (Pattern 2) will process: To register and discover tools.Registration and discovery of tools.

  • Session state There are a number of aspects that are important to consider for Azure Load Balancer, which are not mentioned here and will be the subject of a later post (it does matter).
  • Backend orchestration

Deploy everywhere with Terraform. For now the MCP control plane bits require the azapi service, not azurerm: the native resource doesn't exist, but they are clean enough.

An Architecture Diagram

Architecture diagram

Baseline APIM Policy

Here is an initial Entra ID validation policy for your front door:

<policies>
    <inbound>
        <base />
        <validate-jwt header-name="Authorization" failed-validation-httpcode="401" require-scheme="Bearer">
            <openid-config url="[https://login.microsoftonline.com/](https://login.microsoftonline.com/){{tenant-id}}/v2.0/.well-known/openid-configuration" />
            <audiences>
                <audience>{{api-client-id}}</audience>
            </audiences>
            <issuers>
                <issuer>[https://sts.windows.net/](https://sts.windows.net/){{tenant-id}}/</issuer>
            </issuers>
        </validate-jwt>
    </inbound>
</policies> 

Are you considering this?

If your team is considering Azure AI infrastructure, agent governance, or MCP, be sure to reach out via the contact page or LinkedIn DM to discuss the architecture with me.

Contact: jack@weldonweb.co.uk

See the code here https://github.com/jackweldonweb/apim-mcp-terraform, check license for usage information.