Summary
On a server connection negotiated at protocol version 2026-07-28, a client ping request fails with MCPError: Method not found (-32601). The same ping works on handshake-era (2025-11-25 and earlier) connections.
Root cause
mcp_types.methods.CLIENT_REQUESTS (mcp-types 2.0.0) has ping entries for 2024-11-05, 2025-03-26, 2025-06-18, and 2025-11-25 — but no ("ping", "2026-07-28") entry. PingRequest is also absent from the vendored _v2026_07_28 schema module.
In mcp/server/runner.py ServerRunner._on_request:
if method in _methods.SPEC_CLIENT_METHODS:
try:
_methods.validate_client_request(method, version, params)
except KeyError:
raise MCPError(code=METHOD_NOT_FOUND, message="Method not found", data=method) from None
validate_client_request does surface[(method, version)], which raises KeyError for ("ping", "2026-07-28"), and the runner converts that to METHOD_NOT_FOUND. So ping is dead on all 2026-07-28 connections even though Server still registers the _ping_handler for the method.
Reproduction
import asyncio
from mcp.server.lowlevel import Server
from mcp.shared.memory import create_client_server_memory_streams
from mcp.client.session import ClientSession
server = Server("ping-probe")
async def main():
async with create_client_server_memory_streams() as (client_streams, server_streams):
c_read, c_write = client_streams
s_read, s_write = server_streams
async with ClientSession(c_read, c_write) as session:
task = asyncio.create_task(
server.run(s_read, s_write, server.create_initialization_options())
)
await session.initialize() # negotiates 2026-07-28 in v2.0.0
await session.send_ping() # MCPError: Method not found
task.cancel()
asyncio.run(main())
(With FastMCP 4.0.0b2, this also breaks fastmcp.Client(...).ping() whenever the client negotiates the modern era — e.g. mode="auto" probing server/discover. Pinning mode="legacy" works around it.)
Expected
Ping is a keepalive primitive; many clients send it on a timer regardless of negotiated version. Either:
- add
("ping", "2026-07-28") to CLIENT_REQUESTS with a PingRequest in the 2026 schema (ping is not listed as removed in the 2026-07-28 changelog), or
- exempt ping from the per-version surface gate the way the init-exempt methods are handled.
Environment
- mcp 2.0.0 (PyPI release, 2026-07-28)
- mcp-types 2.0.0
- Python 3.13
Summary
On a server connection negotiated at protocol version
2026-07-28, a clientpingrequest fails withMCPError: Method not found(-32601). The same ping works on handshake-era (2025-11-25 and earlier) connections.Root cause
mcp_types.methods.CLIENT_REQUESTS(mcp-types 2.0.0) has ping entries for 2024-11-05, 2025-03-26, 2025-06-18, and 2025-11-25 — but no("ping", "2026-07-28")entry.PingRequestis also absent from the vendored_v2026_07_28schema module.In
mcp/server/runner.pyServerRunner._on_request:validate_client_requestdoessurface[(method, version)], which raisesKeyErrorfor("ping", "2026-07-28"), and the runner converts that to METHOD_NOT_FOUND. So ping is dead on all 2026-07-28 connections even thoughServerstill registers the_ping_handlerfor the method.Reproduction
(With FastMCP 4.0.0b2, this also breaks
fastmcp.Client(...).ping()whenever the client negotiates the modern era — e.g.mode="auto"probingserver/discover. Pinningmode="legacy"works around it.)Expected
Ping is a keepalive primitive; many clients send it on a timer regardless of negotiated version. Either:
("ping", "2026-07-28")toCLIENT_REQUESTSwith aPingRequestin the 2026 schema (ping is not listed as removed in the 2026-07-28 changelog), orEnvironment