From 26e99af2eca88343746eb67bfb4af26c7d252091 Mon Sep 17 00:00:00 2001 From: blasty Date: Fri, 24 Jul 2026 01:49:57 +0200 Subject: worker: wrap non-dict tool returns as {"result": ...} to match MCP shapes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MCP server sets structuredContent = result if isinstance(result, dict) else {"result": result} (zeromcp mcp.py:832), and domain.py parses that exact shape — e.g. function_of() reads payload["result"] from lookup_funcs, which returns a bare list. Our worker returned the raw list, so function_of got a non-dict and returned None: hence "F5 — cursor is not inside a defined function" on Tab. Replicate the rule in the worker's dispatch: dict passes through, anything else (list/scalar) is wrapped as {"result": ...}. Fixes function_of and every other list-returning tool (resolve_names, xref_query, list_funcs) in one shot. --- idatui/worker.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/idatui/worker.py b/idatui/worker.py index e1d3c44..8e82af8 100644 --- a/idatui/worker.py +++ b/idatui/worker.py @@ -112,7 +112,11 @@ def serve(sockpath: str, binpath: str) -> None: fn = tools.get(name) if fn is None: raise KeyError(f"unknown tool: {name!r}") - return fn(**args) + result = fn(**args) + # Match the MCP server's structuredContent: a dict passes through, any + # other return (list/scalar) is wrapped as {"result": ...}. domain.py + # parses that exact shape (e.g. lookup_funcs -> payload["result"]). + return result if isinstance(result, dict) else {"result": result} try: os.unlink(sockpath) -- cgit v1.3.1-sl0p