Microsoft Foundry
MicrosoftOfficialCreated by Microsoft
- Skill
- Workflow
- Data and AI
- MIT
- Low risk
- Has scripts
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
Microsoft Foundry provides a comprehensive framework for the entire AI agent lifecycle. This skill enables developers to scaffold, provision, deploy, and manage agents while integrating evaluation and optimization workflows. It supports various agent types, including prompt-based, managed harness, and voice agents, and provides tools for CI/CD, continuous monitoring, and fine-tuning models. The skill emphasizes a structured approach using workspace-specific metadata and standard Azure Developer CLI (azd) patterns to ensure consistent environment management and deployment.
What it does
- Scaffold and create new AI agents with support for various harness types.
- Manage the full deployment lifecycle including provisioning and CI/CD integration.
- Execute batch and continuous evaluation workflows to monitor agent quality.
- Optimize agent prompts and instructions using automated evaluation-driven loops.
- Fine-tune models using SFT, DPO, or RFT techniques with dataset curation.
- Troubleshoot agent performance through log analysis, telemetry, and trace inspection.
When to use it
- When building, deploying, or managing AI agents within the Microsoft Foundry ecosystem.
- When you need to evaluate agent performance or optimize prompts based on production traces.
- When setting up CI/CD pipelines for automated agent deployment and monitoring.
- When fine-tuning models or managing capacity and quotas for AI services.
- When troubleshooting deployment failures or agent runtime issues.
Advantages
- Provides a unified, end-to-end workflow for the entire agent development lifecycle.
- Standardizes project structure and metadata management across different environments.
- Integrates seamlessly with Azure Developer CLI (azd) for consistent infrastructure management.
- Enables data-driven improvements through automated evaluation and prompt optimization.
- Supports advanced model customization including fine-tuning and distillation.
Usage examples
- “Create a new hosted Foundry agent from scratch.”
- The agent will guide you through the quick-start workflow to scaffold, provision, and deploy a new agent project.
- “Optimize the prompt for my existing Python hosted agent.”
- The agent will trigger the evaluation-driven optimization workflow to analyze performance and suggest prompt improvements.
- “Set up a CI/CD pipeline for my agent.”
- The agent will configure the necessary deployment pipeline steps for your Foundry agent project.
- “Troubleshoot why my agent deployment is failing.”
- The agent will help you inspect logs, telemetry, and quota settings to diagnose and resolve the deployment issue.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/microsoft/microsoft-foundry/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip microsoft-foundry.zip -d .agents/skills
Documentation by Microsoft
Microsoft Foundry Skill
This skill helps developers work with Microsoft Foundry resources, covering model discovery and deployment, complete dev lifecycle of AI agent, evaluation workflows, and troubleshooting.
Pre-Execution Requirements
Follow each applicable subsection below before starting its corresponding action or workflow.
Dependency Check and Setup
MANDATORY: As the first step after this skill loads, run the dependency check and setup script below from this skill's root and wait for it to finish before continuing. The script checks first and installs only missing dependencies; it does not reinstall dependencies that are already available.
You MUST complete this check before reading or entering any sub-skill, workflow, or workflow-specific reference.
./scripts/check-and-setup-dependencies.sh # macOS / Linux
./scripts/check-and-setup-dependencies.ps1 # Windows (pwsh)Strictly follow the script output for subsequent actions.
Workflow Guidance
MANDATORY: Before executing ANY workflow-specific steps, you MUST read the corresponding sub-skill document. Do not call workflow-specific MCP tools for a workflow without reading its skill document. This applies even if you already know the MCP tool parameters — the skill document contains required workflow steps, pre-checks, and validation logic that must be followed. This rule applies on every new user message that triggers a different workflow, even if the skill is already loaded.
Foundry MCP
MANDATORY: Before using Foundry MCP operations, call the Azure MCP foundry tool and inspect the available Foundry MCP tools and related parameters. Treat this as the discovery/help step for MCP-based workflows.
azd
MANDATORY: Before executing ANY azd command, you MUST read azd-guidance and strictly follow the shared rules defined in it, especially the AZURE_DEV_USER_AGENT setting rules.
Sub-Skills
This skill includes specialized sub-skills for specific workflows. When a sub-skill matches the task, strictly follow its workflow:
| Sub-Skill | When to Use | Reference |
|---|---|---|
| deploy | Deploy hosted agents to Foundry, smoke-test a deployment, create or update prompt agents, and manage agent versions and multi-environment deploys. | deploy |
| cicd | Set up a CI/CD deployment pipeline for a Foundry agent. | cicd |
| invoke | Send messages to an agent, single or multi-turn conversations | invoke |
| routine | Schedule or event-trigger Foundry agents with routines; use azd for CRUD, enable/disable, manual dispatch, and viewing past runs, or define routines in azure.yaml. | routine |
| invocations-ws | Build, deploy, and connect to custom Hosted agents that use developer-defined duplex real-time or media streams over invocations_ws. | invocations-ws |
| observe | Evaluate agent quality, run batch evals, analyze failures, optimize prompts, improve agent instructions, compare versions, set up CI/CD monitoring, and enable continuous production evaluation | observe |
| insights | Pull generated agent insights, evidence, and recommendations from an existing monitor; read-only retrieval, not a new analysis run | insights |
| trace | Query traces, analyze latency/failures, correlate eval results to specific responses via App Insights customEvents | trace |
| troubleshoot | View hosted agent logs, query telemetry, diagnose failures | troubleshoot |
| validate | Use only when the user explicitly asks to use this validation sub-skill or to validate Microsoft Foundry hosted-agent code against best practices. Never invoke it proactively or add it to another workflow. | validate |
| create (quick start) | Create a new hosted Foundry agent from scratch end-to-end — scaffold, provision or use an existing Foundry project, deploy, and smoke-test. Do not use for any work on existing code. For anything not covered by the quickstart, use create. | create/quick-start-hosted.md |
| create | Use when the standard end-to-end happy path (quick start) doesn't fit. Create a new Foundry agent, update code of an existing agent, continue development of an existing agent, wire connections at scaffold time, use advanced setup or A2A (Agent2Agent), or recover from a failed quickstart run. | create |
| create managed harness | Create or continue developing a Prompt Agent that explicitly uses the Foundry-managed Copilot harness. Uses azd and azure.yaml, not the ordinary Prompt Agent MCP workflow. | create-managed-harness |
| create voice | Create, configure, or extend a Foundry Voice Agent, defaulting generic requests to managed Prompt Voice and supporting self-deployed Prompt Voice or two-agent Hosted Voice. | create-voice |
| agent-optimizer | Make existing Python hosted-agent code optimization-ready, configure eval.yaml, run Agent Optimizer jobs, apply candidates locally, and deploy through azd after review. | agent-optimizer |
| eval-datasets | Harvest production traces into evaluation datasets, manage dataset versions and splits, track evaluation metrics over time, detect regressions, and maintain full lineage from trace to deployment. Use for: create dataset from traces, dataset versioning, evaluation trending, regression detection, dataset comparison, eval lineage. | eval-datasets |
| project/create | Creating a new Microsoft Foundry project for hosting agents and models. Use when onboarding to Foundry or setting up new infrastructure. | project/create/create-foundry-project.md |
| resource/create | Creating Azure AI Services multi-service resource (Foundry resource) using Azure CLI. Use when manually provisioning AI Services resources with granular control. | resource/create/create-foundry-resource.md |
| private-network | Answer questions about Foundry network isolation and deploy Foundry with VNet isolation (BYO VNet, Managed VNet, hybrid). Covers architecture concepts, template selection, deployment, and post-deployment validation. | resource/private-network/private-network.md |
| models/deploy-model | Unified model deployment with intelligent routing. Handles quick preset deployments, fully customized deployments (version/SKU/capacity/RAI), and capacity discovery across regions. Routes to sub-skills: preset (quick deploy), customize (full control), capacity (find availability). | models/deploy-model/SKILL.md |
| quota | Managing quotas and capacity for Microsoft Foundry resources. Use when checking quota usage, troubleshooting deployment failures due to insufficient quota, requesting quota increases, or planning capacity. | quota/quota.md |
| rbac | Managing RBAC permissions, role assignments, managed identities, and service principals for Microsoft Foundry resources. Use for access control, auditing permissions, and CI/CD setup. | rbac/rbac.md |
| finetuning | Fine-tune models on Microsoft Foundry — SFT distillation, DPO preference optimization, RFT with graders and tool calling. Dataset preparation, grader calibration, training, checkpoint selection, deployment, evaluation. Use for: fine-tune, SFT, DPO, RFT, training data, grader, distillation, fine-tuned model, large file upload. | finetuning/SKILL.md |
| azd-guidance | Provide shared azd knowledge and guidance for managing Foundry agents. Read this first for any workflows related to azd. | azd-guidance |
💡 Tip: For a complete onboarding flow:
project/create(public) orprivate-network(VNet isolation) →models/deploy-model→ agent workflows (create→deploy→invoke).
💡 Fine-Tuning: Use
finetuningfor all model customization — SFT distillation, DPO preference optimization, and RFT with graders. Includes quickstart, grader calibration, and training curve analysis.
💡 Model Deployment: Use
models/deploy-modelfor all deployment scenarios — it intelligently routes between quick preset deployment, customized deployment with full control, and capacity discovery across regions.
💡 Prompt Optimization: For requests like "optimize my prompt" or "improve my agent instructions," load observe and use the
prompt_optimizeMCP tool through that eval-driven workflow.
Infrastructure Lifecycle
Match user intent to the correct infrastructure workflow.
| User Intent | Workflow |
|---|---|
| "Create Foundry" / "Set up Foundry" (ambiguous) | Use AskUserQuestion: (a) just an AI Services resource, (b) a project with public access, or (c) a project with network isolation? Route: (a) → resource/create, (b) → project/create, (c) → private-network |
| Set up Foundry with VNet isolation | private-network |
| Create a Foundry project (public) | project/create |
| Create a bare Foundry resource | resource/create |
Agent Development Lifecycle
Match user intent to the correct agent workflow. Read each sub-skill in order before executing.
| User Intent | Workflow (read in order) |
|---|---|
| Create or develop a Voice Agent (Prompt Voice or Hosted Voice) | dependency check and setup → azd-guidance → create-voice → deploy → invoke |
| Create or develop an explicitly requested Managed Harness Agent / Copilot harness agent | dependency check and setup → azd-guidance → create-managed-harness → deploy → invoke |
| Create a new hosted agent end-to-end (scaffold + deploy + test) | dependency check and setup → azd-guidance → quick-start-hosted (self-contained end-to-end) |
| Anything beyond the standard quickstart (existing code, migration, re-hosting, deployment customization, scaffold-time connections, A2A (Agent2Agent), recovery) | dependency check and setup → azd-guidance → create → deploy → invoke |
| Optimize existing Python hosted agent | dependency check and setup → azd-guidance → agent-optimizer → scaffold/review → eval.yaml → optimize → apply candidate → deploy → invoke |
| Deploy an agent (code already exists) | dependency check and setup → azd-guidance → deploy (includes eval-suite setup) → invoke → observe (evaluate/optimize) |
| Update/redeploy an agent after code changes | dependency check and setup → azd-guidance → deploy (includes eval-suite setup) → invoke → observe (evaluate/optimize) |
| Set up a CI/CD deployment pipeline for a hosted agent | dependency check and setup → azd-guidance → cicd |
| Invoke/test/chat with an agent | dependency check and setup → azd-guidance → invoke |
| Schedule/event-trigger an agent, or CRUD/enable/disable/dispatch a routine | dependency check and setup → azd-guidance → routine |
| Optimize / improve agent prompt or instructions | observe (Step 4: Optimize) |
| Evaluate and optimize agent (full loop) | observe |
| Enable continuous evaluation monitoring | observe (Step 6: CI/CD & Monitoring) |
| Pull agent insights / list generated issues and recommendations | dependency check and setup → insights (all pages with expanded evidence; read-only) |
| Troubleshoot an agent issue | dependency check and setup → azd-guidance → invoke → troubleshoot |
| Fix a broken agent (troubleshoot + redeploy) | dependency check and setup → azd-guidance → invoke → troubleshoot → apply fixes → deploy → invoke |
Agent: .foundry Workspace Standard
Every agent source folder can keep Foundry-specific cache and overlay state under .foundry/:
<agent-root>/
.foundry/
agent-metadata.yaml
agent-metadata.prod.yaml
suites/
datasets/
evaluators/
results/In azd projects, derive deployment context (project endpoint, agent name/version, ACR, App Insights) from
azure.yamlplusazd env get-values; do not duplicate those values in metadata when azd already provides them.agent-metadata.yamlis the preferred local/dev overlay for non-azd values, remote Foundry suite references, local cache paths, result summaries, and explicit overrides. Optional sidecar files such asagent-metadata.prod.yamlcan hold a single prod or CI-targeted overlay without mixing multiple environments in one file.suites/,datasets/, andevaluators/are local cache folders. Reuse them when they are current, and ask before refreshing or overwriting them.See Agent Metadata Contract for the canonical schema and workflow rules.
Agent: Setup References
Standard Agent Setup — advanced setup for production workloads that need data-residency control (bring-your-own Cosmos DB / Storage / AI Search via a Foundry capability host). The default
azd ai agentflow uses Basic Agent Setup and does not provisioncapabilityHosts/agents— do not flag its absence as a bug. For default post-provision state, see the "Expected env-var fingerprint" section in foundry-agent/create/create-hosted.md.
Agent: Common Project Context Resolution
Agent skills should run this step only when they need configuration values they don't already have. If a value (for example, agent root, environment, project endpoint, or agent name) is already known from the user's message or a previous skill in the same session, skip resolution for that value.
Step 1: Discover Agent Roots and azd Context
First check whether the workspace has azure.yaml with services using host: azure.ai.agent.
One azd agent service -> classify it from
kind,harness,modelType, andconversationEngine, then use that service'sprojectfolder or theazure.yamldirectory as the agent root.Multiple azd agent services -> check whether a Voice wrapper references a
kind: hostedservice viaconversationEngine.name:Selecting the Hosted Voice wrapper implies its named
kind: hostedtarget as an upstream dependency (uses: [<target>],conversationEngine.name: <target>); deploy and verification must report both services separately.Selecting the
kind: hostedtarget alone scopes changes/debugging to the target container and does not automatically modify the wrapper.Otherwise -> require the user to choose the target service/folder.
No azd agent service -> search the workspace for
.foundry/folders that containagent-metadata.yamloragent-metadata.<env>.yaml.One match -> use that agent root.
Multiple matches -> require the user to choose the target agent folder.
No matches -> for insights, ask only for missing remote inputs without initializing local files; for create/deploy workflows, seed a new
.foundry/folder during setup; for other workflows, stop and ask the user which agent source folder to initialize.
After selecting an agent root, keep all local .foundry cache inspection, source inspection, evaluator suggestions, dataset suggestions, and prompt-optimization context inside that folder only. Do not scan sibling agent folders unless the user explicitly switches roots.
Step 2: Resolve Environment and Deployment Context
If azure.yaml is present, resolve the azd environment first:
Environment explicitly named by the user
AZURE_ENV_NAMEfromazd env get-valuesazd default environment from
.azure/config.jsonEnvironment already selected earlier in the session
Run azd env get-values for the selected environment when project/deployment values are not already known. Prefer azd values for deployment context:
| azd Variable | Resolves To |
|---|---|
AZURE_AI_PROJECT_ENDPOINT or AZURE_AIPROJECT_ENDPOINT | Project endpoint |
AGENT_<SERVICE>_NAME | Agent name for the selected azd service |
AGENT_<SERVICE>_VERSION | Agent version for the selected azd service |
AZURE_CONTAINER_REGISTRY_NAME or AZURE_CONTAINER_REGISTRY_ENDPOINT | ACR registry name / image URL prefix |
APPLICATIONINSIGHTS_CONNECTION_STRING | App Insights connection string for trace workflows |
AZURE_SUBSCRIPTION_ID, AZURE_RESOURCE_GROUP, AZURE_AI_ACCOUNT_NAME, AZURE_AI_PROJECT_NAME | Azure resource lookup and Playground links |
When azd supplies these values, use them as the source of truth and do not copy them into .foundry/agent-metadata*.yaml on metadata writes.
Step 3: Select Metadata Overlay and Resolve Environment
Inside the selected agent root, choose the metadata file in this order:
Metadata filename or path explicitly provided by the user or workflow
If an explicit environment is already known and
.foundry/agent-metadata.<env>.yamlexists, use that file.foundry/agent-metadata.yamlIf multiple metadata files remain and no rule above selects one, prompt the user to choose
Read the selected metadata file and resolve any remaining environment choice in this order:
Environment explicitly named by the user
If the selected metadata file defines exactly one environment, use it
Environment already selected earlier in the session
defaultEnvironmentfrom metadata
If the selected metadata file still contains multiple environments and none of the rules above selects one, prompt the user to choose. Keep the selected agent root, metadata file, environment, and whether context came from azd or metadata visible in every workflow summary.
If the selected environment exposes older testSuites[] metadata but not evaluationSuites[], treat testSuites[] as the source for this session and normalize each entry in memory to the evaluationSuites[] shape before continuing. If the metadata is older still and only exposes legacy testCases[], normalize that list the same way. Preserve dataset and evaluator fields, keep any existing tags, and map legacy priority to tags.tier only when tags.tier is missing: P0 -> smoke, P1 -> regression, P2 -> coverage.
Step 4: Resolve eval.yaml Local Evaluation Intent
If eval.yaml exists in the selected agent root, parse it before generating new suites:
agent.name-> target agent candidate; verify it matches the selected azd/metadata agent before using it.dataset.local_uri-> local seed dataset candidate; legacydataset_filemay be normalized in memory.dataset.name/dataset.version-> registered dataset candidate.validation_dataset-> optional validation dataset candidate.evaluators[]-> candidate Foundry evaluator names; verify withevaluator_catalog_getbefore treating them as remote evaluators.name-> local eval/suite candidate; verify remotely before persisting assuiteName.options.eval_model,options.optimization_model,options.max_candidates,options.optimization_config.model_search_space,options.pass_threshold,max_samples,trace_days, andgeneration_instruction-> setup defaults.
Treat eval.yaml as local evaluation intent, not proof that a Foundry suite exists. Persist synced suite/dataset/evaluator references to .foundry only after remote lookup or registration succeeds.
Step 5: Resolve Common Configuration
Layer sources in this order:
Explicit user input and values already selected in the session
azd environment values for deployment context
.foundry/agent-metadata*.yamloverlay values and remote suite/cache referencesazure.yamlandeval.yamllocal source configurationUser prompts for anything still missing
If azd and metadata both provide the same value and they differ, stop and ask which source is authoritative. If they match, use the azd value and avoid rewriting the duplicate on future metadata writes.
| Effective Value | Preferred Source | Used By |
|---|---|---|
| Project endpoint | azd env | deploy, invoke, observe, trace, troubleshoot |
| Agent name/version | azd agent variables, then azure.yaml | invoke, observe, trace, troubleshoot |
| ACR | azd env | deploy |
| Evaluation suites and cache paths | .foundry/agent-metadata*.yaml | observe, eval-datasets |
| Local seed dataset/evaluator intent | eval.yaml | observe, eval-datasets |
Step 6: Write Metadata Overlay (Create/Deploy/Observe Only)
On any metadata write (deploy, auto-setup, dataset refresh, or trace-to-dataset update), persist only non-derivable overlay/cache state in the selected metadata file:
azd binding (
azd.environmentName,azd.service) when useful for future resolutionevaluationSuites[]with remote suite/dataset/evaluator references and local cache pathslastEval, result files, comparison summaries, or explicit non-azd overrides
Do not copy azd-owned deployment values into metadata when azd already provides them. If the selected file is a preferred single-environment file, rewrite only that one environment block. If the selected file is a legacy multi-environment file, rewrite only the selected environment block. Never copy or merge environments across sibling metadata files automatically. If the selected environment still uses older testSuites[] or legacy testCases[], rewrite it to evaluationSuites[] and remove migrated priority fields from the rewritten entries.
Step 7: Collect Missing Values
Use the ask_user or askQuestions tool only for values not resolved from the user's message, session context, metadata, or azd bootstrap. Common values skills may need:
Agent root — Target azd service project folder or folder containing
.foundry/agent-metadata*.yamlMetadata file —
agent-metadata.yamlfor local/dev, or an explicit sidecar such asagent-metadata.prod.yamlEnvironment — azd environment,
dev,prod, or another environment key from metadataProject endpoint — Microsoft Foundry project endpoint URL
Agent name — Name of the target agent
💡 Tip: If the user already provides the agent path, environment, project endpoint, or agent name, extract it directly — do not ask again.
Agent: Agent Types
Agent workflows distinguish four first-class agent types:
| Type | Kind | Description |
|---|---|---|
| Prompt | "prompt" | LLM-based agents backed by a model deployment; managed via Foundry MCP or SDK |
| Hosted | "hosted" | Container-based agents running custom code; developed and deployed via azd |
| Managed Harness Agent | "prompt" with harness.type: "microsoft_copilot_preview" for new authoring | Prompt Agent running on the Foundry-managed Copilot harness; developed and deployed via azd |
| Voice | "voice" | Managed real-time Voice Agent — either Prompt Voice (1 agent, modelType: managed or self_deployed) or Hosted Voice (2 agents: kind: voice wrapper with conversationEngine.type: hosted_agent + kind: hosted target over invocations_ws 1.0.0 and Voice Live Bridge 1.0); developed and deployed via azd and verified over the voice WebSocket endpoint |
Classify an azure.yaml service by its definition in this exact order, not by host alone:
kind: voice-> Voice. For compatibility, silently classify an existingkind: prompt-voiceservice as Voice, then normalize it when editing its YAML. Classify the subtype:conversationEngine.type: hosted_agent-> Hosted Voice wrapper (paired with a namedkind: hostedtarget service).modelType: managedormodelType: self_deployed-> Prompt Voice (Foundry infers native speech-to-speech vs cascaded STT -> LLM -> TTS frommodel.id).Having both
modelType/modelandconversationEngineis invalid (stop and fixazure.yaml); having neither is incomplete (do not guess). Never use obsoletemodelType: hosted_agent,targetAgent, or a nestedconfig:block.
kind: hosted-> Hosted. When it declaresprotocols: [{ protocol: invocations_ws, version: 1.0.0 }]andmetadata.voiceLiveCompatible: "true"alongside akind: voicewrapper, it is a Hosted Voice target; otherwise treat a standaloneinvocations_wsservice as a custom Hosted real-time/audio agent.kind: promptplusharness.type: microsoft_copilot_previewor legacygithub_copilot_preview-> Managed Harness Agent.kind: promptwithout that harness -> ordinary Prompt Agent.
Use agent_get only when the type cannot be resolved from project context. Preserve the harness discriminator already authored on an existing Managed Harness Agent; do not migrate it during ordinary edits or redeploys. Do not convert an existing Agent between Prompt, Hosted, Managed Harness Agent, and Voice types; create a new Agent instead. Before creating any Voice Agent, determine the model strategy first per create-voice.
Tool Usage Conventions
Use the
ask_useroraskQuestionstool whenever collecting information from the userUse the
taskorrunSubagenttool to delegate long-running or independent sub-tasks (e.g., env var scanning, status polling, Dockerfile generation)Prefer azd for Hosted Agents, Managed Harness Agents, and Voice Agents; prefer Foundry MCP for ordinary Prompt Agents.
Reference official Microsoft documentation URLs instead of embedding CLI command syntax
Azure Authentication
Additional Resources
Network Isolation Errors
Applies to any call against a Foundry project or its parent Foundry account — Foundry MCP tools, azd, az CLI, curl, REST, or SDK.
If an error matches Public access is disabled / PublicNetworkAccessDisabled / 403 Forbidden from a private endpoint / connection timeout / the project endpoint FQDN resolves to a public IP, this typically means the parent Foundry account has publicNetworkAccess=Disabled or Enabled from selected IP addresses, and the current shell is outside its VNet.
Only if the error is ambiguous, confirm against the Foundry account using a management-plane call (works from anywhere with reader access):
az cognitiveservices account show \
--name <account> --resource-group <rg> \
--query "properties.{publicNetworkAccess:publicNetworkAccess, networkAcls:networkAcls, privateEndpointConnections:privateEndpointConnections[].properties.privateLinkServiceConnectionState.status}"publicNetworkAccess: "Disabled" — or "Enabled" together with non-empty networkAcls.ipRules / virtualNetworkRules — confirms isolation. If publicNetworkAccess: "Enabled" and networkAcls is empty, the failure is a caller-side network issue (e.g. Private DNS resolving the FQDN to a public IP from inside a VNet with a private endpoint), not an account-config issue.
If it's indeed a network isolation issue, supported connection options are documented in Choose a secure connection method to Foundry.
ℹ️ Foundry MCP tools cannot reach a VNet-isolated project even from inside the VNet.
Files
- .gitignore0 B
- ATTRIBUTION.mdAdded by AutoGineer983 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md30.4 KiB
- foundry-agent/agent-optimizer/agent-optimizer.md3.3 KiB
- foundry-agent/agent-optimizer/references/azd-setup.md1.2 KiB
- foundry-agent/agent-optimizer/references/eval-yaml.md3.2 KiB
- foundry-agent/agent-optimizer/references/optimize-workflow.md2.1 KiB
- foundry-agent/agent-optimizer/references/python-patterns.md4.0 KiB
- foundry-agent/agent-optimizer/references/scaffold.md3.3 KiB
- foundry-agent/azd-guidance/azd-guidance.md1.2 KiB
- foundry-agent/azd-guidance/references/azd-ai-cli.md10.3 KiB
- foundry-agent/cicd/cicd.md301 B
- foundry-agent/create/create-hosted.md33.8 KiB
- foundry-agent/create/create-managed-harness.md7.2 KiB
- foundry-agent/create/create-prompt.md4.6 KiB
- foundry-agent/create/create-voice.md13.1 KiB
- foundry-agent/create/quick-start-hosted.md23.6 KiB
- foundry-agent/create/references/enable-incoming-a2a.md3.7 KiB
- foundry-agent/create/references/foundry-model.md1.6 KiB
- foundry-agent/create/references/foundry-tool-catalog.md42.9 KiB
- foundry-agent/create/references/guardrails/guardrail-api-create.md3.8 KiB
- foundry-agent/create/references/guardrails/guardrail-attach.md3.8 KiB
- foundry-agent/create/references/guardrails/guardrail-manage.md2.1 KiB
- foundry-agent/create/references/hosted-voice-yaml.md1.7 KiB
- foundry-agent/create/references/langchain-langgraph-hosting.md2.2 KiB
- foundry-agent/create/references/local-run.md11.5 KiB
- foundry-agent/create/references/managed-harness-agent.md3.5 KiB
- foundry-agent/create/references/re-host.md2.6 KiB
- foundry-agent/create/references/sdk-operations.md2.2 KiB
- foundry-agent/create/references/skills/managed-harness-agent-skill-attach.md1.3 KiB
- foundry-agent/create/references/skills/skill-attach.md7.0 KiB
- foundry-agent/create/references/skills/skill-manage.md5.4 KiB
- foundry-agent/create/references/skills/skill-toolbox-attach.md5.1 KiB
- foundry-agent/create/references/tools/managed-harness-agent/agent-tools.md1.8 KiB
- foundry-agent/create/references/tools/managed-harness-agent/tool-a2a.md1.1 KiB
- foundry-agent/create/references/tools/managed-harness-agent/tool-azure-ai-search.md1.2 KiB
- foundry-agent/create/references/tools/managed-harness-agent/tool-code-interpreter.md391 B
- foundry-agent/create/references/tools/managed-harness-agent/tool-fabric-iq.md1.1 KiB
- foundry-agent/create/references/tools/managed-harness-agent/tool-file-search.md526 B
- foundry-agent/create/references/tools/managed-harness-agent/tool-github-copilot-toolset.md1.2 KiB
- foundry-agent/create/references/tools/managed-harness-agent/tool-mcp.md1.7 KiB
- foundry-agent/create/references/tools/managed-harness-agent/tool-openapi.md1.2 KiB
- foundry-agent/create/references/tools/managed-harness-agent/tool-toolbox.md2.1 KiB
- foundry-agent/create/references/tools/managed-harness-agent/tool-web-search.md387 B
- foundry-agent/create/references/tools/managed-harness-agent/tool-work-iq.md1.3 KiB
- foundry-agent/create/references/tools/prompt-agent/agent-tools.md4.5 KiB
- foundry-agent/create/references/tools/prompt-agent/tool-a2a.md675 B
- foundry-agent/create/references/tools/prompt-agent/tool-azure-ai-search.md3.3 KiB
- foundry-agent/create/references/tools/prompt-agent/tool-bing-grounding.md2.8 KiB
- foundry-agent/create/references/tools/prompt-agent/tool-code-interpreter.md1.0 KiB
- foundry-agent/create/references/tools/prompt-agent/tool-fabric-iq.md1.9 KiB
- foundry-agent/create/references/tools/prompt-agent/tool-file-search.md2.6 KiB
- foundry-agent/create/references/tools/prompt-agent/tool-function-calling.md842 B
- foundry-agent/create/references/tools/prompt-agent/tool-mcp.md3.4 KiB
- foundry-agent/create/references/tools/prompt-agent/tool-memory.md4.8 KiB
- foundry-agent/create/references/tools/prompt-agent/tool-openapi.md1.5 KiB
- foundry-agent/create/references/tools/prompt-agent/tool-web-search.md3.6 KiB
- foundry-agent/create/references/tools/prompt-agent/tool-work-iq.md1.7 KiB
- foundry-agent/create/references/use-toolbox-in-hosted-agent.md10.4 KiB
- foundry-agent/create/references/voice-agent-common.md1.6 KiB
- foundry-agent/create/references/voice-agent-hosted-bridge.md8.1 KiB
- foundry-agent/create/references/voice-agent-prompt-yaml.md3.9 KiB
- foundry-agent/create/references/voice-agent-settings.md5.8 KiB
- foundry-agent/create/references/voice-agent-smoke-test.md7.8 KiB
- foundry-agent/create/scripts/check-copilot-app-entry.ps1Script5.5 KiB
- foundry-agent/create/scripts/check-copilot-app-entry.shScript4.2 KiB
- foundry-agent/create/scripts/resolve-project-id.ps1Script5.8 KiB
- foundry-agent/create/scripts/resolve-project-id.shScript9.0 KiB
- foundry-agent/create/scripts/smoke-test-voice.ps1Script2.6 KiB
- foundry-agent/create/scripts/smoke-test-voice.shScript966 B
- foundry-agent/create/scripts/smoke_test_voice.pyScript14.5 KiB
- foundry-agent/create/scripts/verify-environment.ps1Script8.2 KiB
- foundry-agent/create/scripts/verify-environment.shScript6.5 KiB
- foundry-agent/deploy/deploy.md25.7 KiB
- foundry-agent/deploy/references/container-deploy.md2.1 KiB
- foundry-agent/deploy/references/voice-deploy.md2.2 KiB
- foundry-agent/eval-datasets/eval-datasets.md11.2 KiB
- foundry-agent/eval-datasets/references/dataset-comparison.md4.7 KiB
- foundry-agent/eval-datasets/references/dataset-curation.md4.1 KiB
- foundry-agent/eval-datasets/references/dataset-organization.md4.7 KiB
- foundry-agent/eval-datasets/references/dataset-versioning.md7.3 KiB
- foundry-agent/eval-datasets/references/eval-lineage.md4.0 KiB
- foundry-agent/eval-datasets/references/eval-regression.md6.9 KiB
- foundry-agent/eval-datasets/references/eval-trending.md4.8 KiB
- foundry-agent/eval-datasets/references/generate-seed-dataset.md8.7 KiB
- foundry-agent/eval-datasets/references/trace-to-dataset.md17.0 KiB
- foundry-agent/insights/insights.md4.5 KiB
- foundry-agent/insights/references/tool-contract.md3.4 KiB
- foundry-agent/invocations-ws/invocations-ws.md10.4 KiB
- foundry-agent/invocations-ws/references/invocations-ws-protocol.md7.8 KiB
- foundry-agent/invoke/invoke.md11.8 KiB
- foundry-agent/invoke/references/file-operations.md2.8 KiB
- foundry-agent/invoke/references/invocations-protocol.md3.4 KiB
- foundry-agent/invoke/references/session-management.md3.6 KiB
- foundry-agent/observe/observe.md15.3 KiB
- foundry-agent/observe/references/analyze-results.md6.3 KiB
- foundry-agent/observe/references/cicd-monitoring.md3.6 KiB
- foundry-agent/observe/references/compare-iterate.md3.3 KiB
- foundry-agent/observe/references/continuous-eval.md15.1 KiB
- foundry-agent/observe/references/deploy-and-setup.md5.5 KiB
- foundry-agent/observe/references/evaluate-step.md8.5 KiB
- foundry-agent/observe/references/evaluation-suite-generation.md12.3 KiB
- foundry-agent/observe/references/optimize-deploy.md1.5 KiB
- foundry-agent/routine/references/azure-yaml.md2.6 KiB
- foundry-agent/routine/references/cli-crud.md6.0 KiB
- foundry-agent/routine/routine.md8.0 KiB
- foundry-agent/toolbox/references/mcp-protocol.md3.2 KiB
- foundry-agent/toolbox/references/test-endpoint.md6.4 KiB
- foundry-agent/toolbox/references/tool-a2a.md2.2 KiB
- foundry-agent/toolbox/references/tool-azure-ai-search.md7.0 KiB
- foundry-agent/toolbox/references/tool-browser-automation.md3.5 KiB
- foundry-agent/toolbox/references/tool-code-interpreter.md3.5 KiB
- foundry-agent/toolbox/references/tool-fabric-iq.md4.4 KiB
- foundry-agent/toolbox/references/tool-file-search.md4.1 KiB
- foundry-agent/toolbox/references/tool-mcp-agent-identity.md7.8 KiB
- foundry-agent/toolbox/references/tool-mcp-custom-oauth-azure-starter.md4.0 KiB
- foundry-agent/toolbox/references/tool-mcp-custom-oauth.md7.9 KiB
- foundry-agent/toolbox/references/tool-mcp-key-auth.md4.2 KiB
- foundry-agent/toolbox/references/tool-mcp-managed-oauth.md6.3 KiB
- foundry-agent/toolbox/references/tool-mcp-noauth.md3.9 KiB
- foundry-agent/toolbox/references/tool-mcp-user-entra-token.md5.2 KiB
- foundry-agent/toolbox/references/tool-openapi.md6.2 KiB
- foundry-agent/toolbox/references/tool-tool-search.md5.9 KiB
- foundry-agent/toolbox/references/tool-web-search.md3.1 KiB
- foundry-agent/toolbox/references/tool-work-iq.md7.6 KiB
- foundry-agent/toolbox/references/toolbox-azd.md6.1 KiB
- foundry-agent/toolbox/scripts/get-catalog-inputs.ps1Script12.7 KiB
- foundry-agent/toolbox/scripts/get-catalog-inputs.shScript13.0 KiB
- foundry-agent/toolbox/toolbox.md7.8 KiB
- foundry-agent/trace/references/analyze-failures.md3.9 KiB
- foundry-agent/trace/references/analyze-latency.md3.8 KiB
- foundry-agent/trace/references/conversation-detail.md3.7 KiB
- foundry-agent/trace/references/eval-correlation.md2.5 KiB
- foundry-agent/trace/references/kql-templates.md10.6 KiB
- foundry-agent/trace/references/search-traces.md6.8 KiB
- foundry-agent/trace/trace.md6.5 KiB
- foundry-agent/troubleshoot/troubleshoot.md8.7 KiB
- foundry-agent/validate/references/default-rules.yaml18.1 KiB
- foundry-agent/validate/references/report-schema.json3.3 KiB
- foundry-agent/validate/references/report-template.md.tpl2.8 KiB
- foundry-agent/validate/references/rules-schema.json2.5 KiB
- foundry-agent/validate/validate.md7.4 KiB
- project/connections.md3.1 KiB
- project/create/create-foundry-project.md8.4 KiB
- quota/quota.md9.0 KiB
- quota/references/capacity-planning.md8.2 KiB
- quota/references/error-resolution.md4.9 KiB
- quota/references/optimization.md7.6 KiB
- quota/references/ptu-guide.md6.2 KiB
- quota/references/troubleshooting.md7.3 KiB
- quota/references/workflows.md6.9 KiB
- rbac/rbac.md7.1 KiB
- references/agent-metadata-contract.md8.7 KiB
- references/auth-best-practices.md6.5 KiB
- references/standard-agent-setup.md4.2 KiB
- resource/create/create-foundry-resource.md6.1 KiB
- resource/create/references/patterns.md3.9 KiB
- resource/create/references/troubleshooting.md2.4 KiB
- resource/create/references/workflows.md6.7 KiB
- resource/private-network/private-network.md6.3 KiB
- resource/private-network/references/custom-template-adaptation.md1.6 KiB
- resource/private-network/references/deploy.md3.7 KiB
- resource/private-network/references/end-to-end-test.md4.1 KiB
- resource/private-network/references/intake.md6.5 KiB
- resource/private-network/references/post-deployment-validation.md3.7 KiB
- resource/private-network/references/scaffold.md1.7 KiB
- resource/private-network/references/template-index.md1.6 KiB
- resource/private-network/references/vpn-dns-setup.bicep4.5 KiB
- resource/private-network/references/vpn-dns-setup.md6.4 KiB
- scripts/check-and-setup-dependencies.ps1Script1.2 KiB
- scripts/check-and-setup-dependencies.shScript845 B
foundry-agent/create/references/foundry-tool-catalog.md
Foundry Tool Catalog — Project Connections for Remote Tools
Reference for wiring a remote tool (catalog tile or generic MCP server) into a Foundry project as a RemoteTool project connection, so a toolbox can attach to it.
🚦 Toolbox creation gate: before creating a toolbox/connection, you MUST read the boundary rules in create-hosted.md → Toolbox creation boundary and follow them, then continue with the rest of this file.
Three catalog backends cooperate: the asset-gallery index discovers connectors, the Logic Apps managedApis GET supplies OAuth metadata, and the Logic Apps apiOperations GET supplies the operation list and input schemas. Skip these calls only for fully BYO generic_mcp servers — every catalog-MCP or connector-namespace flow needs all three.
📘 For the toolbox MCP endpoint, protocol, and testing, see use-toolbox-in-hosted-agent.md. 📘 For prompt-agent MCP wiring (without a toolbox), see tool-mcp.md.
When to use this reference
Use when the user mentions any of:
Build → Tools → Connect a tool (any subtab — Configured, Catalog, Custom)
"Tool connection", "Remote MCP", "Catalog tile", "Custom · Preview"
A specific catalog tile (GitHub, Box, Pipedrive, monday.com, Microsoft Learn, …)
RemoteToolconnection,gateway_connector,catalog_MCP,generic_mcpConnector Namespace / managed MCP server (powered by the Connector Namespace)
"Bring my own OAuth App" (BYO
client_id+client_secret) for a catalog connectorDiscovering connector operations (
x-ms-operations/ Logic AppsapiOperations) or trigger support (x-ms-trigger) via the catalog APIs
Do not use for: non-tool connections (Azure OpenAI, AI Search account, Storage), or general toolbox CRUD beyond the attach-and-verify recipe below.
Inputs to gather upfront
Before generating any PUT body, ask the user in one batched question for:
Subscription id
Resource group
Cognitive Services account name (the Foundry account)
Project name (under the account)
Connection name — lowercase,
[a-z0-9-], ≤ 24 chars (e.g.box-1,gh-byo)Tool scenario in plain language — e.g. "list my files in Box", "create issues on GitHub". Map this onto operations from the connector's
apiOperationscatalog forgateway_connector, or onto the catalog MCP server'stools/listforcatalog_MCP/ BYO.Toolbox name to attach into for verification (defaults to
default-tb)Secrets (BYO
clientId/clientSecret,CustomKeysheader value, …) — ask the user to type these directly into the terminal, never via tooling that echoes them
The caller's AAD oid / tid (needed only for the consent-link step) are auto-discovered via az ad signed-in-user show --query id -o tsv and az account show --query tenantId -o tsv. For a service-principal caller, use az ad sp show --id <appId> instead. These values can also be read from the oid / tid claims on the ARM bearer token; the gateway validates the caller principal owns them.
ARM endpoint (shared by every variant)
PUT https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}
/providers/Microsoft.CognitiveServices/accounts/{acct}
/projects/{proj}/connections/{name}?api-version=2025-04-01-previewPreflight RBAC
Caller needs Foundry Project Manager or Cognitive Services Contributor on the project scope. Run this before the first PUT to surface 403s early:
$oid = az ad signed-in-user show --query id -o tsv
$projId = "/subscriptions/$sub/resourceGroups/$rg/providers/Microsoft.CognitiveServices/accounts/$acct/projects/$proj"
az role assignment list --assignee $oid --scope $projId --include-inherited --all `
--query "[?roleDefinitionName=='Foundry Project Manager' || roleDefinitionName=='Cognitive Services Contributor'].roleDefinitionName" -o tsvEmpty output → caller lacks the required role; expect 403 AuthorizationFailed on PUT until granted.
Common request template
$tok = az account get-access-token --resource "https://management.azure.com" --query accessToken -o tsv
$h = @{ Authorization = "Bearer $tok"; "Content-Type" = "application/json" }
$uri = "https://management.azure.com/subscriptions/$sub/resourceGroups/$rg/providers/Microsoft.CognitiveServices/accounts/$acct/projects/$proj/connections/${connName}?api-version=2025-04-01-preview"
Invoke-WebRequest -Method PUT -Headers $h -UseBasicParsing -Body $body -Uri $uriBody invariants
properties.targetis required for everyauthType(validation rejects empty). The exact value depends on the variant — see each body shape. Forgateway_connectorspecifically, the literal string"https://placeholder"is the correct value on PUT #1 and is rewritten by the platform on PUT #2 to the real gateway URL.properties.groupis server-filled (GenericProtocolforRemoteTool).properties.credentialsis scrubbed tonullon GET.properties.peRequirementdefaults to"NotRequired".
Allowed authType for category=RemoteTool (per api-version=2025-04-01-preview):
None, CustomKeys, OAuth2, ProjectManagedIdentity, DeveloperConnection, UserEntraToken, AgentUserImpersonation, AgenticIdentityToken, AgenticUser, UserTokenAndProjectManagedIdentity. ApiKey is rejected for RemoteTool. The authoritative list is whatever the Cognitive Services projects API reference returns for the current API version — if you hit invalid_payload: unsupported authType, re-check against the schema for the version you're calling.
Decision tree
| User scenario | authType | metadata.type | Notes |
|---|---|---|---|
| Catalog tile tagged "Custom · Preview" (Box, Pipedrive, GitHub, Salesforce, Outlook, …) | OAuth2 | gateway_connector | Connector-namespace managed MCP. Powered by the Connector Namespace in your Foundry account; the namespace handles OAuth, token storage, and per-user passthrough. Needs two PUTs plus listConsentLinks per caller (see Gateway connector full flow). |
Catalog MCP tile with Microsoft-managed OAuth (no client_id needed) | OAuth2 | catalog_MCP | Foundry brokers the OAuth app for you. The Catalog API tile prepopulates target (server URL); listConsentLinks flow same as gateway. |
| Catalog MCP tile with your own OAuth App | OAuth2 | (omit) | Supply your own client_id + client_secret + raw authorizationUrl / tokenUrl / scopes. Do not mix BYO credentials with metadata.type=catalog_MCP. See BYO OAuth caveats. |
| Remote MCP, Azure-side identity (project MI calls the server) | ProjectManagedIdentity | catalog_MCP (when listed) or generic_mcp | For catalog-listed MCP servers, prefer catalog_MCP so target is prepopulated. Requires audience in metadata. See PMI limitations. |
| Remote MCP, static shared secret / header key | CustomKeys | catalog_MCP (when listed) or generic_mcp | Header name and format are NOT always Authorization: Bearer .... Read the required header name from the Catalog API entry's x-ms-connection-parameters and use that exact name in credentials.keys. |
| Remote MCP, user's Entra token forwarded | UserEntraToken | generic_mcp | Per-user identity passthrough. Not supported when the agent is published to Teams. Pair with metadata.audience for the upstream resource URI. |
| Custom OpenAPI / A2A tool (no MCP) | varies | n/a | Use the Custom subtab shapes; outside the MCP toolbox path. See Custom subtab — OpenAPI / A2A. |
Catalog APIs — three backends, three calls
There are three read endpoints the portal hits to populate a connection form. Programmatic callers should use the same three.
1. Asset-gallery (Foundry's index)
POST https://eastus.api.azureml.ms/asset-gallery/v1.0/tools
Headers:
Authorization: Bearer <token for https://management.azure.com>
Content-Type: application/json
Body:
{
"freeTextSearch": "*",
"filters": [
{ "field": "entityContainerId", "operator": "eq", "values": ["connectors-registry-prod-bl"] },
{ "field": "type", "operator": "eq", "values": ["tools"] },
{ "field": "annotations/name", "operator": "contains", "values": ["<name>"] }
],
"pageSize": 20
}Catalog lives only in
eastus.westus2.api.azureml.msreturnstotalCount=0for the same body.entityIds are portable across project regions.Use this only to discover the connector's
entityId— pullobjectIdout of the returnedentityId(e.g.…/objectId/github). ThatobjectIdis theconnectorNameyou pass to PUTs and the next two catalog calls.The response is a thin index.
properties.remotes[],xMsSecuritySchemes, OAuth endpoints, scopes, and operation schemas are not included. DirectGET /asset-gallery/v1.0/tools/{entityId}returns 404. There is no expand/projection flag that surfaces these fields — fetch them from calls 2 and 3 below.
Two registries are indexed here — distinguished by entityContainerId:
| Registry | entityContainerId | Contents | Pair with |
|---|---|---|---|
| Public catalog | connectors-registry-prod-bl | Catalog connector definitions (GitHub, Box, Salesforce, …). | metadata.type=catalog_MCP or gateway_connector |
| Private MCP entries | registry-prod-bl | MCP-server entries used by the portal Connections UI (e.g. github-mcp-server). Sometimes carries a canonical MCP URL when the public-catalog row lacks remotes[]. | metadata.type=catalog_MCP |
Always query both when surfacing "available tools" to a user — the private MCP entries can fill gaps in the public catalog row.
2. Logic Apps managedApis — OAuth source-of-truth
GET https://management.azure.com/subscriptions/{sub}
/providers/Microsoft.Web/locations/{region}/managedApis/{connectorName}
?api-version=2016-06-01connectorName is the objectId from the asset-gallery entityId. Verified response shape for github (2026-05-21):
{
"properties": {
"displayName": "GitHub",
"runtimeUrls": ["https://logic-apis-eastus.azure-apim.net/apim/github"],
"connectionParameters": {
"token": {
"type": "oauthSetting",
"oAuthSettings": {
"identityProvider": "GitHub",
"clientId": "faa5f56b825cbc649ae1", // Microsoft's default OAuth-App id
"scopes": ["repo","workflow","read:org","admin:org"],
"redirectMode": "Direct",
"redirectUrl": "https://logic-apis-eastus.consent.azure-apim.net/redirect"
}
}
}
}
}Raw authorizationUrl / tokenUrl are NOT in this response. Logic Apps abstracts them via the identityProvider string and resolves them inside the gateway. For BYO you must map identityProvider → endpoints yourself. Known mappings:
identityProvider | authorizationUrl | tokenUrl |
|---|---|---|
GitHub | https://github.com/login/oauth/authorize | https://github.com/login/oauth/access_token |
Google | https://accounts.google.com/o/oauth2/v2/auth | https://oauth2.googleapis.com/token |
Box | https://account.box.com/api/oauth2/authorize | https://api.box.com/oauth2/token |
AzureActiveDirectory / aad3rdPartySNI | https://login.microsoftonline.com/common/oauth2/v2.0/authorize | https://login.microsoftonline.com/common/oauth2/v2.0/token |
For identityProvider values not in this table (dynamicscrmonlinecertificate, salesforce, dropbox, oauth2generic, …), look the provider's well-known OAuth endpoints up in its developer docs — the catalog API does not surface them.
Use the scopes array from this response as the default scopes list. The catalog clientId is Microsoft's default OAuth App; replace it with your own only when going BYO.
Derive authType from connectionParameters:
Any parameter with
type: oauthSetting→authType = OAuth2.Else any parameter with
type: securestring→authType = CustomKeys.Else →
authType = None(anonymous) orProjectManagedIdentityif the connector explicitly supports MI.
3. Logic Apps apiOperations — operation catalog (gateway_connector only)
For gateway_connector you need the list of operations the connector exposes plus each operation's parameter schema, because that's what gets serialized into metadata.mcpserverConfigProperties on PUT #2. Asset-gallery does not carry this.
GET https://management.azure.com/subscriptions/{sub}
/providers/Microsoft.Web/locations/{region}/managedApis/{connectorName}
/apiOperations?api-version=2016-06-01Returns value[] of operations with name, properties.summary (display name), properties.description, properties.annotation.family, and properties.visibility (important / advanced / internal). Verified 2026-05-21: Box returns 14 operations including ListRootFolder, ListFolder, GetFileMetadata, GetFileContent, DeleteFile, CreateFile, plus several On* triggers (not agent-callable).
To get parameter schemas, fetch a single operation with $expand=properties/inputsDefinition:
GET .../managedApis/{connectorName}/apiOperations/{operationName}
?api-version=2016-06-01&$expand=properties/inputsDefinitionproperties.inputsDefinition is a JSON-Schema-shaped object with type:"object", properties:{...}, and required:[...]. Map each entry to one agentParameters entry:
inputsDefinition.properties[name] field | → agentParameters[].schema field |
|---|---|
type | type |
description | description |
title | x-ms-summary |
default | default (omit if absent) |
If inputsDefinition.properties is empty / missing, the operation takes no arguments and agentParameters is [] (e.g. Box ListRootFolder).
Skip any operation whose properties.isWebhook or isNotification is true — these are Logic Apps triggers, not agent-callable actions.
Picking ops from a plain-language scenario. Match the user's words against properties.summary and properties.description, then prefer the simplest variant (fewest required parameters) and the one whose annotation.family aligns with the user intent. For Box "list my files", ListRootFolder (zero params) wins over ListFolder (requires id); if the user asks to list a specific folder, register both.
Gateway connector full flow
For Catalog tiles tagged Custom · Preview (Box, Pipedrive, GitHub, Salesforce, Outlook, iManage Work, PDF4me, Qdrant, Medallia, Fulcrum, monday.com, SuperMCP, IA-Connect JML, iMIS, Huddo Boards, The Events Calendar, PUG Gamified Engagement, Nitro Sign Enterprise Verified, Soft1, Elfsquad Product Configurator, MintNFT, …).
Step 1 — Discover
Query the asset-gallery (call #1) for the connector. Extract:
objectIdfromentityId→connectorNameFull
entityId→metadata.toolEntityId
Then call managedApis (call #2) and apiOperations (call #3) for OAuth and operation metadata.
Step 2 — PUT #1 (create connection)
Verbatim PUT body (captured from the portal's Box wizard, 2026-05-21):
{
"properties": {
"authType": "OAuth2",
"category": "RemoteTool",
"target": "https://placeholder",
"credentials": {},
"connectorName": "box",
"metadata": {
"type": "gateway_connector",
"toolEntityId": "azureml://location/eastus/apiCenter/connectors-registry-prod-bl/type/tools/objectId/box/version/1",
"connectionproperties": "{\"connectorName\":\"box\"}"
}
}
}Spelling traps (case-sensitive):
toolEntityId— NOTentityId.connectionproperties— lowercase, value is a stringified JSON object, not a nested object."{\"connectorName\":\"box\"}"is correct;{"connectorName":"box"}is rejected.connectorNameappears at top-level underpropertiesand insidemetadataand insideconnectionproperties.
target = "https://placeholder" is the persisted value on PUT #1, not a stub. There is no follow-up call that rewrites it before PUT #2. Runtime dispatch keys off metadata.toolEntityId + metadata.connectionproperties.connectorName + OAuth consent state. PUT #2 (register-actions) rewrites target to the real gateway URL https://app-XX.<region>.logic.azure.com/api/connectorGateways/{envId}/mcpServerConfigs/{connectionName}/mcp.
Step 3 — Per-caller consent
For every distinct end-user (or service principal), call listConsentLinks:
POST .../connections/{name}/listConsentLinks?api-version=2025-04-01-previewVerbatim portal body:
{
"parameters": [{
"objectId": "<caller AAD oid>",
"parameterName": "token",
"redirectUrl": "https://ai.azure.com/nextgen/authConsentPopup",
"tenantId": "<caller AAD tid>"
}]
}Notes:
The portal sends
redirectUrl=https://int.ai.azure.com/...from the INT environment; for production (ai.azure.com) usehttps://ai.azure.com/nextgen/authConsentPopup. The redirect URL only gates which Foundry origin the OAuth popup closes back into — it does not affect what tokens are minted.Returns a per-user OAuth authorization URL (e.g. a
box.com/api/oauth2/authorize?...link). User navigates → consents → gateway stores the token.Cross-tenant calls return
InvalidConsentLinkParameter(objectId+tenantIdmust match the caller principal).
Consent link expiry (~1 hour)
Each listConsentLinks response mints a short-lived signed token (≈ 1 hour TTL based on ExpirationTime in the base64 payload). A 500 from the consent host when clicking the link is most often caused by an expired or stale link, not a server outage. Fix: call listConsentLinks again to get a fresh link and use it immediately. Do not reuse a link from a previous step or previous session.
Portal popup lifecycle (pending-true happy path)
The portal pre-opens a blank popup (about:blank) before calling listConsentLinks, then drives the flow as follows once the consent URL is in hand. Code-first callers should replicate this:
Register listeners on
window.postMessageandBroadcastChannel('connector-oauth-callback')to receive completion signals.Navigate the popup to the consent URL.
Poll
popup.closedevery 1 second to detect finish / dismiss.When the popup closes, wait 500 ms grace for any in-flight postMessage / BroadcastChannel messages.
If a
{ pending: true }signal arrives (consent completed server-side but no authorization code returned to the opener):Issue a PUT to the connection (same body as the original create PUT) to prompt the backend to finalise auth state.
If
overallStatusisConnectedin the response, done ✅.Otherwise poll
GET .../connections/{name}every 2 seconds, up to 15 attempts, untiloverallStatusflips toConnected.
If no signal before popup close, treat as user-cancelled and surface an error.
Cleanup: remove listeners, clear polling, force-close the popup if still open.
The { pending: true } path is the normal happy-path because the provider closes the popup by redirecting to ai.azure.com/nextgen/authConsentPopup, which has no JavaScript opener to post back to. Don't assume consent is done just because the popup closed. The "blank Foundry page" seen after authorising in a detached tab is this same redirect arriving without an opener — the gateway token is still stored; retry PUT #2 to confirm.
Consent-host hosts
Links served from logic-apis-df.consent.azure-apim.net are the dogfood / INT consent host (DF = dogfood). Production region traffic goes through logic-apis-{region}.consent.azure-apim.net (e.g. logic-apis-eastus.consent.azure-apim.net). Either host can return DF links depending on which Logic Apps environment the connector is deployed in; the caller cannot force the host.
Dogfood OAuth-app runtime allowlist trap
Some connectors (Spotify spotifyip confirmed) are backed by a dogfood-env Microsoft OAuth app registered in provider "development mode" with a hard-coded test-user allowlist. Consent + Connected status work fine code-first for any caller, but tools/call at runtime returns:
{ "error": { "code": 403, "source": "...logic-df.azure-apihub.net",
"innerError": "Check settings on https://developer.spotify.com/dashboard, the user may not be registered." } }Detect by inspecting the consent URL's first 302: if the redirect_uri is https://global-test.consent.azure-apim.net/redirect (rather than global.consent...), the connector is on the dogfood OAuth app. The connection will still go Connected and tools/list will work; only the actual API invocation fails. Not fixable client-side; requires Microsoft to promote the app or add the caller's email to the provider-side allowlist.
$consentUrl = ($r.Content | ConvertFrom-Json).value[0].link
try { Invoke-WebRequest -Uri $consentUrl -MaximumRedirection 0 -ErrorAction Stop | Out-Null }
catch { $loc = $_.Exception.Response.Headers.Location.ToString() }
if ($loc -match 'global-test\.consent\.azure-apim\.net') {
Write-Warning "Connector uses dogfood OAuth app; tools/call may 403 with 'user may not be registered' even after Connected."
}Step 4 — PUT #2 (register actions)
After OAuth, the portal issues a second PUT against the same connection name to register which connector operations the agent can invoke. Without this PUT the runtime has no actions to dispatch even though overallStatus shows Authenticated.
The body is identical to PUT #1 plus an additional metadata.mcpserverConfigProperties field (stringified JSON). Verbatim example for Box connection box-5:
{
"properties": {
"authType": "OAuth2",
"category": "RemoteTool",
"target": "https://placeholder",
"credentials": {},
"connectorName": "box",
"metadata": {
"type": "gateway_connector",
"toolEntityId": "azureml://location/eastus/apiCenter/connectors-registry-prod-bl/type/tools/objectId/box/version/1",
"connectionproperties": "{\"connectorName\":\"box\"}",
"mcpserverConfigProperties": "{\"description\":\"\",\"state\":\"Enabled\",\"connectors\":[{\"name\":\"box\",\"connectionName\":\"box-5\",\"displayName\":\"box\",\"description\":\"\",\"operations\":[{\"name\":\"GetFileMetadata\",\"displayName\":\"Get file metadata using id\",\"description\":\"\",\"userParameters\":[],\"agentParameters\":[{\"name\":\"id\",\"schema\":{\"type\":\"string\",\"description\":\"The unique identifier of the file in Box.\",\"x-ms-summary\":\"File Id\"}}]}]}]}"
}
}
}Decoded mcpserverConfigProperties schema:
{
"description": "",
"state": "Enabled",
"connectors": [
{
"name": "<connectorName>", // same as properties.connectorName
"connectionName": "<this connection name>",
"displayName": "<connectorName>",
"description": "",
"operations": [
{
"name": "<OperationId>", // operation id from apiOperations
"displayName": "<friendly>",
"description": "",
"userParameters": [], // bound at connection time (rare for Custom·Preview)
"agentParameters": [ // parameters the agent fills at call time
{
"name": "<paramName>",
"schema": {
"type": "string|number|boolean",
"description": "...",
"x-ms-summary": "...",
"default": "..." // optional
}
}
]
}
]
}
]
}Each operation in operations[] corresponds 1:1 to one apiOperations entry; agentParameters[].schema is translated from inputsDefinition.properties per the mapping in Catalog APIs §3.
The portal lets the user multi-select via checkboxes in the wizard's "Configure actions" page; the selection is serialized into this string. When the selection changes later, the portal replaces mcpserverConfigProperties wholesale — no merge. Your code must do the same: any time the agent-callable op list changes, re-run PUT #2 with the full new list.
Step 5 — overallStatus flip semantics
Two independent conditions must BOTH be true for overallStatus to flip Unauthenticated → Connected:
PUT #2 issued with non-empty
metadata.mcpserverConfigProperties(rewritestargetto the real gateway URL; target rewrite is visible immediately on PUT #2 regardless of consent state).OAuth consent completed (user followed the
listConsentLinksURL and clicked Authorize). Gateway then stores the token.
Order-independent observations:
PUT #2 before consent →
targetrewrites, status staysUnauthenticated.Consent before PUT #2 → status stays
Unauthenticateduntil PUT #2 fires; PUT #2 then flips toConnectedin the same response.
Body shape — OAuth2 + catalog_MCP (Microsoft-managed OAuth)
Use when the catalog entry is an MCP server and you accept Microsoft's managed OAuth App + consent flow (no BYO secret):
{
"properties": {
"authType": "OAuth2",
"category": "RemoteTool",
"target": "https://api.githubcopilot.com/mcp",
"credentials": {},
"metadata": {
"type": "catalog_MCP",
"toolEntityId": "azureml://location/eastus/apiCenter/connectors-registry-prod-bl/type/tools/objectId/github/version/1"
},
"peRequirement": "NotRequired"
}
}For MCP URL discovery when connectors-registry-prod-bl lacks remotes[], look up the peer entry in registry-prod-bl (e.g. github-mcp-server) — its asset-gallery row sometimes carries the canonical MCP URL. Consent uses the same listConsentLinks flow as gateway_connector.
BYO OAuth App against a catalog MCP server
When the user has their own OAuth App (e.g. GitHub https://github.com/organizations/<org>/settings/applications/<app-id>) and wants the connection to mint tokens via their app instead of Microsoft's managed one. Verified shape, 2026-05-21:
{
"properties": {
"authType": "OAuth2",
"category": "RemoteTool",
"target": "<MCP server URL>",
"credentials": { "clientId": "<your client id>", "clientSecret": "<your client secret>" },
"authorizationUrl": "https://github.com/login/oauth/authorize",
"tokenUrl": "https://github.com/login/oauth/access_token",
"scopes": ["repo","workflow","read:org","admin:org"],
"peRequirement": "NotRequired"
}
}Filling the OAuth fields from the catalog APIs
Find the connector
entityId— asset-gallery POST withannotations/name contains <name>. PullobjectIdout of the returnedentityId.Look up OAuth metadata —
GET .../managedApis/<objectId>?api-version=2016-06-01. Fromproperties.connectionParameters.token.oAuthSettings:identityProvider→ look upauthorizationUrl/tokenUrlin the mapping table in Catalog APIs §2.scopes→ use as the default scopes array (override only if the user explicitly needs different scopes).
Supply your own
clientId/clientSecretincredentials. Do not reuse the catalogclientIdfrom step 2 — that's Microsoft's managed OAuth App and you cannot mint with it.PUT the body above.
Hard rules verified by probe (2026-05-21)
scopesMUST be a JSON array. A space-separated string returns400 "Error when parsing request; unable to deserialize request body".DO NOT send
useCustomConnector. It is ignored on input; server fillsfalse.DO NOT send
metadata.{type=catalog_MCP, toolEntityId, ...}for BYO. Those fields anchor the connection to the catalog's managed OAuth App and conflict with your suppliedcredentials.DO NOT call
listConsentLinksfor BYO — the gateway handles consent via the standard authorization_code flow using the server-filledredirectUrl. CallinglistConsentLinksagainst a fresh BYO connection returns404 AIGatewayConnectionNotFound.
Server-filled response fields
credentials→null(scrubbed).connectorName→<gatewayId>-<connectionName>(your input ignored).redirectUrl→https://global.consent.azure-apim.net/redirect/<32-hex>— the OAuth callback URL the provider (e.g. GitHub OAuth App) must allow-list. Generated per-connection on first PUT. Two-pass flow:PUT with placeholder client_secret.
Read
properties.redirectUrlfrom the response.Register it as the "Authorization callback URL" on the OAuth App.
PUT again with the real client_secret.
Caveat: api.githubcopilot.com/mcp rejects BYO OAuth-App tokens
The GitHub Copilot MCP server requires GitHub-App-minted Copilot tokens (the microsoft-foundry-agent-service GitHub App). A token from a user OAuth App will be rejected at runtime even if the connection PUT is 200. For real BYO testing point target at a self-hosted GitHub MCP server, or use an OpenAPI tool against api.github.com instead.
ProjectManagedIdentity Remote MCP
For MCP servers that accept Azure-side identity (the project's system MI calls the MCP server's bearer endpoint):
{
"properties": {
"authType": "ProjectManagedIdentity",
"category": "RemoteTool",
"target": "<MCP server URL with required query string>",
"metadata": { "type": "generic_mcp", "audience": "<upstream resource URI>" }
}
}For catalog-listed MCP servers, prefer metadata.type = catalog_MCP with toolEntityId so target is prepopulated. audience is required for MI auth — it tells Foundry which resource URI to request a token for. Read the required audience from the connector's catalog entry or its documentation (typical values: an app ID URI like api://contoso-mcp, or an Azure service resource ID like https://cognitiveservices.azure.com). If you omit audience, the MCP server rejects the call with 401.
ProjectManagedIdentity limitations
Verified end-to-end against Azure Language /language/mcp, 2026-05-21:
Forwarder drops the query string. The connection
target's?api-version=...is not preserved on the upstream call. If the upstream MCP requires a query parameter, PMI fails with 401/404 even when RBAC is correct.Forwarder mints the wrong audience. The MI token Foundry sends does not have
aud=https://cognitiveservices.azure.comorhttps://ai.azure.com. Settingproperties.audienceon the connection is accepted but does not change what is minted.Endpoints not on the trust list reject the forwarded MI token with
-32007 PERMISSION_DENIED "Cannot pass Microsoft token to untrusted MCP endpoint"(e.g.api.githubcopilot.com/mcp). This is the expected security gate.
CustomKeys Remote MCP
Static header(s) injected on every upstream call. Minimum body:
{
"properties": {
"authType": "CustomKeys",
"category": "RemoteTool",
"target": "<MCP server URL>",
"credentials": { "keys": { "Ocp-Apim-Subscription-Key": "<value>" } },
"metadata": { "type": "generic_mcp" }
}
}Verified PUT 200 / GET 200 / DELETE 200 round-trip. The header name is arbitrary — it is forwarded as-is to the MCP server. Different connectors require different header shapes:
GitHub PAT:
Authorization: Bearer <pat>orAuthorization: token <pat>— catalog dictates.API-key services:
x-api-key: <key>orOcp-Apim-Subscription-Key: <key>.Multi-header schemes: e.g.
X-Account-Id: <id>+X-Account-Secret: <secret>.
Always read the canonical header set from the connector's connectionParameters (each securestring parameter names the header it maps to) before writing the keys block. Do not default to Authorization: Bearer — it's wrong for many connectors.
For catalog-listed servers, swap metadata.type to catalog_MCP and add toolEntityId.
UserEntraToken Remote MCP
For MCP servers that consume the caller's Entra token directly. Body includes metadata.audience so the platform mints the correct token for the upstream:
{
"properties": {
"authType": "UserEntraToken",
"category": "RemoteTool",
"target": "<MCP server URL>",
"metadata": { "type": "generic_mcp", "audience": "<upstream resource URI>" }
}
}Not available when the agent is published to Teams (Teams agents use the project MI).
Custom subtab — OpenAPI / A2A
Not catalog-driven — the user provides the spec themselves. Each Save in this subtab maps to a single PUT against the same connections endpoint:
| Tile | authType options | target | Notes |
|---|---|---|---|
| OpenAPI | None, CustomKeys, ApiKey, OAuth2 | OpenAPI spec URL or upstream API base | Agent gets tools[].openapi.auth.security_scheme.connection_id. |
| A2A (Preview) | None / CustomKeys / UserEntraToken / AAD (mapped from UI) | A2A endpoint | metadata.agentCardPath default /.well-known/agent-card.json; agent gets tools=[A2APreviewTool(project_connection_id=...)]; runtime emits a2a_preview_call / a2a_preview_call_output events. |
| MCP | covered above | — | This tile is just a router to the catalog / BYO flows. |
Toolbox attach — gateway_connector tool naming
Attach the same as generic_mcp — the tool block uses type:"mcp" and project_connection_id set to the full ARM resource id of the connection (NOT just the name):
{
"tools": [{
"type": "mcp",
"server_label": "box5",
"project_connection_id":
"/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.CognitiveServices/accounts/{acct}/projects/{proj}/connections/{connName}"
}]
}tools/list returns one MCP tool per registered operation. Tool names follow the verified pattern (probed 2026-05-22 against Box):
<server_label>___<connectorName>_<OperationName>Note ___ (three underscores) between server_label and the rest, then a single _ between connectorName and operation name. Example for Box attached with server_label="box5":
mcpserverConfigProperties op | tools/list name | description |
|---|---|---|
ListRootFolder | box5___box_ListRootFolder | box - List files and folders in root folder |
GetFileMetadata | box5___box_GetFileMetadata | box - Get file metadata using id |
The MCP tool's inputSchema is exactly the JSON schema derived from apiOperations/{op}?$expand=properties/inputsDefinition (the agentParameters[].schema values, re-keyed by parameter name). For an operation with no agent parameters, inputSchema is {"type":"object"}.
Worked tools/call for "list my files in Box" — verified end-to-end:
POST {dp}/toolboxes/{tb}/mcp?api-version=v1
{
"jsonrpc": "2.0", "id": 2, "method": "tools/call",
"params": { "name": "box5___box_ListRootFolder", "arguments": {} }
}
→ 200
{
"jsonrpc": "2.0", "id": 2,
"result": {
"content": [{ "type": "text", "text": "[]" }],
"isError": false
}
}(text carries a JSON-stringified array of Box file/folder objects; empty [] means the root folder is empty.)
outlook connector — verified end-to-end (2026-05-22)
Uses identityProvider: oauth2generic (MSA / consumers tenant). connectorName = "outlook", toolEntityId objectId = outlook. tools/call response wraps in { "value": [...] } (not a bare array like Box):
POST {dp}/toolboxes/{tb}/mcp?api-version=v1
{
"jsonrpc": "2.0", "id": 2, "method": "tools/call",
"params": { "name": "outlook-1___outlook_GetEmailsV2",
"arguments": { "folderPath": "Inbox", "top": 3 } }
}
→ 200
{
"jsonrpc": "2.0", "id": 2,
"result": {
"content": [{ "type": "text",
"text": "{\n \"value\": [\n { \"Subject\": \"...\", \"From\": \"...\", ... }\n ]\n}" }],
"isError": false
}
}Operations registered for the test: GetEmailsV2 (read emails with folderPath / top / fetchOnlyUnread agent parameters) and SendEmailV2 (send with emailMessage object param containing required To, Subject, Body). SendEmailV2's top-level schema is object — pass it as a single nested agentParameters entry; the gateway flattens into the Logic Apps emailMessage envelope internally. The follow-up PUT after popup close (pending-true path) immediately returned overallStatus: Connected without needing the GET poll loop — outlook's MSA consent round-trips are fast.
Minimum attach + verify recipe
Verifying a fresh connection is the only toolbox operation in scope of this reference. Toolboxes are upserted implicitly by POST /versions; no separate container create is needed.
The $dp value below is the project's data-plane endpoint, in the same {project_endpoint} form used elsewhere in these references — https://<account>.services.ai.azure.com/api/projects/<project>. The host segment varies by Foundry account/region; read it from a non-FOUNDRY_-prefixed env var (see use-toolbox-in-hosted-agent.md § Set TOOLBOX_ENDPOINT) rather than hardcoding. The bearer-token resource is https://ai.azure.com, NOT ARM.
# 0. Constants.
$dp = $env:PROJECT_ENDPOINT # https://<account>.services.ai.azure.com/api/projects/<project>
$tb = "default-tb"
$lbl = "box5" # becomes the "<label>___" prefix on tool names
$connId = "/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.CognitiveServices/accounts/<acct>/projects/<proj>/connections/<connName>"
$tok = az account get-access-token --resource "https://ai.azure.com" --query accessToken -o tsv
$hdr = @{ Authorization = "Bearer $tok"
"Content-Type" = "application/json"
Accept = "application/json, text/event-stream" }
# 1. Create a toolbox version with the connection attached.
$body = @{ tools = @(@{
type = "mcp"
server_label = $lbl
project_connection_id = $connId
}) } | ConvertTo-Json -Depth 6 -Compress
$v = Invoke-WebRequest -Method POST -Headers $hdr -UseBasicParsing -Body $body `
-Uri "$dp/toolboxes/$tb/versions?api-version=v1"
$ver = ($v.Content | ConvertFrom-Json).version
# 2. Promote the new version to default. default_version MUST be a JSON STRING, not a number.
# Use ${tb} to terminate the variable name unambiguously before the literal '?'.
Invoke-WebRequest -Method PATCH -Headers $hdr -UseBasicParsing `
-Body (@{ default_version = "$ver" } | ConvertTo-Json) `
-Uri "$dp/toolboxes/${tb}?api-version=v1" | Out-Null
# 3. tools/list → expect one entry per registered op, named "<server_label>___<connectorName>_<OpName>".
$req = '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
Invoke-WebRequest -Method POST -Headers $hdr -UseBasicParsing -Body $req `
-Uri "$dp/toolboxes/$tb/mcp?api-version=v1"
# 4. tools/call → the prefixed name and arguments per inputSchema.
$call = @{ jsonrpc="2.0"; id=2; method="tools/call"; params=@{
name="$lbl`___box_ListRootFolder"; arguments=@{} } } | ConvertTo-Json -Depth 5 -Compress
Invoke-WebRequest -Method POST -Headers $hdr -UseBasicParsing -Body $call `
-Uri "$dp/toolboxes/$tb/mcp?api-version=v1"The response body for /mcp is plain JSON (no SSE data: framing) despite the text/event-stream Accept.
Required RBAC summary
| Operation | Role |
|---|---|
| PUT any connection above | Foundry Project Manager on the project (or Cognitive Services Contributor on the account) |
Drive OAuth consent (gateway_connector, catalog_MCP managed-OAuth) | The end-user themselves, signed in to the subscription's tenant |
ProjectManagedIdentity against a Cognitive Services upstream | Project MI needs the upstream's data-plane role (e.g. Cognitive Services Language Owner for /language/mcp) |
Pitfalls / common mistakes
Do not forget PUT #2 for
gateway_connector(Step 4). The first PUT + OAuth flips status toAuthenticatedbut the runtime has no actions to dispatch until you PUT again withmetadata.mcpserverConfigProperties.Do not invent a "real" target URL for the
gateway_connectorflow on PUT #1."https://placeholder"is correct on PUT #1; PUT #2 rewrites it.Do not mix BYO
credentialswithmetadata.type=catalog_MCPin the BYO body. They conflict; the server accepts the PUT but the runtime uses the catalog's managed app and ignores your secret — or fails with consent confusion.Do not send
scopesas a space-separated string anywhere. Always an array.Do not call
listConsentLinksfor BYO OAuth. Use only forgateway_connectorand managed-OAuthcatalog_MCP.Do not assume the asset-gallery search response contains OAuth metadata — it does not. Always pair it with the Logic Apps
managedApisGET (or hardcode the identityProvider mapping) to getscopesand to deriveauthorizationUrl/tokenUrl.Use exact field spelling for
gateway_connector:toolEntityId(NOTentityId),connectionproperties(lowercase, stringified JSON).Sign in to the subscription's tenant before calling
listConsentLinks— it validates the caller principal owns the suppliedobjectId+tenantId.Toolbox PATCH
default_versionmust be a JSON STRING, not a number. Sending{"default_version": 1}returns400 invalid_payload "requires an element of type 'String', but the target element has type 'Number'". Use{"default_version": "1"}.metadata.audienceis required forProjectManagedIdentity. Without it the MCP server returns 401.Header names for
CustomKeyscome from the catalog, not from a defaultAuthorization: Bearertemplate.ApiKeyis rejected forcategory=RemoteTool. UseCustomKeysfor static secrets.OAuth consent is per-user, per-connection, per-project. Each new caller hits
CONSENT_REQUIREDonce (returned as a nested string code inside an outer-32006error) and must open the URL the toolbox returns.api.githubcopilot.com/mcprejects user OAuth-App tokens. Use a self-hosted MCP or fall back to OpenAPI.PMI forwarder drops
targetquery strings and mints a fixed audience. Settingproperties.audienceis accepted but does not change what is sent.Network-secured Foundry projects cannot use private-endpoint-only MCP servers — only public endpoints reachable from the Foundry data plane and the Connector Namespace.
References
tool-mcp.md — prompt-agent MCP wiring (no toolbox)
use-toolbox-in-hosted-agent.md — MCP endpoint, auth, testing, troubleshooting
agent-tools.md — the agent-tools index
use-toolbox-in-hosted-agent.md — wiring a toolbox into a hosted agent
Requirements and compatibility
Written for: Claude Code
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Names Claude Code tools, Needs a command-line tool, Needs Python
Security
What our scanner noticed· Low risk
- Phrasing that asks for actions without confirmation
- Instructions that use the network
- Scripts that your agent may run
This skill includes scripts that your agent may run. Read them before you use it.
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Microsoft
- Publisher
- Microsoft (Official)
- Source
- microsoft/skills · .github/plugins/azure-skills/skills/microsoft-foundry · commit 0696600
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from .github/plugins/azure-skills/LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Also distributed in
- microsoft/azure-skills
AutoGineer is not affiliated with or endorsed by Microsoft.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download microsoft-foundry.zip