Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Dans cet article, vous allez apprendre à créer et gérer des serveurs MCP dans Gestion des API Azure à l’aide de l’API REST, des modèles ARM, des Bicep, des Azure CLI et terraform.
Important
Les fonctionnalités de gestion des serveurs MCP décrites dans cet article nécessitent l’API REST d’API Management, version 2025-09-01-preview ou une version ultérieure. Épinglez cette version dans chaque requête.
Pour plus d’informations sur les fonctionnalités du serveur MCP, consultez À propos des serveurs MCP dans Gestion des API Azure.
Prerequisites
Votre identité a besoin d’autorisations pour lire le service Gestion des API et créer ou mettre à jour des API, des outils d’API, des stratégies d’API et des liaisons d’API de produit. Pour Terraform, l’identité doit également disposer d’un accès en lecture au service API Management existant utilisé par la source de données
azurerm_api_management.Pour Azure CLI :
Utilisez l’environnement Bash dans Azure Cloud Shell. Pour plus d’informations, consultez Démarrez avec Azure Cloud Shell.
Si vous préférez exécuter des commandes de référence CLI localement, installez Azure CLI. Si vous exécutez sur Windows ou macOS, envisagez d’exécuter Azure CLI dans un conteneur Docker. Pour plus d’informations, consultez Comment exécuter Azure CLI dans un conteneur Docker.
Si vous utilisez une installation locale, connectez-vous à Azure CLI à l’aide de la commande az login. Pour terminer le processus d’authentification, suivez les étapes affichées dans votre terminal. Pour obtenir d’autres options de connexion, consultez S’authentifier auprès d’Azure à l’aide d’Azure CLI.
Lorsque vous y êtes invité, installez l’extension Azure CLI lors de la première utilisation. Pour plus d’informations sur les extensions, consultez Utiliser et gérer des extensions avec Azure CLI.
Exécutez az version pour rechercher la version et les bibliothèques dépendantes installées. Pour effectuer une mise à niveau vers la dernière version, exécutez az upgrade.
Pour Azure PowerShell :
- Si vous choisissez d’utiliser Azure PowerShell localement :
- Installez la dernière version du module Az PowerShell.
- Connectez-vous à votre compte Azure à l’aide de la cmdlet Connect-AzAccount.
- Si vous choisissez d’utiliser Azure Cloud Shell :
- Pour plus d’informations, consultez Vue d’ensemble d’Azure Cloud Shell.
- Si vous choisissez d’utiliser Azure PowerShell localement :
Modèle de ressource
Azure Resource Manager représente les serveurs MCP comme suit :
Serveur de relais : Pointe vers un backend MCP externe existant. La ressource de serveur MCP déclare l’URL du serveur principal et le type de transport (HTTP ou SSE pouvant être diffusé en continu).
Outil: Sous-ressource de l’outil API d’un serveur MCP. Vous pouvez gérer en toute sécurité les ressources d’outils à partir de CI/CD. Vous pouvez ajouter, renommer ou supprimer des outils sans recréer le serveur MCP.
Politiques: Comme avec les API régulières, attachez une stratégie d’API ou des sous-ressources de stratégie à un serveur MCP.
Produits : la liaison de produit est une relation enfant distincte (
products/{productId}/apis/{mcpServerId}), permettant un déploiement indépendant et une liaison à plusieurs produits.
Exemples REST
Pour plus de clarté, les exemples suivants montrent des corps de réponse abrégés. Pour obtenir des schémas de réponse complets, consultez la référence de l’API REST Gestion des API.
L’ajout de l’en-tête If-Match: * dans les exemples d’appels PUT et DELETE rend les requêtes idempotentes. Cet en-tête s'applique que la ressource existe déjà ou non, ce qui constitue le modèle recommandé pour les pipelines CI/CD.
Avant de commencer
Définissez les variables suivantes avant d’exécuter un exemple. Tous les exemples de cette section référencent ces variables.
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)
Répertorier les serveurs MCP
Renvoie toutes les API de l’instance filtrées par type mcp. Utilisez les paramètres de requête $top et $skip pour paginer dans de grands ensembles de résultats.
Référence : API - Liste par service
curl -sG "${BASE_URL}/apis" \
--data-urlencode "api-version=${API_VERSION}" \
--data-urlencode "\$filter=type eq 'mcp'" \
-H "Authorization: Bearer ${TOKEN}"
Réponse (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" ]
}
}
]
}
Erreur courante :401 Unauthorized. Le token Bearer a expiré. Réexécutez la commande d’acquisition de jetons.
Obtenir un seul serveur MCP
Référence : API - GET
MCP_SERVER_ID="my-mcp-server"
curl -s "${BASE_URL}/apis/${MCP_SERVER_ID}?api-version=${API_VERSION}" \
-H "Authorization: Bearer ${TOKEN}"
Réponse (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"
}
}
Erreur courante :404 Not Found. Vérifiez que mcpServerId correspond au champ name renvoyé par l’opération List.
Créer un serveur MCP soutenu par l’API REST
Crée la ressource de serveur MCP. Après la création, ajoutez des outils individuellement à l’aide de l’opération Ajouter ou mettre à jour un outil . Chaque outil fait référence à une opération spécifique dans une ressource d’API REST de stockage.
Référence : API - Créer ou mettre à jour
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"]
}
}'
Réponse (201 créé)
{
"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 est attendu pour les opérations PUT asynchrones. Interrogez l'URL renvoyée dans l'en-tête de réponse Azure-AsyncOperation afin de confirmer l'achèvement de l'opération.
Erreur courante :400 Bad Request. Vérifiez que type est "mcp" et que path est unique dans l’instance de service.
Créer un serveur MCP relais
Un serveur passthrough transfère toutes les requêtes MCP directement à un serveur principal MCP externe. Défini mcpProperties.transportType pour correspondre au transport que votre back-end implémente.
Avant de créer un serveur passthrough, vérifiez que le serveur principal est accessible à partir de la passerelle Gestion des API et implémente le transport MCP sélectionné sur les chemins d’accès au point de terminaison que vous configurez. Si le back-end nécessite une authentification, configurez les informations d’identification ou les en-têtes requis à l’aide de stratégies de gestion des API ou de la configuration back-end.
Référence : API - Créer ou mettre à jour
Transport HTTP diffusable en continu
Utiliser streamable pour les back-ends qui implémentent la spécification de transport HTTP streamable mcP actuelle. Une définition de point de terminaison unique est requise.
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" }
]
}
}
}'
Réponse (201 créé)
{
"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" } ]
}
}
}
Transport SSE
Utiliser sse pour les back-ends qui implémentent le transport HTTP+SSE (Server-Sent Events). Définissez deux points de terminaison : un pour le flux d’événements SSE et un pour le canal de message.
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" }
]
}
}
}'
Erreurs courantes :
-
400 Bad Request. Non validemcpProperties. Vérifiez quetransportTypeeststreamableousseet que chaqueuriTemplatecommence par/. -
400 Bad Request. Le transport SSE nécessite exactement deux points de terminaison (sseetmessage). Le transport Streamable en exige un (message).
Ajouter ou mettre à jour un outil
Ajoute un nouvel outil à un serveur MCP soutenu par l’API REST ou met à jour un serveur MCP existant. Le champ operationId associe l’outil à une opération spécifique dans une ressource sous-jacente d’API REST. Vous pouvez ajouter, mettre à jour ou supprimer des outils indépendamment sans recréer le serveur parent.
Référence : Outil Api - Créer ou mettre à jour
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}\"
}
}"
Réponse (201 créé)
{
"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"
}
}
Erreurs courantes :
-
400 Bad Request. LeoperationIdchemin d’accès est incorrect ou l’opération référencée n’existe pas. -
404 Not Found. Le serveur MCP parent n’existe pas. Créez le serveur avant d’ajouter des outils.
Supprimer un outil
Supprime un outil d’un serveur MCP. Supprimez les outils avant de supprimer les opérations de l’API REST de stockage qu’ils référencent ; sinon, la suppression échoue avec une erreur de dépendance.
Référence : Outil Api - Supprimer
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: *"
Réponse:200 OK en cas de succès.
Erreur courante :412 Precondition Failed — If-Match est requis pour les suppressions. Utilisez If-Match: * pour correspondre à n’importe quel ETag.
Appliquer une stratégie à l'étendue MCP
Crée ou remplace le document de stratégie attaché à un serveur MCP. Le serveur évalue les stratégies à cette étendue pour chaque appel d’outil. Le rawxml format accepte le code XML de stratégie non codé.
Référence : Stratégie d’API - Créer ou mettre à jour
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}\"}}"
Réponse (200 OK)
{
"id": "/subscriptions/.../apis/my-mcp-server/policies/policy",
"name": "policy",
"type": "Microsoft.ApiManagement/service/apis/policies",
"properties": {
"value": "<policies>...</policies>"
}
}
Erreur courante :400 Bad Request. XML de stratégie mal formé. Validez le document avant d’envoyer.
Lier un serveur MCP à un produit
Associe le serveur MCP à un produit afin que les abonnés de ce produit puissent appeler les outils du serveur. La requête ne comporte aucun corps.
Lorsque vous liez le serveur MCP à un produit, vous le rendez disponible via ce produit, mais les clients ont toujours besoin d’un accès en fonction de la configuration du produit. Si le produit nécessite des abonnements, le client doit utiliser une clé d’abonnement valide pour ce produit.
Référence : API produit - Créer ou mettre à jour
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"
Réponse :201 Created avec le contrat d’API du serveur MCP dans le corps.
Erreur courante :404 Not Found. Vérifiez que les deux productId et mcpServerId existent avant de créer la liaison.
Supprimer un serveur MCP
Supprime un serveur MCP et tous ses outils et sous-ressources de stratégie. Avant de supprimer le serveur, supprimez tous les outils qui référencent les opérations dans les API de stockage ; sinon, vous ne pouvez pas supprimer ces opérations pendant que la référence de l’outil existe.
Référence : API - Supprimer
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: *"
Réponse:200 OK en cas de succès.
Erreur courante :412 Precondition Failed.
If-Match est requis pour les suppressions. Utilisez If-Match: * pour contourner la vérification des ETag.
Modèles ARM et Bicep
Les modèles suivants déploient une configuration complète du serveur MCP dans un seul déploiement. Chaque modèle suppose une instance de service Gestion des API existante et utilise une table de paramètres pour pouvoir réutiliser le même fichier dans les environnements en modifiant uniquement les valeurs de paramètre.
Serveur MCP soutenu par l’API REST
Ces modèles créent un serveur MCP, définissent un outil qui correspond à une opération dans une API REST sous-jacente existante, appliquent une stratégie de limitation du débit au niveau du serveur et lient le serveur à un produit existant. Vous pouvez effectuer toutes ces tâches dans un seul déploiement.
Prérequis : un service Gestion des API existant, une API REST (backingApiId) avec au moins une opération (backingOperationId) et un produit existant (productId).
| Paramètre | Obligatoire | Default | Description |
|---|---|---|---|
serviceName |
Oui | — | Nom de l’instance de service Gestion des API existante. |
mcpServerId |
Non | orders-mcp |
Nom de la ressource pour le nouveau serveur MCP. Doit être unique au sein du service. |
backingApiId |
Oui | — | Nom de ressource de l’API REST existante qui sauvegarde ce serveur MCP. |
backingOperationId |
Oui | — | Nom de la ressource de l’opération à exposer en tant qu’outil. |
toolId |
Non | sampleTool |
Nom de la ressource et nom complet de l’outil MCP à créer. |
productId |
Non | starter |
Nom de ressource du produit existant auquel lier le serveur. |
@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 ]
}
Pour déployer :
# 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
Serveur MCP en mode passthrough
Ces modèles créent un serveur MCP passthrough qui utilise le transport HTTP streamable. L’étendue du serveur a une stratégie de limite de débit et le serveur est lié à un produit existant. Les modèles ne définissent aucune sous-ressource d’outil. Le back-end externe détermine la surface de l’outil.
Note
Les modèles suivants utilisent transportType: streamable, qui implémente la spécification HTTP streamable MCP actuelle. Pour utiliser le transport SSE à la place, définissez transportTypesse et remplacez le endpoints tableau par deux entrées : { "name": "sse", "uriTemplate": "/sse" } et { "name": "message", "uriTemplate": "/messages" }. En Bicep, utilisez les mêmes valeurs avec des chaînes entre apostrophes.
Conditions préalables : un service Gestion des API existant, une URL principale MCP accessible (backendUrl) qui implémente les chemins de transport et de point de terminaison sélectionnés et un produit existant (productId).
| Paramètre | Obligatoire | Default | Description |
|---|---|---|---|
serviceName |
Oui | — | Nom de l’instance de service Gestion des API existante. |
mcpServerId |
Non | external-mcp |
Nom de la ressource pour le nouveau serveur MCP. Doit être unique au sein du service. |
backendUrl |
Oui | — | URL absolue du back-end MCP externe. |
productId |
Non | starter |
Nom de ressource du produit existant auquel lier le serveur. |
@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 ]
}
Pour déployer :
# 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
Actuellement, vous pouvez utiliser az rest pour appeler directement l’API REST. Le script suivant crée un serveur MCP passthrough, attache une stratégie de limite de débit et la lie à un produit. Ce processus couvre le même scénario que le modèle Bicep dans la section précédente.
Définissez des variables, puis exécutez les quatre az rest appels dans l’ordre.
Note
az rest utilise les informations d’identification de votre session active az login . Vous n’avez pas besoin d’une étape d’authentification distincte.
# 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}"
Chaque étape est idempotente. La réexécutation du script met à jour la ressource en place. Pour vérifier que le serveur a été créé, exécutez la commande suivante :
az rest --method GET \
--uri "${BASE}/apis/${MCP_SERVER_ID}?api-version=${API_VERSION}"
Terraform
Le fournisseur Terraform AzureRM n’a pas encore de ressources natives pour les serveurs MCP. Actuellement, vous pouvez utiliser le azapi_resource type de ressource à partir du fournisseur AzAPI, ce qui vous permet de gérer n’importe quel type de ressource Azure par rapport à n’importe quelle version de l’API. L’exemple suivant reprend le modèle Bicep du serveur MCP passthrough.
Conditions préalables : un service gestion des API existant, une URL principale MCP accessible et un produit existant. Ajoutez le fournisseur AzAPI à votre terraform bloc s’il n’est pas déjà présent.
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"
}
Ressources
# 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]
}
Pour déployer :
Note
azapi_resource utilise l’authentification du fournisseur AzAPI, qui s’appuie sur les mêmes az login informations d’identification que l’Azure CLI. Vous n’avez pas besoin de configurer l’authentification distincte lors de l’exécution locale.
terraform init
terraform apply \
-var="resource_group_name=<resource-group>" \
-var="service_name=<api-management-name>" \
-var="backend_url=https://mcp-backend.contoso.com"
Modèles CI/CD
Upserts idempotents : envoyez des requêtes PUT avec
If-Match: "*"afin que le même modèle s'applique que la ressource existe déjà ou non.Promouvoir les configurations entre les environnements : traitez les définitions de serveur MCP et les listes d’outils en tant qu’artefacts contrôlés par la source. Paramétrez uniquement les valeurs propres à l’environnement, telles que le nom de l’instance et l’URL du back-end.
Générez la liste des outils à partir de votre spécification d’API : alimentez la sous-ressource « outils » à partir de votre fichier OpenAPI source afin que la surface des outils reste synchronisée avec l’API sous-jacente à mesure que celle-ci évolue.
Supprimer dans l’ordre approprié : supprimez les références d’outils MCP avant de supprimer les API de stockage ou les opérations vers lesquelles elles pointent. Sinon, la suppression échoue en raison d'une vérification de clé étrangère.