Azure / Azure/azure-sdk-for-python
Foundry Toolbox MCP proxy rejects MCPStreamableHTTPTool.call_tool() from custom tool code — "No tool config matches tool name"
- Dominant language
- Python
- Stars
- 5.6k
- Forks
- 3.4k
- Avg merge
- 1d 21h
- Merged PRs (30d)
- 193
Description
## 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.
Contributor guide
Assessment
This issue has not been assessed yet.