MCP-servers programmatisch beheren in API Management

In dit artikel leert u hoe u MCP-servers maakt en beheert in Azure API Management met behulp van de REST API, ARM-sjablonen, Bicep, de Azure CLI en Terraform. 

Important

Voor de beheerfuncties voor MCP-servers die in dit artikel worden beschreven, is API Management REST API versie 2025-09-01-preview of hoger vereist. Maak deze versie vast in elke aanvraag. 

Zie Over MCP-servers in Azure API Management voor achtergrondinformatie over de mogelijkheden van MCP-servers.

Vereiste voorwaarden

Resourcemodel

Azure Resource Manager vertegenwoordigt MCP-servers als volgt:

  • MCP-server: Een API Management API-resource van het typeMCP.

  • Passthrough-server: Wijst naar een bestaande externe MCP-back-end. De MCP-serverresource declareert de back-end-URL en het transporttype (streamable HTTP of SSE).

  • Tool: Een API-tool-subresource van een MCP-server. U kunt hulpprogrammabronnen veilig beheren vanuit CI/CD. U kunt hulpprogramma's toevoegen, een andere naam geven of verwijderen zonder de MCP-server opnieuw te maken.

  • Beleid: Net als bij reguliere API's koppelt u API-beleid of subbronnen voor beleid aan een MCP-server.

  • Producten: Productbinding is een afzonderlijke onderliggende relatie (products/{productId}/apis/{mcpServerId}), waardoor onafhankelijke implementatie en binding met meerdere producten mogelijk zijn.

REST-voorbeelden

Voor de duidelijkheid tonen de volgende voorbeelden verkorte antwoordteksten. Zie de API Management REST API-naslaginformatie voor volledige antwoordschema's.

Door de If-Match: *-header toe te voegen in de voorbeelden van PUT- en DELETE-aanroepen, worden de verzoeken idempotent. Deze header is van toepassing ongeacht of de resource al bestaat; dit is de aanbevolen werkwijze voor CI/CD-pipelines.

Voordat u begint

Stel de volgende variabelen in voordat u een voorbeeld uitvoert. Alle voorbeelden in deze sectie verwijzen naar deze variabelen.

SUBSCRIPTION_ID="<your-subscription-id>"
RESOURCE_GROUP="<your-resource-group>"
APIM_NAME="<your-api-management-service-name>"
API_VERSION="2025-09-01-preview"
BASE_URL="https://management.azure.com/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.ApiManagement/service/${APIM_NAME}"
TOKEN=$(az account get-access-token --resource https://management.azure.com --query accessToken -o tsv)

MCP-servers vermelden

Geeft alle API's in de instantie terug, gefilterd op type mcp. Gebruik de queryparameters $top en $skip om grote resultatensets te pagineren.

Referentie: Api - List By Service

curl -sG "${BASE_URL}/apis" \
  --data-urlencode "api-version=${API_VERSION}" \
  --data-urlencode "\$filter=type eq 'mcp'" \
  -H "Authorization: Bearer ${TOKEN}"

Antwoord (200 OK)

{
  "count": 1,
  "value": [
    {
      "id": "/subscriptions/.../apis/my-mcp-server",
      "name": "my-mcp-server",
      "type": "Microsoft.ApiManagement/service/apis",
      "properties": {
        "type": "mcp",
        "displayName": "My MCP Server",
        "path": "my-mcp",
        "protocols": [ "https" ]
      }
    }
  ]
}

Veelvoorkomende fout:401 Unauthorized. Het bearer-token is verlopen. Voer de opdracht voor het ophalen van tokens opnieuw uit.


Eén MCP-server ophalen

Referentie: Api - Get

MCP_SERVER_ID="my-mcp-server"

curl -s "${BASE_URL}/apis/${MCP_SERVER_ID}?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${TOKEN}"

Antwoord (200 OK)

{
  "id": "/subscriptions/.../apis/my-mcp-server",
  "name": "my-mcp-server",
  "type": "Microsoft.ApiManagement/service/apis",
  "properties": {
    "type": "mcp",
    "displayName": "My MCP Server",
    "path": "my-mcp",
    "protocols": [ "https" ],
    "serviceUrl": "https://api.contoso.com"
  }
}

Veelvoorkomende fout:404 Not Found. Bevestig dat mcpServerId overeenkomt met het veld name dat door de List-bewerking wordt geretourneerd.


Een MCP-server met REST API-ondersteuning maken

Hiermee maakt u de MCP-serverresource. Voeg na het maken hulpprogramma's afzonderlijk toe met behulp van de bewerking Een hulpprogramma toevoegen of bijwerken . Elk hulpprogramma verwijst naar een specifieke bewerking in een BACKing REST API-resource.

Referentie: API - Maken of bijwerken

MCP_SERVER_ID="my-mcp-server"

curl -s -X PUT \
  "${BASE_URL}/apis/${MCP_SERVER_ID}?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -H "If-Match: *" \
  -d '{
    "properties": {
      "type": "mcp",
      "path": "my-mcp",
      "displayName": "My MCP Server",
      "description": "MCP server backed by a REST API",
      "protocols": ["https"]
    }
  }'

Antwoord (201 Aangemaakt)

{
  "id": "/subscriptions/.../apis/my-mcp-server",
  "name": "my-mcp-server",
  "type": "Microsoft.ApiManagement/service/apis",
  "properties": {
    "type": "mcp",
    "displayName": "My MCP Server",
    "path": "my-mcp",
    "protocols": ["https"],
    "provisioningState": "InProgress"
  }
}

Note

provisioningState: InProgress wordt verwacht voor asynchrone PUT-bewerkingen. Controleer regelmatig de URL die wordt geretourneerd in de Azure-AsyncOperation responsheader om te bevestigen dat de bewerking is voltooid.

Veelvoorkomende fout:400 Bad Request. Zorg ervoor dat type"mcp" is en path uniek is binnen de service-instantie.


Een passthrough MCP-server maken

Een passthrough-server stuurt alle MCP-aanvragen rechtstreeks door naar een externe MCP-back-end. Ingesteld mcpProperties.transportType op overeenstemming met het transport dat uw back-end implementeert.

Voordat u een passthrough-server maakt, controleert u of de back-end bereikbaar is vanaf de API Management-gateway en implementeert u het geselecteerde MCP-transport op de eindpuntpaden die u configureert. Als voor de backend authenticatie is vereist, configureer dan de vereiste aanmeldingsgegevens of headers met behulp van API Management-beleid of backendconfiguratie.

Referentie: API - Maken of bijwerken

Streambaar HTTP-transport

Gebruik streamable voor backends die de huidige MCP-specificatie voor streambaar HTTP-transport implementeren. Er is één eindpuntdefinitie vereist.

MCP_SERVER_ID="my-mcp-passthrough"

curl -s -X PUT \
  "${BASE_URL}/apis/${MCP_SERVER_ID}?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -H "If-Match: *" \
  -d '{
    "properties": {
      "type": "mcp",
      "path": "my-mcp-passthrough",
      "displayName": "My Passthrough MCP Server",
      "description": "Passthrough MCP server using streamable HTTP transport",
      "protocols": ["https"],
      "serviceUrl": "https://mcp-backend.contoso.com",
      "mcpProperties": {
        "transportType": "streamable",
        "endpoints": [
          { "name": "message", "uriTemplate": "/mcp" }
        ]
      }
    }
  }'

Antwoord (201 Aangemaakt)

{
  "id": "/subscriptions/.../apis/my-mcp-passthrough",
  "name": "my-mcp-passthrough",
  "type": "Microsoft.ApiManagement/service/apis",
  "properties": {
    "type": "mcp",
    "displayName": "My Passthrough MCP Server",
    "path": "my-mcp-passthrough",
    "protocols": ["https"],
    "serviceUrl": "https://mcp-backend.contoso.com",
    "provisioningState": "InProgress",
    "mcpProperties": {
      "transportType": "streamable",
      "endpoints": [ { "name": "message", "uriTemplate": "/mcp" } ]
    }
  }
}

SSE-transport

Gebruik sse voor backends die het HTTP+SSE-transport (Server-Sent Events) implementeren. Definieer twee eindpunten: één voor de SSE-gebeurtenisstroom en één voor het berichtkanaal.

MCP_SERVER_ID="my-mcp-sse"

curl -s -X PUT \
  "${BASE_URL}/apis/${MCP_SERVER_ID}?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -H "If-Match: *" \
  -d '{
    "properties": {
      "type": "mcp",
      "path": "my-mcp-sse",
      "displayName": "My SSE MCP Server",
      "description": "Passthrough MCP server using SSE transport",
      "protocols": ["https"],
      "serviceUrl": "https://mcp-backend.contoso.com",
      "mcpProperties": {
        "transportType": "sse",
        "endpoints": [
          { "name": "sse",     "uriTemplate": "/sse" },
          { "name": "message", "uriTemplate": "/messages" }
        ]
      }
    }
  }'

Veelvoorkomende fouten:

  • 400 Bad Request. Ongeldig mcpProperties. Controleer of transportTypestreamable of sse is en of elke uriTemplate met / begint.
  • 400 Bad Request. SSE-transport vereist precies twee eindpunten (sse en message). Stroombaar transport vereist één (message).

Een hulpprogramma toevoegen of bijwerken

Voegt een nieuw hulpprogramma toe aan een MCP-server met REST API-ondersteuning of werkt een bestaand hulpprogramma bij. Het operationId veld koppelt het hulpprogramma aan een specifieke bewerking in een BACKing REST API-resource. U kunt hulpprogramma's onafhankelijk toevoegen, bijwerken of verwijderen zonder de bovenliggende server opnieuw te maken.

Referentie: API-tool - Aanmaken of bijwerken

MCP_SERVER_ID="my-mcp-server"
TOOL_ID="listOrders"
BACKING_API_ID="orders-api"
BACKING_OP_ID="list-orders"
OP_ID="/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.ApiManagement/service/${APIM_NAME}/apis/${BACKING_API_ID}/operations/${BACKING_OP_ID}"

curl -s -X PUT \
  "${BASE_URL}/apis/${MCP_SERVER_ID}/tools/${TOOL_ID}?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -H "If-Match: *" \
  --data-raw "{
    \"properties\": {
      \"displayName\": \"listOrders\",
      \"description\": \"List all orders for a customer\",
      \"operationId\": \"${OP_ID}\"
    }
  }"

Antwoord (201 Aangemaakt)

{
  "id": "/subscriptions/.../apis/my-mcp-server/tools/listOrders",
  "name": "listOrders",
  "type": "Microsoft.ApiManagement/service/apis/tools",
  "properties": {
    "displayName": "listOrders",
    "description": "List all orders for a customer",
    "operationId": "/subscriptions/.../apis/orders-api/operations/list-orders"
  }
}

Veelvoorkomende fouten:

  • 400 Bad Request. Het operationId pad is ongeldig of de bewerking waarnaar wordt verwezen, bestaat niet.
  • 404 Not Found. De bovenliggende MCP-server bestaat niet. Maak de server voordat u hulpprogramma's toevoegt.

Een hulpprogramma verwijderen

Hiermee verwijdert u een hulpprogramma van een MCP-server. Verwijder hulpprogramma's voordat u de BACKing REST API-bewerkingen verwijdert waarnaar ze verwijzen; anders mislukt het verwijderen met een afhankelijkheidsfout.

Referentie: Api Tool - Verwijderen

MCP_SERVER_ID="my-mcp-server"
TOOL_ID="listOrders"

curl -s -X DELETE \
  "${BASE_URL}/apis/${MCP_SERVER_ID}/tools/${TOOL_ID}?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "If-Match: *"

Antwoord:200 OK bij succes.

Veelvoorkomende fout:412 Precondition FailedIf-Match is vereist voor verwijderingen. Gebruik If-Match: * om overeen te komen met elke ETag.


Beleid toepassen op MCP-niveau

Hiermee maakt of vervangt u het beleidsdocument dat is gekoppeld aan een MCP-server. De server evalueert beleidsregels op dit bereik voor elke aanroep van hulpprogramma's. De rawxml indeling accepteert niet-gecodeerde beleids-XML.

Referentie: API-beleid - Maken of bijwerken

MCP_SERVER_ID="my-mcp-server"
POLICY='<policies><inbound><base /><rate-limit calls="100" renewal-period="60" /></inbound><backend><forward-request /></backend><outbound><base /></outbound></policies>'

curl -s -X PUT \
  "${BASE_URL}/apis/${MCP_SERVER_ID}/policies/policy?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -H "If-Match: *" \
  --data-raw "{\"properties\":{\"format\":\"rawxml\",\"value\":\"${POLICY}\"}}"

Antwoord (200 OK)

{
  "id": "/subscriptions/.../apis/my-mcp-server/policies/policy",
  "name": "policy",
  "type": "Microsoft.ApiManagement/service/apis/policies",
  "properties": {
    "value": "<policies>...</policies>"
  }
}

Veelvoorkomende fout:400 Bad Request. Ongeldige beleids-XML. Valideer het document voordat u het verzendt.


Een MCP-server verbinden met een product

Koppelt de MCP-server aan een product, zodat abonnees van dat product de hulpprogramma's van de server kunnen aanroepen. De aanvraag heeft geen hoofdtekst.

Wanneer u de MCP-server verbindt met een product, maakt u deze beschikbaar via dat product, maar hebben clients nog steeds toegang nodig volgens de configuratie van het product. Als het product abonnementen vereist, moet de client een geldige abonnementscode voor dat product gebruiken.

Referentie: Product Api - Aanmaken of bijwerken

MCP_SERVER_ID="my-mcp-server"
PRODUCT_ID="my-product"

curl -s -X PUT \
  "${BASE_URL}/products/${PRODUCT_ID}/apis/${MCP_SERVER_ID}?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Length: 0"

Reactie:201 Created met het API-contract van de MCP-server in de hoofdtekst.

Veelvoorkomende fout:404 Not Found. Controleer of beide productId en mcpServerId bestaan voordat u de binding maakt.


Een MCP-server verwijderen

Verwijdert een MCP-server en alle subresources van hulpprogramma's en beleid. Voordat u de server verwijdert, verwijdert u alle hulpprogramma's die verwijzen naar bewerkingen in back-up-API's; anders kunt u deze bewerkingen niet verwijderen terwijl de verwijzing naar het hulpprogramma bestaat.

Referentie: Api - Verwijderen

MCP_SERVER_ID="my-mcp-server"

curl -s -X DELETE \
  "${BASE_URL}/apis/${MCP_SERVER_ID}?api-version=${API_VERSION}" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "If-Match: *"

Antwoord:200 OK bij succes.

Veelvoorkomende fout:412 Precondition Failed. If-Match is vereist voor verwijderingen. Gebruik If-Match: * dit om ETag-controle te omzeilen.

ARM- en Bicep-sjablonen

Met de volgende sjablonen wordt een volledige MCP-serverconfiguratie geïmplementeerd in één implementatie. Elke sjabloon gaat uit van een bestaand exemplaar van de API Management-service en gebruikt een parametertabel, zodat u hetzelfde bestand in verschillende omgevingen kunt hergebruiken door alleen de parameterwaarden te wijzigen.

MCP-server met REST API-ondersteuning

Met deze sjablonen maakt u een MCP-server, definieert u een hulpprogramma dat wordt toegewezen aan een bewerking in een bestaande BACKing REST API, koppelt u een beleid voor frequentielimiet aan het serverbereik en verbindt u de server met een bestaand product. U kunt al deze taken uitvoeren in één implementatie.

Vereisten: een bestaande API Management-service, een REST API (backingApiId) met ten minste één bewerking (backingOperationId) en een bestaand product (productId).

Parameter Vereist Default Beschrijving
serviceName Ja Naam van de bestaande API Management-service-instantie.
mcpServerId No orders-mcp Resourcenaam voor de nieuwe MCP-server. Moet uniek zijn binnen de service.
backingApiId Ja De resourcenaam van de bestaande REST API die deze MCP-server ondersteunt.
backingOperationId Ja Resourcenaam van de bewerking die moet worden weergegeven als een hulpprogramma.
toolId No sampleTool Resourcenaam en weergavenaam van het MCP-hulpprogramma dat u wilt maken.
productId No starter Resourcenaam van het bestaande product waaraan de server moet worden gekoppeld.
@description('Name of the existing API Management service instance.')
param serviceName string

@description('Resource name for the new MCP server.')
param mcpServerId string = 'orders-mcp'

@description('Resource name of the existing REST API that backs this MCP server.')
param backingApiId string

@description('Resource name of the operation in the backing REST API to expose as a tool.')
param backingOperationId string

@description('Resource name and display name of the MCP tool to create.')
param toolId string = 'sampleTool'

@description('Resource name of the existing product to bind the MCP server to.')
param productId string = 'starter'

resource apimService 'Microsoft.ApiManagement/service@2025-09-01-preview' existing = {
  name: serviceName
}

resource mcpServer 'Microsoft.ApiManagement/service/apis@2025-09-01-preview' = {
  parent: apimService
  name: mcpServerId
  properties: {
    type: 'mcp'
    displayName: 'Orders MCP Server'
    description: 'MCP server backed by the Orders REST API'
    path: mcpServerId
    protocols: [ 'https' ]
    subscriptionRequired: true
  }
}

resource mcpTool 'Microsoft.ApiManagement/service/apis/tools@2025-09-01-preview' = {
  parent: mcpServer
  name: toolId
  properties: {
    displayName: toolId
    description: 'MCP tool backed by an API operation'
    operationId: resourceId(
      'Microsoft.ApiManagement/service/apis/operations',
      serviceName, backingApiId, backingOperationId
    )
  }
}

resource mcpPolicy 'Microsoft.ApiManagement/service/apis/policies@2025-09-01-preview' = {
  parent: mcpServer
  name: 'policy'
  properties: {
    format: 'rawxml'
    value: '''<policies>
  <inbound>
    <base />
    <rate-limit calls="100" renewal-period="60" />
  </inbound>
  <backend>
    <forward-request />
  </backend>
  <outbound>
    <base />
  </outbound>
</policies>'''
  }
}

resource product 'Microsoft.ApiManagement/service/products@2025-09-01-preview' existing = {
  parent: apimService
  name: productId
}

resource productBinding 'Microsoft.ApiManagement/service/products/apis@2025-09-01-preview' = {
  parent: product
  name: mcpServerId
  dependsOn: [ mcpServer ]
}

Om te implementeren:

# Use orders-mcp.json if you're deploying the ARM template.
az deployment group create \
  --resource-group <resource-group> \
  --template-file orders-mcp.bicep \
  --parameters serviceName=<api-management-name> \
               backingApiId=orders-api \
               backingOperationId=get-orders \
               toolId=getOrders

Passthrough MCP-server

Deze sjablonen maken een passthrough MCP-server die gebruikmaakt van het streambare HTTP-transport. Het serverbereik heeft een beleid voor frequentielimiet en de server wordt verbonden met een bestaand product. Met de sjablonen worden geen subbronnen voor hulpprogramma's gedefinieerd. De externe back-end bepaalt het gereedschapoppervlak.

Note

De volgende sjablonen gebruiken transportType: streamable, waarmee de huidige MCP-streambare HTTP-specificatie wordt geïmplementeerd. Om in plaats daarvan SSE-transport te gebruiken, stelt u transportType in op sse en vervangt u de array endpoints door twee items: { "name": "sse", "uriTemplate": "/sse" } en { "name": "message", "uriTemplate": "/messages" }. Gebruik in Bicep dezelfde waarden in tekenreeksen tussen enkele aanhalingstekens.

Vereisten: een bestaande API Management-service, een bereikbaar MCP-back-end-URL (backendUrl) waarmee de geselecteerde transport- en eindpuntpaden en een bestaand product (productId) worden geïmplementeerd.

Parameter Vereist Default Beschrijving
serviceName Ja Naam van de bestaande API Management-service-instantie.
mcpServerId No external-mcp Resourcenaam voor de nieuwe MCP-server. Moet uniek zijn binnen de service.
backendUrl Ja Absolute URL van de externe MCP-back-end.
productId No starter Resourcenaam van het bestaande product waaraan de server moet worden gekoppeld.
@description('Name of the existing API Management service instance.')
param serviceName string

@description('Resource name for the new MCP server.')
param mcpServerId string = 'external-mcp'

@description('Absolute URL of the external MCP backend.')
param backendUrl string

@description('Resource name of the existing product to bind the MCP server to.')
param productId string = 'starter'

resource apimService 'Microsoft.ApiManagement/service@2025-09-01-preview' existing = {
  name: serviceName
}

resource mcpServer 'Microsoft.ApiManagement/service/apis@2025-09-01-preview' = {
  parent: apimService
  name: mcpServerId
  properties: {
    type: 'mcp'
    displayName: 'External MCP Server'
    description: 'Passthrough MCP server using streamable HTTP transport'
    path: mcpServerId
    protocols: [ 'https' ]
    serviceUrl: backendUrl
    subscriptionRequired: true
    mcpProperties: {
      transportType: 'streamable'
      endpoints: [
        {
          name: 'message'
          uriTemplate: '/mcp'
        }
      ]
    }
  }
}

resource mcpPolicy 'Microsoft.ApiManagement/service/apis/policies@2025-09-01-preview' = {
  parent: mcpServer
  name: 'policy'
  properties: {
    format: 'rawxml'
    value: '''<policies>
  <inbound>
    <base />
    <rate-limit calls="100" renewal-period="60" />
  </inbound>
  <backend>
    <forward-request />
  </backend>
  <outbound>
    <base />
  </outbound>
</policies>'''
  }
}

resource product 'Microsoft.ApiManagement/service/products@2025-09-01-preview' existing = {
  parent: apimService
  name: productId
}

resource productBinding 'Microsoft.ApiManagement/service/products/apis@2025-09-01-preview' = {
  parent: product
  name: mcpServerId
  dependsOn: [ mcpServer ]
}

Om te implementeren:

# Use external-mcp.json if you're deploying the ARM template.
az deployment group create \
  --resource-group <resource-group> \
  --template-file external-mcp.bicep \
  --parameters serviceName=<api-management-name> \
               backendUrl=https://mcp-backend.contoso.com

Azure CLI

Momenteel kunt u az rest gebruiken om de REST API rechtstreeks aan te roepen. Met het volgende script wordt een passthrough MCP-server gemaakt, een rate-limitbeleid gekoppeld en dit aan een product gebonden. Dit proces beschrijft hetzelfde scenario als de Bicep-sjabloon in de vorige paragraaf.

Stel variabelen in en voer vervolgens de vier az rest aanroepen in volgorde uit.

Note

az rest gebruikt de referentie van uw huidige az login sessie. U hebt geen afzonderlijke verificatiestap nodig.

# Variables. Edit these for your environment
SUBSCRIPTION_ID=$(az account show --query id -o tsv)
RESOURCE_GROUP="<your-resource-group>"
APIM_NAME="<your-apim-service-name>"
MCP_SERVER_ID="external-mcp"
BACKEND_URL="https://mcp-backend.contoso.com"
PRODUCT_ID="starter"
API_VERSION="2025-09-01-preview"

BASE="https://management.azure.com/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.ApiManagement/service/${APIM_NAME}"

# 1. Create the passthrough MCP server

az rest --method PUT \
  --uri "${BASE}/apis/${MCP_SERVER_ID}?api-version=${API_VERSION}" \
  --headers "If-Match=*" \
  --body '{
    "properties": {
      "type": "mcp",
      "displayName": "External MCP Server",
      "description": "Passthrough MCP server using streamable HTTP transport",
      "path": "external-mcp",
      "protocols": ["https"],
      "serviceUrl": "'"${BACKEND_URL}"'",
      "subscriptionRequired": true,
      "mcpProperties": {
        "transportType": "streamable",
        "endpoints": [
          { "name": "message", "uriTemplate": "/mcp" }
        ]
      }
    }
  }'

# 2. Attach a rate-limit policy at the server scope

az rest --method PUT \
  --uri "${BASE}/apis/${MCP_SERVER_ID}/policies/policy?api-version=${API_VERSION}" \
  --headers "If-Match=*" \
  --body '{
    "properties": {
      "format": "rawxml",
      "value": "<policies><inbound><base /><rate-limit calls=\"100\" renewal-period=\"60\" /></inbound><backend><forward-request /></backend><outbound><base /></outbound></policies>"
    }
  }'


# 3. Bind the server to a product

az rest --method PUT \
  --uri "${BASE}/products/${PRODUCT_ID}/apis/${MCP_SERVER_ID}?api-version=${API_VERSION}"

Elke stap is idempotent. Door het script opnieuw uit te voeren, wordt de bestaande resource direct bijgewerkt. Voer de volgende opdracht uit om te controleren of de server is gemaakt:

az rest --method GET \
  --uri "${BASE}/apis/${MCP_SERVER_ID}?api-version=${API_VERSION}"

Terraform

De AzureRM Terraform-provider heeft nog geen systeemeigen resources voor MCP-servers. Op dit moment kunt u het azapi_resource resourcetype van de AzAPI-provider gebruiken, waarmee u elk Azure resourcetype kunt beheren op basis van elke API-versie. Het volgende voorbeeld is een afspiegeling van de Bicep-sjabloon voor de passthrough MCP-server.

Vereisten: een bestaande API Management-service, een bereikbaar MCP-back-end-URL en een bestaand product. Voeg de AzAPI-provider toe aan uw terraform blok als deze nog niet aanwezig is.

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = ">= 3.0"
    }
    azapi = {
      source  = "Azure/azapi"
      version = ">= 1.13"
    }
  }
}

provider "azurerm" {
  features {}
}

provider "azapi" {}

Variables

variable "resource_group_name" {
  description = "Name of the resource group containing the API Management service."
  type        = string
}

variable "service_name" {
  description = "Name of the existing API Management service instance."
  type        = string
}

variable "mcp_server_id" {
  description = "Resource name for the new MCP server."
  type        = string
  default     = "external-mcp"
}

variable "backend_url" {
  description = "Absolute URL of the external MCP backend."
  type        = string
}

variable "product_id" {
  description = "Resource name of the existing product to bind the server to."
  type        = string
  default     = "starter"
}

Hulpmiddelen

# Reference the existing API Management service
data "azurerm_api_management" "apim" {
  name                = var.service_name
  resource_group_name = var.resource_group_name
}

# 1. Create the passthrough MCP server
resource "azapi_resource" "mcp_server" {
  type      = "Microsoft.ApiManagement/service/apis@2025-09-01-preview"
  name      = var.mcp_server_id
  parent_id = data.azurerm_api_management.apim.id

  body = {
    properties = {
      type                = "mcp"
      displayName         = "External MCP Server"
      description         = "Passthrough MCP server using streamable HTTP transport"
      path                = var.mcp_server_id
      protocols           = ["https"]
      serviceUrl          = var.backend_url
      subscriptionRequired = true
      mcpProperties = {
        transportType = "streamable"
        endpoints = [
          {
            name        = "message"
            uriTemplate = "/mcp"
          }
        ]
      }
    }
  }
}

# 2. Attach a rate-limit policy at the server scope
resource "azapi_resource" "mcp_policy" {
  type      = "Microsoft.ApiManagement/service/apis/policies@2025-09-01-preview"
  name      = "policy"
  parent_id = azapi_resource.mcp_server.id

  body = {
    properties = {
      format = "rawxml"
      value  = "<policies><inbound><base /><rate-limit calls=\"100\" renewal-period=\"60\" /></inbound><backend><forward-request /></backend><outbound><base /></outbound></policies>"
    }
  }

  depends_on = [azapi_resource.mcp_server]
}

# 3. Bind the server to a product
resource "azapi_resource" "product_binding" {
  type      = "Microsoft.ApiManagement/service/products/apis@2025-09-01-preview"
  name      = var.mcp_server_id
  parent_id = "${data.azurerm_api_management.apim.id}/products/${var.product_id}"

  body = {}

  depends_on = [azapi_resource.mcp_server]
}

Om te implementeren:

Note

azapi_resourcemaakt gebruik van de verificatie van de AzAPI-provider, die wordt gelezen uit dezelfde az login referentie als de Azure CLI. U hoeft geen aparte authenticatie te configureren als u lokaal werkt.

terraform init
terraform apply \
  -var="resource_group_name=<resource-group>" \
  -var="service_name=<api-management-name>" \
  -var="backend_url=https://mcp-backend.contoso.com"

CI/CD-patronen

  • Idempotente upserts: Verstuur PUT-aanvragen met If-Match: "*", zodat dezelfde sjabloon werkt, ongeacht of de resource al bestaat of niet. 

  • Configuraties promoten in omgevingen: McP-serverdefinities en hulpprogrammalijsten behandelen als bronbeheerde artefacten. Alleen omgevingsspecifieke waarden parameteriseren, zoals de naam van het exemplaar en de back-end-URL. 

  • Genereer de lijst met tools vanuit uw API-specificatie: baseer de subresource voor tools op uw bronbestand met OpenAPI-specificatie, zodat het beschikbare tooloppervlak synchroon blijft met de onderliggende API terwijl deze zich verder ontwikkelt. 

  • Verwijder in de juiste volgorde: Verwijder verwijzingen naar MCP-hulpprogramma's voordat u de onderliggende API's of bewerkingen verwijdert waarnaar ze verwijzen. Anders mislukt de verwijderbewerking door een foreign-keycontrole.