DEV Community

Manoranjan Rajguru
Manoranjan Rajguru

Posted on

MCP in Microsoft Foundry: The Toolbox Pattern for Trustworthy Tool Calling

Connecting Foundry Agents to MCP Servers: Auth, Approval, and the Toolbox Pattern

Day 6 of the Microsoft Foundry 100 Days / 100 Blogs series.

The problem nobody wants to admit they have

Every agent framework eventually runs into the same wall: you've got a model that reasons well, but the moment it needs to do something — read a GitHub issue, query an internal knowledge base, hit a partner API — you're back to writing bespoke client code, stuffing credentials into environment variables, and hoping nobody pastes a system prompt into a public repo. Multiply that by five agents, three environments, and a compliance team that wants an audit trail, and "add a tool" stops being a two-line change.

Model Context Protocol (MCP) was designed to solve exactly this: a standard wire format so any MCP-compatible client can talk to any MCP-compatible server without custom glue code. Microsoft Foundry Agent Service adopted MCP as a first-class tool type, but the more interesting engineering decision is what Foundry built on top of it — a construct called the Toolbox that turns MCP from "one more tool integration" into a governance layer for how agents get their hands on external capabilities.

This article is about the parts of that system a developer actually has to reason about: how MCP tool calls flow through the Responses API, what the six authentication models mean for your identity design, why the Toolbox exists and when it's worth the extra indirection, and where things break in production (timeouts, private networking, prompt injection through tool metadata).

Why this matters now

MCP crossed from "interesting protocol" to "the thing everyone is standardizing on" faster than almost any AI infrastructure decision in the last two years. GitHub, Azure DevOps, Databricks Genie, Fabric, Neon, Vercel, and dozens of SaaS vendors now ship official MCP servers. If you're building agents on Foundry, the question isn't whether you'll connect to an MCP server — it's whether you'll do it in a way that's auditable, revocable, and doesn't leak a GitHub PAT into your agent instructions.

Foundry's answer is architecturally interesting because it separates three concerns that most tutorials conflate:

  1. Transport — the MCP tool declaration itself (server_url, server_label).
  2. Identity — how the call to the MCP server authenticates (six distinct auth types, from none to agentic-identity).
  3. Governance — the Toolbox, which centralizes credential management, tool allow-listing, and reuse across agents and even across runtimes (Agent Framework, LangGraph, GitHub Copilot SDK).

Understanding why those are three separate layers — instead of one config blob — is the actual engineering lesson here.


Table of Contents

  1. Core Concepts: What MCP Actually Standardizes
  2. Foundry's MCP Architecture
  3. The Tool Call Lifecycle at Runtime
  4. Six Authentication Models, One Decision Tree
  5. Implementation: Prompt Agents
  6. Implementation: Hosted Agents + FoundryToolbox
  7. The Toolbox Pattern in Depth
  8. Real-World Scenario: A Support Agent With Three MCP Backends
  9. Production Considerations
  10. Security Considerations
  11. Performance, Scale, and Cost
  12. Common Mistakes
  13. Alternatives and Trade-offs
  14. Practical Recommendations
  15. Conclusion
  16. References

1. Core Concepts: What MCP Actually Standardizes

Model Context Protocol, published by Anthropic and now adopted widely across the industry (including Microsoft), defines a JSON-RPC-based contract between an MCP client (in our case, Foundry Agent Service) and an MCP server (GitHub, an internal REST wrapper, a data warehouse connector). The protocol standardizes three primitives:

  • Tools — callable functions with a JSON schema for input, discoverable via tools/list and invoked via tools/call.
  • Resources — addressable, read-only data the model can pull into context (a file, a document, a database row).
  • Prompts — reusable prompt templates the server can expose to the client.

In practice, almost all production MCP usage today revolves around tools. What MCP gives you that a hand-rolled function-calling integration doesn't is discoverability — the client asks the server what it can do at connection time, rather than the tool schema being hardcoded into the client's source. That's what makes a single mcp tool declaration in Foundry capable of exposing dozens of GitHub operations without you writing a single wrapper function.

The trade-off is that discoverability cuts both ways: the server controls the tool descriptions the model sees, and the server can change its surface area at any time. That fact drives a lot of the security posture discussed later.

2. Foundry's MCP Architecture

Foundry Agent Service implements MCP as a remote tool type, meaning the agent doesn't run an MCP client library itself — the platform's tool-execution layer does. When you declare an MCPTool on an agent, three things get wired together at the platform level:

┌────────────────────┐        ┌──────────────────────────┐        ┌───────────────────────┐
│   Foundry Agent      │        │   Foundry Tool Execution  │        │   Remote MCP Server    │
│  (Prompt or Hosted)  │──────▶│   Layer (approval gate,   │──────▶│  (GitHub, internal,    │
│                       │        │   auth injection, retry)  │        │   Toolbox endpoint)    │
└────────────────────┘        └──────────────────────────┘        └───────────────────────┘
          ▲                                │
          │                                ▼
          │                    project_connection_id
          │                    (auth type resolved here)
          └────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

[IMAGE: Professional architecture diagram showing a Foundry Agent (Prompt or Hosted) on the left connecting to a central "Foundry Toolbox (MCP-compatible endpoint)" box, which fans out to three MCP servers on the right — a GitHub MCP server (OAuth2), an internal MCP server behind a private VNet/Container Apps boundary, and a public Microsoft Learn MCP server (no auth). Annotate the arrows with "mcp_approval_request", "require_approval=always", and "project_connection_id" labels. Corporate blue/gray/white palette, clean documentation style.]

The important architectural point: the agent never sees raw credentials. The project_connection_id on the MCPTool declaration points at a Foundry project connection — a stored, RBAC-governed object that holds the auth configuration (API key, OAuth app registration, or an identity reference). At call time, the tool execution layer resolves the connection, attaches the right credential or token, makes the tools/call request to the MCP server, and returns the result back into the model's context window as a tool output.

This is the same separation of concerns you'd want in any multi-tenant system: the what (tool declaration) is agent-scoped, the how (credentials) is connection-scoped and centrally managed, and the where (network path) depends on whether the MCP server is public or sits behind a private endpoint.

3. The Tool Call Lifecycle at Runtime

Here's what actually happens on the wire when a Foundry agent with an MCP tool gets a user request that requires a tool call, assuming require_approval="always" (the recommended default):

  1. Model turn — The model decides it needs the get_me tool from the api-specs MCP server to answer "what's my GitHub username?"
  2. Approval request emitted — Instead of executing the call, the Responses API returns an output item of type mcp_approval_request, containing the server label, tool name, and arguments. The response is not yet complete — no tool has run.
  3. Client-side review — Your application code inspects the request. This is the only point where you can stop a malicious or unintended tool call before it touches an external system.
  4. Approval response — You send back an mcp_approval_response (approve or deny) tied to the approval_request_id, referencing the previous response.id to keep continuity.
  5. Execution — Only after approval does the platform actually issue tools/call to the MCP server, using the credential resolved from the connection.
  6. Result folded back into context — The tool result is appended as a new item, and the model produces its final answer in the same or a subsequent turn.

This matters because it means MCP tool calls are not fire-and-forget the way a local Python function tool might be. There's a full request/response round-trip for approval baked into the protocol surface, which is the mechanism Foundry uses to keep a human (or a policy engine) in the loop for anything that touches an external, third-party system.

If you set require_approval="never", this step is skipped entirely and the tool executes immediately — appropriate only for read-only, trusted, internal servers where the latency cost of a human-in-the-loop step isn't worth it.

4. Six Authentication Models, One Decision Tree

This is the part of MCP integration that trips up most teams, because "authentication" for a remote tool call actually branches into six distinct patterns in Foundry, each suited to a different identity story:

Auth type Use when What Foundry does
none Public, unauthenticated MCP server (e.g., Microsoft Learn docs MCP) No credential attached; request goes out as-is
custom-keys Server needs a static header (PAT, API key) Injects Header=Value pairs from the stored connection
oauth2 Server supports OAuth2, either via a Foundry-managed connector or your own app registration Handles the authorization code / token exchange, caches and refreshes tokens
user-entra-token Passthrough of the calling user's Entra identity (e.g., Fabric, Power BI) Exchanges the user's token for the target audience via On-Behalf-Of flow
project-managed-identity Target resource trusts the Foundry project's system-assigned managed identity Requests a token for the target audience using the project's MI
agentic-identity Target resource should authorize the specific agent rather than the whole project Requests a token scoped to the agent's own identity (ties into the Autopilot identity model from Day 3 of this series)

The decision tree in practice:

  • Is the MCP server a Microsoft-partnered service with a Foundry connector (GitHub, Databricks Genie, Neon, Vercel, Pipedream, Infobip, Morningstar, LSEG)? Use oauth2 with --connector-name, and let Foundry manage the OAuth app registration entirely.
  • Is it an internal Azure resource that already trusts Entra ID (Cognitive Services, Fabric)? Prefer project-managed-identity or agentic-identity over static keys — no secret to rotate, and access is auditable through standard Entra sign-in logs.
  • Is it a third-party server with only a static API key, and no OAuth support? Use custom-keys, but treat the connection object as a secret boundary — RBAC on who can create/read that connection matters as much as the key itself.
  • Is it public and read-only (docs, public datasets)? Use none and don't add auth complexity you don't need.

The agentic-identity vs project-managed-identity distinction is worth sitting with. If ten different agents in a project all call the same downstream resource under project-managed-identity, you get one identity in your access logs for all of them — fine for coarse-grained systems, insufficient if you need to answer "which agent did this" during an incident review. agentic-identity gives every agent its own principal, which is the same design tension covered in the Autopilot identity model piece earlier in this series — Foundry is consistent about pushing identity granularity down to the agent level wherever it can.

5. Implementation: Prompt Agents

The simplest integration path uses a server-side prompt agent with an inline MCPTool. This is a simplified, illustrative example based on Foundry's Python SDK pattern — verify exact method names against your installed SDK version before running in production:

import json
from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import PromptAgentDefinition, MCPTool
from openai.types.responses.response_input_param import McpApprovalResponse, ResponseInputParam

PROJECT_ENDPOINT = "https://<account>.services.ai.azure.com/api/projects/<project>"
MCP_CONNECTION_NAME = "my-mcp-connection"  # project connection holding auth config

project = AIProjectClient(endpoint=PROJECT_ENDPOINT, credential=DefaultAzureCredential())
openai_client = project.get_openai_client()

# Declare the MCP tool. require_approval="always" is the safe default for
# any server that isn't fully trusted and read-only.
mcp_tool = MCPTool(
    server_label="api-specs",
    server_url="https://api.githubcopilot.com/mcp",
    require_approval="always",
    project_connection_id=MCP_CONNECTION_NAME,
)

agent = project.agents.create_version(
    agent_name="GitHubInsightsAgent",
    definition=PromptAgentDefinition(
        model="gpt-5-mini",
        instructions="Use MCP tools as needed to answer GitHub-related questions.",
        tools=[mcp_tool],
    ),
)

conversation = openai_client.conversations.create()

response = openai_client.responses.create(
    conversation=conversation.id,
    input="What is my username in my GitHub profile?",
    extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}},
)

# Walk the output for any approval requests before the agent can proceed.
pending_inputs: ResponseInputParam = []
for item in response.output:
    if item.type == "mcp_approval_request":
        print(f"Server: {item.server_label} | Tool: {item.name} | Args: {json.dumps(item.arguments)}")
        # In production this should route to a policy engine or human reviewer,
        # not a blocking input() call.
        approved = input("Approve this MCP tool call? (y/N): ").strip().lower() == "y"
        pending_inputs.append(
            McpApprovalResponse(
                type="mcp_approval_response",
                approve=approved,
                approval_request_id=item.id,
            )
        )

# Resume the same logical turn by chaining previous_response_id.
final = openai_client.responses.create(
    input=pending_inputs,
    previous_response_id=response.id,
    extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}},
)

print(final.output_text)
project.agents.delete_version(agent_name=agent.name, agent_version=agent.version)
Enter fullscreen mode Exit fullscreen mode

Three things worth internalizing from this snippet:

  • previous_response_id is how approvals chain back into the same reasoning turn. The Responses API models this as a linked list of response objects, not a single monolithic call — which is exactly the same pattern used for background/async responses elsewhere in Foundry.
  • The approval loop is synchronous in this example only for clarity. In a real service, mcp_approval_request items should be persisted (e.g., to a queue or database row keyed by approval_request_id) and resolved asynchronously by whatever UI or policy engine owns the approval decision — a human reviewer, an automated allow-list check, or both.
  • server_label is your primary defense against confused-deputy scenarios. Always check the label of the requesting server before auto-approving anything, especially once you have more than one MCP tool attached to an agent.

6. Implementation: Hosted Agents + FoundryToolbox

For hosted agents built on Microsoft Agent Framework, the pattern shifts from an inline tool declaration to referencing a Toolbox endpoint — which is where things get more interesting architecturally:

import asyncio
from agent_framework import Agent
from agent_framework.foundry import FoundryChatClient, FoundryToolbox
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import MCPToolboxTool
from azure.identity import AzureCliCredential

PROJECT_ENDPOINT = "https://<account>.services.ai.azure.com/api/projects/<project>"
MCP_CONNECTION_NAME = "my-mcp-connection"

async def main() -> None:
    credential = AzureCliCredential()
    project = AIProjectClient(endpoint=PROJECT_ENDPOINT, credential=credential)

    # 1. Register the MCP server inside a Toolbox (not directly on the agent).
    server_tool = MCPToolboxTool(
        server_label="api-specs",
        server_url="https://api.githubcopilot.com/mcp",
        require_approval="always",
        project_connection_id=MCP_CONNECTION_NAME,
    )
    toolbox = project.toolboxes.create_version(
        name="mcp-server-toolbox",
        description="Toolbox with the GitHub MCP server",
        tools=[server_tool],
    )

    # 2. The Toolbox itself now exposes an MCP-compatible endpoint.
    toolbox_mcp_url = (
        f"{PROJECT_ENDPOINT}/toolboxes/{toolbox.name}"
        f"/versions/{toolbox.version}/mcp?api-version=v1"
    )

    # 3. Any MCP-compatible runtime — Agent Framework, LangGraph, even a
    #    GitHub Copilot SDK client — can now consume this one endpoint.
    toolbox_tool = FoundryToolbox(credential, url=toolbox_mcp_url)

    agent = Agent(
        client=FoundryChatClient(credential=credential),
        instructions="You are a helpful assistant that uses your MCP tool "
                     "to help with Microsoft documentation questions.",
        tools=[toolbox_tool],
    )

    result = await agent.run("What is Microsoft Agent Framework?")
    print(result.text)

if __name__ == "__main__":
    asyncio.run(main())
Enter fullscreen mode Exit fullscreen mode

The key shift: the hosted agent doesn't talk to GitHub's MCP server directly — it talks to your Toolbox's MCP endpoint, which in turn proxies to GitHub. That extra hop is the entire point, and it's worth understanding why.

7. The Toolbox Pattern in Depth

A Foundry Toolbox bundles multiple tools — MCP servers, OpenAPI specs, Web Search, Code Interpreter, File Search, Azure AI Search, even Agent-to-Agent connections — behind a single MCP-compatible endpoint. Conceptually, it's an API gateway pattern applied to tool calling:

azd ai connection create my-mcp-conn \
  --kind remote-tool \
  --target https://api.githubcopilot.com/mcp/ \
  --auth-type oauth2 \
  --connector-name foundrygithubmcp
Enter fullscreen mode Exit fullscreen mode
# my-toolbox.yaml
description: MCP server tools
connections:
  - name: my-mcp-conn
Enter fullscreen mode Exit fullscreen mode
azd ai toolbox create my-toolbox --from-file my-toolbox.yaml
Enter fullscreen mode Exit fullscreen mode

Why does this indirection earn its keep instead of being unnecessary complexity?

  • Credential centralization. Ten agents that all need GitHub access share one connection and one OAuth consent flow, instead of ten separate credential stores drifting out of sync.
  • Cross-runtime portability. Because the Toolbox endpoint speaks MCP, it works identically whether the consumer is a Foundry prompt agent, a Microsoft Agent Framework hosted agent, a LangGraph graph, or the GitHub Copilot SDK. You configure the tool once and reuse it across every runtime your organization happens to standardize on.
  • Policy enforcement at a chokepoint. allowed_tools, approval policy, and rate limiting can be enforced at the Toolbox layer rather than duplicated per-agent.
  • Decoupled versioning. You can add, remove, or swap tools inside a Toolbox version without touching agent code — agents reference a Toolbox version, not individual tool wiring.

The OAuth consent flow surfaces a specific, easy-to-miss failure mode worth calling out explicitly: the first call from any new user through an OAuth-backed Toolbox connection returns a JSON-RPC error, not a tool result:

{
  "error": {
    "code": -32006,
    "message": "User consent is required. Please visit: https://..."
  }
}
Enter fullscreen mode Exit fullscreen mode

This is expected behavior, not a bug — code your client to catch -32006, surface the consent URL, and retry after the user completes the OAuth flow in a browser. Treat it the same way you'd treat a 401 with a WWW-Authenticate challenge in a normal OAuth client.

8. Real-World Scenario: A Support Agent With Three MCP Backends

Consider a developer-support agent that needs to: (1) look up internal ticket status from a private ticketing system, (2) search Microsoft Learn documentation, and (3) create GitHub issues on behalf of the user.

A Toolbox-first design looks like this:

  • Ticketing system MCP server — deployed on Azure Container Apps with internal-only ingress on a dedicated MCP subnet, auth via agentic-identity so each support agent's actions map to a distinct principal in the ticketing audit log.
  • Microsoft Learn MCP server — public, auth-type none, require_approval="never" since it's read-only and Microsoft-operated.
  • GitHub MCP serverauth-type oauth2 with --connector-name foundrygithubmcp, require_approval="always" because issue creation is a write operation with real consequences.

All three get registered as connections and bundled into one support-agent-toolbox Toolbox. The agent code stays static — swapping the ticketing backend later, or adding a fourth MCP server, is a Toolbox YAML change, not an agent redeploy. This is the pattern that pays for the extra indirection: mixed trust levels, mixed auth models, and a hard requirement (write access to GitHub) that must never silently downgrade from "always approve."

9. Production Considerations

Streaming and timeout behavior. MCP tool calls sit inside a synchronous request/response turn by default, which means a slow downstream MCP server directly extends your agent's response latency — and can trigger client-side timeouts if the tool takes longer than your HTTP client's patience allows. For genuinely long-running operations, Foundry's Toolbox MCP endpoint supports MCP tasks (preview), an extension to the spec for background-style execution — but your agent harness has to explicitly support MCP tasks to take advantage of it. Don't assume long-running tool support exists just because you're using a Toolbox; check the harness compatibility first.

Private networking. Public MCP endpoints work out of the box for both Basic and Standard agent setups, but internal MCP servers require a dedicated MCP subnet delegated to Microsoft.App/environments, with the server deployed on Azure Container Apps behind internal-only ingress. Foundry ships reference Bicep templates (19-private-network-agent-tools, 11-private-network-basic-project) for exactly this topology — worth starting from those rather than hand-rolling the VNet plumbing, since the MCP subnet delegation requirement is easy to get wrong on a first pass.

Version drift on third-party servers. Because MCP is discoverable, a server operator can change tool names, arguments, or descriptions at any time without notifying you. Pin allowed_tools explicitly rather than trusting "whatever the server currently exposes," and re-review the allow-list whenever you notice the server's behavior or exposed toolset has changed.

10. Security Considerations

This is where MCP integration differs meaningfully from calling a REST API you control. You're feeding model context that originates from a third party — the tool descriptions, argument schemas, and even the results — directly into your agent's reasoning loop. That's a textbook indirect prompt injection surface: a malicious or compromised MCP server can craft a tool description or a tool result that instructs the model to take an unintended action on a later turn.

Concrete mitigations that map directly onto Foundry's controls:

  • Always set require_approval="always" for any server that isn't fully trusted and read-only. This is the single biggest lever you have — it converts "the model decided to do something" into "a human or policy engine confirmed it should happen."
  • Use allowed_tools as an allow-list, not a suggestion. Even a trusted server can expose more than you want your agent to touch; restrict at the tool-name level explicitly.
  • Treat tool results as untrusted input, the same way you'd treat user-supplied text — don't let a tool result silently expand what the model is authorized to do next without another approval gate.
  • Log every approval decision and tool call for audit purposes; you will eventually need to answer "why did this agent do that" during an incident review, and the approval log is your primary evidence trail.
  • Prefer identity-based auth (project-managed-identity, agentic-identity) over static keys wherever the target system supports Entra ID — it removes an entire class of credential-leakage risk and gives you native audit logs on the resource side.
  • Review third-party MCP servers' terms and data handling before connecting them. Foundry is explicit that Microsoft doesn't test or verify remote MCP servers — you're passing prompt content and potentially sensitive arguments to a system you don't control.

11. Performance, Scale, and Cost

From a scale perspective, the Toolbox pattern is the right default the moment you have more than one agent needing the same external capability: it turns an O(agents × servers) credential and configuration matrix into O(servers) connections plus O(agents) toolbox references. The cost angle is subtler — every MCP tool call in an approval-gated flow costs you an extra model turn (the turn that surfaces the mcp_approval_request and the turn that resumes after approval), which is real token and latency overhead compared to require_approval="never". That overhead is the price of the audit trail; don't remove it purely to save a few hundred tokens on a write-capable tool.

Connection reuse also matters for OAuth token lifecycle: a Toolbox-mediated connection handles token refresh centrally, so you're not paying the OAuth handshake cost (or risking expired-token failures) on every agent instance independently.

12. Common Mistakes

  • Setting require_approval="never" on a write-capable server "to keep the demo smooth." This is the most common shortcut that turns into a production incident.
  • Hardcoding a PAT or API key directly in agent instructions or tool config instead of routing it through a project connection — defeats the entire point of centralized credential management.
  • Not checking server_label before auto-approving when an agent has multiple MCP tools attached — a confused-deputy bug waiting to happen.
  • Ignoring the -32006 consent-required error as if it were a hard failure, instead of building the consent-URL redirect into the client flow.
  • Assuming MCP tasks (long-running support) are available by default — they require both Toolbox preview support and harness-side compatibility.
  • Skipping the private-networking setup for internal MCP servers and instead exposing them publicly "just for now" — that "now" tends to become permanent.

13. Alternatives and Trade-offs

MCP isn't the only tool-integration mechanism in Foundry, and it isn't always the right one:

  • OpenAPI tools are a better fit when you already have a well-documented REST API and don't need dynamic tool discovery — less protocol overhead, and you control the schema completely rather than trusting a server's self-description.
  • Native/function tools (plain Python functions registered on the agent) win when the logic is simple, fully in your control, and doesn't warrant a network hop at all.
  • Agent-to-Agent (A2A) delegation (covered in Day 2 of this series) is the right choice when you're calling another agent with its own reasoning loop, not a stateless tool.
  • MCP wins specifically when you want to consume a capability someone else built and maintains, especially when that capability might evolve its own surface area over time, or when cross-runtime portability (Agent Framework, LangGraph, Copilot SDK all speaking the same protocol) is a real requirement rather than a nice-to-have.

The trade-off in the other direction: MCP's dynamic discovery is precisely what makes it a bigger trust surface than a statically-defined OpenAPI tool. If you fully control both sides, a native tool or a pinned OpenAPI spec is simpler and has a smaller attack surface — reach for MCP when the "someone else's server, someone else's roadmap" dynamic is actually part of your requirement.

14. Practical Recommendations

  • Default every new MCP tool to require_approval="always" and only relax it after you've reviewed the server's full tool surface and trust level.
  • Build your approval-handling code to be asynchronous and persistent from day one — a blocking input() call is fine for a demo, not for a service with concurrent users.
  • Put every MCP server behind a Toolbox once you have more than one agent that needs it — the credential-centralization and cross-runtime benefits outweigh the extra indirection almost immediately.
  • Prefer agentic-identity over project-managed-identity when you need per-agent audit granularity on the downstream resource.
  • Budget real Bicep/networking time for internal MCP servers — don't treat the private-endpoint requirement as an afterthought.

15. Conclusion

MCP support in Microsoft Foundry isn't just "another tool type" — it's a deliberate architectural bet that tool integration should be governed the same way network access and identity are: centrally managed, RBAC-scoped, and auditable by default. The approval-gated call lifecycle, the six-way authentication decision tree, and the Toolbox-as-API-gateway pattern all point at the same underlying philosophy: treat every external MCP server as an untrusted dependency until you've explicitly decided otherwise, and design the plumbing so that decision is enforced at the platform layer rather than left to each agent's author to remember.

If you're building anything beyond a single-agent demo, start with a Toolbox from day one, keep require_approval="always" until you have real evidence a server deserves otherwise, and pick your auth type based on how granular your audit story needs to be — not just on what's fastest to wire up.

16. References

(verify current SDK method signatures and preview-feature availability against the latest Foundry SDK release before shipping to production — MCP task support and some connector names are explicitly called out as preview/evolving in the docs)


This is Day 6 of the Microsoft Foundry 100 Days / 100 Blogs series — one deep technical post a day covering the breadth of the Foundry ecosystem. Previous days covered crash-resilient long-running agents, hosted agent protocols (Responses vs. Invocations), the Autopilot identity model, Foundry Local on-device inference, and the closed-loop Agent Optimizer.

Top comments (0)