rohitg00/ai-engineering-from-scratch · error · LookupError

Method not found: {method}

Error message

Method not found: {method}

What it means

The teaching MCP server's _dispatch routes only a fixed method set (initialize, tools/list, tools/call, resources/list, resources/read, prompts/list, prompts/get). Any other method string falls through to raise LookupError, mirroring JSON-RPC error -32601 method-not-found. It means the request reached a valid server but named a method outside its implemented surface.

Source

Thrown at certifications/claude/lessons/11-mcp-server-design-and-integration/code/main.py:304

            ]
            return self._complete(
                prompts=prompts, ttlMs=300_000, cacheScope="public"
            ), []
        if method == "prompts/get":
            name = params["name"]
            if not isinstance(name, str):
                raise ValueError("name must be a string")
            if name not in self.prompts:
                raise ValueError("unknown prompt")
            return self._complete(
                messages=[
                    {
                        "role": "user",
                        "content": {"type": "text", "text": self.prompts[name]},
                    }
                ]
            ), []
        raise LookupError(f"Method not found: {method}")

    def _call_tool(
        self, params: dict[str, Any], metadata: dict[str, Any]
    ) -> tuple[dict[str, Any], list[dict[str, Any]]]:
        name = params["name"]
        if not isinstance(name, str) or not name:
            raise ValueError("name must be a non-empty string")
        tool = self.tools.get(name)
        if tool is None:
            raise ValueError("unknown tool")
        arguments = tool.validate_arguments(params.get("arguments", {}))
        if name == "prepare_review":
            return self._prepare_review(params, metadata, arguments), []

        token = metadata.get("progressToken")
        notifications: list[dict[str, Any]] = []
        if token is not None:
            if not isinstance(token, (str, int)) or isinstance(token, bool):

View on GitHub (pinned to 39ea8a1c6d)

Solutions

  1. Send only the methods _dispatch implements: initialize, tools/list, tools/call, resources/list, resources/read, prompts/list, prompts/get
  2. Inspect the initialize result's capabilities object to learn which feature areas the server exposes before calling them
  3. Catch LookupError in the client and map it to JSON-RPC error code -32601 instead of crashing

Example fix

# before
result = server.exchange("ping", {})  # LookupError

# after
result = server.exchange("tools/list", {})
Defensive patterns

Strategy: try-catch

Validate before calling

SUPPORTED = {"initialize", "tools/list", "tools/call", "resources/list", "resources/read", "prompts/list", "prompts/get"}
if method not in SUPPORTED:
    raise ValueError(f"unsupported method: {method}")
result = server.exchange(method, params)

Type guard

def is_supported_method(method: object) -> bool:
    return isinstance(method, str) and method in {
        "initialize", "tools/list", "tools/call",
        "resources/list", "resources/read",
        "prompts/list", "prompts/get",
    }

Try / catch

try:
    result = server.exchange(method, params)
except LookupError as exc:
    respond_error(request_id, -32601, str(exc))

Prevention

When it happens

Trigger: Calling exchange() with methods the server never implements: 'ping', 'notifications/initialized', 'completion/complete', 'logging/setLevel', or a case typo like 'tools/List' (dispatch is case-sensitive).

Common situations: Pointing a generic MCP client SDK built against a newer or older spec revision at this lesson server; hand-crafting JSON-RPC requests and misspelling the method; assuming every server supports optional features like ping or completion.

Related errors


AI-assisted analysis of rohitg00/ai-engineering-from-scratch@39ea8a1c6d (2026-08-26). Data as JSON: /api/errors/659210ebf1b06e54. Report an issue: GitHub.