@@ -186,15 +186,9 @@ async def _inner(ctx: ServerRequestContext[LifespanT, Any]) -> HandlerResult:
186186 # Read method/params off `ctx` so a middleware that rewrote them via
187187 # `call_next(replace(ctx, ...))` reaches lookup and the handler.
188188 method , params = ctx .method , ctx .params
189- # Pinned compat: spec methods are surface-validated before lookup,
190- # so malformed params are INVALID_PARAMS even with no handler
191- # registered. Custom methods miss the monolith map and fall through
192- # to `entry.params_type` exactly as before.
193- if method in _methods .SPEC_CLIENT_METHODS :
194- try :
195- _methods .validate_client_request (method , version , params )
196- except KeyError :
197- raise MCPError (code = METHOD_NOT_FOUND , message = "Method not found" , data = method ) from None
189+ # Spec version gate: if a spec method is not valid at this protocol version, reject it.
190+ if method in _methods .SPEC_CLIENT_METHODS and (method , version ) not in _methods .CLIENT_REQUESTS :
191+ raise MCPError (code = METHOD_NOT_FOUND , message = "Method not found" , data = method )
198192 # TODO(L29): the 2026-07-28 spec drops the handshake; this branch and
199193 # the gate become a per-version legacy path then. Initialize runs inline
200194 # (read loop parked), so awaiting the peer anywhere on this path deadlocks.
@@ -211,6 +205,8 @@ async def _inner(ctx: ServerRequestContext[LifespanT, Any]) -> HandlerResult:
211205 if not self .connection .initialize_accepted and method not in _INIT_EXEMPT :
212206 # Pinned compat: the same error shape the union validation produced.
213207 raise MCPError (code = INVALID_PARAMS , message = "Invalid request parameters" , data = "" )
208+ if method in _methods .SPEC_CLIENT_METHODS :
209+ _methods .validate_client_request (method , version , params )
214210 # Absent params validate as {} (required fields still reject), so
215211 # the handler receives the model with its defaults, never None.
216212 typed_params = entry .params_type .model_validate ({} if params is None else params , by_name = False )
0 commit comments