python-sdk 废弃特性迁移指南:2026-07-28 规范下的 Deprecation 全面解读

python-sdk 废弃特性迁移指南:2026-07-28 规范下的 Deprecation 全面解读

【免费下载链接】python-sdkThe official Python SDK for Model Context Protocol servers and clients项目地址: https://gitcode.com/gh_mirrors/pythonsd/python-sdk

MCP(Model Context Protocol)官方 Python SDK(python-sdk)针对 2026-07-28 版协议规范对一批旧特性做了系统性收编:Roots、服务端发起的 Sampling、协议内 Logging 被标记为 deprecated,Progress 被限定为服务端到客户端单向,ping则被直接移出协议。本指南以 docs/deprecated.md 为骨架,逐项说明哪些 API 已废弃、为什么废弃、迁移到哪个新写法,并结合仓库源码(src/mcp/shared/exceptions.py、src/mcp/client/client.py 等)验证每一个行为,帮你把存量代码平滑升级到新协议时代。

一、2026-07-28 规范废弃了什么

1.1 五件被收编的事

官方文档用一张表列出了 2026-07-28 规范回收的五类能力,SDK 仍完整实现它们,但每一处调用现在都会触发Deprecation 警告:

废弃内容废弃原因替代方案
Roots:ctx.session.list_roots()、client.send_roots_list_changed()、传给Client(...)的list_roots_callback=SEP-2577)
服务端发起的 Sampling:ctx.session.create_message()、传给Client(...)的sampling_callback=SEP-2577 将该项能力整体标废返回InputRequiredResult,让客户端重试该调用(见 Multi-roundtrip 请求)
协议内 Logging:ctx.log()、ctx.debug()、ctx.info()、ctx.warning()、ctx.error()、ctx.session.send_log_message()、client.set_logging_level()SEP-2577 将该项能力整体标废,协议内没有替代品改用普通import logging输出到 stderr(见 Logging)
ping:client.send_ping()从协议中移除(而非简单废弃),2026-07-28 里没有ping方法没有替代品,它只在mode="legacy"连接上有效
客户端到服务端的 Progress:client.send_progress_notification()2026-07-28 只允许 Progress 从服务端到客户端客户端没有可发送的内容;由你的服务端用ctx.report_progress()上报进度(见 Progress)

1.2 从表里浮出来的三个结论

  1. Roots、Sampling、Logging 是一伙的:它们仨被同一个提案SEP-2577一次性标废。
  2. Sampling 和 Roots 共享一个更深层的问题:这两处都是服务端向客户端发请求的场景,而整个"服务端→客户端请求"方向,正是 2026-07-28 用 Multi-roundtrip 请求(multi-round-trip requests)取代的东西。消失的是独立的 RPC 方法(sampling/createMessage、roots/list,以及推送式的elicitation/create);而CreateMessageRequest/ListRootsRequest/ElicitRequest这些载荷类型被保留下来,嵌入到InputRequiredResult.input_requests中,客户端侧仍然落到同一批回调上。
  3. ping是个异类:协议没有废弃它,而是直接删除。SDK 方法仍然会警告(提示语写的是removed而不是deprecated),在现代连接上调用会得到"Method not found"响应。

二、"废弃"是提示,不是禁令

2.1 今天什么都不会坏

上述每一个方法,在协商版本为 2025-11-25 或更早的会话上都继续正常工作。客户端固定mode="legacy",就能拿到 2026 年之前完全一致的行为:线上数据格式不变,能力协商逻辑不变。

变化只发生在首次运行某个废弃方法时,你会看到一条可见的警告:

MCPDeprecationWarning: The logging capability is deprecated as of 2026-07-28 (SEP-2577).

2.2 为什么用UserWarning而不是DeprecationWarning

MCPDeprecationWarning是UserWarning的子类,不是DeprecationWarning的子类。这是有意为之:Python 的默认过滤器只在代码以__main__方式直接运行时显示DeprecationWarning,这正是"库废弃一个东西、两年没人发现"的经典路径。而这条自定义警告在任何位置都会显示,无需任何-W标志。

源码佐证见 src/mcp/shared/exceptions.py:class MCPDeprecationWarning(UserWarning)的 docstring 明确写道,继承UserWarning是为了"默认可见,让用户无需显式开启 warnings 就能发现废弃特性"。

2.3 提示的边界:线路上没有通道

"提示性质"止步于线路。Sampling 和 Roots 是服务端发给客户端的请求,而一个 2026-07-28 会话根本没有承载这种请求的通道。在工具内部、现代连接上调用ctx.session.create_message(),警告照样触发,但随后的发送会以错误失败:

Cannot send 'sampling/createMessage': this transport context has no back-channel for server-initiated requests.

这两个信号按顺序出现:

  • MCPDeprecationWarning在你调用方法的那一刻触发,与连接类型无关;
  • 错误是 SDK 随后尝试发送时返回的结果。

这两条路径只有在全程运行于mode="legacy"连接、且客户端注册了对应回调时才能端到端走通。对应地,仓库在 src/mcp/shared/exceptions.py 定义了NoBackChannelError:当请求作用域的通道报告TransportContext.can_send_request为False时抛出,序列化为INVALID_REQUEST错误响应——这正是文档中那段报错文案的实现源头。

三、在 legacy 会话上使用ping

Ping是一个空请求,任一方都可以发送它来确认对方仍在应答。2026-07-28 规范将其移除(SEP-2575):现代客户端发送的每个请求本身就证明了服务端在线,而现代服务端也没有通道主动发一个 ping。两条 SDK 方法在握手时代(handshake-era)的会话上仍然可用。

客户端侧:

async def main() -> None: async with Client("http://localhost:8000/mcp", mode="legacy") as client: await client.send_ping() # warns; returns an EmptyResult

服务端侧,在任意 handler 内:

@mcp.tool() async def check_client(ctx: Context) -> str: """A tool that still pings the client mid-call.""" await ctx.session.send_ping() # no warning; an EmptyResult while the client is connected return "client answered"

需要区分几个细节:

  • client.send_ping()每次调用都会触发MCPDeprecationWarning。在默认(2026-07-28)连接上,服务端会以MCPError: Method not found回应。
  • ctx.session.send_ping()不带警告。在现代连接上,它会像任何其他服务端发起的请求一样,因为缺少返回通道(back-channel)而抛出同样的错误。
  • 任何一侧都不会注册"应答 ping"的处理逻辑。

源码层面,src/mcp/client/client.py 中send_ping被@deprecated("ping is removed as of 2026-07-28; the method only works under mode='legacy'.", category=MCPDeprecationWarning)装饰——提示语用的正是removed,与文档一致;而 src/mcp/client/session.py 中的底层实现只是把PingRequest通过send_request发出去,本身没有任何警告装饰。

四、Roots 变更通知的完整链路

一个 2025 时代的客户端若声明了 roots 能力,可以通过发送notifications/roots/list_changed告知服务端自己的工作目录发生了变化;服务端收到后重新请求roots/list。2026-07-28 规范把这条通知连同整个推送式 roots 流程一起移除了。

4.1 客户端:回调声明 + 一个调用兑现承诺

在客户端,传入list_roots_callback=(详见 Client 回调)就是在声明"roots": {"listChanged": true},而下面这一个调用负责兑现这个承诺:

async def open_folder(client: Client, uri: str, name: str) -> None: """The user opened another folder: expose it through the roots callback, then tell the server.""" workspace.append(Root(uri=FileUrl(uri), name=name)) await client.send_roots_list_changed()

4.2 服务端:底层Server接收处理函数

在服务端,底层Server通过构造函数参数接收这个处理函数:

async def roots_changed(ctx: ServerRequestContext, params: NotificationParams | None) -> None: """The client's roots changed: ask for the new list.""" roots = (await ctx.session.list_roots()).roots server = Server("Bookshop", on_roots_list_changed=roots_changed)

4.3 行为细节

  • workspace是你的list_roots_callback返回的那个列表。client.send_roots_list_changed()会触发警告,而且它需要一个mode="legacy"客户端:在现代连接上,这条通知会被静默丢弃。调用后请保持会话开启,因为服务端随后的roots/list请求会经由这条会话送达。
  • MCPServer(高层封装)没有针对这条通知的钩子;只有底层Server的on_roots_list_changed=能注册 handler(该参数同样已废弃,构造时会警告)。通知本身不携带 payload,所以 handler 通过ctx.session.list_roots()去取新列表。

仓库侧的证据链完整:客户端方法 src/mcp/client/client.py 的send_roots_list_changed被@deprecated("The roots capability is deprecated as of 2026-07-28 (SEP-2577).", ...)装饰;服务端底层构造函数在 src/mcp/server/lowlevel/server.py 对on_roots_list_changed等参数统一发出废弃提示。测试 tests/client/test_list_roots_callback.py 则端到端验证了这条链路:mode="legacy"下,工具内context.session.list_roots()能取回回调返回的ListRootsResult;而不注册回调时,服务端会收到MCPError,其error.code == INVALID_REQUEST。

五、抑制警告(以及把警告变成测试失败)

5.1 新代码里:不要抑制

在新代码中,请直接按替代方案迁移,不要为了安静而屏蔽警告。

5.2 存量服务:按类别过滤

不过,一个确实还在服务 2026 年前客户端的存量服务,完全有权利拥有一份干净的日志。在第一个废弃调用运行之前,过滤掉该类别即可:

import warnings from mcp import MCPDeprecationWarning warnings.filterwarnings("ignore", category=MCPDeprecationWarning)

这就是全部 API。没有按方法区分的开关,也不该有:单一类别的意义就在于"一行让它静音,一行把它请回来"。

5.3 反转过滤器:白送一个回归测试

把过滤器反过来用,你会白得一个回归测试。在 pytest 配置的filterwarnings设置中加入"error::mcp.MCPDeprecationWarning",废弃调用就会从"警告"变成抛出异常。一个仍调用ctx.info()的名为old_log的工具将不再通过:调用会以is_error=True和Error executing tool old_log返回,而被捕获的服务端日志会点名元凶:

mcp.shared.exceptions.MCPDeprecationWarning: The logging capability is deprecated as of 2026-07-28 (SEP-2577).

一行 pytest 配置,就能让废弃调用再也无法悄悄溜回你的代码库而不让某个测试失败。

六、SDK 层面的废弃帮助函数

以下不是协议变更,只是 SDK 使用方式有了更好的替代品。它们用同一条MCPDeprecationWarning警告,且3.0 会移除旧形式。

废弃内容替代做法
FuncMetadata.call_fn_with_arg_validation()先FuncMetadata.validate_arguments(),再FuncMetadata.call_fn()。事实上只有直接驱动FuncMetadata的代码(比如自定义的Tool子类)才会调用它。
AuthSettings(resource_server_url=...)且不传validate_token_resource=显式设置它:True表示服务端拒绝你的 verifier 未报告为"为resource_server_url签发"的 Bearer Token;False表示由你的 verifier 自行检查 token 的 audience(见 Authorization:Token Verifier)。不设置时行为等同False;3.0 将在设置了resource_server_url时把True作为默认值。
ClientCredentialsOAuthProvider(...)或PrivateKeyJWTOAuthProvider(...)且不传issuer=传入issuer=,指名签发这批凭证的授权服务器(见 编写 OAuth 客户端:Machine-to-machine)。不传时由 MCP 服务器决定把凭证送给哪个授权服务器;3.0 会把这个关键字参数变为必填。

关于issuer的警告行为,仓库测试 tests/client/auth/extensions/test_client_credentials.py 中pytest.warns(MCPDeprecationWarning, match="Omittingissueris deprecated")给出了精确印证。

七、总结

  • 2026-07-28 规范废弃了Roots、服务端发起的Sampling和协议内Logging(都来自 SEP-2577),把Progress限定为服务端到客户端单向,并移除了ping。
  • 替代方案一栏指明了出路:Multi-roundtrip 请求 用于 Sampling 和 Roots,Logging 用于日志,Progress 用于进度;ping则什么都不需要。
  • 废弃是提示:没有线上格式变更,一切在 2026 年前的会话上照常工作,你会得到一条默认可见的MCPDeprecationWarning(它是UserWarning,因此默认开启)。
  • Sampling 和 Roots 额外需要一个 2026-07-28 会话所不具备的返回通道。在现代连接上,它们会先警告、随后抛出异常。
  • warnings.filterwarnings("ignore", category=MCPDeprecationWarning)可以静音整个类别;pytest 里的"error::mcp.MCPDeprecationWarning"则把它变成测试失败。
  • SDK 层面的废弃 遵循同一规则:现在警告,3.0 移除旧形式。
  • 新代码不应构建在任何这些废弃 API 之上。

本仓库文档的其余页面(docs)教授的都是当前(现代)API,升级时可据此对照迁移。

【免费下载链接】python-sdkThe official Python SDK for Model Context Protocol servers and clients项目地址: https://gitcode.com/gh_mirrors/pythonsd/python-sdk

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考