API Management'ta MCP sunucularını program aracılığıyla yönetme

Bu makalede REST API, ARM şablonları, Bicep, Azure CLI ve Terraform kullanarak Azure API Management'de MCP sunucuları oluşturmayı ve yönetmeyi öğreneceksiniz. 

Important

Bu makalede açıklanan MCP sunucu yönetimi özellikleri, API Management REST API’sinin 2025-09-01-preview veya sonraki bir sürümünü gerektirir. Bu sürümü her istekte sabitleyin. 

MCP sunucu özellikleri hakkında arka plan için bkz. Azure API Management'da MCP sunucuları hakkında.

Prerequisites

Kaynak modeli

Azure Resource Manager MCP sunucularını aşağıdaki gibi temsil eder:

  • MCP sunucusu:type türünde bir API Management MCP kaynağı.

  • Geçiş sunucusu: Mevcut bir dış MCP arka ucuna işaret edin. MCP sunucu kaynağı arka uç URL'sini ve aktarım türünü (akışla aktarılabilir HTTP veya SSE) bildirir.

  • Araç: Bir MCP sunucusunun API aracı alt kaynağı. Araç kaynaklarını CI/CD'den güvenle yönetebilirsiniz. MCP sunucusunu yeniden oluşturmadan araçları ekleyebilir, yeniden adlandırabilir veya kaldırabilirsiniz.

  • Politikalar: Normal API'lerde olduğu gibi, bir MCP sunucusuna API politikası veya politika alt kaynaklarını ekleyin.

  • Ürünler: Ürün bağlama, bağımsız dağıtımı ve çok ürünlü bağlamayı etkinleştiren ayrı bir alt ilişkidir (products/{productId}/apis/{mcpServerId} ).

REST örnekleri

Netlik sağlamak için aşağıdaki örneklerde kısaltılmış yanıt gövdeleri gösterilmektedir. Tam yanıt şemaları için bkz. API Management REST API başvurusu.

PUT ve DELETE çağrı örneklerine If-Match: * üst bilgisini eklemek, istekleri idempotent hâle getirir. Bu üst bilgi, kaynağın zaten mevcut olup olmadığına bakılmaksızın geçerlidir; bu, CI/CD ardışık düzenleri için önerilen yaklaşımdır.

Başlamadan önce

Herhangi bir örneği çalıştırmadan önce aşağıdaki değişkenleri ayarlayın. Bu bölümdeki tüm örnekler bu değişkenlere başvurur.

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 sunucularını listeleme

türüne göre filtrelenmiş örnekteki tüm API'leri mcpdöndürür. Büyük sonuç kümelerini sayfalamak için $top ve $skip sorgu parametrelerini kullanın.

Referans: API - Hizmete Göre Listele

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

Yanıt (200 Tamam)

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

Yaygın hata:401 Unauthorized. Taşıyıcı belirtecinin süresi doldu. Belirteç alma komutunu yeniden çalıştırın.


Tek bir MCP sunucusu alma

Referans: API - Getir

MCP_SERVER_ID="my-mcp-server"

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

Yanıt (200 Tamam)

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

Yaygın hata:404 Not Found. mcpServerId öğesinin, Liste işlemi tarafından döndürülen name alanıyla eşleştiğini doğrulayın.


REST API destekli MCP sunucusu oluşturma

MCP sunucu kaynağını oluşturur. Oluşturma işleminden sonra, Araç ekle veya güncelleştir işlemini kullanarak araçları tek tek ekleyin. Her araç, bir yedekleme REST API kaynağındaki belirli bir işleme başvurur.

Başvuru: API - Oluştur veya Güncelleştir

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

Yanıt (201 Oluşturuldu)

{
  "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 eşzamansız PUT işlemlerinde beklenir. Tamamlandığını doğrulamak için Azure-AsyncOperation yanıt üst bilgisinde döndürülen URL’yi yoklayın.

Yaygın hata:400 Bad Request. type öğesinin "mcp" olduğundan ve path öğesinin hizmet örneği içinde benzersiz olduğundan emin olun.


Geçişli MCP sunucusu oluşturma

Geçiş sunucusu, tüm MCP isteklerini doğrudan bir dış MCP arka ucuna iletir. Arka ucunuzun uyguladığı aktarımla eşleşecek şekilde ayarlayın mcpProperties.transportType .

Geçiş sunucusu oluşturmadan önce, arka uç sistemin API Management ağ geçidinden erişilebilir olduğunu ve yapılandırdığınız uç nokta yollarında seçilen MCP aktarımını desteklediğini doğrulayın. Arka uç kimlik doğrulaması gerektiriyorsa, API Management ilkelerini veya arka uç yapılandırmasını kullanarak gerekli kimlik bilgilerini veya üst bilgileri yapılandırın.

Başvuru: API - Oluştur veya Güncelleştir

Akışla aktarılabilir HTTP aktarımı

Geçerli MCP akış tabanlı HTTP taşıma belirtimini uygulayan arka uçlar için streamable kullanın. Tek bir uç nokta tanımı gereklidir.

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

Yanıt (201 Oluşturuldu)

{
  "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 taşıma

HTTP+SSE (Sunucu Gönderimli Olaylar) taşımasını uygulayan arka uçlar için sse’u kullanın. biri SSE olay akışı, diğeri de ileti kanalı için iki uç nokta tanımlayın.

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

Yaygın hatalar:

  • 400 Bad Request. Geçersiz mcpProperties. transportType öğesinin streamable veya sse olduğunu ve her uriTemplate öğesinin / ile başladığını doğrulayın.
  • 400 Bad Request. SSE aktarımı için tam olarak iki uç nokta (sse ve message) gerekir. Akış tabanlı taşıma için bir (message) gerekir.

Araç ekleme veya güncelleştirme

REST API destekli MCP sunucusuna yeni bir araç ekler veya mevcut bir aracı güncelleştirir. operationId alanı, aracı arka plandaki bir REST API kaynağındaki belirli bir işleme bağlar. Üst sunucuyu yeniden oluşturmadan araçları bağımsız olarak ekleyebilir, güncelleştirebilir veya kaldırabilirsiniz.

Referans: API Aracı - Oluştur veya Güncelle

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

Yanıt (201 Oluşturuldu)

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

Yaygın hatalar:

  • 400 Bad Request. operationId yol hatalı biçimlendirilmiş veya başvurulan işlem mevcut değil.
  • 404 Not Found. Üst MCP sunucusu yok. Araç eklemeden önce sunucuyu oluşturun.

Aracı sil

McP sunucusundan bir aracı kaldırır. Başvurdıkları yedekleme REST API işlemlerini silmeden önce araçları silin; aksi takdirde silme işlemi bir bağımlılık hatasıyla başarısız olur.

Referans: API Aracı - Sil

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

Yanıt:200 OK başarılı olduğunda.

Yaygın hata:412 Precondition FailedIf-Match silme işlemleri için gereklidir. Herhangi bir ETag ile eşleştirmek için kullanın If-Match: * .


MCP kapsamında bir ilke uygulayın

BIR MCP sunucusuna bağlı ilke belgesini oluşturur veya değiştirir. Sunucu, her araç çağrısı için bu kapsamdaki ilkeleri değerlendirir. Biçim rawxml , kodlanmamış ilke XML'sini kabul eder.

Referans: API İlkesi - Oluşturma veya Güncelleştirme

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

Yanıt (200 Tamam)

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

Yaygın hata:400 Bad Request. Yanlış biçimlendirilmiş ilke XML'i. Göndermeden önce belgeyi doğrulayın.


MCP sunucusunu bir ürüne bağlama

MCP sunucusunu bir ürünle ilişkilendirir, böylece bu ürünün aboneleri sunucunun araçlarını çağırabilir. İsteğin gövdesi yok.

MCP sunucusunu bir ürüne bağladığınızda, bu ürün aracılığıyla kullanılabilir hale getirirsiniz, ancak istemcilerin yine de ürünün yapılandırmasına göre erişmesi gerekir. Ürün abonelik gerektiriyorsa, istemcinin bu ürün için geçerli bir abonelik anahtarı kullanması gerekir.

Referans: Ürün API - Oluştur veya Güncelle

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"

Yanıt:201 Created içinde MCP sunucusunun API sözleşmesiyle.

Yaygın hata:404 Not Found. Bağlamayı oluşturmadan önce hem hem productId de mcpServerId var olduğunu doğrulayın.


MCP sunucusunu silme

Bir MCP sunucusunu ve tüm araç ve ilke alt kaynaklarını siler. Sunucuyu silmeden önce, arkadaki API'lerdeki işlemlere başvuran tüm araçları kaldırın; aksi takdirde, araç başvurusu bulunduğu sürece bu işlemleri silemezsiniz.

Referans: API - Sil

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

Yanıt:200 OK başarılı olduğunda.

Yaygın hata:412 Precondition Failed. If-Match silme işlemleri için gereklidir. ETag denetimini atlamak için kullanın If-Match: * .

ARM ve Bicep şablonları

Aşağıdaki şablonlar tek bir dağıtımda eksiksiz bir MCP sunucu yapılandırması dağıtır. Her şablon, var olan bir API Management hizmet örneğini varsayar ve bir parametre tablosu kullanır, böylece ortamlar arasında yalnızca parametre değerlerini değiştirerek aynı dosyayı yeniden kullanabilirsiniz.

REST API destekli MCP sunucusu

Bu şablonlar bir MCP sunucusu oluşturur, mevcut bir yedekleme REST API'sindeki bir işleme eşleyen bir araç tanımlar, sunucu kapsamında bir hız sınırı ilkesi ekler ve sunucuyu mevcut bir ürüne bağlar. Tüm bu görevleri tek bir dağıtımda gerçekleştirebilirsiniz.

Önkoşullar: var olan bir API Management hizmeti, en az bir işlemi (backingApiId) olan bir REST API (backingOperationId) ve mevcut bir ürün (productId).

Parametre Zorunlu Varsayılan Description
serviceName Evet Mevcut API Management hizmet örneğinin adı.
mcpServerId Hayır orders-mcp Yeni MCP sunucusunun kaynak adı. Hizmet içinde benzersiz olmalıdır.
backingApiId Evet Bu MCP sunucusunu destekleyen mevcut REST API'nin kaynak adı.
backingOperationId Evet Araç olarak kullanıma sunma işleminin kaynak adı.
toolId Hayır sampleTool Oluşturulacak MCP aracının kaynak adı ve görünen adı.
productId Hayır starter Sunucuyu bağlamak için mevcut ürünün kaynak adı.
@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 ]
}

Dağıtım için:

# 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

Doğrudan geçiş MCP sunucusu

Bu şablonlar, akışla aktarılabilir HTTP aktarımını kullanan bir geçiş MCP sunucusu oluşturur. Sunucu kapsamı bir hız sınırı ilkesine sahiptir ve sunucu mevcut bir ürüne bağlanır. Şablonlar hiçbir araç alt kaynağı tanımlamaz. Dış arka uç, araç yüzeyini belirler.

Note

Aşağıdaki şablonlar, geçerli MCP akış destekli HTTP spesifikasyonunu uygulayan transportType: streamable öğesini kullanır. Bunun yerine SSE aktarımını kullanmak için transportType öğesini sse olarak ayarlayın ve endpoints dizisini iki girdiyle değiştirin: { "name": "sse", "uriTemplate": "/sse" } ve { "name": "message", "uriTemplate": "/messages" }. Bicep'de, tek tırnaklı dizelerle aynı değerleri kullanın.

Önkoşullar: Mevcut bir API Management hizmeti, seçili aktarım ve uç nokta yollarını uygulayan erişilebilir bir MCP arka uç URL'si (backendUrl) ve mevcut bir ürün (productId).

Parametre Zorunlu Varsayılan Description
serviceName Evet Mevcut API Management hizmet örneğinin adı.
mcpServerId Hayır external-mcp Yeni MCP sunucusunun kaynak adı. Hizmet içinde benzersiz olmalıdır.
backendUrl Evet Harici MCP arka ucunun mutlak URL'si.
productId Hayır starter Sunucuyu bağlamak için mevcut ürünün kaynak adı.
@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 ]
}

Dağıtım için:

# 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

Şu anda REST API'yi doğrudan çağırmak için kullanabilirsiniz az rest . Aşağıdaki betik bir passthrough MCP sunucusu oluşturur, bir oran sınırlama ilkesi uygular ve sunucuyu bir ürüne bağlar. Bu işlem, önceki bölümdeki Bicep şablonuyla aynı senaryoyu kapsar.

Değişkenleri ayarlayın ve ardından dört az rest çağrıyı sırayla çalıştırın.

Note

az rest geçerli az login oturumunuzun kimlik bilgilerini kullanır. Ayrı bir kimlik doğrulama adımına ihtiyacınız yoktur.

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

Her adım idempotenttir. Betiğin yeniden çalıştırılması kaynağı yerinde günceller. Sunucunun oluşturulduğunu doğrulamak için aşağıdaki komutu çalıştırın:

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

Terraform

AzureRM Terraform sağlayıcısı henüz MCP sunucuları için yerel kaynaklara sahip değildir. Şu anda, herhangi bir AZURE kaynak türünü herhangi bir API sürümüne göre yönetmenize olanak tanıyan azapi_resource kaynak türünü kullanabilirsiniz. Aşağıdaki örnek, geçiş MCP sunucusu Bicep şablonunu yansıtır.

Önkoşullar: mevcut bir API Management hizmeti, erişilebilir bir MCP arka uç URL'si ve mevcut bir ürün. AzAPI sağlayıcısı henüz mevcut değilse bloğunuza terraform ekleyin.

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

Resources

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

Dağıtım için:

Note

azapi_resource, Azure CLI'nin kullandığı aynı az login kimlik bilgisini okuyan AzAPI sağlayıcısının kimlik doğrulamasını kullanır. Yerel olarak çalışırken ayrı kimlik doğrulaması yapılandırmanız gerekmez.

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 kalıpları

  • Idempotent upserts: PUT isteklerini If-Match: "*" ile göndererek, kaynak zaten mevcut olsun ya da olmasın aynı şablonun uygulanmasını sağlayın. 

  • Ortamlar arasında yapılandırmaları yükseltme: MCP sunucu tanımlarını ve araç listelerini kaynak denetimli yapıtlar olarak değerlendirin. Örnek adı ve arka uç URL'si gibi yalnızca ortama özgü değerleri parametreleştirin. 

  • API spesifikasyonunuzdan araç listesini oluşturun: Araç arayüzünün, arkasındaki API geliştikçe onunla senkronize kalması için araçlar alt kaynağını kaynak OpenAPI dosyanızdan türetin. 

  • Doğru sırayla silin: MCP araç başvurularını, işaret ettikleri temel API'leri veya işlemleri silmeden önce kaldırın. Aksi takdirde, silme işlemi yabancı anahtar denetiminde başarısız olur.