Skip to content

Python: [BREAKING] Remove deprecated MCP compatibility surfaces in vNext #9452

Open

Description

Context

The MCP SDK 2.x migration in #9236 retained several deprecated compatibility surfaces so existing applications could move forward without an immediate second breaking change. PR #9237 documents the final high-level Client versus low-level ClientSession ownership boundary and formalizes the remaining low-level paths as deprecated.

This issue tracks removing those compatibility surfaces in the next major release. It is an API cleanup issue, not a request to remove supported legacy MCP peer/protocol behavior. Legacy negotiation and wire compatibility should remain unless separately deprecated.

The current MCP Tasks extension should be designed independently in #9215 rather than reviving the removed pre-2.x task implementation.

Removal checklist

Caller-supplied low-level session path

  • Remove the session: ClientSession | None constructor parameter from MCPTool, MCPStdioTool, and MCPStreamableHTTPTool.
  • Remove _SessionMCPConnection and all direct-operation routing through caller-supplied ClientSession objects.
  • Remove MCPTool.session and its setter; framework-owned and caller-owned high-level Client connections must continue to route operations through Client.
  • Remove low-level-session initialization, ownership, reconnect, header-identity, cleanup, and compatibility branches that become unreachable.
  • Remove or migrate tests that exercise unnegotiated, caller-owned, caller-replaced, or directly mocked ClientSession connections.
  • Update skills, Declarative, Foundry Toolbox, security helpers, and other integrations that read or assign MCPTool.session to use the normalized high-level connection/operation seam.
  • Remove low-level session examples and documentation from API references, docstrings, ADRs, and contributor guidance.

Removed Tasks API compatibility

  • Remove the deprecated MCPTaskOptions compatibility class.
  • Remove MCPTaskOptions from root lazy exports, __all__, and agent_framework/__init__.pyi.
  • Remove the ignored task_options parameter from MCPTool, MCPStdioTool, MCPStreamableHTTPTool, and any remaining compatibility constructors.
  • Remove the associated deprecation warnings, docstrings, typing suppressions, and compatibility tests.
  • Confirm the removed mcp_long_running_task.py server/sample and its prerequisites/documentation are not reintroduced by the cleanup.
  • Keep the new MCP Tasks design scoped to Python: Design MCP 2026 Tasks client support with SDK v2 extensions #9215; do not restore the pre-MCP-2.x polling, cancellation, TTL, or tasks/get / tasks/result implementation as part of this issue.

Removed transport compatibility

  • Remove the deprecated MCPWebsocketTool class and constructor compatibility surface.
  • Remove MCPWebsocketTool from root lazy exports, __all__, and agent_framework/__init__.pyi.
  • Remove WebSocket-specific telemetry attributes, compatibility kwargs, docstrings, and deprecation tests.
  • Remove remaining documentation that presents WebSocket as an available MCP transport; direct users to MCPStreamableHTTPTool.

Deprecated MCP sampling surface

  • Remove the deprecated MCPTool.sampling_callback implementation and its deprecation-warning machinery.
  • Remove SamplingApprovalCallback and the wrapper-owned sampling options (client, sampling_approval_callback, sampling_max_tokens, and sampling_max_requests) from MCP tool constructors and root exports where they exist only for MCP sampling.
  • Remove sampling counters, token-cap helpers, approval gates, callback conversion code, and modern/legacy sampling compatibility tests.
  • Remove the dedicated sampling approval sample and its README entry if they have not already been removed by Python: Document MCP v2 client lifecycle and update samples #9237.
  • Update remaining docs to state that deprecated MCP sampling is no longer implemented by Agent Framework.

Server/hosting and cross-package cleanup from #9236

  • Verify agent-framework-hosting-mcp adapters expose only the current MCP 2.x server model/error/result APIs; remove any compatibility-only aliases, fallbacks, or tests that exist solely for the deprecated surfaces above.
  • Remove Tasks-era server fixtures, task-advertisement assumptions, and sample documentation that belonged to the deleted pre-2.x Tasks implementation.
  • Complete the hosting sample naming cleanup from FastMCP / fastmcp_app.py to MCPServer / mcpserver_app.py if Python: Document MCP v2 client lifecycle and update samples #9237 has not already merged it.
  • Update Declarative MCP handling and Foundry Toolbox integrations so they no longer depend on MCPTool.session or a caller-supplied low-level session.
  • Remove compatibility-only tests across Core, Hosting MCP, Declarative, Foundry Hosting, security, observability, and skills while preserving current high-level Client coverage.
  • Verify package metadata, type stubs, public API snapshots, samples, and generated documentation contain no removed symbol or parameter.

Validation and release readiness

  • Add a migration note for each removed public symbol/parameter with the supported high-level mcp.Client replacement.
  • Run repository-wide code search for MCPTaskOptions, task_options, MCPWebsocketTool, SamplingApprovalCallback, sampling_callback, sampling constructor options, and MCPTool.session.
  • Run full Python formatting, linting, typing, package tests, sample checks, and public-API validation.
  • Confirm legacy MCP peer negotiation and operation coverage still passes; removing these deprecated Python APIs must not accidentally remove supported legacy wire compatibility.
  • Update the relevant changelog/release documentation as a next-major breaking change.

Acceptance criteria

  • The deprecated compatibility symbols and parameters above are absent from runtime exports, type stubs, docs, and tests.
  • Framework-owned and caller-owned high-level MCP connections use mcp.Client as the only public connection ownership model.
  • No pre-MCP-2.x Tasks implementation is restored; future Tasks support follows Python: Design MCP 2026 Tasks client support with SDK v2 extensions #9215.
  • Current MCP 2.x server/hosting adapters and supported legacy peer behavior continue to work.
  • The next-major migration guidance clearly identifies replacements for removed APIs.

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    breaking changeUsage: [PRs], Target: all PRs that introduce changes that are not backward compatible
    mcpUsage: [Issues, PRs], Target: MCP
    vnextUsage: [Issues, PRs], Target: breaking-change features deferred to the next major release
    on Oct 16, 2026
  2. changed the title [-]Python: Remove deprecated MCP compatibility surfaces in vNext[/-] [+]Python: [BREAKING] Remove deprecated MCP compatibility surfaces in vNext[/+] on Oct 16, 2026
  3. jpalvarezl commented on Oct 16, 2026

    @jpalvarezl
    MemberAuthor

    MCPSkills and Foundry composition follow-ups

    These items came out of the MCP v2 lifecycle review. They are intentionally tracked as vNext follow-ups rather than expanding the current PR:

    • Remove deprecated ClientSession support from MCPSkillsSource and MCPSkill; accept and document high-level mcp.Client as the connection model.
    • Replace or remove the compatibility-named session_provider API. If a replacement provider API is needed, name it for connections/resource reads and document that returned Clients are borrowed, already entered, and never closed by MCPSkills.
    • Remove session-centric internal names and documentation (_session_provider, "session resolver", swapped MCPTool.session) in favor of connection/resource-read terminology.
    • Remove remaining MCPSkills samples and contributor guidance that construct or promote raw ClientSession; migrate them to high-level Client or FoundryToolbox.as_skills_provider().
    • Remove Foundry Toolbox tests and adapters that read, assign, or impersonate MCPTool.session / ClientSession solely for skills resource access.
    • Replace the internal Foundry session-shaped resource adapter and ClientSession cast with a narrowly typed resource-read abstraction if that adapter is still needed after low-level session removal.
    • Add or retain real high-level Client coverage for fixed connections, provider-resolved replacement connections, response caching, MRTR, and caller-owned lifecycle behavior.
    • Decide separately whether Foundry Toolbox needs a public composable SkillsSource API for aggregating local and Toolbox skills. Do not introduce an as_skills_source() API as incidental cleanup; require an explicit API proposal, naming review, caching/identity semantics, samples, and tests.
    • If no public composable source API is approved, document the supported composition pattern and update mixed local/Toolbox skill samples accordingly.
  4. jpalvarezl commented on Oct 16, 2026

    @jpalvarezl
    MemberAuthor

    Follow-up: connection-owning MCPSkillsSource(url=...)

    Related review discussion: #9237 (comment)

    The suggestion is to let callers write something like:

    source = MCPSkillsSource(url="https://example.com/mcp")

    instead of constructing and entering an mcp.Client themselves. This is more than a constructor convenience because the source would then own an asynchronous connection lifecycle.

    Today, SkillsSource exposes only get_skills(context). SkillsProvider calls that method from before_run, but it does not enter or close the source. An MCP Client also cannot be opened only for the index read and immediately closed: the returned MCPSkill objects fetch SKILL.md bodies and resources later, so the same owned connection must remain available beyond discovery.

    Design TODOs

    • Decide whether the public input should be url, server, or a broader SDK transport/server input matching mcp.Client(...).
    • Define the ownership rule: a URL/server/transport input creates an Agent Framework-owned Client; a supplied Client remains caller-owned and already entered.
    • Decide where source lifecycle belongs:
      • add an async lifecycle contract to SkillsSource and have SkillsProvider enter/close it;
      • make SkillsProvider specifically own managed MCP sources;
      • or introduce a separate managed MCP skills source/provider type rather than changing every source.
    • Keep the owned Client entered across index discovery, lazy SKILL.md loading, sibling resource reads, and archive downloads.
    • Define cleanup through agent/provider open/close, partial-open failure, cancellation, repeated close, and failed discovery.
    • Define concurrency semantics when multiple runs or agents share one source: connect coalescing, in-flight reads, close while active, and reconnect/replacement behavior.
    • Define authentication and transport configuration for URL-owned sources without duplicating MCPStreamableHTTPTool header/HTTP-client APIs.
    • Preserve SDK Client caching and MRTR behavior for all resource reads; do not fall back to ClientSession operations.
    • Ensure a managed source closes only Clients it created and never closes a caller-supplied Client.
    • Decide how managed connection lifetime interacts with CachingSkillsSource, especially cached MCPSkill objects retained after discovery.
    • Add tests for ownership, lazy reads after discovery, caching, MRTR, reconnect, concurrency, cancellation, and cleanup.
    • Add a minimal URL-based sample only after the lifecycle contract is established.

    This should be treated as an explicit lifecycle/API feature, not folded into terminology cleanup or the current PR incidentally.

  5. jpalvarezl commented on Oct 19, 2026

    @jpalvarezl
    MemberAuthor

    MCP transport-tool ownership cleanup

    Follow-up from #9369: the stabilized transport constructors distinguish framework-owned construction parameters from a caller-owned high-level mcp.Client. The compatibility branches below should be removed in vNext rather than carried into the final API.

    MCPStreamableHTTPTool

    • Remove the deprecated session: ClientSession | None parameter, including the temporarily preserved url + session constructor path.
    • Remove HTTP-tool branches that initialize, inspect, trace, reset, or route operations through a caller-supplied low-level session; retain supported legacy wire-protocol negotiation through the high-level mcp.Client.
    • Remove the caller-supplied http_client: httpx2.AsyncClient | None constructor parameter and its borrowed-lifecycle contract.
    • Simplify _httpx_client handling so any HTTP client created inside URL-owned mode is always framework-owned and deterministically closed; remove owned-versus-borrowed HTTP-client cleanup branches and tests.
    • Direct callers that need a customized HTTP client or transport to configure an SDK transport/high-level mcp.Client themselves and pass it through mcp_client=.
    • Revisit HTTP-only constructor options and supporting hooks that exist primarily to configure or protect a caller-supplied HTTP client; keep only options required for the final framework-owned URL transport contract.
    • Remove compatibility docstrings, warnings, telemetry branches, security tests, and lifecycle tests that exist solely for session= or caller-supplied http_client=.

    MCPStdioTool

    • Remove the deprecated session: ClientSession | None parameter, including temporarily preserved command + session and session-only compatibility paths.
    • Remove stdio-tool branches that initialize, inspect, reset, or route operations through a caller-supplied low-level session.
    • Remove compatibility tests and documentation that require placeholder process configuration for an externally owned connection.
    • Keep command, args, env, encoding, and stdio transport kwargs scoped exclusively to framework-owned process construction.
    • Ensure transport telemetry represents only a process/transport the wrapper actually created; do not report pipe transport solely because a caller-owned Client was wrapped by MCPStdioTool.
    • Decide explicitly whether caller-owned high-level Clients remain accepted by transport-specific wrappers or move to a transport-neutral Client-backed MCP tool. Do not infer transport identity from SDK Client internals.

    Final ownership surface

    • Reduce transport constructors to their final ownership modes after compatibility removal: framework-owned URL/command construction or caller-owned high-level Client, never contradictory combinations.
    • Remove associated compatibility docstrings, warnings, telemetry branches, security tests, lifecycle tests, and type suppressions.
    • Add migration guidance showing how low-level-session users and custom-transport users construct an entered high-level mcp.Client and pass mcp_client= without transferring ownership.

    This cleanup must not remove automatic fallback to supported legacy MCP peers; it removes deprecated Python ownership/configuration surfaces only.

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

Metadata

Metadata

Labels

breaking changeUsage: [PRs], Target: all PRs that introduce changes that are not backward compatiblemcpUsage: [Issues, PRs], Target: MCPpythonUsage: [Issues, PRs], Target: PythonvnextUsage: [Issues, PRs], Target: breaking-change features deferred to the next major release

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions