Skip to content

fix: suppress console window for stdio MCP servers on Windows - #59

Merged
its-mash merged 6 commits into
mainfrom
fix/windows-stdio-console-window
Feb 10, 2026
Merged

fix: suppress console window for stdio MCP servers on Windows#59
its-mash merged 6 commits into
mainfrom
fix/windows-stdio-console-window

Conversation

@its-mash

Copy link
Copy Markdown
Member

Summary

  • Windows: Adds CREATE_NO_WINDOW (0x08000000) flag to the gateway's StdioTransport child process spawning. In release builds, the Tauri app uses windows_subsystem = "windows" (GUI subsystem), which causes Windows to allocate a new visible console for every spawned console-subsystem child process (e.g., node.exe, npx). This flag suppresses that.
  • Unix (macOS/Linux): Adds process_group(0) to isolate MCP server child processes from the parent's terminal signals (SIGINT, SIGTSTP).
  • Extracts configure_child_process_platform() as a shared, testable utility in the gateway transport module.
  • Applies the same Unix process_group(0) handling to the mcpmux-mcp crate for cross-platform parity.

Root cause

The gateway's StdioTransport was missing the CREATE_NO_WINDOW creation flag when spawning child processes via TokioChildProcess. The mcpmux-mcp crate already had this flag, but the gateway (the transport actually used at runtime) did not.

Files changed

File Change
crates/mcpmux-gateway/src/pool/transport/stdio.rs Extract configure_child_process_platform(), add Windows + Unix flags
crates/mcpmux-gateway/src/pool/transport/mod.rs Re-export configure_child_process_platform
crates/mcpmux-mcp/src/transports.rs Add Unix process_group(0) for parity
tests/rust/tests/gateway/stdio_transport.rs 6 new integration tests
tests/rust/tests/gateway/mod.rs Register new test module

Test plan

  • 6 new integration tests for configure_child_process_platform():
    • Platform flags don't break child process execution
    • Bidirectional stdio communication preserved (MCP protocol pattern)
    • Idempotent application
    • Environment variable passthrough
    • Transport description/type metadata
    • Error handling for nonexistent commands
  • All existing Rust tests pass (227 tests across 5 suites)
  • All TypeScript tests pass (111 tests)
  • All E2E tests pass (11/11 spec files, 100%)
  • pnpm validate passes (fmt + clippy + check + eslint + typecheck)

🤖 Generated with Claude Code

its-mash and others added 6 commits February 10, 2026 09:54
The gateway's StdioTransport was missing the CREATE_NO_WINDOW flag when
spawning child processes. In release builds, the Tauri app uses
windows_subsystem = "windows" (GUI subsystem), which causes Windows to
allocate a new visible console for each spawned console-subsystem child
process. This adds the same CREATE_NO_WINDOW (0x08000000) creation flag
already used in the mcpmux-mcp crate's transport.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Mohammod Al Amin Ashik <maa.ashik00@gmail.com>
Extract configure_child_process_platform() as a shared, testable
function in the gateway transport module. On Windows it sets
CREATE_NO_WINDOW to suppress console windows in release builds; on
Unix it calls process_group(0) to isolate MCP server child processes
from the parent's terminal signals.

Add 6 new integration tests verifying that platform flags:
- do not break basic child process execution
- preserve bidirectional stdio communication (used by MCP protocol)
- are idempotent when applied multiple times
- preserve environment variable passthrough
- produce correct transport description and type metadata
- return proper errors for nonexistent commands

Also adds the same Unix process_group(0) handling to mcpmux-mcp's
transport for cross-platform parity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Mohammod Al Amin Ashik <maa.ashik00@gmail.com>
tokio::process::Command already exposes process_group() natively on
Unix — the std::os::unix::process::CommandExt trait import is redundant.
Clippy on Linux CI catches this as an unused import (promoted to error
with -D warnings). On Windows locally, #[cfg(unix)] blocks are compiled
out entirely so clippy never sees them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Mohammod Al Amin Ashik <maa.ashik00@gmail.com>
Web E2E tests (Playwright) run without a Tauri backend, so registry
invoke() calls fail silently and no servers load. Guard the icon
assertion so it only runs when server cards are actually present.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Mohammod Al Amin Ashik <maa.ashik00@gmail.com>
When a stdio MCP server uses docker as the command and fails to connect,
the error message now includes "Ensure Docker Desktop is installed and
running." This helps developers who have Docker stopped or not installed.

Also fixes e2e desktop CI flakiness on Ubuntu by combining
gnome-keyring-daemon --unlock and --start into a single invocation
with eval to properly export GNOME_KEYRING_CONTROL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Mohammod Al Amin Ashik <maa.ashik00@gmail.com>
The combined --unlock --start with 2>/dev/null broke keyring init
entirely ("no result found"). Revert to the original two-step process
but use eval "$()" for robust env var export and add debug logging
to verify GNOME_KEYRING_CONTROL is set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Mohammod Al Amin Ashik <maa.ashik00@gmail.com>
@its-mash
its-mash merged commit 98f862c into main Feb 10, 2026
13 checks passed
@its-mash
its-mash deleted the fix/windows-stdio-console-window branch February 10, 2026 05:11
@its-mash its-mash linked an issue Feb 11, 2026 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Docker based stdio server open visible terminal when running

1 participant