Found by a six-lens audit of the desktop app on 27 Aug 2026. Every finding was reproduced against the code, not inferred.
Severity: medium · audit rank 14 of 16.
Breaks: the settings registry describes "Tool servers launched over stdio. Each is disabled until you enable it" (ui/settings-registry.js:188) and offers an enable switch that persists across restarts and has no consumer whatsoever. The model never sees an MCP tool.
Who / likelihood: everyone who configures one. The whole feature.
Where: engine/server.py:631 load_mcp() has exactly two consumers — GET /mcp (:1504) and the POST /mcp editor (:1675). _get_agent (:1129) builds Agent(..., tools=_builtin_tools()). grep -i mcp engine/*.py finds no client, no stdio spawn, no import.
Building an MCP client is not a "minimal fix". The minimal honest fix is to stop advertising a live capability:
--- a/ui/settings-registry.js
+++ b/ui/settings-registry.js
@@ -186,7 +186,8 @@
- hint: 'Tool servers launched over stdio. Each is disabled until you enable it.',
+ hint: 'Saved for a future release. Servers listed here are stored only \u2014 '
+ + 'the engine does not launch them yet, so the model cannot use them.',
plus disabling the enable switch until a client exists. Ship the client or ship the sentence; the current text is the defect.
Test — engine/test_chat_stream.py: configure one enabled MCP server, run a turn, and assert the tool names the agent was constructed with include it. That test should be written now and expected to fail until the client lands — or, for the honest-text fix, frontend/tests/registry-drift.test.mjs: assert every registry hint claiming a runtime behaviour has a named consumer in engine/.
Not yet fixed. Filed so it is not lost with the session that found it. The fix and the test above are proposals from the audit — worth re-checking against current main before implementing, since the file has moved since.
Breaks: the settings registry describes "Tool servers launched over stdio. Each is disabled until you enable it" (
ui/settings-registry.js:188) and offers an enable switch that persists across restarts and has no consumer whatsoever. The model never sees an MCP tool.Who / likelihood: everyone who configures one. The whole feature.
Where:
engine/server.py:631load_mcp()has exactly two consumers —GET /mcp(:1504) and thePOST /mcpeditor (:1675)._get_agent(:1129) buildsAgent(..., tools=_builtin_tools()).grep -i mcp engine/*.pyfinds no client, no stdio spawn, no import.Building an MCP client is not a "minimal fix". The minimal honest fix is to stop advertising a live capability:
plus disabling the enable switch until a client exists. Ship the client or ship the sentence; the current text is the defect.
Test —
engine/test_chat_stream.py: configure one enabled MCP server, run a turn, and assert the tool names the agent was constructed with include it. That test should be written now and expected to fail until the client lands — or, for the honest-text fix,frontend/tests/registry-drift.test.mjs: assert every registry hint claiming a runtime behaviour has a named consumer inengine/.Not yet fixed. Filed so it is not lost with the session that found it. The fix and the test above are proposals from the audit — worth re-checking against current
mainbefore implementing, since the file has moved since.