Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion autoassistant/mcp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand All @@ -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")
Expand Down
21 changes: 21 additions & 0 deletions skills/af_inspect_results_mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
Loading