gabriel / musehub public
fix BREAKING fix/208-stdio-sql-echo-stdout #1 / 1
AI Agent gabriel · 1 day ago · Oct 22, 2026 · Diff

fix: SQLAlchemy echo=True floods MCP stdio's stdout with raw SQL, corrupting the JSON-RPC stream (musehub#208)

Root cause confirmed (the reporter's own suspicion was exactly right): musehub/db/database.py::init_db() creates the async engine with echo=settings.debug. SQLAlchemy's InstanceLogger.__init__ (sqlalchemy/log.py) installs its own hardcoded logging.StreamHandler(sys.stdout) directly on the engine's uniquely-named child logger whenever echo is truthy and that logger has no handlers yet. This has nothing to do with stdio_server.py's own logging.basicConfig(stream=sys.stderr) call -- basicConfig only configures the ROOT logger, never the per-engine child logger SQLAlchemy creates and attaches its own stdout handler to directly. Under this project's own default local-dev config (DEBUG=true), every SQL statement got written straight to stdout -- the exact byte stream the stdio MCP transport uses as its JSON-RPC wire protocol.

Reproduced live against the real container (DEBUG=true): a single initialize request produced 2199 lines of raw SQL echo text on stdout before the fix, 1 clean JSON-RPC response line after.

Fix: init_db() gains an echo override parameter (None default = use settings.debug, unchanged for every HTTP/worker caller). The stdio transport now calls init_db(echo=False) unconditionally -- stdio's wire protocol correctness can never depend on a debug flag someone else sets for an unrelated transport.

sha256:71af3895204576a6667c619af9df11ac35f47c40f8a3dbcbde64540cf544f301 sha
+12 ~2 symbols
3 changed · 1113 in snapshot files
sha256:4325986066887b4362afb1a5c7b8c6956d27e47386953df09fc507f952b6dd90 snapshot
+12
symbols added
~2
symbols modified
3
files changed
1113
files in snapshot
0
dead code introduced
Semantic Changes 14 symbols
~ tests/test_stdio_sql_echo.py .py 12 symbols added
+ TestInitDbEchoOverride class class TestInitDbEchoOverride L27–96
+ test_default_uses_settings_debug_false method async_method test_default_uses_settings_debug_false L45–60
+ test_default_uses_settings_debug_true method async_method test_default_uses_settings_debug_true L28–43
+ test_echo_override_forces_false_even_when_debug_true method async_method test_echo_override_forces_false_even_when_debug_true L62–79
+ test_echo_override_forces_true_even_when_debug_false method async_method test_echo_override_forces_true_even_when_debug_false L81–96
+ TestStdioServerForcesEchoOff class class TestStdioServerForcesEchoOff L100–133
+ test_stdio_run_calls_init_db_with_echo_false method async_method test_stdio_run_calls_init_db_with_echo_false L101–133
+ AsyncMock import import AsyncMock L21–21
+ MagicMock import import MagicMock L21–21
+ annotations import import annotations L19–19
+ patch import import patch L21–21
+ pytest import import pytest L23–23
~ musehub/db/database.py .py 1 symbol modified
~ musehub/mcp/stdio_server.py .py 1 symbol modified
~ _run
Files Changed
+1 ~2
1113 in snapshot
← Older Oldest on fix/208-stdio-sql-echo-stdout
All commits
Newer → Latest on fix/208-stdio-sql-echo-stdout

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:71af3895204576a6667c619af9df11ac35f47c40f8a3dbcbde64540cf544f301 --body "your comment"