Programmgesteuertes Verwalten von MCP-Servern in der API-Verwaltung

In diesem Artikel erfahren Sie, wie Sie MCP-Server in Azure API Management mithilfe der REST-API, ARM-Vorlagen, Bicep, der Azure CLI und Terraform erstellen und verwalten. 

Von Bedeutung

Die in diesem Artikel beschriebenen MCP-Serververwaltungsfunktionen erfordern die API Management REST API-Version 2025-09-01-preview oder höher. Heften Sie diese Version bei jeder Anfrage an. 

Hintergrundinformationen zu MCP-Serverfunktionen finden Sie unter Informationen zu MCP-Servern in Azure API Management.

Voraussetzungen

Ressourcenmodell

Azure Resource Manager stellt MCP-Server wie folgt dar:

  • MCP-Server: Eine API-Verwaltungs-API-Ressource vom TypMCP.

  • Passthrough-Server: Verweist auf ein vorhandenes externes MCP-Back-End. Die MCP-Serverressource deklariert die Back-End-URL und den Transporttyp (streambares HTTP oder SSE).

  • Werkzeug: Eine API-Tool-Unterressource eines MCP-Servers. Sie können Toolressourcen sicher über CI/CD verwalten. Sie können Tools hinzufügen, umbenennen oder entfernen, ohne den MCP-Server neu zu erstellen.

  • Richtlinien: Wie bei regulären APIs fügen Sie API-Richtlinien oder Richtlinienunterressourcen an einen MCP-Server an.

  • Produkte: Die Produktbindung ist eine separate untergeordnete Beziehung (products/{productId}/apis/{mcpServerId}), die eine unabhängige Bereitstellung und die Bindung an mehrere Produkte ermöglicht.

REST-Beispiele

Aus Gründen der Klarheit zeigen die folgenden Beispiele abgekürzte Antworttexte. Vollständige Antwortschemas finden Sie in der API-Verwaltungs-REST-API-Referenz.

Wenn Sie den If-Match: * Header in den PUT- und DELETE-Aufrufbeispielen hinzufügen, werden die Anforderungen idempotent. Dieser Header gilt unabhängig davon, ob die Ressource bereits vorhanden ist oder nicht; dies ist das empfohlene Muster für CI/CD-Pipelines.

Bevor Sie anfangen

Legen Sie die folgenden Variablen fest, bevor Sie ein Beispiel ausführen. Alle Beispiele in diesem Abschnitt verweisen auf diese Variablen.

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-Server auflisten

Gibt alle APIs in der Instanz zurück, die nach Typ mcpgefiltert wurde. Verwenden Sie die Abfrageparameter $top und $skip, um durch große Ergebnismengen zu blättern.

Referenz: API – Nach Dienst auflisten

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

Antwort (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" ]
      }
    }
  ]
}

Häufig auftretender Fehler:401 Unauthorized. Das Bearertoken ist abgelaufen. Führen Sie den Tokenerwerbsbefehl erneut aus.


Einzelnen MCP-Server abrufen

Referenz: Api - Get

MCP_SERVER_ID="my-mcp-server"

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

Antwort (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"
  }
}

Häufig auftretender Fehler:404 Not Found. Vergewissern Sie sich, dass mcpServerId mit dem von der List-Operation zurückgegebenen Feld name übereinstimmt.


Erstellen eines REST-API-gesicherten MCP-Servers

Erstellt die MCP-Serverressource. Fügen Sie nach der Erstellung Tools einzeln hinzu, indem Sie den Vorgang Tool hinzufügen oder aktualisieren verwenden. Jedes Tool verweist auf einen bestimmten Vorgang in einer zugrunde stehenden REST-API-Ressource.

Referenz: API – Erstellen oder Aktualisieren

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"]
    }
  }'

Antwort (201 Erstellt)

{
  "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 wird für asynchrone PUT-Vorgänge erwartet. Rufen Sie die URL, die im Antwortheader Azure-AsyncOperation zurückgegeben wird, wiederholt ab, um den Abschluss zu bestätigen.

Häufig auftretender Fehler:400 Bad Request. Stellen Sie sicher, dass type"mcp" ist und path innerhalb der Dienstinstanz eindeutig ist.


Erstellen Sie einen Passthrough-MCP-Server

Ein Passthrough-Server leitet alle MCP-Anforderungen direkt an ein externes MCP-Back-End weiter. Stellen Sie mcpProperties.transportType so ein, dass es dem Transport entspricht, den Ihr Backend implementiert.

Vergewissern Sie sich vor dem Erstellen eines Passthrough-Servers, dass das Back-End über das API-Verwaltungsgateway erreichbar ist, und implementiert den ausgewählten MCP-Transport an den von Ihnen konfigurierten Endpunktpfaden. Wenn das Back-End eine Authentifizierung erfordert, konfigurieren Sie die erforderlichen Anmeldeinformationen oder Header mithilfe von API-Verwaltungsrichtlinien oder back-End-Konfiguration.

Referenz: API – Erstellen oder Aktualisieren

Streambarer HTTP-Transport

Verwenden Sie streamable für Backends, die die aktuelle MCP-Spezifikation für streambaren HTTP-Transport implementieren. Eine einzelne Endpunktdefinition ist erforderlich.

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" }
        ]
      }
    }
  }'

Antwort (201 Erstellt)

{
  "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

sse für Backends verwenden, die den HTTP+SSE-Transport (Server-Sent Events) implementieren. Definieren Sie zwei Endpunkte: eine für den SSE-Ereignisstream und eine für den Nachrichtenkanal.

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" }
        ]
      }
    }
  }'

Häufige Fehler:

  • 400 Bad Request. Ungültig mcpProperties. Überprüfen Sie transportType, ob es sich um streamable oder sse handelt und dass jedes uriTemplate mit / beginnt.
  • 400 Bad Request. SSE-Transport erfordert genau zwei Endpunkte (sse und message). Streaming-Transport erfordert eine (message).

Hinzufügen oder Aktualisieren eines Tools

Fügt einem REST-API-gesicherten MCP-Server ein neues Tool hinzu oder aktualisiert ein vorhandenes Tool. Das operationId Feld verknüpft das Tool mit einem bestimmten Vorgang in einer zugrunde stehenden REST-API-Ressource. Sie können Tools unabhängig hinzufügen, aktualisieren oder entfernen, ohne den übergeordneten Server neu zu erstellen.

Referenz: API-Tool – Erstellen oder Aktualisieren

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}\"
    }
  }"

Antwort (201 Erstellt)

{
  "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"
  }
}

Häufige Fehler:

  • 400 Bad Request. Der operationId Pfad ist falsch formatiert, oder der verweisfähige Vorgang ist nicht vorhanden.
  • 404 Not Found. Der übergeordnete MCP-Server ist nicht vorhanden. Erstellen Sie den Server, bevor Sie Tools hinzufügen.

Löschen eines Tools

Entfernt ein Tool von einem MCP-Server. Löschen Sie Tools, bevor Sie die zugrunde stehenden REST-API-Vorgänge löschen, auf die sie verweisen; andernfalls schlägt der Löschvorgang mit einem Abhängigkeitsfehler fehl.

Referenz: API-Tool - Löschen

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: *"

Antwort:200 OK bei Erfolg.

Häufig auftretender Fehler:412 Precondition FailedIf-Match ist für Löschungen erforderlich. Verwenden Sie If-Match: *, um mit einem beliebigen ETag übereinzustimmen.


Eine Richtlinie im MCP-Bereich anwenden

Erstellt oder ersetzt das an einen MCP-Server angefügte Richtliniendokument. Der Server wertet Richtlinien in diesem Bereich für jeden Toolaufruf aus. Das rawxml Format akzeptiert nicht codierte Richtlinien-XML.

Referenz: API-Richtlinie – Erstellen oder Aktualisieren

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}\"}}"

Antwort (200 OK)

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

Häufig auftretender Fehler:400 Bad Request. Falsch formatierte Richtlinien-XML. Überprüfen Sie das Dokument vor dem Senden.


Binden eines MCP-Servers an ein Produkt

Ordnet den MCP-Server einem Produkt zu, sodass Abonnenten dieses Produkts die Tools des Servers aufrufen können. Die Anforderung hat keinen Text.

Wenn Sie den MCP-Server an ein Produkt binden, stellen Sie ihn über dieses Produkt zur Verfügung, aber Clients benötigen weiterhin Zugriff gemäß der Konfiguration des Produkts. Wenn für das Produkt Abonnements erforderlich sind, muss der Client einen gültigen Abonnementschlüssel für dieses Produkt verwenden.

Referenz: Produkt-API – Erstellen oder Aktualisieren

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"

Antwort:201 Created mit dem API-Vertrag des MCP-Servers im Textkörper.

Häufig auftretender Fehler:404 Not Found. Überprüfen Sie, ob sowohl productId als auch mcpServerId vorhanden sind, bevor Sie die Bindung erstellen.


Löschen eines MCP-Servers

Löscht einen MCP-Server und alle zugehörigen Tool- und Richtlinienunterressourcen. Entfernen Sie vor dem Löschen des Servers alle Tools, die auf Vorgänge in Sicherungs-APIs verweisen; andernfalls können Sie diese Vorgänge nicht löschen, während der Toolverweis vorhanden ist.

Referenz: API - Löschen

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: *"

Antwort:200 OK bei Erfolg.

Häufig auftretender Fehler:412 Precondition Failed. If-Match ist für Löschungen erforderlich. Verwenden Sie If-Match: *, um die ETag-Überprüfung zu umgehen.

ARM- und Bicep-Vorlagen

Die folgenden Vorlagen stellen eine vollständige MCP-Serverkonfiguration in einer einzigen Bereitstellung bereit. Jede Vorlage setzt eine vorhandene API-Verwaltungsdienstinstanz voraus und verwendet eine Parametertabelle, sodass Sie dieselbe Datei in allen Umgebungen wiederverwenden können, indem Sie nur die Parameterwerte ändern.

REST-API-gesicherter MCP-Server

Diese Vorlagen erstellen einen MCP-Server, definieren ein Tool, das einer Operation in einer bestehenden zugrunde liegenden REST-API zugeordnet ist, fügen auf Serverebene eine Richtlinie zur Ratenbegrenzung hinzu und verknüpfen den Server mit einem vorhandenen Produkt. Sie können all diese Aufgaben in einer einzigen Bereitstellung ausführen.

Voraussetzungen: ein vorhandener API-Verwaltungsdienst, eine REST-API (backingApiId) mit mindestens einem Vorgang (backingOperationId) und ein vorhandenes Produkt (productId).

Parameter Erforderlich Standard Description
serviceName Ja Name der vorhandenen API-Verwaltungsdienstinstanz.
mcpServerId No orders-mcp Ressourcenname für den neuen MCP-Server. Muss innerhalb des Diensts eindeutig sein.
backingApiId Ja Ressourcenname der vorhandenen REST-API, die als Backend für diesen MCP-Server dient.
backingOperationId Ja Ressourcenname des Vorgangs, der als Tool verfügbar gemacht werden soll.
toolId No sampleTool Ressourcenname und Anzeigename des zu erstellenden MCP-Tools.
productId No starter Ressourcenname des vorhandenen Produkts, an das der Server gebunden werden soll.
@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 ]
}

Bereitstellung:

# 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

Durchleitungs-MCP-Server

Diese Vorlagen erstellen einen MCP-Server mit Passthrough, der den streambaren HTTP-Transport verwendet. Der Serverbereich verfügt über eine Richtlinie zur Ratenbegrenzung, und der Server ist mit einem vorhandenen Produkt verknüpft. Die Vorlagen definieren keine Toolunterressourcen. Das externe Back-End bestimmt die Tooloberfläche.

Note

Die folgenden Vorlagen verwenden transportType: streamable, die die aktuelle MCP streamable HTTP-Spezifikation implementiert. Wenn Sie stattdessen den SSE-Transport verwenden möchten, setzen Sie transportType auf sse und ersetzen Sie das Array endpoints durch zwei Einträge: { "name": "sse", "uriTemplate": "/sse" } und { "name": "message", "uriTemplate": "/messages" }. Verwenden Sie in Bicep dieselben Werte mit einfach in Anführungszeichen eingeschlossenen Zeichenfolgen.

Voraussetzungen: ein vorhandener API-Verwaltungsdienst, eine erreichbare MCP-Back-End-URL (backendUrl), die die ausgewählten Transport- und Endpunktpfade implementiert, und ein vorhandenes Produkt (productId).

Parameter Erforderlich Standard Description
serviceName Ja Name der vorhandenen API-Verwaltungsdienstinstanz.
mcpServerId No external-mcp Ressourcenname für den neuen MCP-Server. Muss innerhalb des Diensts eindeutig sein.
backendUrl Ja Absolute URL des externen MCP-Backends.
productId No starter Ressourcenname des vorhandenen Produkts, an das der Server gebunden werden soll.
@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 ]
}

Bereitstellung:

# 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

Derzeit können Sie az rest verwenden, um die REST-API direkt aufzurufen. Mit dem folgenden Skript wird ein MCP-Server mit Passthrough erstellt, eine Richtlinie für die Zinsgrenze angefügt und an ein Produkt gebunden. Dieser Prozess deckt dasselbe Szenario ab wie die Bicep-Vorlage im vorherigen Abschnitt.

Legen Sie Variablen fest, und führen Sie dann die vier az rest Aufrufe in der reihenfolge aus.

Note

az rest verwendet die Anmeldeinformationen aus Ihrer aktuellen az login Sitzung. Sie benötigen keinen separaten Authentifizierungsschritt.

# 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}"

Jeder Schritt ist idempotent. Führen Sie das Skript erneut aus, um die Ressource an Ort und Stelle zu aktualisieren. Führen Sie den folgenden Befehl aus, um zu überprüfen, ob der Server erstellt wurde:

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

Terraform

Der AzureRM Terraform-Anbieter verfügt noch nicht über systemeigene Ressourcen für MCP-Server. Derzeit können Sie den azapi_resource Ressourcentyp vom AzAPI-Anbieter verwenden, mit dem Sie jeden Azure Ressourcentyp für jede API-Version verwalten können. Das folgende Beispiel entspricht der Bicep-Vorlage für den Passthrough-MCP-Server.

Voraussetzungen: ein vorhandener API-Verwaltungsdienst, eine erreichbare MCP-Back-End-URL und ein vorhandenes Produkt. Fügen Sie den AzAPI-Anbieter zu Ihrem terraform Block hinzu, wenn er noch nicht vorhanden ist.

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"
}

Ressourcen

# 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]
}

Bereitstellung:

Note

azapi_resourceverwendet die Authentifizierung des AzAPI-Anbieters, die aus denselben az login Anmeldeinformationen wie die Azure CLI liest. Sie müssen keine separate Authentifizierung konfigurieren, wenn sie lokal ausgeführt wird.

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-Muster

  • Idempotente Upserts: Senden Sie PUT-Anfragen mit If-Match: "*", sodass dieselbe Vorlage verwendet wird, unabhängig davon, ob die Ressource bereits existiert oder nicht. 

  • Konfigurationen zwischen Umgebungen übertragen: Behandeln Sie MCP-Serverdefinitionen und Toollisten als versionsverwaltete Artefakte. Parametrisieren Sie nur umgebungsspezifische Werte, z. B. Instanzname und Back-End-URL. 

  • Generieren Sie die Toolliste aus Ihrer API-Spezifikation: Steuern Sie die Unterressource der Tools aus der OpenAPI-Quelldatei, damit die Tooloberfläche mit der zugrunde stehenden API synchronisiert bleibt, während sie sich weiterentwickelt. 

  • Löschen Sie in der richtigen Reihenfolge: Entfernen Sie MCP-Toolverweise, bevor Sie die zugrunde stehenden APIs oder Vorgänge löschen, auf die sie verweisen. Andernfalls schlägt der Löschvorgang bei einer Fremdschlüsselüberprüfung fehl.