@@ -426,9 +426,95 @@ await client.read_resource("test://resource")
426426await client.read_resource(str (my_any_url))
427427```
428428
429- ## Deprecations
429+ ### Low-Level Server Decorator-Based API Removed
430430
431- <!-- Add deprecations below -->
431+ The decorator-based API for registering handlers on the low-level ` Server ` class has been removed. Use the constructor-based handler registration instead, which provides better type safety and clearer dependencies.
432+
433+ ** Before (v1):**
434+
435+ ``` python
436+ from mcp.server.lowlevel import Server
437+
438+ server = Server(" my-server" )
439+
440+ @server.list_tools ()
441+ async def list_tools ():
442+ return [types.Tool(name = " tool" , description = " ..." )]
443+
444+ @server.call_tool ()
445+ async def call_tool (name : str , arguments : dict ):
446+ return {" result" : " ..." }
447+ ```
448+
449+ ** After (v2):**
450+
451+ ``` python
452+ from mcp.server.lowlevel import Server
453+ from mcp.server.session import ServerSession
454+ from mcp.shared.context import RequestContext
455+ import mcp.types as types
456+ from typing import Any
457+
458+ async def list_tools (
459+ ctx : RequestContext[ServerSession, Any, Any],
460+ params : types.PaginatedRequestParams | None ,
461+ ) -> types.ListToolsResult:
462+ return types.ListToolsResult(tools = [
463+ types.Tool(name = " tool" , description = " ..." , input_schema = {" type" : " object" })
464+ ])
465+
466+ async def call_tool (
467+ ctx : RequestContext[ServerSession, Any, Any],
468+ params : types.CallToolRequestParams,
469+ ) -> types.CallToolResult:
470+ return types.CallToolResult(
471+ content = [types.TextContent(type = " text" , text = " result" )]
472+ )
473+
474+ server = Server(
475+ " my-server" ,
476+ on_list_tools = list_tools,
477+ on_call_tool = call_tool,
478+ )
479+ ```
480+
481+ ** Key differences:**
482+
483+ 1 . Handlers receive ` (context, params) ` instead of extracted arguments
484+ 2 . Handlers return proper result types (` ListToolsResult ` , ` CallToolResult ` , etc.)
485+ 3 . Context provides access to session, lifespan data, and request metadata
486+ 4 . Handlers are passed to the constructor using ` on_* ` parameters
487+
488+ ** Migration steps:**
489+
490+ 1 . Update handler signatures to accept ` (ctx, params) `
491+ 2 . Update return types to use proper result classes
492+ 3 . Pass handlers to the Server constructor using ` on_* ` parameters
493+ 4 . Remove decorator calls
494+
495+ ** Available constructor parameters:**
496+
497+ | Constructor Parameter | Params Type | Return Type |
498+ | -----------------------| -------------| -------------|
499+ | ` on_list_prompts ` | ` PaginatedRequestParams \| None ` | ` ListPromptsResult ` |
500+ | ` on_get_prompt ` | ` GetPromptRequestParams ` | ` GetPromptResult ` |
501+ | ` on_list_resources ` | ` PaginatedRequestParams \| None ` | ` ListResourcesResult ` |
502+ | ` on_list_resource_templates ` | ` PaginatedRequestParams \| None ` | ` ListResourceTemplatesResult ` |
503+ | ` on_read_resource ` | ` ReadResourceRequestParams ` | ` ReadResourceResult ` |
504+ | ` on_subscribe_resource ` | ` SubscribeRequestParams ` | ` EmptyResult ` |
505+ | ` on_unsubscribe_resource ` | ` UnsubscribeRequestParams ` | ` EmptyResult ` |
506+ | ` on_list_tools ` | ` PaginatedRequestParams \| None ` | ` ListToolsResult ` |
507+ | ` on_call_tool ` | ` CallToolRequestParams ` | ` CallToolResult ` |
508+ | ` on_set_logging_level ` | ` SetLevelRequestParams ` | ` EmptyResult ` |
509+ | ` on_completion ` | ` CompleteRequestParams ` | ` CompleteResult ` |
510+ | ` on_progress_notification ` | ` ProgressNotificationParams ` | ` None ` |
511+
512+ ** Benefits:**
513+
514+ - Context available in all handlers (session, lifespan data, request metadata)
515+ - Type-safe params and return types
516+ - Clearer dependencies at construction time
517+ - Better testability (handlers can be mocked/replaced)
432518
433519## Bug Fixes
434520
@@ -462,13 +548,20 @@ The `streamable_http_app()` method is now available directly on the lowlevel `Se
462548
463549``` python
464550from mcp.server.lowlevel.server import Server
465-
466- server = Server(" my-server" )
467-
468- # Register handlers...
469- @server.list_tools ()
470- async def list_tools ():
471- return [... ]
551+ from mcp.server.session import ServerSession
552+ from mcp.shared.context import RequestContext
553+ import mcp.types as types
554+ from typing import Any
555+
556+ async def list_tools (
557+ ctx : RequestContext[ServerSession, Any, Any],
558+ params : types.PaginatedRequestParams | None ,
559+ ) -> types.ListToolsResult:
560+ return types.ListToolsResult(tools = [
561+ types.Tool(name = " my_tool" , description = " ..." , inputSchema = {" type" : " object" })
562+ ])
563+
564+ server = Server(" my-server" , on_list_tools = list_tools)
472565
473566# Create a Starlette app for streamable HTTP
474567app = server.streamable_http_app(
0 commit comments