Skip to content

fix(mcp): default omitted path to workspace, not process cwd/$HOME - #41

Merged
snowmead merged 11 commits into
mainfrom
snowmead/mcp-default-project-root-cd40
Jul 30, 2026
Merged

fix(mcp): default omitted path to workspace, not process cwd/$HOME#41
snowmead merged 11 commits into
mainfrom
snowmead/mcp-default-project-root-cd40

Conversation

@snowmead

@snowmeadsnowmead commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

MCP hosts (Cursor/Claude) often start the oxcode MCP server with cwd=$HOME even when the agent workspace is a project folder. Omitting path previously resolved to process cwd, so oxcode_watch could cold-index the home directory.

Default root resolution (omitted path)

  1. Explicit path
  2. OXCODE_ROOT (explicit pin)
  3. Client MCP roots (roots/list, refreshed on roots/list_changed)
  4. CLAUDE_PROJECT_DIR / WORKSPACE_FOLDER_PATHS (host env snapshots; cold-start only when roots are not ready)
  5. Process cwd — refused when it is $HOME unless path was explicit

Live MCP roots sit above sticky host env so a folder switch that only updates roots does not keep querying the previous project. While replacing a previously ready root, a wait timeout suppresses host-env fallback (cold-start still allows it).

Implementation notes

  • Roots fetched only from on_initialized / on_roots_list_changed (never nested roots/list in tool handlers).
  • RootsCache: Cold / Refreshing(previous) / Ready, with a fetch mutex so overlapping notifications cannot wipe/restore the wrong root.
  • Windows file:///C:/... URIs normalize to C:/....
  • Split into mcp/mod.rs, mcp/project_root.rs, mcp/roots.rs, mcp/integration_tests.rs.
  • Tool params share OptionalProjectRoot via #[serde(flatten)].

Docs

  • README.md, server instructions, and prompts/arms/oxcode-mcp.md updated for the new default order.

Test plan

  • cargo test -p oxcode-cli (omitted-path roots, priority, refresh/cold-start wait outcomes)
  • cargo clippy -p oxcode-cli --all-targets -- -D warnings
  • CI green on latest commit
  • Human: dismiss stale Thermos CHANGES_REQUESTED reviews (all threads resolved; bot token cannot dismiss) or re-run Thermos approve
  • Confirm in Cursor: omitted path watches the open workspace, not $HOME
Open in WebOpen in Cursor

cursoragentand others added 3 commits July 30, 2026 02:29
MCP hosts often start oxcode with cwd=$HOME even when the agent is in a
project folder. Omitting `path` previously resolved "." to that process
cwd, so oxcode_watch could cold-index the entire home directory.
Prefer OXCODE_ROOT / CLAUDE_PROJECT_DIR / WORKSPACE_FOLDER_PATHS, then
MCP roots/list; refuse $HOME unless path was explicit.
Co-authored-by: Michael Assaf <snowmead@users.noreply.github.com>
Co-authored-by: Michael Assaf <snowmead@users.noreply.github.com>
RUSTSEC-2026-0190 / RUSTSEC-2026-0204 fail the deny gate on a stale lockfile.
Co-authored-by: Michael Assaf <snowmead@users.noreply.github.com>
@snowmead
snowmead marked this pull request as ready for review July 30, 2026 03:41
Comment threadcrates/oxcode-cli/src/mcp.rs Outdated
Comment threadcrates/oxcode-cli/src/mcp.rs Outdated
Fetch MCP roots only from on_initialized / roots/list_changed. Tool
handlers wait briefly for that in-flight fetch and never issue nested
roots/list (which can hang some hosts). Empty successful lists leave
the cache as None so a later list_changed can still populate it.
Co-authored-by: Michael Assaf <snowmead@users.noreply.github.com>
Comment threadcrates/oxcode-cli/src/mcp.rs Outdated
Comment threadcrates/oxcode-cli/src/mcp.rs Outdated
Cold resolves wait on the fetch lock so roots/list_changed updates are
observed. Explicitly empty client lists clear the cache; unparseable URI
payloads leave a previously good root in place.
Co-authored-by: Michael Assaf <snowmead@users.noreply.github.com>
Comment threadcrates/oxcode-cli/src/mcp.rs Outdated
When roots/list_changed is running, cold and warm omitted-path resolves
wait on the fetch lock so tools do not keep using the previous workspace.
Co-authored-by: Michael Assaf <snowmead@users.noreply.github.com>
Comment threadcrates/oxcode-cli/src/mcp.rs Outdated
Comment threadcrates/oxcode-cli/src/mcp.rs Outdated
Comment threadcrates/oxcode-cli/src/mcp.rs Outdated
Comment threadcrates/oxcode-cli/src/mcp.rs Outdated
Comment threadcrates/oxcode-cli/src/mcp.rs Outdated
Split path defaulting and RootsCache (Pending/Ready watch) out of the
MCP server module. On fetch timeout skip stale cache; parse Windows
file:///C:/... roots; flatten OptionalProjectRoot docs; keep prior root
on unparseable URI lists.
Co-authored-by: Michael Assaf <snowmead@users.noreply.github.com>
Comment threadcrates/oxcode-cli/src/mcp/mod.rs Outdated
Comment threadcrates/oxcode-cli/src/mcp/roots.rs
CLAUDE_PROJECT_DIR / WORKSPACE_FOLDER_PATHS are process-start snapshots and
must not outrank a refreshed roots cache after a folder switch. Keep
OXCODE_ROOT as an explicit pin above roots.
Co-authored-by: Michael Assaf <snowmead@users.noreply.github.com>
Comment threadcrates/oxcode-cli/src/mcp/roots.rs
Overlapping roots/list fetches could wipe a good Ready root when a late
failure saw Pending. Hold a fetch mutex and keep last-good under
Refreshing. On wait timeout during refresh, skip sticky host env so an
older CLAUDE_PROJECT_DIR cannot win mid-switch.
Co-authored-by: Michael Assaf <snowmead@users.noreply.github.com>

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 2bb2f08. Configure here.

Comment threadcrates/oxcode-cli/src/mcp/roots.rs Outdated
cursoragentand others added 2 commits July 30, 2026 04:26
RefreshInFlight (and host-env suppression) only applies when replacing a
previously ready MCP root. Refreshing(None) on first fetch still falls
through to CLAUDE_PROJECT_DIR / WORKSPACE_FOLDER_PATHS.
Co-authored-by: Michael Assaf <snowmead@users.noreply.github.com>
Parallel tests mutated CLAUDE_PROJECT_DIR / OXCODE_ROOT without the same
mutex as integration tests, racing resolve_project_root assertions in CI.
Co-authored-by: Michael Assaf <snowmead@users.noreply.github.com>
cursor[bot]
cursorBot approved these changes Jul 30, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thermos review @ 2becdd6

No medium+ findings. Security/correctness and code-quality passes agree after re-checking prior threads against HEAD.

Prior findings — verified fixed

  • Concurrent RootsCache::fetch wipe/restore → fetch_lock + Cold / Refreshing / Ready
  • Refresh timeout falling through to sticky host env → RefreshInFlight + allow_host_env: false
  • Cold-start Refreshing(None) blocking host env → only Refreshing(Some(_)) yields RefreshInFlight (1ab8c7b)
  • Live MCP roots vs sticky host env priority, Windows file:///C:/, module split, OptionalProjectRoot

Rejected near-misses

  • CQ: allow_host_env duplicates RootsWait policy — single production call site, documented, speculative misuse only
  • Unbounded peer.list_roots() during notification fetch — intentional fail-closed vs sticky env; hosts that answer after in-flight tools recover

cargo test -p oxcode-cli --bin oxcode -- mcp:: — 19 passed.

Open in WebView Automation

Sent by Cursor Automation: Find vulnerabilities

@snowmead
snowmead merged commit 0b28e3a into mainJul 30, 2026
14 checks passed
@snowmead
snowmead deleted the snowmead/mcp-default-project-root-cd40 branch July 30, 2026 12:29
@snowmeadsnowmead mentioned this pull request Jul 30, 2026
3 tasks
Sign up for freeto 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.

2 participants

@snowmead@cursoragent