From 2d11f9cfcc3a8e92725a07eb18a73bd451acccf3 Mon Sep 17 00:00:00 2001 From: Jammy2211 Date: Tue, 21 Jul 2026 14:12:10 +0100 Subject: [PATCH] fix: run results-inspector MCP server from any launcher MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pin the server config to the assistant own config/ and force JAX onto CPU + guard stdout, all before importing autofit, so the stdio server no longer depends on the launch directory or extra environment. Fixes two defects surfaced by the Claude Desktop acceptance walkthrough (autofit_assistant#17): - autonerves.conf defaults its config dir to os.getcwd()/config and autofit reads config at import, so a foreign CWD (Desktop -> wsl.exe in a Windows folder) scanned a desktop.ini and crashed configparser interpolation. - jax._src.xla_bridge logged its backend probe to stdout during import, corrupting the JSON-RPC channel. Verified: both servers complete an MCP stdio handshake from a neutral CWD with a minimal env (PATH+HOME+PYTHONPATH) — gaussian-first ranking, zero stdout noise. Docs: Windows/WSL launch note. Core kept mirrored across both assistants. Closes PyAutoLabs/autofit_assistant#18 Co-Authored-By: Claude Opus 4.8 --- autoassistant/mcp/server.py | 32 +++++++++++++++++++++++++++++++- skills/af_inspect_results_mcp.md | 21 +++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/autoassistant/mcp/server.py b/autoassistant/mcp/server.py index 1fa4891..9fd7732 100644 --- a/autoassistant/mcp/server.py +++ b/autoassistant/mcp/server.py @@ -10,13 +10,32 @@ into `output/`. """ +import contextlib import io import logging +import os import sys +from pathlib import Path from mcp.server.fastmcp import FastMCP, Image -from autoassistant.mcp import tools + +def _pin_config(): + """ + autonerves derives its config directory from the process working directory + (`conf.instance` defaults to `os.getcwd()/config`) and autofit reads config + at import time. A server launched from a foreign directory — e.g. a chat + client spawning `wsl.exe`, which lands in a Windows folder — would otherwise + scan unrelated files and crash on import (a `desktop.ini` trips configparser + interpolation). Pin the config to this assistant's own `config/` so the + server runs from any working directory. + """ + from autonerves import conf + + config_path = Path(__file__).resolve().parents[2] / "config" + conf.instance = conf.Config( + str(config_path), output_path=str(config_path.parent / "output") + ) def _route_logging_to_stderr(): @@ -37,6 +56,17 @@ def _route_logging_to_stderr(): handler.setStream(sys.stderr) +# Importing the tool modules imports autofit, which (a) reads autonerves config +# at import and (b) lets jax's xla_bridge log its backend probe to stdout — both +# fatal to the JSON-RPC channel. So, before that import: force CPU (skips the +# jax backend probe), pin the config so it does not depend on the launch +# directory, and redirect any residual import-time stdout to stderr. Rebind +# logging handlers afterwards for anything attached during import. +os.environ.setdefault("JAX_PLATFORMS", "cpu") +_pin_config() +with contextlib.redirect_stdout(sys.stderr): + from autoassistant.mcp import tools + _route_logging_to_stderr() mcp = FastMCP("pyauto-results-inspector") diff --git a/skills/af_inspect_results_mcp.md b/skills/af_inspect_results_mcp.md index 684a1a0..1cc01f7 100644 --- a/skills/af_inspect_results_mcp.md +++ b/skills/af_inspect_results_mcp.md @@ -62,6 +62,27 @@ propagates. Anything the stack needs (`PYTHONPATH` for editable/source checkouts `NUMBA_CACHE_DIR`/`MPLCONFIGDIR` in restricted setups) must be declared in the config's `env` block. +**Windows (Claude Desktop → WSL):** when the interpreter lives in WSL, launch it +through `wsl.exe`. Nothing beyond `PYTHONPATH` is required — the server pins its own +config directory and forces JAX onto CPU before importing autofit, so it does not +depend on the launch directory or extra environment: + +```json +{ + "mcpServers": { + "pyauto-results-inspector": { + "command": "wsl.exe", + "args": ["-e", "bash", "-c", + "PYTHONPATH=/home/you/autofit_assistant /home/you/venv/bin/python -m autoassistant.mcp"] + } + } +} +``` + +For the Microsoft Store build of Claude Desktop, the config and the failure log +(`logs/mcp-server-pyauto-results-inspector.log`) live under +`%LOCALAPPDATA%\Packages\Claude_*\LocalCache\Roaming\Claude\`, not `%APPDATA%\Claude\`. + **Claude Code**: the repo-root `.mcp.json` registers the same server automatically for sessions opened in this repo (marginal there — a Claude Code session can already run the aggregator in Python — but it costs nothing and exercises the same wiring).