Skip to content

fix(lsp-client): pass workspace root as spawn cwd - #3

Open
nl0 wants to merge 2 commits into
ProfessioneIT:mainfrom
nl0:fix/spawn-cwd-to-workspace-root
Open

fix(lsp-client): pass workspace root as spawn cwd#3
nl0 wants to merge 2 commits into
ProfessioneIT:mainfrom
nl0:fix/spawn-cwd-to-workspace-root

Conversation

@nl0

@nl0 nl0 commented Apr 23, 2026

Copy link
Copy Markdown

Summary

Language servers that resolve project-level configuration from the current working directory — e.g. Astral's ty searching for .venv, pyright scanning for pyproject.toml, gopls looking up go.mod — fail to discover the correct environment when lsp-mcp-server is launched from a directory that isn't the workspace root (which is the common case when Claude Code is started from the user's shell cwd). The LSP still receives the right rootUri via initialize, but for tools that read getcwd() directly, that's irrelevant.

Manifests as e.g. spurious Cannot resolve imported module <X> errors pointing at the MCP host's shell venv (or uvx's own tool-env), not the project's.

Fix

Pass this._workspaceRoot as cwd to spawn() in LSPClientImpl.initialize. The value is already known and normalized at that point (assigned one line above from the rootUri parameter).

Reproducer

  1. In a shell with VIRTUAL_ENV pointing at some unrelated venv, launch an MCP client that spawns lsp-mcp-server.
  2. Configure a Python server entry backed by uvx ty server.
  3. Open a Python file whose project has .venv in its root.
  4. lsp_diagnostics returns unresolved-import errors for packages that are actually present in the project venv.

With this fix, ty sees the project's .venv via getcwd() and the false positives disappear.

Secondary commit

The second commit adds a prepare script so npm install / npx from a git source (e.g. github:…) builds dist/ automatically. Orthogonal to the fix — happy to split off or drop if you'd rather keep the git-install path separate.

Test plan

  • npm run build clean
  • npm run typecheck clean
  • npm test — all 32 existing unit tests pass
  • Manual verification: with the patched fork wired into Claude Code via npx github:nl0/lsp-mcp-server#fix/spawn-cwd-to-workspace-root, ty correctly resolves the project's .venv imports; typescript-language-server continues to work (it was already unaffected because it uses initialize.rootUri).

🤖 Generated with Claude Code

nl0 and others added 2 commits April 23, 2026 12:49
Language servers that auto-discover project config from the current
working directory (e.g. Astral ty looking for .venv, pytest for
pyproject.toml, gopls for go.mod) can't find the right project when
the server is spawned with the parent process's cwd. This surfaces
as false-positive unresolved-import diagnostics when the MCP host
(Claude Code, etc.) is launched from outside the workspace.

Inherit the workspace root for the LSP child process so `getcwd()`
inside the language server matches the LSP initialize rootUri.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Installing from a git source (e.g. `npx github:owner/lsp-mcp-server`
or `npm install github:...`) does not execute prepublishOnly, so the
repo otherwise fails to produce the `dist/` output that `bin` and
`main` reference. Add a `prepare` hook that mirrors `prepublishOnly`
so git-sourced installs work out of the box, while keeping the
existing publish-time build path unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ramfjord

Copy link
Copy Markdown

Hit the same root cause from Ruby/Sorbet via bundle exec srb tc --lsp: without cwd on spawn(), bundle either can't find the Gemfile or resolves the wrong Ruby version through mise's activate env. Confirmed your one-line fix resolves it across two large Rails monorepos. +1 to merging — would be great to drop our local patch.

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.

2 participants