Deprecate roots, sampling, and logging methods per SEP-2577 (#2926)
This commit is contained in:
parent
5734acf18e
commit
4573e4ac33
44 changed files with 206 additions and 123 deletions
18
README.v2.md
18
README.v2.md
|
|
@ -360,7 +360,7 @@ mcp = MCPServer(name="Progress Example")
|
|||
@mcp.tool()
|
||||
async def long_running_task(task_name: str, ctx: Context, steps: int = 5) -> str:
|
||||
"""Execute a task with progress updates."""
|
||||
await ctx.info(f"Starting: {task_name}")
|
||||
await ctx.info(f"Starting: {task_name}") # pyright: ignore[reportDeprecated]
|
||||
|
||||
for i in range(steps):
|
||||
progress = (i + 1) / steps
|
||||
|
|
@ -369,7 +369,7 @@ async def long_running_task(task_name: str, ctx: Context, steps: int = 5) -> str
|
|||
total=1.0,
|
||||
message=f"Step {i + 1}/{steps}",
|
||||
)
|
||||
await ctx.debug(f"Completed step {i + 1}")
|
||||
await ctx.debug(f"Completed step {i + 1}") # pyright: ignore[reportDeprecated]
|
||||
|
||||
return f"Task '{task_name}' completed"
|
||||
```
|
||||
|
|
@ -707,7 +707,7 @@ mcp = MCPServer(name="Progress Example")
|
|||
@mcp.tool()
|
||||
async def long_running_task(task_name: str, ctx: Context, steps: int = 5) -> str:
|
||||
"""Execute a task with progress updates."""
|
||||
await ctx.info(f"Starting: {task_name}")
|
||||
await ctx.info(f"Starting: {task_name}") # pyright: ignore[reportDeprecated]
|
||||
|
||||
for i in range(steps):
|
||||
progress = (i + 1) / steps
|
||||
|
|
@ -716,7 +716,7 @@ async def long_running_task(task_name: str, ctx: Context, steps: int = 5) -> str
|
|||
total=1.0,
|
||||
message=f"Step {i + 1}/{steps}",
|
||||
)
|
||||
await ctx.debug(f"Completed step {i + 1}")
|
||||
await ctx.debug(f"Completed step {i + 1}") # pyright: ignore[reportDeprecated]
|
||||
|
||||
return f"Task '{task_name}' completed"
|
||||
```
|
||||
|
|
@ -948,7 +948,7 @@ async def generate_poem(topic: str, ctx: Context) -> str:
|
|||
"""Generate a poem using LLM sampling."""
|
||||
prompt = f"Write a short poem about {topic}"
|
||||
|
||||
result = await ctx.session.create_message(
|
||||
result = await ctx.session.create_message( # pyright: ignore[reportDeprecated]
|
||||
messages=[
|
||||
SamplingMessage(
|
||||
role="user",
|
||||
|
|
@ -982,10 +982,10 @@ mcp = MCPServer(name="Notifications Example")
|
|||
async def process_data(data: str, ctx: Context) -> str:
|
||||
"""Process data with logging."""
|
||||
# Different log levels
|
||||
await ctx.debug(f"Debug: Processing '{data}'")
|
||||
await ctx.info("Info: Starting processing")
|
||||
await ctx.warning("Warning: This is experimental")
|
||||
await ctx.error("Error: (This is just a demo)")
|
||||
await ctx.debug(f"Debug: Processing '{data}'") # pyright: ignore[reportDeprecated]
|
||||
await ctx.info("Info: Starting processing") # pyright: ignore[reportDeprecated]
|
||||
await ctx.warning("Warning: This is experimental") # pyright: ignore[reportDeprecated]
|
||||
await ctx.error("Error: (This is just a demo)") # pyright: ignore[reportDeprecated]
|
||||
|
||||
# Notify about resource changes
|
||||
await ctx.session.send_resource_list_changed()
|
||||
|
|
|
|||
|
|
@ -1245,7 +1245,26 @@ Tasks are expected to return as a separate MCP extension in a future release.
|
|||
|
||||
## Deprecations
|
||||
|
||||
<!-- Add deprecations below -->
|
||||
### Roots, Sampling, and Logging methods deprecated (SEP-2577)
|
||||
|
||||
[SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577) deprecates the Roots, Sampling, and Logging features as of the 2026-07-28 spec. The deprecation is advisory only: there are no wire-level changes, capability negotiation is unchanged, and every method keeps working for sessions negotiating 2025-11-25 and earlier.
|
||||
|
||||
The user-facing methods for these features now carry `typing_extensions.deprecated`, so type checkers, IDEs, and the runtime surface a deprecation warning where they are called:
|
||||
|
||||
- Sampling: `ServerSession.create_message()`, `ClientPeer.sample()`
|
||||
- Roots: `ServerSession.list_roots()`, `ClientPeer.list_roots()`, `ClientSession.send_roots_list_changed()`, `Client.send_roots_list_changed()`
|
||||
- Logging: `ServerSession.send_log_message()`, `Connection.log()`, `ClientSession.set_logging_level()`, `Client.set_logging_level()`, `mcp.server.context.Context.log()` (the lowlevel `Context`), and the `MCPServer` `Context` helpers `log()`, `debug()`, `info()`, `warning()`, `error()`
|
||||
|
||||
The runtime warning is emitted as `mcp.MCPDeprecationWarning`, which subclasses `UserWarning` (not `DeprecationWarning`) so it is visible by default. To silence it, filter that category:
|
||||
|
||||
```python
|
||||
import warnings
|
||||
from mcp import MCPDeprecationWarning
|
||||
|
||||
warnings.filterwarnings("ignore", category=MCPDeprecationWarning)
|
||||
```
|
||||
|
||||
No migration is required during the deprecation window. New code should avoid building on these features, since they may be removed in a future spec version.
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
|
|
|
|||
|
|
@ -143,13 +143,13 @@ def test_multiple_content_types() -> list[TextContent | ImageContent | EmbeddedR
|
|||
@mcp.tool()
|
||||
async def test_tool_with_logging(ctx: Context) -> str:
|
||||
"""Tests tool that emits log messages during execution"""
|
||||
await ctx.info("Tool execution started")
|
||||
await ctx.info("Tool execution started") # pyright: ignore[reportDeprecated]
|
||||
await asyncio.sleep(0.05)
|
||||
|
||||
await ctx.info("Tool processing data")
|
||||
await ctx.info("Tool processing data") # pyright: ignore[reportDeprecated]
|
||||
await asyncio.sleep(0.05)
|
||||
|
||||
await ctx.info("Tool execution completed")
|
||||
await ctx.info("Tool execution completed") # pyright: ignore[reportDeprecated]
|
||||
return "Tool with logging executed successfully"
|
||||
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ async def test_sampling(prompt: str, ctx: Context) -> str:
|
|||
"""Tests server-initiated sampling (LLM completion request)"""
|
||||
try:
|
||||
# Request sampling from client
|
||||
result = await ctx.session.create_message(
|
||||
result = await ctx.session.create_message( # pyright: ignore[reportDeprecated]
|
||||
messages=[SamplingMessage(role="user", content=TextContent(type="text", text=prompt))],
|
||||
max_tokens=100,
|
||||
)
|
||||
|
|
@ -314,13 +314,13 @@ def test_error_handling() -> str:
|
|||
@mcp.tool()
|
||||
async def test_reconnection(ctx: Context) -> str:
|
||||
"""Tests SSE polling by closing stream mid-call (SEP-1699)"""
|
||||
await ctx.info("Before disconnect")
|
||||
await ctx.info("Before disconnect") # pyright: ignore[reportDeprecated]
|
||||
|
||||
await ctx.close_sse_stream()
|
||||
|
||||
await asyncio.sleep(0.2) # Wait for client to reconnect
|
||||
|
||||
await ctx.info("After reconnect")
|
||||
await ctx.info("After reconnect") # pyright: ignore[reportDeprecated]
|
||||
return "Reconnection test completed"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ async def handle_call_tool(ctx: ServerRequestContext, params: types.CallToolRequ
|
|||
|
||||
# Send the specified number of notifications with the given interval
|
||||
for i in range(count):
|
||||
await ctx.session.send_log_message(
|
||||
await ctx.session.send_log_message( # pyright: ignore[reportDeprecated]
|
||||
level="info",
|
||||
data=f"Notification {i + 1}/{count} from caller: {caller}",
|
||||
logger="notification_stream",
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ async def handle_call_tool(ctx: ServerRequestContext, params: types.CallToolRequ
|
|||
for i in range(count):
|
||||
# Include more detailed message for resumability demonstration
|
||||
notification_msg = f"[{i + 1}/{count}] Event from '{caller}' - Use Last-Event-ID to resume if disconnected"
|
||||
await ctx.session.send_log_message(
|
||||
await ctx.session.send_log_message( # pyright: ignore[reportDeprecated]
|
||||
level="info",
|
||||
data=notification_msg,
|
||||
logger="notification_stream",
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ async def handle_call_tool(ctx: ServerRequestContext, params: types.CallToolRequ
|
|||
content=[types.TextContent(type="text", text="Error: checkpoint_every must be between 1 and 20")]
|
||||
)
|
||||
|
||||
await ctx.session.send_log_message(
|
||||
await ctx.session.send_log_message( # pyright: ignore[reportDeprecated]
|
||||
level="info",
|
||||
data=f"Starting batch processing of {items} items...",
|
||||
logger="process_batch",
|
||||
|
|
@ -86,7 +86,7 @@ async def handle_call_tool(ctx: ServerRequestContext, params: types.CallToolRequ
|
|||
await anyio.sleep(0.5)
|
||||
|
||||
# Report progress
|
||||
await ctx.session.send_log_message(
|
||||
await ctx.session.send_log_message( # pyright: ignore[reportDeprecated]
|
||||
level="info",
|
||||
data=f"[{i}/{items}] Processing item {i}",
|
||||
logger="process_batch",
|
||||
|
|
@ -95,7 +95,7 @@ async def handle_call_tool(ctx: ServerRequestContext, params: types.CallToolRequ
|
|||
|
||||
# Checkpoint: close stream to trigger client reconnect
|
||||
if i % checkpoint_every == 0 and i < items:
|
||||
await ctx.session.send_log_message(
|
||||
await ctx.session.send_log_message( # pyright: ignore[reportDeprecated]
|
||||
level="info",
|
||||
data=f"Checkpoint at item {i} - closing SSE stream for polling",
|
||||
logger="process_batch",
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ mcp = MCPServer(name="Notifications Example")
|
|||
async def process_data(data: str, ctx: Context) -> str:
|
||||
"""Process data with logging."""
|
||||
# Different log levels
|
||||
await ctx.debug(f"Debug: Processing '{data}'")
|
||||
await ctx.info("Info: Starting processing")
|
||||
await ctx.warning("Warning: This is experimental")
|
||||
await ctx.error("Error: (This is just a demo)")
|
||||
await ctx.debug(f"Debug: Processing '{data}'") # pyright: ignore[reportDeprecated]
|
||||
await ctx.info("Info: Starting processing") # pyright: ignore[reportDeprecated]
|
||||
await ctx.warning("Warning: This is experimental") # pyright: ignore[reportDeprecated]
|
||||
await ctx.error("Error: (This is just a demo)") # pyright: ignore[reportDeprecated]
|
||||
|
||||
# Notify about resource changes
|
||||
await ctx.session.send_resource_list_changed()
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ async def generate_poem(topic: str, ctx: Context) -> str:
|
|||
"""Generate a poem using LLM sampling."""
|
||||
prompt = f"Write a short poem about {topic}"
|
||||
|
||||
result = await ctx.session.create_message(
|
||||
result = await ctx.session.create_message( # pyright: ignore[reportDeprecated]
|
||||
messages=[
|
||||
SamplingMessage(
|
||||
role="user",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ mcp = MCPServer(name="Progress Example")
|
|||
@mcp.tool()
|
||||
async def long_running_task(task_name: str, ctx: Context, steps: int = 5) -> str:
|
||||
"""Execute a task with progress updates."""
|
||||
await ctx.info(f"Starting: {task_name}")
|
||||
await ctx.info(f"Starting: {task_name}") # pyright: ignore[reportDeprecated]
|
||||
|
||||
for i in range(steps):
|
||||
progress = (i + 1) / steps
|
||||
|
|
@ -15,6 +15,6 @@ async def long_running_task(task_name: str, ctx: Context, steps: int = 5) -> str
|
|||
total=1.0,
|
||||
message=f"Step {i + 1}/{steps}",
|
||||
)
|
||||
await ctx.debug(f"Completed step {i + 1}")
|
||||
await ctx.debug(f"Completed step {i + 1}") # pyright: ignore[reportDeprecated]
|
||||
|
||||
return f"Task '{task_name}' completed"
|
||||
|
|
|
|||
|
|
@ -213,6 +213,10 @@ filterwarnings = [
|
|||
"error",
|
||||
# pywin32 internal deprecation warning
|
||||
"ignore:getargs.*The 'u' format is deprecated:DeprecationWarning",
|
||||
# SEP-2577 deprecates the roots/sampling/logging methods; the SDK still calls
|
||||
# them internally (e.g. `ctx.debug` -> `log` -> `send_log_message`), so the
|
||||
# advisory warning is silenced. Tests asserting it opt back in with pytest.warns.
|
||||
"ignore:.*is deprecated as of 2026-07-28 \\(SEP-2577\\).:mcp.MCPDeprecationWarning",
|
||||
]
|
||||
|
||||
[tool.markdown.lint]
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from .client.session_group import ClientSessionGroup
|
|||
from .client.stdio import StdioServerParameters, stdio_client
|
||||
from .server.session import ServerSession
|
||||
from .server.stdio import stdio_server
|
||||
from .shared.exceptions import MCPError, UrlElicitationRequiredError
|
||||
from .shared.exceptions import MCPDeprecationWarning, MCPError, UrlElicitationRequiredError
|
||||
from .types import (
|
||||
CallToolRequest,
|
||||
ClientCapabilities,
|
||||
|
|
@ -96,6 +96,7 @@ __all__ = [
|
|||
"ListToolsResult",
|
||||
"LoggingLevel",
|
||||
"LoggingMessageNotification",
|
||||
"MCPDeprecationWarning",
|
||||
"MCPError",
|
||||
"Notification",
|
||||
"PingRequest",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ from contextlib import AsyncExitStack
|
|||
from dataclasses import KW_ONLY, dataclass, field
|
||||
from typing import Any
|
||||
|
||||
from typing_extensions import deprecated
|
||||
|
||||
from mcp.client._memory import InMemoryTransport
|
||||
from mcp.client._transport import Transport
|
||||
from mcp.client.session import ClientSession, ElicitationFnT, ListRootsFnT, LoggingFnT, MessageHandlerFnT, SamplingFnT
|
||||
|
|
@ -13,6 +15,7 @@ from mcp.client.streamable_http import streamable_http_client
|
|||
from mcp.server import Server
|
||||
from mcp.server.mcpserver import MCPServer
|
||||
from mcp.shared.dispatcher import ProgressFnT
|
||||
from mcp.shared.exceptions import MCPDeprecationWarning
|
||||
from mcp.types import (
|
||||
CallToolResult,
|
||||
CompleteResult,
|
||||
|
|
@ -197,9 +200,10 @@ class Client:
|
|||
message=message,
|
||||
)
|
||||
|
||||
@deprecated("The logging capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def set_logging_level(self, level: LoggingLevel, *, meta: RequestParamsMeta | None = None) -> EmptyResult:
|
||||
"""Set the logging level on the server."""
|
||||
return await self.session.set_logging_level(level=level, meta=meta)
|
||||
return await self.session.set_logging_level(level=level, meta=meta) # pyright: ignore[reportDeprecated]
|
||||
|
||||
async def list_resources(
|
||||
self,
|
||||
|
|
@ -314,7 +318,8 @@ class Client:
|
|||
"""List available tools from the server."""
|
||||
return await self.session.list_tools(params=PaginatedRequestParams(cursor=cursor, _meta=meta))
|
||||
|
||||
@deprecated("The roots capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def send_roots_list_changed(self) -> None:
|
||||
"""Send a notification that the roots list has changed."""
|
||||
# TODO(Marcelo): Currently, there is no way for the server to handle this. We should add support.
|
||||
await self.session.send_roots_list_changed()
|
||||
await self.session.send_roots_list_changed() # pyright: ignore[reportDeprecated]
|
||||
|
|
|
|||
|
|
@ -10,13 +10,13 @@ import anyio
|
|||
import anyio.abc
|
||||
import anyio.lowlevel
|
||||
from pydantic import BaseModel, TypeAdapter, ValidationError
|
||||
from typing_extensions import Self, TypeVar
|
||||
from typing_extensions import Self, TypeVar, deprecated
|
||||
|
||||
from mcp import types
|
||||
from mcp.client._transport import ReadStream, WriteStream
|
||||
from mcp.shared._compat import resync_tracer
|
||||
from mcp.shared.dispatcher import CallOptions, DispatchContext, Dispatcher, ProgressFnT
|
||||
from mcp.shared.exceptions import MCPError
|
||||
from mcp.shared.exceptions import MCPDeprecationWarning, MCPError
|
||||
from mcp.shared.jsonrpc_dispatcher import JSONRPCDispatcher
|
||||
from mcp.shared.message import ClientMessageMetadata, SessionMessage
|
||||
from mcp.shared.session import RequestResponder
|
||||
|
|
@ -386,6 +386,7 @@ class ClientSession:
|
|||
)
|
||||
)
|
||||
|
||||
@deprecated("The logging capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def set_logging_level(
|
||||
self,
|
||||
level: types.LoggingLevel,
|
||||
|
|
@ -550,6 +551,7 @@ class ClientSession:
|
|||
|
||||
return result
|
||||
|
||||
@deprecated("The roots capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def send_roots_list_changed(self) -> None:
|
||||
"""Send a roots/list_changed notification."""
|
||||
await self.send_notification(types.RootsListChangedNotification())
|
||||
|
|
|
|||
|
|
@ -20,9 +20,10 @@ from typing import Any, TypeVar, overload
|
|||
|
||||
import anyio
|
||||
from pydantic import BaseModel
|
||||
from typing_extensions import deprecated
|
||||
|
||||
from mcp.shared.dispatcher import CallOptions, Outbound
|
||||
from mcp.shared.exceptions import NoBackChannelError
|
||||
from mcp.shared.exceptions import MCPDeprecationWarning, NoBackChannelError
|
||||
from mcp.shared.peer import Meta, dump_params
|
||||
from mcp.types import (
|
||||
ClientCapabilities,
|
||||
|
|
@ -209,6 +210,7 @@ class Connection:
|
|||
"""
|
||||
await self.send_raw_request("ping", dump_params(None, meta), opts)
|
||||
|
||||
@deprecated("The logging capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def log(self, level: LoggingLevel, data: Any, logger: str | None = None, *, meta: Meta | None = None) -> None:
|
||||
"""Send a `notifications/message` log entry on the standalone stream. Best-effort."""
|
||||
params: dict[str, Any] = {"level": level, "data": data}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@ from dataclasses import dataclass
|
|||
from typing import Any, Generic, Protocol
|
||||
|
||||
from pydantic import BaseModel
|
||||
from typing_extensions import TypeVar
|
||||
from typing_extensions import TypeVar, deprecated
|
||||
|
||||
from mcp.server.connection import Connection
|
||||
from mcp.server.session import ServerSession
|
||||
from mcp.shared.context import BaseContext
|
||||
from mcp.shared.dispatcher import DispatchContext
|
||||
from mcp.shared.exceptions import MCPDeprecationWarning
|
||||
from mcp.shared.message import CloseSSEStreamCallback
|
||||
from mcp.shared.peer import Meta
|
||||
from mcp.shared.transport_context import TransportContext
|
||||
|
|
@ -92,6 +93,7 @@ class Context(BaseContext[TransportContext], Generic[LifespanT_co]):
|
|||
"""
|
||||
return self.transport.headers
|
||||
|
||||
@deprecated("The logging capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def log(self, level: LoggingLevel, data: Any, logger: str | None = None, *, meta: Meta | None = None) -> None:
|
||||
"""Send a request-scoped `notifications/message` log entry.
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ from collections.abc import Iterable
|
|||
from typing import TYPE_CHECKING, Any, Generic
|
||||
|
||||
from pydantic import AnyUrl, BaseModel
|
||||
from typing_extensions import deprecated
|
||||
|
||||
from mcp.server.context import LifespanContextT, RequestT, ServerRequestContext
|
||||
from mcp.server.elicitation import (
|
||||
|
|
@ -14,6 +15,7 @@ from mcp.server.elicitation import (
|
|||
elicit_with_validation,
|
||||
)
|
||||
from mcp.server.lowlevel.helper_types import ReadResourceContents
|
||||
from mcp.shared.exceptions import MCPDeprecationWarning
|
||||
from mcp.types import LoggingLevel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -189,6 +191,7 @@ class Context(BaseModel, Generic[LifespanContextT, RequestT]):
|
|||
related_request_id=self.request_id,
|
||||
)
|
||||
|
||||
@deprecated("The logging capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def log(
|
||||
self,
|
||||
level: LoggingLevel,
|
||||
|
|
@ -205,7 +208,7 @@ class Context(BaseModel, Generic[LifespanContextT, RequestT]):
|
|||
(string, dict, list, number, bool, etc.) per the MCP specification.
|
||||
logger_name: Optional logger name
|
||||
"""
|
||||
await self.request_context.session.send_log_message(
|
||||
await self.request_context.session.send_log_message( # pyright: ignore[reportDeprecated]
|
||||
level=level,
|
||||
data=data,
|
||||
logger=logger_name,
|
||||
|
|
@ -265,18 +268,22 @@ class Context(BaseModel, Generic[LifespanContextT, RequestT]):
|
|||
await self._request_context.close_standalone_sse_stream()
|
||||
|
||||
# Convenience methods for common log levels
|
||||
@deprecated("The logging capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def debug(self, data: Any, *, logger_name: str | None = None) -> None:
|
||||
"""Send a debug log message."""
|
||||
await self.log("debug", data, logger_name=logger_name)
|
||||
await self.log("debug", data, logger_name=logger_name) # pyright: ignore[reportDeprecated]
|
||||
|
||||
@deprecated("The logging capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def info(self, data: Any, *, logger_name: str | None = None) -> None:
|
||||
"""Send an info log message."""
|
||||
await self.log("info", data, logger_name=logger_name)
|
||||
await self.log("info", data, logger_name=logger_name) # pyright: ignore[reportDeprecated]
|
||||
|
||||
@deprecated("The logging capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def warning(self, data: Any, *, logger_name: str | None = None) -> None:
|
||||
"""Send a warning log message."""
|
||||
await self.log("warning", data, logger_name=logger_name)
|
||||
await self.log("warning", data, logger_name=logger_name) # pyright: ignore[reportDeprecated]
|
||||
|
||||
@deprecated("The logging capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def error(self, data: Any, *, logger_name: str | None = None) -> None:
|
||||
"""Send an error log message."""
|
||||
await self.log("error", data, logger_name=logger_name)
|
||||
await self.log("error", data, logger_name=logger_name) # pyright: ignore[reportDeprecated]
|
||||
|
|
|
|||
|
|
@ -12,12 +12,13 @@ used to live here are now owned by `JSONRPCDispatcher` and `ServerRunner`.
|
|||
from typing import Any, TypeVar, cast, overload
|
||||
|
||||
from pydantic import AnyUrl, BaseModel
|
||||
from typing_extensions import deprecated
|
||||
|
||||
from mcp import types
|
||||
from mcp.server.connection import Connection
|
||||
from mcp.server.validation import validate_sampling_tools, validate_tool_use_result_messages
|
||||
from mcp.shared.dispatcher import CallOptions, Dispatcher, ProgressFnT
|
||||
from mcp.shared.exceptions import NoBackChannelError, StatelessModeNotSupported
|
||||
from mcp.shared.exceptions import MCPDeprecationWarning, NoBackChannelError, StatelessModeNotSupported
|
||||
from mcp.shared.message import ServerMessageMetadata
|
||||
from mcp.types import methods as _methods
|
||||
|
||||
|
|
@ -126,6 +127,7 @@ class ServerSession:
|
|||
"""Check if the client supports a specific capability."""
|
||||
return self._connection.check_capability(capability)
|
||||
|
||||
@deprecated("The logging capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def send_log_message(
|
||||
self,
|
||||
level: types.LoggingLevel,
|
||||
|
|
@ -154,6 +156,7 @@ class ServerSession:
|
|||
)
|
||||
|
||||
@overload
|
||||
@deprecated("The sampling capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def create_message(
|
||||
self,
|
||||
messages: list[types.SamplingMessage],
|
||||
|
|
@ -173,6 +176,7 @@ class ServerSession:
|
|||
...
|
||||
|
||||
@overload
|
||||
@deprecated("The sampling capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def create_message(
|
||||
self,
|
||||
messages: list[types.SamplingMessage],
|
||||
|
|
@ -191,6 +195,7 @@ class ServerSession:
|
|||
"""Overload: With tools, returns array-capable content."""
|
||||
...
|
||||
|
||||
@deprecated("The sampling capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def create_message(
|
||||
self,
|
||||
messages: list[types.SamplingMessage],
|
||||
|
|
@ -267,6 +272,7 @@ class ServerSession:
|
|||
metadata=metadata_obj,
|
||||
)
|
||||
|
||||
@deprecated("The roots capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def list_roots(self) -> types.ListRootsResult:
|
||||
"""Send a roots/list request."""
|
||||
if self._stateless:
|
||||
|
|
|
|||
|
|
@ -5,6 +5,17 @@ from typing import Any, cast
|
|||
from mcp.types import INVALID_REQUEST, URL_ELICITATION_REQUIRED, ElicitRequestURLParams, ErrorData, JSONRPCError
|
||||
|
||||
|
||||
class MCPDeprecationWarning(UserWarning):
|
||||
"""A custom deprecation warning for the MCP SDK.
|
||||
|
||||
Unlike the built-in `DeprecationWarning`, this inherits from `UserWarning` so
|
||||
it is shown by default, helping users discover deprecated features without
|
||||
enabling warnings explicitly.
|
||||
|
||||
Reference: https://sethmlarson.dev/deprecations-via-warnings-dont-work-for-python-libraries
|
||||
"""
|
||||
|
||||
|
||||
class MCPError(Exception):
|
||||
"""Exception type raised when an error arrives over an MCP connection."""
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@ from collections.abc import Mapping
|
|||
from typing import Any, cast, overload
|
||||
|
||||
from pydantic import BaseModel
|
||||
from typing_extensions import deprecated
|
||||
|
||||
from mcp.shared.dispatcher import CallOptions, Outbound
|
||||
from mcp.shared.exceptions import MCPDeprecationWarning
|
||||
from mcp.types import (
|
||||
CreateMessageRequestParams,
|
||||
CreateMessageResult,
|
||||
|
|
@ -83,6 +85,7 @@ class ClientPeer:
|
|||
await self._outbound.notify(method, params)
|
||||
|
||||
@overload
|
||||
@deprecated("The sampling capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def sample(
|
||||
self,
|
||||
messages: list[SamplingMessage],
|
||||
|
|
@ -100,6 +103,7 @@ class ClientPeer:
|
|||
opts: CallOptions | None = None,
|
||||
) -> CreateMessageResult: ...
|
||||
@overload
|
||||
@deprecated("The sampling capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def sample(
|
||||
self,
|
||||
messages: list[SamplingMessage],
|
||||
|
|
@ -116,6 +120,7 @@ class ClientPeer:
|
|||
meta: Meta | None = None,
|
||||
opts: CallOptions | None = None,
|
||||
) -> CreateMessageResultWithTools: ...
|
||||
@deprecated("The sampling capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def sample(
|
||||
self,
|
||||
messages: list[SamplingMessage],
|
||||
|
|
@ -195,6 +200,7 @@ class ClientPeer:
|
|||
result = await self.send_raw_request("elicitation/create", dump_params(params, meta), opts)
|
||||
return ElicitResult.model_validate(result, by_name=False)
|
||||
|
||||
@deprecated("The roots capability is deprecated as of 2026-07-28 (SEP-2577).", category=MCPDeprecationWarning)
|
||||
async def list_roots(self, *, meta: Meta | None = None, opts: CallOptions | None = None) -> ListRootsResult:
|
||||
"""Send a `roots/list` request.
|
||||
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ async def test_client_unsubscribe_resource(simple_server: Server):
|
|||
async def test_client_set_logging_level(simple_server: Server):
|
||||
"""Test setting logging level."""
|
||||
async with Client(simple_server) as client:
|
||||
result = await client.set_logging_level("debug")
|
||||
result = await client.set_logging_level("debug") # pyright: ignore[reportDeprecated]
|
||||
assert result == snapshot(EmptyResult())
|
||||
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue