Skip to content

Bug connecting Claude Desktop to R Studio on windows #20

Description

@ndtivendale

Bug: ClaudeR fails to connect on Windows when HOME points to OneDrive (two issues)

Environment

  • OS: Windows
  • RStudio: 2026.4.0.526 (or similar)
  • ClaudeR installed via devtools::install_github("IMNMV/ClaudeR")
  • Claude Desktop with clauder-mcp via uvx

Description

On Windows machines where the HOME environment variable points to a OneDrive-synced Documents folder (a common configuration), ClaudeR fails to connect to Claude Desktop. There are two distinct bugs that compound each other.


Bug 1: HOME/USERPROFILE mismatch causes discovery file to be written to the wrong location

What happens

ClaudeR (the R addin) writes the session discovery file using R's path.expand("~"), which resolves to the HOME environment variable. On many Windows machines, HOME points to a OneDrive-synced folder such as:

C:\Users\username\OneDrive - Organisation\Documents\.claude_r_sessions\

However, clauder-mcp (the Python MCP bridge) locates the discovery file using Python's os.path.expanduser("~"), which on Windows resolves to USERPROFILE:

C:\Users\username\.claude_r_sessions\

These are different directories, so clauder-mcp never finds the discovery file written by the R addin.

Reproduction

  1. On a Windows machine where HOME != USERPROFILE (common when Documents is redirected to OneDrive), install and run ClaudeR.
  2. Note that ClaudeR:::discovery_dir() returns a path under HOME (OneDrive).
  3. Note that clauder-mcp looks for discovery files under USERPROFILE.
  4. Claude Desktop reports "No active R sessions found" despite the addin running.

Fix

In clauder-mcp/server.py, change:

SESSIONS_DIR = os.path.expanduser("~/.claude_r_sessions")

To use USERPROFILE consistently on Windows:

if sys.platform == "win32":
    SESSIONS_DIR = os.path.join(os.environ.get("USERPROFILE", os.path.expanduser("~")), ".claude_r_sessions")
else:
    SESSIONS_DIR = os.path.expanduser("~/.claude_r_sessions")

And update discovery_dir() in the R package to match, using USERPROFILE on Windows:

discovery_dir <- function() {
  base <- if (.Platform$OS.type == "windows") {
    Sys.getenv("USERPROFILE", unset = path.expand("~"))
  } else {
    path.expand("~")
  }
  file.path(base, ".claude_r_sessions")
}

Bug 2: os.kill(pid, 0) does not work correctly on Windows, causing discovery files to be deleted immediately

What happens

After the discovery file is written, clauder-mcp calls _pid_alive(pid) to verify the R process is still running before using the session. This function uses os.kill(pid, 0), which is a standard POSIX signal check. However, on Windows, os.kill() does not support signal 0 in the same way — it raises an OSError even for running processes, causing _pid_alive() to incorrectly return False. As a result, clauder-mcp treats every session as dead and deletes the discovery file immediately after finding it.

Reproduction

  1. On Windows, get Bug 1 resolved so the discovery file is written to the correct location.
  2. Observe that the discovery file appears briefly then disappears.
  3. clauder-mcp is pruning valid sessions because os.kill(pid, 0) fails on Windows.

Fix

In clauder-mcp/server.py, update _pid_alive() to use the Windows-appropriate process check:

def _pid_alive(pid: int) -> bool:
    """Check if a process is running."""
    if sys.platform == "win32":
        import ctypes
        SYNCHRONIZE = 0x00100000
        handle = ctypes.windll.kernel32.OpenProcess(SYNCHRONIZE, False, pid)
        if handle == 0:
            return False
        ctypes.windll.kernel32.CloseHandle(handle)
        return True
    try:
        os.kill(pid, 0)
        return True
    except (OSError, ProcessLookupError):
        return False

Workaround (until fixed)

  1. Set HOME to match USERPROFILE at the Windows system level:

    setx HOME "C:\Users\username"
    

    Then restart RStudio.

  2. Patch _pid_alive() in the installed clauder-mcp/server.py to return True unconditionally on Windows:

    def _pid_alive(pid: int) -> bool:
        if sys.platform == "win32":
            return True
        try:
            os.kill(pid, 0)
            return True
        except (OSError, ProcessLookupError):
            return False

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions