You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor: replace lowlevel Server decorators with on_* constructor kwargs
Replace the decorator-based handler registration on the lowlevel Server with
direct on_* keyword arguments on the constructor. Handlers are raw callables
with a uniform (ctx, params) -> result signature.
- Server constructor takes on_list_tools, on_call_tool, etc.
- String-keyed dispatch instead of type-keyed
- Remove RequestT generic from Server (transport-specific, not bound at construction)
- Delete handler.py and func_inspection.py (no longer needed)
- Update ExperimentalHandlers to use callback-based registration
- Update MCPServer to pass on_* kwargs via _create_handler_kwargs()
- Update migration docs and docstrings
### Lowlevel `Server`: decorator-based handlers replaced with constructor `on_*` params
475
+
476
+
The lowlevel `Server` class no longer uses decorator methods for handler registration. Instead, handlers are passed as `on_*` keyword arguments to the constructor.
- Handlers receive `(ctx, params)` instead of the full request object or unpacked arguments. `ctx` is a `RequestContext` with `session`, `lifespan_context`, and `experimental` fields (plus `request_id`, `meta`, etc. for request handlers). `params` is the typed request params object.
533
+
- Handlers return the full result type (e.g. `ListToolsResult`) rather than unwrapped values (e.g. `list[Tool]`).
534
+
- The automatic `jsonschema` input/output validation that the old `call_tool()` decorator performed has been removed. There is no built-in replacement — if you relied on schema validation in the lowlevel server, you will need to validate inputs yourself in your handler.
The `server.request_context` property has been removed. Request context is now passed directly to handlers as the first argument (`ctx`). The `request_ctx` module-level contextvar still exists but should not be needed — use `ctx` directly instead.
557
+
558
+
**Before (v1):**
559
+
560
+
```python
561
+
from mcp.server.lowlevel.server import request_ctx
### `RequestContext`: request-specific fields are now optional
587
+
588
+
The `RequestContext` class now uses optional fields for request-specific data (`request_id`, `meta`, etc.) so it can be used for both request and notification handlers. In notification handlers, these fields are `None`.
589
+
590
+
```python
591
+
from mcp.shared.context import RequestContext
592
+
593
+
# request_id, meta, etc. are available in request handlers
594
+
# but None in notification handlers
595
+
```
596
+
597
+
### Experimental: task handler decorators removed
598
+
599
+
The experimental decorator methods on `ExperimentalHandlers` (`@server.experimental.list_tasks()`, `@server.experimental.get_task()`, etc.) have been removed.
600
+
601
+
Default task handlers are still registered automatically via `server.experimental.enable_tasks()`.
The `streamable_http_app()` method is now available directly on the lowlevel `Server` class, not just `MCPServer`. This allows using the streamable HTTP transport without the MCPServer wrapper.
507
659
508
660
```python
509
-
from mcp.server.lowlevel.server import Server
510
-
511
-
server = Server("my-server")
512
-
513
-
# Register handlers...
514
-
@server.list_tools()
515
-
asyncdeflist_tools():
516
-
return [...]
661
+
from mcp.server.lowlevel import Server
662
+
from mcp.shared.context import RequestContext
663
+
from mcp.types import ListToolsResult, PaginatedRequestParams
0 commit comments