Describe the bug
In a workspace served with repowise serve (from the workspace root), the web-UI chat for a non-primary repo can stream a response but its tool calls fail with:
{ "error": "LookupError: Repository not found: <repoName>" }
Root cause
The chat agentic loop executes tools via execute_tool(name, args) (packages/server/src/repowise/server/chat_tools.py), which dispatches into the MCP tool functions using module-global state in packages/server/src/repowise/server/mcp_server/_state.py. That state is set once at server startup by init_tool_state(...) (chat_tools.py), which wires _session_factory / _repo_path to the primary repo and never sets the workspace _registry.
So for a non-primary repo:
- the tools query the primary repo's DB/stores, not the repo being chatted with, and
- the
repo argument the LLM passes (the repo's display name) doesn't resolve, so _get_repo raises LookupError: Repository not found (mcp_server/_helpers.py:72).
The chat messages DB lookup is already routed correctly per-repo via resolve_request_session_factory; only the tool execution path is not.
Why it's not a quick patch
Simply injecting the repo into the tool args isn't enough — the underlying session factory/stores are global, and the globals are not request-safe, so concurrent chats to different repos would race.
Proposed fix
Thread a per-request RepoContext (session factory, repo_path, fts, vector_store, decision_store) into execute_tool and the tool functions, instead of mutating MCP module globals. In workspace mode resolve it from the request's repo_id (the same routing chat messages already use); in single-repo mode keep the existing _state wrapper for backward compatibility.
Related
The chat provider/model resolution in workspace mode is fixed separately in #426 / #434. This issue is only about the tool-execution repo routing.
Reported by @zuberek in #426.
Describe the bug
In a workspace served with
repowise serve(from the workspace root), the web-UI chat for a non-primary repo can stream a response but its tool calls fail with:{ "error": "LookupError: Repository not found: <repoName>" }Root cause
The chat agentic loop executes tools via
execute_tool(name, args)(packages/server/src/repowise/server/chat_tools.py), which dispatches into the MCP tool functions using module-global state inpackages/server/src/repowise/server/mcp_server/_state.py. That state is set once at server startup byinit_tool_state(...)(chat_tools.py), which wires_session_factory/_repo_pathto the primary repo and never sets the workspace_registry.So for a non-primary repo:
repoargument the LLM passes (the repo's display name) doesn't resolve, so_get_reporaisesLookupError: Repository not found(mcp_server/_helpers.py:72).The chat messages DB lookup is already routed correctly per-repo via
resolve_request_session_factory; only the tool execution path is not.Why it's not a quick patch
Simply injecting the repo into the tool args isn't enough — the underlying session factory/stores are global, and the globals are not request-safe, so concurrent chats to different repos would race.
Proposed fix
Thread a per-request
RepoContext(session factory, repo_path, fts, vector_store, decision_store) intoexecute_tooland the tool functions, instead of mutating MCP module globals. In workspace mode resolve it from the request'srepo_id(the same routing chat messages already use); in single-repo mode keep the existing_statewrapper for backward compatibility.Related
The chat provider/model resolution in workspace mode is fixed separately in #426 / #434. This issue is only about the tool-execution repo routing.
Reported by @zuberek in #426.