Acknowledge notification POSTs with 202 on the 2026-07-28 HTTP entry (#3326)
This commit is contained in:
parent
9057285683
commit
b2025ab815
2 changed files with 254 additions and 37 deletions
|
|
@ -173,7 +173,7 @@ The constructor covers the methods MCP defines. `add_request_handler` covers eve
|
|||
--8<-- "docs_src/lowlevel/tutorial006.py"
|
||||
```
|
||||
|
||||
* The first argument is the method string. Notifications have a twin, `add_notification_handler`.
|
||||
* The first argument is the method string. Notifications have a twin, `add_notification_handler`. Its handlers fire on stdio and on handshake-era HTTP connections; on the `2026-07-28` streamable-HTTP path a client's notification POST is acknowledged `202` and not dispatched, because that revision defines no client-to-server notifications over HTTP.
|
||||
* `params_type` is the model the incoming `params` are validated against **before** your handler runs, so custom methods *do* get the validation tools don't. Subclass `RequestParams` so the `_meta` field parses like every other method's.
|
||||
* The handler returns a `BaseModel`, a `dict`, or `None`. The SDK serialises it into the JSON-RPC result.
|
||||
|
||||
|
|
|
|||
|
|
@ -48,8 +48,11 @@ That is the point. Middleware wraps **every** inbound message:
|
|||
|
||||
* The connection setup: `server/discover`, or `initialize` and `notifications/initialized`
|
||||
on a legacy session.
|
||||
* Every request and every notification. For a notification, `ctx.request_id is None`,
|
||||
`call_next(ctx)` returns `None`, and whatever you return is discarded.
|
||||
* Every request and every notification that reaches the server. For a notification,
|
||||
`ctx.request_id is None`, `call_next(ctx)` returns `None`, and whatever you return is discarded.
|
||||
(On the `2026-07-28` streamable-HTTP path a client's notification POST is acknowledged `202` at
|
||||
the transport and never dispatched, so it does not reach middleware either; that revision
|
||||
defines no client-to-server notifications over HTTP.)
|
||||
* Even a method the server has no handler for: `call_next` raises the
|
||||
`MCPError(-32601, "Method not found")` *through* your middleware on its way to the client.
|
||||
|
||||
|
|
@ -105,8 +108,8 @@ don't think about it. It is a no-op until you install an exporter, and it has it
|
|||
|
||||
* A middleware is `async (ctx, call_next) -> result`, passed as `MCPServer(middleware=[...])` (or
|
||||
appended to `mcp.middleware`), and appended to `server.middleware` on the low-level `Server`.
|
||||
* It wraps **every** inbound message (`server/discover`, `initialize`, requests, notifications,
|
||||
unknown methods) and runs outermost-first.
|
||||
* It wraps **every** inbound message that reaches the server (`server/discover`, `initialize`,
|
||||
requests, notifications, unknown methods) and runs outermost-first.
|
||||
* `ctx.request_id is None` is how you tell a notification from a request.
|
||||
* Raise instead of calling `call_next` to refuse one message; the connection survives.
|
||||
* The SDK's own OpenTelemetry tracing is a middleware too, already on the list. See
|
||||
|
|
|
|||
Loading…
Reference in a new issue