Skip to content

Commit 8d55e06

Browse files
agaonkerclaude
andcommitted
Deprecate the SSE transport
HTTP+SSE was superseded by Streamable HTTP in protocol revision 2025-03-26, and the spec now documents it only for backwards compatibility. Emit a DeprecationWarning from both SSE transport primitives — `sse_client` (client) and `SseServerTransport` (server) — and note the deprecation in their docstrings. The high-level `MCPServer.sse_app()` / `run(transport="sse")` build on `SseServerTransport`, so they surface the warning too. Unlike the WebSocket deprecation, SSE is used internally (the high-level server app, `ClientSessionGroup`, the `python -m mcp.client` CLI) and across the transport-parametrized interaction test suite. A `typing_extensions.deprecated` decorator would therefore force a `# pyright: ignore[reportDeprecated]` at every internal call site, which AGENTS.md discourages. A plain `warnings.warn` gives the same runtime signal with no static-analysis fallout. `filterwarnings = ["error"]` would otherwise promote the SDK's own deprecation notice to a test error wherever SSE is exercised, so add two scoped `ignore` entries (mirroring the existing pywin32 one) and assert the warnings are emitted in tests/shared/test_sse.py. Closes #2278 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent cf110e3 commit 8d55e06

7 files changed

Lines changed: 187 additions & 0 deletions

File tree

.serena/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/cache
2+
/project.local.yml

.serena/project.yml

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# the name by which the project can be referenced within Serena
2+
project_name: "python-sdk"
3+
4+
5+
# list of languages for which language servers are started; choose from:
6+
# al angular ansible bash clojure
7+
# cpp cpp_ccls crystal csharp csharp_omnisharp
8+
# dart elixir elm erlang fortran
9+
# fsharp go groovy haskell haxe
10+
# hlsl html java json julia
11+
# kotlin lean4 lua luau markdown
12+
# matlab msl nix ocaml pascal
13+
# perl php php_phpactor powershell python
14+
# python_jedi python_ty r rego ruby
15+
# ruby_solargraph rust scala scss solidity
16+
# svelte swift systemverilog terraform toml
17+
# typescript typescript_vts vue yaml zig
18+
# (This list may be outdated. For the current list, see values of Language enum here:
19+
# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py
20+
# For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.)
21+
# Note:
22+
# - For C, use cpp
23+
# - For JavaScript, use typescript
24+
# - For Angular projects, use angular (subsumes typescript+html; requires `npm install` in the project root)
25+
# - For Svelte projects, use svelte (subsumes typescript/javascript for .svelte projects; requires npm)
26+
# - For SCSS / Sass / plain CSS, use scss (some-sass-language-server handles all three)
27+
# - For Free Pascal/Lazarus, use pascal
28+
# Special requirements:
29+
# Some languages require additional setup/installations.
30+
# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers
31+
# When using multiple languages, the first language server that supports a given file will be used for that file.
32+
# The first language is the default language and the respective language server will be used as a fallback.
33+
# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored.
34+
languages:
35+
- python
36+
37+
# the encoding used by text files in the project
38+
# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings
39+
encoding: "utf-8"
40+
41+
# line ending convention to use when writing source files.
42+
# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default)
43+
# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings.
44+
line_ending:
45+
46+
# The language backend to use for this project.
47+
# If not set, the global setting from serena_config.yml is used.
48+
# Valid values: LSP, JetBrains
49+
# Note: the backend is fixed at startup. If a project with a different backend
50+
# is activated post-init, an error will be returned.
51+
language_backend:
52+
53+
# whether to use project's .gitignore files to ignore files
54+
ignore_all_files_in_gitignore: true
55+
56+
# advanced configuration option allowing to configure language server-specific options.
57+
# Maps the language key to the options.
58+
# Have a look at the docstring of the constructors of the LS implementations within solidlsp (e.g., for C# or PHP) to see which options are available.
59+
# No documentation on options means no options are available.
60+
ls_specific_settings: {}
61+
62+
# list of additional workspace folder paths for cross-package reference support (e.g. in monorepos).
63+
# Paths can be absolute or relative to the project root.
64+
# Each folder is registered as an LSP workspace folder, enabling language servers to discover
65+
# symbols and references across package boundaries.
66+
# Currently supported for: TypeScript.
67+
# Example:
68+
# additional_workspace_folders:
69+
# - ../sibling-package
70+
# - ../shared-lib
71+
additional_workspace_folders: []
72+
73+
# list of additional paths to ignore in this project.
74+
# Same syntax as gitignore, so you can use * and **.
75+
# Note: global ignored_paths from serena_config.yml are also applied additively.
76+
ignored_paths: []
77+
78+
# whether the project is in read-only mode
79+
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
80+
# Added on 2025-04-18
81+
read_only: false
82+
83+
# list of tool names to exclude.
84+
# This extends the existing exclusions (e.g. from the global configuration)
85+
# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html
86+
excluded_tools: []
87+
88+
# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default).
89+
# This extends the existing inclusions (e.g. from the global configuration).
90+
# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html
91+
included_optional_tools: []
92+
93+
# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools.
94+
# This cannot be combined with non-empty excluded_tools or included_optional_tools.
95+
# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html
96+
fixed_tools: []
97+
98+
# list of mode names that are to be activated by default, overriding the setting in the global configuration.
99+
# The full set of modes to be activated is base_modes (from global config) + default_modes + added_modes.
100+
# If the setting is undefined/empty, the default_modes from the global configuration (serena_config.yml) apply.
101+
# Otherwise, this overrides the setting from the global configuration (serena_config.yml).
102+
# Therefore, you can set this to [] if you do not want the default modes defined in the global config to apply
103+
# for this project.
104+
# This setting can, in turn, be overridden by CLI parameters (--mode).
105+
# See https://oraios.github.io/serena/02-usage/050_configuration.html#modes
106+
default_modes:
107+
108+
# list of mode names to be activated additionally for this project, e.g. ["query-projects"]
109+
# The full set of modes to be activated is base_modes (from global config) + default_modes + added_modes.
110+
# See https://oraios.github.io/serena/02-usage/050_configuration.html#modes
111+
added_modes:
112+
113+
# initial prompt for the project. It will always be given to the LLM upon activating the project
114+
# (contrary to the memories, which are loaded on demand).
115+
initial_prompt: ""
116+
117+
# time budget (seconds) per tool call for the retrieval of additional symbol information
118+
# such as docstrings or parameter information.
119+
# This overrides the corresponding setting in the global configuration; see the documentation there.
120+
# If null or missing, use the setting from the global configuration.
121+
symbol_info_budget:
122+
123+
# list of regex patterns which, when matched, mark a memory entry as read‑only.
124+
# Extends the list from the global configuration, merging the two lists.
125+
read_only_memory_patterns: []
126+
127+
# list of regex patterns for memories to completely ignore.
128+
# Matching memories will not appear in list_memories or activate_project output
129+
# and cannot be accessed via read_memory or write_memory.
130+
# To access ignored memory files, use the read_file tool on the raw file path.
131+
# Extends the list from the global configuration, merging the two lists.
132+
# Example: ["_archive/.*", "_episodes/.*"]
133+
ignored_memory_patterns: []

docs/migration.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ named `mcp.os.win32.utilities` (was `client.stdio.win32`).
149149

150150
The WebSocket transport has been removed: `mcp.client.websocket.websocket_client`, `mcp.server.websocket.websocket_server`, and the `ws` optional dependency extra (`mcp[ws]`) no longer exist. WebSocket was never part of the MCP specification. Use the streamable HTTP transport instead (`mcp.client.streamable_http.streamable_http_client` on the client, `streamable_http_app()` on the server), which supports bidirectional communication with server-to-client streaming over standard HTTP.
151151

152+
### SSE transport deprecated
153+
154+
The HTTP+SSE transport is now deprecated and emits a `DeprecationWarning`. The client transport `mcp.client.sse.sse_client` and the server transport `mcp.server.sse.SseServerTransport` (including the high-level `MCPServer.sse_app()` / `MCPServer.run(transport="sse")`, which build on it) are affected. HTTP+SSE was superseded by Streamable HTTP in protocol revision 2025-03-26 and the specification now documents it only for backwards compatibility. The transport still works and will be removed in a future version; migrate to the streamable HTTP transport (`streamable_http_client` on the client, `streamable_http_app()` on the server).
155+
152156
### Removed type aliases and classes
153157

154158
The following deprecated type aliases and classes have been removed from `mcp.types`:

pyproject.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,12 @@ filterwarnings = [
210210
"error",
211211
# pywin32 internal deprecation warning
212212
"ignore:getargs.*The 'u' format is deprecated:DeprecationWarning",
213+
# The SSE transport is intentionally deprecated (see sse_client / SseServerTransport). It is still
214+
# exercised across the suite (directly and via the transport-parametrized interaction tests), so the
215+
# SDK's own deprecation notice must not be promoted to an error here. tests/shared/test_sse.py asserts
216+
# the warning is emitted.
217+
"ignore:The SSE client transport is deprecated:DeprecationWarning",
218+
"ignore:The SSE server transport is deprecated:DeprecationWarning",
213219
]
214220

215221
[tool.markdown.lint]

src/mcp/client/sse.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
import warnings
23
from collections.abc import Callable
34
from contextlib import asynccontextmanager
45
from typing import Any
@@ -39,6 +40,10 @@ async def sse_client(
3940
):
4041
"""Client transport for SSE.
4142
43+
Deprecated: this transport will be removed in a future version. The HTTP+SSE
44+
transport was superseded by Streamable HTTP in protocol revision 2025-03-26;
45+
use the streamable HTTP transport (`streamable_http_client`) instead.
46+
4247
`sse_read_timeout` determines how long (in seconds) the client will wait for a new
4348
event before disconnecting. All other HTTP operations are controlled by `timeout`.
4449
@@ -51,6 +56,13 @@ async def sse_client(
5156
auth: Optional HTTPX authentication handler.
5257
on_session_created: Optional callback invoked with the session ID when received.
5358
"""
59+
warnings.warn(
60+
"The SSE client transport is deprecated and will be removed in a future version. The HTTP+SSE transport was"
61+
" superseded by Streamable HTTP in protocol revision 2025-03-26; use the streamable HTTP transport"
62+
" (`streamable_http_client`) instead.",
63+
DeprecationWarning,
64+
stacklevel=2,
65+
)
5466
logger.debug(f"Connecting to SSE endpoint: {remove_request_params(url)}")
5567
async with httpx_client_factory(
5668
headers=headers, auth=auth, timeout=httpx.Timeout(timeout, read=sse_read_timeout)

src/mcp/server/sse.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ async def handle_sse(request):
3737
"""
3838

3939
import logging
40+
import warnings
4041
from contextlib import asynccontextmanager
4142
from typing import Any
4243
from urllib.parse import quote
@@ -70,6 +71,10 @@ class SseServerTransport:
7071
2. handle_post_message() is an ASGI application which receives incoming POST
7172
requests, which should contain client messages that link to a
7273
previously-established SSE session.
74+
75+
Deprecated: this transport will be removed in a future version. The HTTP+SSE
76+
transport was superseded by Streamable HTTP in protocol revision 2025-03-26;
77+
use the streamable HTTP transport instead.
7378
"""
7479

7580
_endpoint: str
@@ -100,6 +105,13 @@ def __init__(self, endpoint: str, security_settings: TransportSecuritySettings |
100105
Raises:
101106
ValueError: If the endpoint is a full URL instead of a relative path
102107
"""
108+
warnings.warn(
109+
"The SSE server transport is deprecated and will be removed in a future version. The HTTP+SSE transport"
110+
" was superseded by Streamable HTTP in protocol revision 2025-03-26; use the streamable HTTP transport"
111+
" instead.",
112+
DeprecationWarning,
113+
stacklevel=2,
114+
)
103115

104116
super().__init__()
105117

tests/shared/test_sse.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,24 @@ def make_server_app() -> Starlette:
108108
return make_app(Server(SERVER_NAME, on_read_resource=_handle_read_resource))
109109

110110

111+
def test_sse_server_transport_emits_deprecation_warning() -> None:
112+
"""Constructing SseServerTransport warns that the SSE server transport is deprecated."""
113+
with pytest.warns(DeprecationWarning, match="The SSE server transport is deprecated"):
114+
SseServerTransport(
115+
"/messages/", security_settings=TransportSecuritySettings(enable_dns_rebinding_protection=False)
116+
)
117+
118+
119+
@pytest.mark.anyio
120+
async def test_sse_client_emits_deprecation_warning() -> None:
121+
"""Entering sse_client warns that the SSE client transport is deprecated."""
122+
factory = in_process_client_factory(make_server_app())
123+
with anyio.fail_after(5):
124+
with pytest.warns(DeprecationWarning, match="The SSE client transport is deprecated"):
125+
async with sse_client(f"{BASE_URL}/sse", httpx_client_factory=factory):
126+
pass
127+
128+
111129
@pytest.mark.anyio
112130
async def test_raw_sse_connection() -> None:
113131
"""The SSE GET responds 200 with an event-stream content type, announcing the session

0 commit comments

Comments
 (0)