fix(server): return METHOD_NOT_FOUND for unregistered spec methods (#3193)
Fixes #3193.
In ServerRunner._on_request, _methods.validate_client_request was previously called before checking self.server.get_request_handler(method). For spec methods (SPEC_CLIENT_METHODS) where no handler was registered on the server, sending malformed or missing parameters triggered parameter validation first, returning -32602 Invalid params instead of -32601 Method not found.
Motivation and Context
Per JSON-RPC 2.0 specification (Section 5.1), calling a method that is not available / served by the server must return -32601 Method not found. Previously, probing an unregistered spec method (such as triggers/list or tools/call on a server without handlers) returned -32602 Invalid params when parameters were missing or malformed.
This change separates the version-surface check from parameter validation:
- Upfront Version Gate: Added an upfront check
if method in _methods.SPEC_CLIENT_METHODS and (method, version) not in _methods.CLIENT_REQUESTS:so methods invalid at the negotiated version return-32601 Method not found. - Post-Lookup Schema Validation: Moved
_methods.validate_client_requestdown afterself.server.get_request_handler(method). Unregistered spec methods now fall through toentry is None(-32601 Method not found), while registered handlers continue to surface-validate parameters (-32602 Invalid params). - Initialize Handshake Untouched: The
initializehandshake branch remains 100% untouched.
How Has This Been Tested?
- Ran unit test suite (
uv run pytest tests/server/test_runner.py): 113/113 passed. - Updated
tests/server/test_runner.pyto assert-32601 Method not foundfor unregistered spec methods and-32602 Invalid paramsfor registered spec methods with invalid parameters. - Ran repo-wide test suite (
uv run pytest): 5,572 passed. - Code formatting and linting verified with
uv run ruff check .anduv run ruff format --check ..
Breaking Changes
No breaking changes. Existing registered handler behavior and parameter validation rules are fully preserved.
Types of changes
- Bug fix (non-breaking change which fixes an issue)
- New feature (non-breaking change which adds functionality)
- Breaking change (fix or feature that would cause existing functionality to change)