Skip to content

Python: MCP tools with execution.taskSupport "optional" are skipped, although they can be called without Tasks #9675

Closed

Description

@gluc

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.

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 24, 2026
  2. Sainath-Reddy7 commented on Oct 25, 2026

    @Sainath-Reddy7

    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.

  3. eavanvalkenburg commented on Oct 26, 2026

    @eavanvalkenburg
    Member

    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.

  4. pamelafox commented on Oct 26, 2026

    @pamelafox
    Member

    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 a tasks capability:

    ← initialize: {"protocolVersion":"2025-11-25","capabilities":{"logging":{},"tools":{"listChanged":true}}}
    ← tools/list: {"name":"knowledge_base_retrieve", ..., "execution":{"taskSupport":"optional"}}
    

    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).

  5. pm25coder commented on Oct 27, 2026

    @pm25coder

    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 forbidden is 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.

  6. jpalvarezl commented on Oct 27, 2026

    @jpalvarezl
    Member

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

pythonUsage: [Issues, PRs], Target: Pythonready-for-implementationMaintainers agree the problem and direction are ready for implementation.triageUsage: [Issues], Target: All issues that still need to be triaged

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions