You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Python: MCP tools with execution.taskSupport "optional" are skipped, although they can be called without Tasks #9675
Versions: agent-framework 1.23.0, agent-framework-foundry-hosting 1.0.0b261022, mcp 2.3.0 (worked in agent-framework 1.21.0 with mcp 1.x).
What happens
Since the MCP 2.x migration (#9236), _load_tools_locked skips every tool whose execution.taskSupport is "required"or"optional":
Skipping MCP tool 'pbi-mcp___ExecuteQuery' because it (might) require the Tasks extension, which MCP Python SDK 2.2 does not implement.
A Foundry Toolbox (FoundryToolbox) marks its Power BI MCP tools and its Foundry IQ knowledge-base tool as "optional". After upgrading from 1.21 to 1.23, all of them disappear from the agent; only tools without taskSupport remain.
Expected
Per the MCP spec, "optional" means the client may invoke the tool with task augmentation, but a plain tools/call is valid. Only "required" tools need the Tasks extension. With 1.21 / mcp 1.x the same tools were called normally and work.
Suggestion
Skip only "required", and call "optional" tools as plain calls until Tasks client support (#9215) lands. Alternatively, make this configurable on MCPStreamableHTTPTool / FoundryToolbox.
Impact
Blocks upgrading Foundry-hosted agents that use Toolbox connections, with no workaround short of patching internals.
Reproduced on agent-framework-core 1.23.0 + mcp 2.3.0 — thanks for the clear report.
Minimal repro (mirroring the mock-session pattern from tests/core/test_mcp.py): a session exposing two tools, one plain and one with execution.task_support="optional", produces
Skipping MCP tool 'optional_task_tool' because it (might) require the Tasks extension, which MCP Python SDK 2.2 does not implement.
and only the plain tool ends up in tool._functions.
Root cause is the membership test at python/packages/core/agent_framework/_mcp.py (~line 3110): if task_support in ["required", "optional"] skips both. Per the Tasks-extension semantics, "optional" means the tool works without the extension (it may use it when available), so only "required" warrants skipping — which would also let the warning message drop the "(might)" hedge.
Proposed direction: skip only when task_support == "required", load "optional" tools normally, and add a regression test with both variants.
Following the AI-assisted contributions policy: this analysis and repro were prepared with an AI coding agent at my direction and reviewed by me; happy to implement once a maintainer adds ready-for-implementation or agrees with the direction.
Jose Alvarez (@jpalvarezl) could you take a look and comment on whether task-optional MCP tools should be callable through the ordinary tools/call path while task-required tools remain excluded?
Current tests and ADR 0045 exclude both, so we need your view on the intended compatibility boundary before settling the direction. This would not add Tasks-extension support. Related PR: #9690.
This also affects Azure AI Search knowledge base MCP endpoints used directly with MCPStreamableHTTPTool, not only via Foundry Toolbox. The server marks the tool "optional" but never declares a tasks capability:
On the compatibility-boundary question, the 2025-11-25 spec gates this before taskSupport is even considered:
If a server's capabilities do not include tasks.requests.tools.call, then clients MUST NOT attempt to use task augmentation on that server's tools, regardless of the execution.taskSupport value.
So for servers like this, the tool should simply be called normally. Suggestion: only evaluate taskSupport when the server declares tasks.requests.tools.call, and even then skip only "required" (as #9690 does).
On the boundary question: the client can't currently draw it on the peer, because it never holds the peer's Tasks answer.
On main (1168c00) the skip at python/packages/core/agent_framework/_mcp.py:3114-3121 reads one field from each tools/list entry — execution.task_support — and tests it against the literal pair ["required", "optional"]. The capabilities the client does cache are three flags at :2280-2282 (tools, prompts, logging); there is no fourth for tasks anywhere in that file. So a peer announcing tasks.requests.tools.call and a peer announcing nothing at all take the same branch.
I measured that rather than reading it off the source. With 1.23.0 from PyPI and mcp 2.3.0, a mock session exposing four tools (plain / optional / required / forbidden), run once presenting a tasks capability and once presenting none: both runs loaded ['plain', 'forbidden'] and skipped optional and required with the same "(might) require" warning, and nothing in the client read a capability attribute off the session during load_tools(). Applying #9690's change to the same install and re-running gave, in both arms, ['plain', 'optional', 'forbidden'], only required skipped, and the optional tool invoking through the ordinary path and returning content.
For settling the direction, two things already in the repo say the narrow rule is the intended one. python/packages/core/AGENTS.md:244 states it outright: tools advertising execution.taskSupport == "required" are skipped with a warning, while optional and task-free tools continue through ordinary tools/call. And tests/core/test_mcp.py:596 is what holds the code to the other reading — it asserts ['forbidden', 'ordinary'], which reads as correct at a glance because loading forbiddenis correct; the only wrong row is optional, and it's the test's name that encodes the rule.
ADR 0045:185 ("Tools that may require Tasks are not presented as ordinary supported calls") turns, for optional, on whether this client would ever attempt augmentation — and it can't, since a plain call is the only call it makes. That's the reading under which the ADR agrees with AGENTS.md instead of contradicting it.
If you'd rather make the peer's capability the gate, as Pamela Fox (@pamelafox) suggests, it isn't there to reuse: it would be that fourth flag at :2280-2282, and its one visible effect would be on required tools from peers that declare no tasks — where today's message blames the SDK's missing runtime rather than the peer's capabilities.
Agreed. I have opened a PR with the fix that is similar to the one you linked Pamela Fox (@pamelafox) , but also contains documentation updates. Thank you for reporting the issue.
Activity
Sainath-Reddy7 commentedon Oct 25, 2026
Reproduced on agent-framework-core 1.23.0 + mcp 2.3.0 — thanks for the clear report.
Minimal repro (mirroring the mock-session pattern from
tests/core/test_mcp.py): a session exposing two tools, one plain and one withexecution.task_support="optional", producesand only the plain tool ends up in
tool._functions.Root cause is the membership test at
python/packages/core/agent_framework/_mcp.py(~line 3110):if task_support in ["required", "optional"]skips both. Per the Tasks-extension semantics,"optional"means the tool works without the extension (it may use it when available), so only"required"warrants skipping — which would also let the warning message drop the "(might)" hedge.Proposed direction: skip only when
task_support == "required", load"optional"tools normally, and add a regression test with both variants.Following the AI-assisted contributions policy: this analysis and repro were prepared with an AI coding agent at my direction and reviewed by me; happy to implement once a maintainer adds
ready-for-implementationor agrees with the direction.eavanvalkenburg commentedon Oct 26, 2026
Jose Alvarez (@jpalvarezl) could you take a look and comment on whether task-optional MCP tools should be callable through the ordinary
tools/callpath while task-required tools remain excluded?Current tests and ADR 0045 exclude both, so we need your view on the intended compatibility boundary before settling the direction. This would not add Tasks-extension support. Related PR: #9690.
pamelafox commentedon Oct 26, 2026
Written with GitHub Copilot + Claude Opus 5.5.
This also affects Azure AI Search knowledge base MCP endpoints used directly with
MCPStreamableHTTPTool, not only via Foundry Toolbox. The server marks the tool"optional"but never declares ataskscapability:On the compatibility-boundary question, the 2025-11-25 spec gates this before
taskSupportis even considered:So for servers like this, the tool should simply be called normally. Suggestion: only evaluate
taskSupportwhen the server declarestasks.requests.tools.call, and even then skip only"required"(as #9690 does).pm25coder commentedon Oct 27, 2026
On the boundary question: the client can't currently draw it on the peer, because it never holds the peer's Tasks answer.
On main (1168c00) the skip at
python/packages/core/agent_framework/_mcp.py:3114-3121reads one field from eachtools/listentry —execution.task_support— and tests it against the literal pair["required", "optional"]. The capabilities the client does cache are three flags at:2280-2282(tools,prompts,logging); there is no fourth for tasks anywhere in that file. So a peer announcingtasks.requests.tools.calland a peer announcing nothing at all take the same branch.I measured that rather than reading it off the source. With 1.23.0 from PyPI and mcp 2.3.0, a mock session exposing four tools (plain / optional / required / forbidden), run once presenting a tasks capability and once presenting none: both runs loaded
['plain', 'forbidden']and skippedoptionalandrequiredwith the same "(might) require" warning, and nothing in the client read a capability attribute off the session duringload_tools(). Applying #9690's change to the same install and re-running gave, in both arms,['plain', 'optional', 'forbidden'], onlyrequiredskipped, and the optional tool invoking through the ordinary path and returning content.For settling the direction, two things already in the repo say the narrow rule is the intended one.
python/packages/core/AGENTS.md:244states it outright: tools advertisingexecution.taskSupport == "required"are skipped with a warning, while optional and task-free tools continue through ordinarytools/call. Andtests/core/test_mcp.py:596is what holds the code to the other reading — it asserts['forbidden', 'ordinary'], which reads as correct at a glance because loadingforbiddenis correct; the only wrong row isoptional, and it's the test's name that encodes the rule.ADR 0045:185 ("Tools that may require Tasks are not presented as ordinary supported calls") turns, for
optional, on whether this client would ever attempt augmentation — and it can't, since a plain call is the only call it makes. That's the reading under which the ADR agrees with AGENTS.md instead of contradicting it.If you'd rather make the peer's capability the gate, as Pamela Fox (@pamelafox) suggests, it isn't there to reuse: it would be that fourth flag at
:2280-2282, and its one visible effect would be onrequiredtools from peers that declare no tasks — where today's message blames the SDK's missing runtime rather than the peer's capabilities.jpalvarezl commentedon Oct 27, 2026
Agreed. I have opened a PR with the fix that is similar to the one you linked Pamela Fox (@pamelafox) , but also contains documentation updates. Thank you for reporting the issue.