Skip to content

Web UI: MCP servers fail to spawn when Instance.directory resolves to base64-encoded path #18805

Description

@david-strejc

Description

When using OpenCode Web UI (opencode web), switching between workspaces causes Instance.directory to resolve to a non-existent path containing a base64-encoded directory name. This causes all local MCP server processes to fail with ENOENT on posix_spawn, leaving sessions without any local MCP tools.

Environment

  • OpenCode version: 1.2.24 (upgraded to 1.3.0, untested yet)
  • Runtime: Bun
  • OS: Debian 12 (bookworm)
  • Setup: opencode web --port 3002 running as systemd service per user, 10 concurrent user instances on same server
  • MCP servers: 2 local (uv for Python, node for JS), 1 remote (HTTP)

Reproduction

  1. Start opencode web --port 3002 as a systemd service
  2. Open the Web UI and create a session in workspace /home/eva/workspace
  3. MCP servers start correctly — all 97 tools from unified-ads load fine
  4. Navigate to a different workspace or create additional sessions
  5. At some point, a new Instance is created where Instance.directory resolves to a base64-encoded path appended to the original workspace path

Observed Behavior

From the logs (~/.local/share/opencode/log/2026-03-12T065837.log):

Working (06:59) — real directory:

service=mcp key=unified-ads toolCount=97 create() successfully created client
directory=/home/eva/workspace

Working (07:06) — another real directory:

service=mcp key=unified-ads toolCount=97 create() successfully created client
directory=/home/eva

Broken (07:07) — base64-encoded path:

ERROR service=mcp key=unified-ads cwd=/home/eva/workspace/L2hvbWUvZXZhL3dvcmtzcGFjZQ error=ENOENT: no such file or directory, posix_spawn '/usr/local/bin/uv' local mcp startup failed
ERROR service=mcp key=imagemaker cwd=/home/eva/workspace/L2hvbWUvZXZhL3dvcmtzcGFjZQ error=ENOENT: no such file or directory, posix_spawn 'node' local mcp startup failed

An earlier log also shows:

cwd=Lw error=ENOENT ...

The string L2hvbWUvZXZhL3dvcmtzcGFjZQ is base64 of /home/eva/workspace.
The string Lw is base64 of /.

OpenCode's Web UI uses base64-encoded paths in URL routing (/<base64-dir>/session/<id>). It appears this base64 string is being used as a literal filesystem path for Instance.directory instead of being decoded first.

Impact

  • ALL local MCP servers fail (uv, node) — both unified-ads (Python/FastMCP) and imagemaker (Node.js) hit the same error
  • Only remote/HTTP MCP servers survive (they don't need posix_spawn)
  • Users see sessions where MCP tools are completely missing with no clear error in the UI
  • The ENOENT error message is misleading — it blames the executable (/usr/local/bin/uv) rather than the CWD (known Bun bug: Bun.spawn throws incorrect ENOENT error when cwd does not exist oven-sh/bun#24012)

Evidence This Is Not an MCP Configuration Issue

  1. Two completely independent MCP servers (Python via uv, Node.js via node) fail identically
  2. Both executables exist and work fine — which uv/usr/local/bin/uv, which node/usr/bin/node
  3. The MCP config is correct and works when Instance.directory is a real path
  4. OpenCode itself logs No such file or directory: '/home/eva/workspace/L2hvbWUvZXZhL3dvcmtzcGFjZQ'

Expected Behavior

Instance.directory should always resolve to a valid filesystem path. If the Web UI uses base64-encoded paths for URL routing, these should be decoded back to real paths before being used as CWD for MCP process spawning.

Potentially Related Issues

MCP Config (for reference)

{
  "unified-ads": {
    "type": "local",
    "command": ["/usr/local/bin/uv", "run", "--directory", "/opt/mcp/adsmcp", "python", "-m", "unified_ads_mcp"],
    "enabled": true,
    "environment": {
      "HOME": "/home/eva",
      "GOOGLE_ADS_CREDENTIALS": "/home/eva/google-ads.yaml",
      "META_ADS_CREDENTIALS": "/home/eva/meta-ads.yaml"
    }
  }
}

Note: There is no cwd field in the McpLocal schema (.strict() validation), so there is no workaround from the configuration side.

Suggested Fix

In the MCP spawning code, either:

  1. Decode the base64 path back to a real filesystem path before using it as CWD
  2. Validate that Instance.directory exists before passing it to Bun.spawn()
  3. Fall back to a safe default CWD (e.g., user's home directory or /tmp) if the directory doesn't exist
  4. Add a cwd option to the McpLocal schema so users can specify a fixed working directory for MCP processes

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions