MCP in Microsoft Foundry: The Toolbox Pattern for Trustworthy Tool Calling Microsoft Foundry Agent Service has adopted the Model Context Protocol (MCP) as a first-class remote tool type, introducing a Toolbox construct that acts as a governance layer for agent tool calling. The design separates server configuration, authentication, and identity into three distinct layers, supporting six authentication models and an approval gate in the platform's tool-execution layer. The writeup examines how MCP tool calls flow through the Responses API and where production issues such as timeouts, private networking, and prompt injection via tool metadata arise. Day 6 of the Microsoft Foundry 100 Days / 100 Blogs series. 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 . 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: server url , server label . none to agentic-identity . Understanding why those are three separate layers — instead of one config blob — is the actual engineering lesson here. 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/list and invoked via tools/call . 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. 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 └────────────────────────────────┘ 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. 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 : get me tool from the api-specs MCP server to answer "what's my GitHub username?" mcp approval request , containing the server label, tool name, and arguments. The response is mcp approval response approve or deny tied to the approval request id , referencing the previous response.id to keep continuity. 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. 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: oauth2 with --connector-name , and let Foundry manage the OAuth app registration entirely. project-managed-identity or 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. 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. 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: python 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://