MiniMax-AI / MiniMax-AI/minimax-code
[Bug]: MCP stdio server always runs with cwd=homedir() and returns home as roots; workspace context is dropped, breaking per-project tools like codegraph
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1.3k
- Forks
- 141
- Avg merge
- 2h 45m
- Merged PRs (30d)
- 46
Description
Issue 内容(MiniMax-AI/minimax-code · [Bug]: MCP stdio server 始终以 home 目录作为 cwd/roots,跨 workspace 不可用)
仓库: MiniMax-AI/minimax-code
模板: 01-bug-report.yml (Bug report / 问题反馈)
Issue area: MCP / OAuth / integration
Version: v3.0.43
Platform: Windows
OS version: Windows 11 23H2
Upload ID: cannot upload (no crash, behavior bug)
Title
[Bug]: MCP stdio server always runs with cwd=homedir() and returns home as roots; workspace context is dropped, breaking per-project tools like codegraph
What happened?
When the daemon starts an MCP server with transport.type === "stdio" and that server relies on the current working directory or the MCP roots/list request to discover the active workspace (e.g. the CodeGraph MCP server, which walks up from process.cwd() looking for .codegraph/), the server always sees the user's home directory instead of the agent's current workspace.
Symptom with the CodeGraph MCP server (configured in ~/.mavis/mcp/mcp.json):
> mavis mcp call codegraph codegraph_search '{"query":"Desktop"}'
No CodeGraph project is loaded for this session.
Searched for a .codegraph/ directory starting from: C:\Users\14378
The user has a valid .codegraph/ index at C:\Users\14378\Documents\Code\Claude\Windows-MCP\.codegraph\, but the server only ever walks up from $HOME, so it never finds it. Switching to a different workspace does not change behavior — every workspace reports the same "starting from home" message.
Workaround: passing projectPath explicitly in the tool args works (e.g. {"query":"Desktop","projectPath":"C:/Users/.../Windows-MCP"}), which confirms the server itself is healthy; the daemon is what is dropping the workspace context.
Root cause (from inspecting daemon.js)
The daemon bundles createStdioTransport and a hard-coded ListRootsRequestSchema handler that both ignore the calling session entirely:
// packages/daemon/src/mcp/runtime/transport/stdio.ts (in daemon.js ~line 493289)
function createStdioTransport(config, options) {
return new StdioClientTransport({
command: config.command,
args: config.args,
env: buildProcessEnv(config.env, options?.env),
cwd: homedir(), // ← always homedir, ignores session
stderr: "pipe"
});
}
// packages/daemon/src/mcp/runtime/connection-pool.ts (in daemon.js ~line 493515)
client.setRequestHandler(ListRootsRequestSchema, async () => ({
roots: [{ uri: pathToFileURL(homedir()).href, name: "home" }] // ← always home
}));
Two related issues:
- The stdio transport spawns the child with
cwd = homedir()regardless of which session/agent triggered the call. - When the server requests
roots/list(the spec-blessed way to learn the workspace), the handler always returns the home directory.
McpConnectionPool.callTool(serverName, toolName, args, overrides, options) accepts an options object, but only options.timeout is read — there is no plumbing for workspace context from session → transport.
Additionally, McpConnectionPool.connections = new Map<serverName, connection>() caches one connection per server name globally, so even if transport were fixed naively, two sessions in different workspaces would share the same child process. CodeGraph supports per-call projectPath to multiplex, but other servers may not.
The session layer already has the data — session.workspaceDir is plumbed everywhere (e.g. agentProcessManager.ensureAgentProcess(ctx, agentName, workspaceDir), spawnSessionProcess(..., { cwd: workspaceDir }), ~235 hits in daemon.js), it just doesn't reach MCP.
Steps to reproduce
- Install the CodeGraph MCP server (or any stdio MCP server that resolves a project root from cwd/roots) and index a project with
codegraph initso.codegraph/exists in the project root. - Start an agent session in MiniMax Code with that project as the workspace.
- From the agent, call any codegraph tool (e.g.
codegraph_search) without passingprojectPath. - Observe the server reports "No CodeGraph project is loaded … starting from: C:\Users<you>".
- Switch to a different project workspace, repeat the call — the error message still says
C:\Users\<you>.
Reproduction from CLI:
mavis mcp call codegraph codegraph_search '{"query":"Desktop"}'
# → No CodeGraph project is loaded for this session.
# Searched for a .codegraph/ directory starting from: C:\Users\14378
echo '{"query":"Desktop","projectPath":"C:/Users/14378/Documents/Code/Claude/Windows-MCP"}' \
| mavis mcp call codegraph codegraph_search --stdin
# → works (10 results)
Expected behavior
The MCP stdio server should be able to discover the active workspace via one of:
process.cwd()reflecting the calling session's workspace, orroots/listreturning{ uri: "file:///path/to/active/workspace", name: "workspace" }for the calling session'sworkspaceDir.
Switching to a different project workspace should change which .codegraph/ (or equivalent per-project state) the server finds.
Actual behavior
Both cwd and roots/list always resolve to the user's home directory. Per-project MCP servers are effectively unusable without manual projectPath workarounds. The user has to inject workspace context into every tool call.
Suggested fix (sketch, not exhaustive)
The minimum changes are in two places, both in daemon.js:
-
createStdioTransport— accept and forward an optionalcwdfromoptions(which already exists oncreateTransport's options), defaulting tohomedir()only when nothing else is available. -
ListRootsRequestSchemahandler — pull the active workspace from a session-aware context (e.g. anAsyncLocalStoragepopulated bycallToolfromsession.workspaceDir); fall back tohomedir()if no session is in flight. -
McpConnectionPool.callTool— extend theoptionsargument to accept{ timeout, workspaceDir, sessionId }, passworkspaceDirinto the transport factory, and store it on the connection soroots/listcan read it without global state. -
Connection caching — consider keying connections by
(serverName, workspaceDir)instead of justserverName, or at minimum guarantee that every call forwards the correctprojectPath(CodeGraph already supports this; the daemon should inject it). For servers that don't support per-call project selection, per-workspace child processes are required.
The session layer already has the data (session.workspaceDir) and threads it into agent process spawning — it just stops at the MCP boundary.
Logs / evidence
From the user's machine:
mavis mcp get codegraph:{ "command": "C:\\Program Files\\nodejs\\node.exe", "args": [ "C:\\Users\\14378\\AppData\\Roaming\\npm\\node_modules\\@colbymchenry\\codegraph\\npm-shim.js", "serve", "--mcp" ], "env": {}, "enabled": true, "configured": true }mavis --version→3.0.43- CodeGraph server's own daemon log (
<project>/.codegraph/daemon.log) shows the server starts fine, just at the wrong root.
Before submitting
- I have searched existing issues. (Searched: "MCP workspace", "roots/list", "stdio cwd" — no matches in open issues)
- I am using the latest version available to me. (3.0.43)
- I have removed sensitive information from logs/screenshots. (paths and tool names only)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Trace workspace handling from session.workspaceDir through McpConnectionPool.callTool into packages/daemon/src/mcp/runtime/transport/stdio.ts and connection-pool.ts. Start by examining the existing transport options and connection cache, then reproduce the CodeGraph CLI flow across two workspaces. Done means stdio cwd and roots/list reflect the active workspace without requiring projectPath, while separate workspaces do not share incorrect context.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, typescript
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100