Chapter 5 of 6
Implement#
1. Load the approved definitions#
Complete sandbox.json, agent-mcp-binding.json, the security evaluation, and the threat model. The approved backend role assignment must already be active.
PowerShell
$approvedSubscriptionId = $env:AZURE_SUBSCRIPTION_ID
$artifactRoot = (Resolve-Path .\artifacts).Path
$environment = Get-Content (Join-Path $artifactRoot "environments\sandbox.json") -Raw | ConvertFrom-Json
$binding = Get-Content (Join-Path $artifactRoot "governance\agent-mcp-binding.json") -Raw | ConvertFrom-Json
Bash
approved_subscription_id="${AZURE_SUBSCRIPTION_ID:?Set AZURE_SUBSCRIPTION_ID.}"
artifact_root="$(cd ./artifacts && pwd)"
environment_path="$artifact_root/environments/sandbox.json"
binding_path="$artifact_root/governance/agent-mcp-binding.json"
2. Run preflight and inspect the preview#
PowerShell
.\scripts\preflight.ps1 -ApprovedSubscriptionId $approvedSubscriptionId
Bash
./scripts/preflight.sh --approved-subscription-id "$approved_subscription_id"
Preflight checks the implementation files and sentinels, the approved subscription and APIM scope, the supported tier, identities, exact backend read assignment, payload-free diagnostics, Foundry project, name collision, Bicep build, and ARM what-if.
Continue only when the preview is limited to the five MCP control values, MCP API, its one tool, policy, and diagnostic.
3. Deploy the APIM control#
PowerShell
.\scripts\deploy.ps1 -ApprovedSubscriptionId $approvedSubscriptionId
Bash
./scripts/deploy.sh --approved-subscription-id "$approved_subscription_id"
The deployment creates the marked policy-catalog-mcp API, get_policy, five nonsecret named values, the inbound and managed-identity policy, and the payload-free diagnostic. Troubleshoot with status, error type, correlation, approved APIM tracing, and governed backend diagnostics. Do not turn on payload logging.
4. Update API Center#
After APIM synchronization creates one policy-catalog-mcp entry, the API program owner applies the APIM gateway process and records the owner, classification, consumer, residency, risk, evaluation, review, and expiry metadata.
Stop on a duplicate, missing runtime owner, or metadata broader than the threat model. The candidate cannot be enabled until this entry is complete.
5. Create the Foundry connection#
PowerShell
$env:session09_MCP_SERVER_URL = "https://$($environment.apiManagementName).azure-api.net/$($environment.mcpServerPath)/mcp"
$projectUrl = "https://$($environment.foundryAccountName).services.ai.azure.com/api/projects/$($environment.foundryProjectName)"
azd ai project set $projectUrl
azd ai connection create $binding.projectConnectionName `
--kind remote-tool `
--target $env:session09_MCP_SERVER_URL `
--auth-type agentic-identity `
--audience $environment.mcpAudience
Bash
readarray -t foundry_values < <(ENVIRONMENT_PATH="$environment_path" BINDING_PATH="$binding_path" python3 - <<'PY'
import json, os, pathlib
e = json.loads(pathlib.Path(os.environ["ENVIRONMENT_PATH"]).read_text())
b = json.loads(pathlib.Path(os.environ["BINDING_PATH"]).read_text())
print(f"https://{e['apiManagementName']}.azure-api.net/{e['mcpServerPath']}/mcp")
print(f"https://{e['foundryAccountName']}.services.ai.azure.com/api/projects/{e['foundryProjectName']}")
print(b["projectConnectionName"])
print(e["mcpAudience"])
PY
)
export session09_MCP_SERVER_URL="${foundry_values[0]}"
azd ai project set "${foundry_values[1]}"
azd ai connection create "${foundry_values[2]}" \
--kind remote-tool \
--target "$session09_MCP_SERVER_URL" \
--auth-type agentic-identity \
--audience "${foundry_values[3]}"
If the installed azd ai surface differs, use the current Foundry portal flow with the same name, target, agentic identity, and audience. Do not use a key or pasted bearer token.
6. Create an unpinned candidate#
Copy the pinned governed agent definition. Keep its model, RAI policy, instructions, temperature, endpoint authorization, and identity behavior. Remove the direct OpenAPI tool, add the MCP connection, set allowed_tools to get_policy, and set require_approval to always.
Save without changing the stable selector. Show the candidate version ID and the prior stable selector to the release owner.