Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Build and deploy AI applications on Azure AI Foundry using Microsoft's model catalog and AI services
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
foundry-agent/create/references/toolbox-reference.md
1# Toolbox Reference23Endpoint format, MCP protocol details, authentication, OAuth consent handling, endpoint testing, citation pattern, and troubleshooting for Foundry Toolboxes.45## Endpoint Format67The toolbox MCP endpoint is constructed from the **project endpoint** + **toolbox name**:89| Endpoint | URL |10|----------|-----|11| Latest version (default) | `{project_endpoint}/toolboxes/{toolbox_name}/mcp?api-version=v1` |12| Specific version | `{project_endpoint}/toolboxes/{toolbox_name}/versions/{version}/mcp?api-version=v1` |1314- **Project endpoint** format: `https://<account>.services.ai.azure.com/api/projects/<project>`15- The latest-version endpoint always serves the toolbox's `default_version`.16- Use the specific-version endpoint to test a version before promoting it.17- **Required header** on every request: `Foundry-Features: Toolboxes=V1Preview`18- `?api-version=v1` query parameter is **required** — requests without it return HTTP 400.1920### Agent env contract2122Hosted 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:2324```25# Latest version (recommended for prod):26TOOLBOX_ENDPOINT=https://{host}/api/projects/{project}/toolboxes/{toolbox_name}/mcp?api-version=v12728# Pinned to a specific version (recommended for testing a new version before promoting):29TOOLBOX_ENDPOINT=https://{host}/api/projects/{project}/toolboxes/{toolbox_name}/versions/{version}/mcp?api-version=v130```3132> ⚠️ **Don't use `FOUNDRY_TOOLBOX_ENDPOINT` in new code.** The Foundry platform **reserves** all environment variables prefixed `FOUNDRY_` and may silently overwrite user-defined values at runtime. Always use a name without the `FOUNDRY_` prefix (e.g. `TOOLBOX_ENDPOINT` or `TOOLBOX_MCP_ENDPOINT`). Some older samples still reference `FOUNDRY_TOOLBOX_ENDPOINT` — treat that as **deprecated/legacy** and only fall back to it when maintaining a sample that already wires it.3334## MCP Protocol3536Toolboxes use **Model Context Protocol (MCP)** — JSON-RPC 2.0 over HTTP POST:3738- **`initialize`** — Handshake to establish an MCP session. Returns a `mcp-session-id` header to include in subsequent requests.39- **`tools/list`** — Returns all available tools with names, descriptions, and input schemas.40- **`tools/call`** — Invokes a tool with arguments and returns structured results.4142> `prompts/list` is **not supported** by the toolbox endpoint. Always pass `load_prompts=False` to MCP client constructors.4344### Tool naming4546- **MCP-sourced tools** (`type: mcp`) are exposed as `{server_label}.{tool_name}` (e.g. `myserver.get_info`). Call them with the prefixed name in `tools/call`.47- **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's `name` field, or the default tool name if `name` is unset.48- **Tool Search** injects two platform meta-tools whose names are always `tool_search` and `call_tool`.49- Some clients (e.g. GitHub Copilot SDK) reject dots in tool names — the Copilot bridge replaces `.` with `_` (so `myserver.get_info` becomes `myserver_get_info`) and reverses it before calling MCP.5051Each 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).5253## Authentication5455- **Agent → Toolbox:** Azure AD bearer token with scope `https://ai.azure.com/.default`, refreshed on every request.56- **Toolbox → External Services:** Managed by the platform via project connections (API keys, OAuth, managed identity). See [foundry-tool-catalog.md](foundry-tool-catalog.md) for the connection shapes that back each tool type.5758> ⚠️ Do **not** use scope `https://cognitiveservices.azure.com/.default`. The toolbox MCP endpoint rejects it with HTTP 401.5960> 💡 **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 standard `https://ai.azure.com/.default` token. This is the recommended path for any OAuth-based MCP server in a hosted agent.6162## OAuth Consent Handling6364When 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.6566**Agent code must handle this:**67681. Catch MCP error code **`-32007`** from `tools/call` **or** during MCP session initialization.692. Extract the consent URL from the error message.703. Log the URL and surface it to the user (e.g., print to stdout or return in the agent response).714. After the user completes the OAuth flow in a browser, retry the call — subsequent calls succeed without re-prompting.7273Example error shape:7475```json76{77"error": {78"code": -32007,79"message": "User consent is required. Please visit: https://..."80}81}82```8384> This is a one-time flow per user per OAuth connection in a project. The agent should not silently swallow this error.8586## Multi-Tool Toolbox Constraint8788A 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`.8990If you include two unnamed tools of the same type (or two MCP tools with the same `server_label`), the API returns:9192```93400 invalid_payload: Multiple tools without identifiers found...94```9596Valid combinations include:9798- `file_search` + one or more `mcp` (each with unique `server_label`)99- `web_search` + one or more `mcp`100- `azure_ai_search` + one or more `mcp`101- `toolbox_search_preview` (the Tool Search directive — doesn't count toward the limit) + any other tools102103## Azure AI Search Citation Pattern104105When 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:106107| Field | Meaning |108|-------|---------|109| `title` | Citation display text |110| `url` | Source link |111| `id` | Source identifier |112| `score` | Retrieval relevance score |113| `knowledgeSourceIndex` | Source grouping / index |114115Verification checklist:1161171. `tools/list` returns the tool name `azure_ai_search`.1182. `tools/call` succeeds with a `query` argument.1193. `result.structuredContent.documents` is present and non-empty.1204. At least one document has both `title` and `url`.121122For File Search and Web Search citation patterns (under `result.content[].resource._meta` and `..._meta.annotations[]` respectively), see the public [Toolbox docs](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/toolbox).123124## Testing the Toolbox Endpoint125126Before 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:127128**1. Get a bearer token:**129130```bash131TOKEN=$(az account get-access-token --resource https://ai.azure.com --query accessToken -o tsv)132TOOLBOX_URL="https://<account>.services.ai.azure.com/api/projects/<project>/toolboxes/<name>/mcp?api-version=v1"133```134135**2. Initialize MCP session:**136137```bash138curl -sS -X POST "$TOOLBOX_URL" \139-H "Authorization: Bearer $TOKEN" \140-H "Content-Type: application/json" \141-H "Foundry-Features: Toolboxes=V1Preview" \142-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"debug","version":"1.0.0"}}}' \143-D - | head -20144```145146Save the `mcp-session-id` header from the response for subsequent calls.147148**3. List tools:**149150```bash151curl -sS -X POST "$TOOLBOX_URL" \152-H "Authorization: Bearer $TOKEN" \153-H "Content-Type: application/json" \154-H "Foundry-Features: Toolboxes=V1Preview" \155-H "mcp-session-id: <session-id-from-step-2>" \156-d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | jq .157```158159Checklist:160161- Response contains `result.tools[]` with `len > 0`162- Each tool has `name`, `description`, and `inputSchema` with a `properties` field163- MCP tool names for remote servers are prefixed with `server_label` (e.g., `myserver.get_info`)164- All other tool types use the entry's `name` field value (or the default tool name)165166**4. Call a tool (optional):**167168```bash169curl -sS -X POST "$TOOLBOX_URL" \170-H "Authorization: Bearer $TOKEN" \171-H "Content-Type: application/json" \172-H "Foundry-Features: Toolboxes=V1Preview" \173-H "mcp-session-id: <session-id-from-step-2>" \174-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"<tool_name>","arguments":{"query":"test"}}}' | jq .175```176177## Troubleshooting178179| Error | Cause | Resolution |180|-------|-------|------------|181| `CONSENT_REQUIRED` (code `-32007`) | OAuth MCP connection needs user consent | Open consent URL in browser, complete OAuth flow, retry |182| 401 on MCP calls | Expired token or wrong scope | Use scope `https://ai.azure.com/.default` (not `cognitiveservices`) and refresh token on every request |183| 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 |184| 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` |185| `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 |186| `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 |187| `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 |188| Tool not found on `tools/call` | Missing `server_label.` prefix for MCP-sourced tools | Call as `{server_label}.{tool_name}` |189| 500 on `prompts/list` | Not supported by toolbox endpoint | Pass `load_prompts=False` to MCP client constructor |190| 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 |191| 500 with non-streaming `tools/call` | Non-streaming not supported | Always use `stream=True` for toolbox MCP tools |192| 400 missing `api-version` | Query string dropped | Append `?api-version=v1` to every toolbox URL |193| Environment variable silently overwritten at runtime | Foundry reserves `FOUNDRY_`-prefixed env vars | Rename to a non-`FOUNDRY_` name (e.g. `TOOLBOX_ENDPOINT`) |194| 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 |195