Azure / Azure/azure-sdk-for-python
Foundry Toolbox MCP proxy rejects MCPStreamableHTTPTool.call_tool() from custom tool code — "No tool config matches tool name"
- Lingua principale
- Python
- Stelle
- 5.6k
- Fork
- 3.4k
- Merge medio
- 2g 2h
- PR unite (30g)
- 213
Descrizione
## Python Version and Packages
- `agent-framework-core`: 1.2.2
- `agent-framework-foundry`: 1.2.2
- `agent-framework-devui`: 1.0.0b260304
- Python: 3.12.10
- OS: Windows 11
- MCP protocol version: 2025-11-25
- Foundry Toolbox endpoint: `{project_endpoint}/toolboxes/{name}/versions/{version}/mcp?api-version=v1`
## Description
Calling `MCPStreamableHTTPTool.call_tool()` directly from Python code inside a custom `@tool` function fails with:
```
McpError: No tool config matches tool name 'WorkIQSharePoint.readSmallBinaryFile'. Provide matching _meta.tools entries.
```
The **exact same tool** succeeds when the framework's executor pipeline invokes it (i.e., when the LLM decides to call it as a tool). This means:
- ✅ LLM → framework executor → `call_tool()` → **works**
- ❌ Custom `@tool` Python code → `toolbox_ref.call_tool()` → **fails**
This is a **regression** — the same code was working in production until recently (around May 10-12, 2026). No SDK or agent code was changed — the Foundry Toolbox MCP server-side appears to have started enforcing `_meta.tool_configuration` validation on `tools/call` requests.
## Steps to Reproduce
1. Create a Foundry Toolbox with MCP tools (e.g., WorkIQ SharePoint connector)
2. Connect via `MCPStreamableHTTPTool` with proper auth headers and `Foundry-Features: Toolboxes=V1Preview`
3. Register the toolbox as a tool on an `Agent`
4. Inside a custom `@tool` function, call `toolbox_ref.call_tool("ServerLabel.ToolName", arg=value)`
```python
from agent_framework import Agent, MCPStreamableHTTPTool, tool
import httpx
# Setup toolbox connection
toolbox = MCPStreamableHTTPTool(
name="my-toolbox",
url=f"{project_endpoint}/toolboxes/my-toolbox/versions/1/mcp?api-version=v1",
http_client=httpx.AsyncClient(
auth=MyAuth(token_provider),
headers={"Foundry-Features": "Toolboxes=V1Preview"},
),
load_prompts=False,
)
# Custom tool that calls MCP toolbox directly
@tool(approval_mode="never_require")
async def save_file_to_storage(document_library_id: str, file_id: str) -> dict:
# This FAILS:
result = await toolbox.call_tool(
"WorkIQSharePoint.readSmallBinaryFile",
documentLibraryId=document_library_id,
fileId=file_id,
)
# ... process result and save to storage ...
agent = Agent(client=client, tools=[toolbox, save_file_to_storage])
```
## Error
```
mcp.shared.exceptions.McpError: No tool config matches tool name 'WorkIQSharePoint.readSmallBinaryFile'. Provide matching _meta.tools entries.
```
The error originates from the Foundry Toolbox MCP server (`POST .../toolboxes/.../mcp`), not from the SDK.
## Root Cause Analysis
Looking at `MCPTool.call_tool()` in `_mcp.py`:
```python
otel_meta = _inject_otel_into_mcp_meta()
result = await self.session.call_tool(tool_name, arguments=filtered_kwargs, meta=otel_meta)
```
The `meta` parameter only contains OpenTelemetry trace context. It does **not** include the `_meta.tool_configuration` block that the Foundry Toolbox MCP proxy now requires.
When the framework's executor pipeline calls a tool (LLM → executor → `call_tool`), the `_meta.tool_configuration` is somehow injected (likely by the responses API or the executor's function invocation pipeline). But direct `call_tool()` from code bypasses this.
## Expected Behavior
`MCPStreamableHTTPTool.call_tool()` should work from custom tool code. The `_meta.tool_configuration` entries (available from `tools/list` response at connect time) should be automatically injected into the `meta` parameter of `session.call_tool()`.
## Actual Behavior
The Foundry Toolbox MCP proxy rejects the call because `_meta.tool_configuration` is missing from the request.
Guida per i contributori
Apri la guida per i contributori
Direzione di ricerca
Inizia in _mcp.py, da MCPTool.call_tool(), quindi segui come vengono conservati la risposta tools/list e i valori _meta prima dell’esecuzione di session.call_tool(). Riproduci il percorso diretto del custom-tool e confronta i metadati della richiesta con la pipeline dell’executor; il lavoro è completo quando Foundry Toolbox accetta la chiamata diretta con la configurazione dello strumento richiesta.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- python
- Ambito
- api, backend
- Tipo di issue
- Bug
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Tranquilla
- Chiarezza
- Specificata chiaramente
- Idoneità per principianti
- 58/100