本文介绍如何使用 REST API、ARM 模板、Bicep、Azure CLI和 Terraform 在 Azure API 管理 中创建和管理 MCP 服务器。
Important
本文中所述的 MCP 服务器管理功能需要 API 管理 REST API 版本 2025-09-01-preview 或更高版本。 在每个请求中固定此版本。
有关 MCP 服务器功能的背景信息,请参阅Azure API 管理中的关于 MCP 服务器。
先决条件
你的身份需要具备读取 API 管理服务以及创建或更新 API、API 工具、API 策略和产品 API 绑定关系的权限。 对于 Terraform 而言,该标识还需要对
azurerm_api_management数据源使用的现有 API 管理服务具有读取权限。对于 Azure CLI:
如需在本地运行 CLI 参考命令,请安装 Azure CLI。 如果在 Windows 或 macOS 上运行,请考虑在 Docker 容器中运行 Azure CLI。 有关详细信息,请参阅如何在 Docker 容器中运行 Azure CLI。
如果使用本地安装,请使用 az login 命令登录到Azure CLI。 若要完成身份验证过程,请遵循终端中显示的步骤。 有关其他登录选项,请参阅使用 Azure CLI 登录。
出现提示时,请在首次使用时安装 Azure CLI 扩展。 有关扩展的详细信息,请参阅 将扩展与 Azure CLI 配合使用。
运行az version命令,以查看已安装的版本和依赖库。 若要升级到最新版本,请运行az upgrade。
对于 Azure PowerShell:
- 如果选择在本地使用Azure PowerShell:
- 安装最新版本的 Az PowerShell 模块。
- 使用 Connect-AzAccount -Environment AzureChinaCloud cmdlet 连接到 Azure 帐户。
- 如果选择在本地使用Azure PowerShell:
对于 Terraform: 安装和配置 Terraform
资源模型
Azure 资源管理器 将 MCP 服务器表示如下:
MCP server: 类型为的 API Management API 资源。直通服务器: 指向现有外部 MCP 后端。 MCP 服务器资源声明后端 URL 和传输类型(可流式传输 HTTP 或 SSE)。
工具: MCP 服务器的 API 工具 子资源。 可以从 CI/CD 安全地管理工具资源。 无需重新创建 MCP 服务器,即可添加、重命名或删除工具。
产品: 产品绑定是单独的子关系(
products/{productId}/apis/{mcpServerId}),可实现独立的部署和多产品绑定。
REST 示例
为了清楚起见,以下示例显示了缩写的响应正文。 有关完整响应架构,请参阅 API 管理 REST API 参考。
在 PUT 和 DELETE 调用示例中添加 If-Match: * 标头,会使这些请求具有幂等性。 无论资源是否已存在,此标头都适用,这是 CI/CD 管道的推荐模式。
在您开始之前
运行任何示例之前,请设置以下变量。 本节中的所有示例都引用这些变量。
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.chinacloudapi.cn/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.ApiManagement/service/${APIM_NAME}"
TOKEN=$(az account get-access-token --resource https://management.chinacloudapi.cn --query accessToken -o tsv)
列出 MCP 服务器
返回筛选为类型 mcp实例中的所有 API。 使用 $top 和 $skip 查询参数对大型结果集进行分页。
参考: Api - 按服务列出
curl -sG "${BASE_URL}/apis" \
--data-urlencode "api-version=${API_VERSION}" \
--data-urlencode "\$filter=type eq 'mcp'" \
-H "Authorization: Bearer ${TOKEN}"
响应(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" ]
}
}
]
}
常见错误:401 Unauthorized. 持有者令牌已过期。 重新运行令牌获取命令。
获取单个 MCP 服务器
参考:API - 获取
MCP_SERVER_ID="my-mcp-server"
curl -s "${BASE_URL}/apis/${MCP_SERVER_ID}?api-version=${API_VERSION}" \
-H "Authorization: Bearer ${TOKEN}"
响应(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"
}
}
常见错误:404 Not Found. 确认 mcpServerId 与 List 操作返回的 name 字段匹配。
创建 REST API 支持的 MCP 服务器
创建 MCP 服务器资源。 创建后,使用 “添加”或更新工具 操作单独向其添加工具。 每个工具引用支持 REST API 资源中的特定操作。
参考: Api - 创建或更新
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"]
}
}'
响应(201 已创建)
{
"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
对于异步 PUT 操作,应使用 provisioningState: InProgress。 轮询响应头中返回的 Azure-AsyncOperation URL,以确认操作已完成。
常见错误:400 Bad Request. 确保type为"mcp",且path在服务实例中是唯一的。
创建透传 MCP 服务器
直通服务器将所有 MCP 请求直接转发到外部 MCP 后端。 将 mcpProperties.transportType 设置为与你的后端实现的传输方式相匹配的值。
在创建直通服务器之前,请确认后端可从 API 管理网关访问,并在配置的终结点路径上实现所选 MCP 传输。 如果后端需要身份验证,请使用 API 管理策略或后端配置配置所需的凭据或标头。
参考: Api - 创建或更新
可以流式传输的 HTTP
对于实现了当前 MCP 可流式传输的 HTTP 传输规范的后端,请使用 streamable。 需要单个终结点定义。
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" }
]
}
}
}'
响应(201 已创建)
{
"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 传输
对于实现 HTTP+SSE(服务器发送事件)传输的后端,请使用 sse。 定义两个终结点:一个用于 SSE 事件流,一个用于消息通道。
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" }
]
}
}
}'
常见错误:
-
400 Bad Request。mcpProperties无效。 验证transportType是否streamable或sse,并且每个uriTemplate开头都以/。 -
400 Bad Request。 SSE 传输需要两个终结点(sse和message)。 流式传输需要一个(message)。
添加或更新工具
将新工具添加到 REST API 支持的 MCP 服务器,或更新现有工具。 该 operationId 字段将该工具链接到支持 REST API 资源中的特定操作。 无需重新创建父服务器,即可独立添加、更新或删除工具。
参考: API 工具 - 创建或更新
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}\"
}
}"
响应(201 已创建)
{
"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"
}
}
常见错误:
-
400 Bad Request。operationId路径格式不正确或引用的操作不存在。 -
404 Not Found。 父 MCP 服务器不存在。 在添加工具之前创建服务器。
删除工具
从 MCP 服务器中删除工具。 在删除它们引用的后备 REST API 操作之前删除工具;否则,删除失败并出现依赖项错误。
参考: API 工具 - 删除
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: *"
响应:200 OK 成功时返回。
常见错误:412 Precondition Failed — If-Match 需要删除。 使用 If-Match: * 来匹配任意 ETag。
在 MCP 范围内应用策略
创建或替换附加到 MCP 服务器的策略文档。 服务器在此范围内评估每个工具调用的策略。 格式 rawxml 接受未编码的策略 XML。
参考: Api 策略 - 创建或更新
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}\"}}"
响应(200 OK)
{
"id": "/subscriptions/.../apis/my-mcp-server/policies/policy",
"name": "policy",
"type": "Microsoft.ApiManagement/service/apis/policies",
"properties": {
"value": "<policies>...</policies>"
}
}
常见错误:400 Bad Request. 策略 XML 格式错误。 在发送之前验证文档。
将 MCP 服务器绑定到产品
将 MCP 服务器与产品相关联,因此该产品的订阅者可以调用服务器的工具。 请求没有正文。
将 MCP 服务器绑定到某个产品时,可以通过该产品使用它,但客户端仍需要根据产品的配置进行访问。 如果产品需要订阅,客户端必须为该产品使用有效的订阅密钥。
参考: 产品 API - 创建或更新
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"
响应:201 Created正文中包含 MCP 服务器的 API 契约。
常见错误:404 Not Found. 在创建绑定之前,请验证这两者是否存在productIdmcpServerId。
删除 MCP 服务器
删除 MCP 服务器及其所有工具和策略子资源。 在删除服务器之前,请删除引用支持 API 中操作的任何工具;否则,不能在工具引用存在时删除这些操作。
参考:API - 删除
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: *"
响应:200 OK 成功时返回。
常见错误:412 Precondition Failed. 删除操作需要 If-Match。 使用 If-Match: * 可绕过 ETag 检查。
ARM 和 Bicep 模板
以下模板在单个部署中部署完整的 MCP 服务器配置。 每个模板假设有一个现有的 API 管理服务实例,并使用参数表,以便通过仅更改参数值,在环境中重复使用同一文件。
REST API 支持的 MCP 服务器
这些模板创建 MCP 服务器,定义一个工具,该工具映射到现有支持 REST API 中的操作,在服务器范围内附加速率限制策略,并将服务器绑定到现有产品。 可以在单个部署中执行所有这些任务。
先决条件:现有 API 管理服务、至少有一个操作()的 REST API(backingApiIdbackingOperationId)和现有产品(productId)。
| 参数 | 必需 | 默认 | 说明 |
|---|---|---|---|
serviceName |
是的 | — | 现有 API 管理服务实例的名称。 |
mcpServerId |
否 | orders-mcp |
新 MCP 服务器的资源名称。 在服务中必须是唯一的。 |
backingApiId |
是的 | — | 用于备份此 MCP 服务器的现有 REST API 的资源名称。 |
backingOperationId |
是的 | — | 要作为工具公开的操作的资源名称。 |
toolId |
否 | sampleTool |
要创建的 MCP 工具的资源名称和显示名称。 |
productId |
否 | starter |
要将服务器绑定到的现有产品的资源名称。 |
@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 ]
}
部署:
# 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
透传 MCP 服务器
这些模板会创建一个使用支持流式传输的 HTTP 传输的透传 MCP 服务器。 服务器范围具有速率限制策略,服务器绑定到现有产品。 模板不定义任何工具子资源。 外部后端决定工具界面。
Note
以下模板使用 transportType: streamable,它实现当前的 MCP 可流式传输 HTTP 规范。 若要改用 SSE 传输,请将 transportType 设置为 sse,并将 endpoints 数组替换为两个条目:{ "name": "sse", "uriTemplate": "/sse" } 和 { "name": "message", "uriTemplate": "/messages" }。 在Bicep中,对单引号字符串使用相同的值。
先决条件: 现有的 API 管理服务、可实现所选传输和终结点路径的可访问 MCP 后端 URLbackendUrl 以及现有产品(productId)。
| 参数 | 必需 | 默认 | 说明 |
|---|---|---|---|
serviceName |
是的 | — | 现有 API 管理服务实例的名称。 |
mcpServerId |
否 | external-mcp |
新 MCP 服务器的资源名称。 在服务中必须是唯一的。 |
backendUrl |
是的 | — | 外部 MCP 后端的绝对网址。 |
productId |
否 | starter |
要将服务器绑定到的现有产品的资源名称。 |
@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 ]
}
部署:
# 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
目前,可用于 az rest 直接调用 REST API。 以下脚本创建直通 MCP 服务器,附加速率限制策略,并将其绑定到产品。 此流程涵盖了与上一部分中的 Bicep 模板相同的场景。
设置变量,然后按顺序运行四 az rest 个调用。
Note
az rest 使用当前 az login 会话中的凭据。 不需要单独的身份验证步骤。
# 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.chinacloudapi.cn/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}"
每个步骤都是幂等的。 重新运行该脚本将就地更新该资源。 若要验证是否已创建服务器,请运行以下命令:
az rest --method GET \
--uri "${BASE}/apis/${MCP_SERVER_ID}?api-version=${API_VERSION}"
Terraform
AzureRM Terraform 提供程序尚未提供适用于 MCP 服务器的原生资源。 目前,可以使用 azapi_resource中的资源类型,这样就可以针对任何 API 版本管理任何Azure资源类型。 以下示例与直通 MCP 服务器的 Bicep 模板一致。
先决条件: 现有的 API 管理服务、可访问的 MCP 后端 URL 和现有产品。 如果 terraform 块中尚未包含 AzAPI 提供程序,请将其添加进去。
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]
}
部署:
Note
azapi_resource使用 AzAPI 提供程序的身份验证,该身份验证从与Azure CLI相同的az login凭据读取。 在本地运行时,无需配置单独的身份验证。
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 模式
幂等插入或更新:发送带有
If-Match: "*"的 PUT 请求,这样无论资源是否已存在,都可应用同一模板。跨环境提升配置:将 MCP 服务器定义和工具列表视为源代码管理的项目。 仅参数化特定于环境的值,例如实例名称和后端 URL。
从 API 规范生成工具列表:根据源 OpenAPI 文件生成并维护工具子资源,使工具接口随着底层 API 的演进而始终保持同步。
按正确的顺序删除:删除 MCP 工具引用,然后再删除它们指向的后盾 API 或操作。 否则,删除操作会因外键检查失败。