Skip to content

Commit c60b1ed

Browse files
committed
Fix Windows command execution fallbacks
1 parent f8edf34 commit c60b1ed

3 files changed

Lines changed: 16 additions & 16 deletions

File tree

minicode/mcp.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -140,29 +140,29 @@ def _prepare_spawn(command: str, args: list[str]) -> tuple[list[str] | str, dict
140140
Arguments are validated by _validate_mcp_args to contain no shell metacharacters,
141141
so shell=True is safe here.
142142
143-
On non-Windows (Linux/macOS), if command=="python" is unavailable, prefer the
144-
interpreter running MiniCode and then fall back to "python3". This keeps MCP
145-
helpers inside the same virtualenv/runtime instead of selecting a broken or
146-
unrelated system Python.
143+
If command=="python" is unavailable, prefer the interpreter running MiniCode
144+
and then fall back to "python3". This keeps MCP helpers inside the same
145+
virtualenv/runtime instead of selecting a broken or unrelated system Python.
147146
148147
Returns (spawn_exec, extra_popen_kwargs): spawn_exec is a list for shell=False,
149148
a single string for shell=True.
150149
"""
150+
resolved = shutil.which(command)
151151
if os.name == "nt":
152-
resolved = shutil.which(command)
153152
if resolved:
154153
if resolved.lower().endswith((".cmd", ".bat")):
155154
return subprocess.list2cmdline([resolved, *args]), {"shell": True}
156155
return [resolved, *args], {}
157-
else:
158-
# Non-Windows: keep python MCP helpers in the current runtime when the
159-
# plain command is unavailable (Linux/macOS often lack plain "python").
160-
if command == "python" and shutil.which(command) is None:
161-
if sys.executable:
162-
return [sys.executable, *args], {}
163-
resolved = shutil.which("python3")
164-
if resolved:
165-
return [resolved, *args], {}
156+
157+
# Keep python MCP helpers in the current runtime when the plain command is
158+
# unavailable. This applies on Windows too, where the launcher may be
159+
# absent even though the current interpreter is available.
160+
if command == "python" and resolved is None:
161+
if sys.executable:
162+
return [sys.executable, *args], {}
163+
fallback = shutil.which("python3")
164+
if fallback:
165+
return [fallback, *args], {}
166166
return [command, *args], {}
167167

168168

tests/test_functional_completeness.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
from __future__ import annotations
1414

1515
import os
16-
import shlex
1716
import tempfile
1817
from pathlib import Path
1918

@@ -125,7 +124,7 @@ def test_run_command_tool(self, context):
125124
"""Test run_command_tool executes successfully."""
126125
from minicode.tools.run_command import run_command_tool
127126
result = run_command_tool.run(
128-
{"command": f"{shlex.quote(sys.executable)} --version"},
127+
{"command": sys.executable, "args": ["--version"]},
129128
context,
130129
)
131130
assert result.ok

tests/test_mcp.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def test_create_mcp_backed_tools_supports_newline_json(tmp_path: Path) -> None:
6060
def test_prepare_spawn_uses_running_python_when_plain_python_is_missing(
6161
monkeypatch: pytest.MonkeyPatch,
6262
) -> None:
63+
monkeypatch.setattr(mcp_module.os, "name", "nt")
6364
monkeypatch.setattr(mcp_module.shutil, "which", lambda command: None)
6465
monkeypatch.setattr(mcp_module.sys, "executable", "/runtime/python")
6566

0 commit comments

Comments
 (0)