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

request did not receive a response

Error message

request did not receive a response

What it means

MCPClient.request sent a JSON-RPC request with a fresh id, but MCPServer.handle returned None — the server treated it as a notification or suppressed the reply (e.g. parse-level failure). The guard converts the silent None into an explicit RuntimeError so callers never mistake a missing reply for a result.

Solutions

  1. Ensure the request carries an 'id' field; messages without one are treated as notifications
  2. Check the server handler for a JSON-RPC error path that returns None instead of an error object
  3. Retry the request with a new id once transport state is verified
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at phases/11-llm-engineering/14-model-context-protocol/code/main.py:306 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at phases/11-llm-engineering/14-model-context-protocol/code/main.py:306

            return self._error(request_id, -32601, f"unknown method: {method}")

        return {"jsonrpc": "2.0", "id": request_id, "result": result}


class MCPClient:
    def __init__(self, server: MCPServer) -> None:
        self.server = server
        self._id = 0

    def request(self, method: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
        self._id += 1
        request_params = dict(params or {})
        request_params["_meta"] = request_metadata()
        response = self.server.handle(
            {"jsonrpc": "2.0", "id": self._id, "method": method, "params": request_params}
        )
        if response is None:
            raise RuntimeError("request did not receive a response")
        if "error" in response:
            raise RuntimeError(response["error"]["message"])
        return response["result"]


server = MCPServer("demo-server")


@server.tool(
    "add",
    "Add two integers and return the sum.",
    {
        "type": "object",
        "properties": {"a": {"type": "integer"}, "b": {"type": "integer"}},
        "required": ["a", "b"],
    },
)
def add(a: int, b: int) -> dict[str, int]:

View on GitHub (pinned to 39ea8a1c6d)