Toolbox Reference
Endpoint format, MCP protocol details, authentication, OAuth consent handling, endpoint testing, citation pattern, and troubleshooting for Foundry Toolboxes.
Endpoint Format
The toolbox MCP endpoint is constructed from the project endpoint + toolbox name:
| Endpoint | URL |
|---|---|
| Latest version (default) | {project_endpoint}/toolboxes/{toolbox_name}/mcp?api-version=v1 |
| Specific version | {project_endpoint}/toolboxes/{toolbox_name}/versions/{version}/mcp?api-version=v1 |
- Project endpoint format:
https://<account>.services.ai.azure.com/api/projects/<project> - The latest-version endpoint always serves the toolbox's
default_version. - Use the specific-version endpoint to test a version before promoting it.
- Required header on every request:
Foundry-Features: Toolboxes=V1Preview ?api-version=v1query parameter is required — requests without it return HTTP 400.
Agent env contract
Hosted agents read the MCP endpoint from a single environment variable. The canonical name is TOOLBOX_ENDPOINT — use it in all new code and .env files:
# Latest version (recommended for prod):
TOOLBOX_ENDPOINT=https://{host}/api/projects/{project}/toolboxes/{toolbox_name}/mcp?api-version=v1
# Pinned to a specific version (recommended for testing a new version before promoting):
TOOLBOX_ENDPOINT=https://{host}/api/projects/{project}/toolboxes/{toolbox_name}/versions/{version}/mcp?api-version=v1⚠️ Don't use
FOUNDRY_TOOLBOX_ENDPOINTin new code. The Foundry platform reserves all environment variables prefixedFOUNDRY_and may silently overwrite user-defined values at runtime. Always use a name without theFOUNDRY_prefix (e.g.TOOLBOX_ENDPOINTorTOOLBOX_MCP_ENDPOINT). Some older samples still referenceFOUNDRY_TOOLBOX_ENDPOINT— treat that as deprecated/legacy and only fall back to it when maintaining a sample that already wires it.
MCP Protocol
Toolboxes use Model Context Protocol (MCP) — JSON-RPC 2.0 over HTTP POST:
initialize— Handshake to establish an MCP session. Returns amcp-session-idheader to include in subsequent requests.tools/list— Returns all available tools with names, descriptions, and input schemas.tools/call— Invokes a tool with arguments and returns structured results.
prompts/listis not supported by the toolbox endpoint. Always passload_prompts=Falseto MCP client constructors.
Tool naming
- MCP-sourced tools (
type: mcp) are exposed as{server_label}.{tool_name}(e.g.myserver.get_info). Call them with the prefixed name intools/call. - All other tool types (
web_search,file_search,azure_ai_search,code_interpreter,openapi,a2a_preview,work_iq_preview,fabric_iq_preview, …) use the value of the entry'snamefield, or the default tool name ifnameis unset. - Tool Search injects two platform meta-tools whose names are always
tool_searchandcall_tool. - Some clients (e.g. GitHub Copilot SDK) reject dots in tool names — the Copilot bridge replaces
.with_(somyserver.get_infobecomesmyserver_get_info) and reverses it before calling MCP.
Each tool returned by tools/list includes a _meta.tool_configuration block with at least the type, plus type-specific fields (e.g. server_label, server_url, require_approval for MCP).
Authentication
- Agent → Toolbox: Azure AD bearer token with scope
https://ai.azure.com/.default, refreshed on every request. - Toolbox → External Services: Managed by the platform via project connections (API keys, OAuth, managed identity). See foundry-tool-catalog.md for the connection shapes that back each tool type.
⚠️ Do not use scope
https://cognitiveservices.azure.com/.default. The toolbox MCP endpoint rejects it with HTTP 401.
💡 If you're hitting OAuth errors (e.g.
CONSENT_REQUIRED, ARA-style "authentication required" errors, or 401s) when calling an MCP server directly from your agent, switch to wiring the same MCP server into a toolbox. The toolbox handles the full OAuth flow — bearer-token acquisition, refresh, consent discovery, and per-user token passthrough — so your agent only ever talks to the toolbox MCP endpoint with a standardhttps://ai.azure.com/.defaulttoken. This is the recommended path for any OAuth-based MCP server in a hosted agent.
OAuth Consent Handling
When a toolbox includes an OAuth-based MCP connection (e.g., GitHub OAuth), the first call from a new user triggers a CONSENT_REQUIRED error (MCP error code -32007). The error message contains the consent URL. This error can surface on either initialize or tools/call depending on when the server discovers the missing grant.
Agent code must handle this:
- Catch MCP error code
-32007fromtools/callor during MCP session initialization. - Extract the consent URL from the error message.
- Log the URL and surface it to the user (e.g., print to stdout or return in the agent response).
- After the user completes the OAuth flow in a browser, retry the call — subsequent calls succeed without re-prompting.
Example error shape:
{
"error": {
"code": -32007,
"message": "User consent is required. Please visit: https://..."
}
}This is a one-time flow per user per OAuth connection in a project. The agent should not silently swallow this error.
Multi-Tool Toolbox Constraint
A single toolbox can combine multiple tools, but at most one tool per unnamed tool type. Tools like web_search, file_search, azure_ai_search, and code_interpreter have no identifier; to include more than one instance of the same type, set a unique name on each instance. MCP tools must each have a unique server_label.
If you include two unnamed tools of the same type (or two MCP tools with the same server_label), the API returns:
400 invalid_payload: Multiple tools without identifiers found...Valid combinations include:
file_search+ one or moremcp(each with uniqueserver_label)web_search+ one or moremcpazure_ai_search+ one or moremcptoolbox_search_preview(the Tool Search directive — doesn't count toward the limit) + any other tools
Azure AI Search Citation Pattern
When calling an azure_ai_search tool through the toolbox MCP endpoint, citation metadata is returned under result.structuredContent.documents[] — not in a separate citations array. Treat each document as one citation:
| Field | Meaning |
|---|---|
title | Citation display text |
url | Source link |
id | Source identifier |
score | Retrieval relevance score |
knowledgeSourceIndex | Source grouping / index |
Verification checklist:
tools/listreturns the tool nameazure_ai_search.tools/callsucceeds with aqueryargument.result.structuredContent.documentsis present and non-empty.- At least one document has both
titleandurl.
For File Search and Web Search citation patterns (under result.content[].resource._meta and ..._meta.annotations[] respectively), see the public Toolbox docs.
Testing the Toolbox Endpoint
Before running the full agent, verify the toolbox MCP endpoint works end-to-end. Use az login for authentication, then test the three MCP operations in order:
1. Get a bearer token:
TOKEN=$(az account get-access-token --resource https://ai.azure.com --query accessToken -o tsv)
TOOLBOX_URL="https://<account>.services.ai.azure.com/api/projects/<project>/toolboxes/<name>/mcp?api-version=v1"2. Initialize MCP session:
curl -sS -X POST "$TOOLBOX_URL" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Foundry-Features: Toolboxes=V1Preview" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"debug","version":"1.0.0"}}}' \
-D - | head -20Save the mcp-session-id header from the response for subsequent calls.
3. List tools:
curl -sS -X POST "$TOOLBOX_URL" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Foundry-Features: Toolboxes=V1Preview" \
-H "mcp-session-id: <session-id-from-step-2>" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | jq .Checklist:
- Response contains
result.tools[]withlen > 0 - Each tool has
name,description, andinputSchemawith apropertiesfield - MCP tool names for remote servers are prefixed with
server_label(e.g.,myserver.get_info) - All other tool types use the entry's
namefield value (or the default tool name)
4. Call a tool (optional):
curl -sS -X POST "$TOOLBOX_URL" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Foundry-Features: Toolboxes=V1Preview" \
-H "mcp-session-id: <session-id-from-step-2>" \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"<tool_name>","arguments":{"query":"test"}}}' | jq .Troubleshooting
| Error | Cause | Resolution |
|---|---|---|
CONSENT_REQUIRED (code -32007) | OAuth MCP connection needs user consent | Open consent URL in browser, complete OAuth flow, retry |
| 401 on MCP calls | Expired token or wrong scope | Use scope https://ai.azure.com/.default (not cognitiveservices) and refresh token on every request |
| OAuth/ARA errors when calling MCP directly from agent | Direct MCP wiring without toolbox token passthrough | Wire the MCP server into a toolbox and call the toolbox endpoint instead — Foundry handles consent + refresh |
400 invalid_payload: Multiple tools without identifiers found | Two unnamed tools of the same type (or duplicate server_label) in one toolbox | Keep at most one unnamed tool per type; give each MCP tool a unique server_label |
tools/list returns 0 tools | Toolbox version still provisioning, or tool type not yet available in the region | Wait ~10s and retry; try a different region |
tools/list returns 0 tools for MCP/A2A only | Invalid or missing connection credentials | Verify project_connection_id exists and credentials are correct; for MI auth, check RBAC on the target service |
tools/list returns 0 tools for OpenAPI only | Invalid OpenAPI spec (malformed paths, missing operationIds) | Validate the spec against OpenAPI 3.0/3.1; for MI auth, also verify RBAC |
Tool not found on tools/call | Missing server_label. prefix for MCP-sourced tools | Call as {server_label}.{tool_name} |
500 on prompts/list | Not supported by toolbox endpoint | Pass load_prompts=False to MCP client constructor |
500 on send_ping() (MAF MCPStreamableHTTPTool._ensure_connected) | Toolbox MCP server doesn't implement ping | Disable the ping check or override with a no-op |
500 with non-streaming tools/call | Non-streaming not supported | Always use stream=True for toolbox MCP tools |
400 missing api-version | Query string dropped | Append ?api-version=v1 to every toolbox URL |
| Environment variable silently overwritten at runtime | Foundry reserves FOUNDRY_-prefixed env vars | Rename to a non-FOUNDRY_ name (e.g. TOOLBOX_ENDPOINT) |
403 on POST /toolboxes or PUT .../connections/... | Caller lacks Foundry User (or Azure AI Developer / Cognitive Services Contributor) on the project | Grant the role at the project scope |