Skip to content

cli: service discovery intermittently times out waiting for the background service #52021

Open

Description

@z291173301

Summary

opencode mcp list intermittently fails with Error: Timed out waiting for the background service to start even though a healthy background service is already running and listening. The same command also intermittently reports No MCP servers configured depending on the working directory. The service registration file stores no port or PID, so the CLI has to re-derive the endpoint, and that re-derivation appears to be where it fails.

Environment

  • opencode version: opencode v2.0.19
  • OS: Windows 11 25H2 (10.0.26200), win32 x64
  • Terminal: Windows Terminal, TERM=xterm-256color
  • Shell: PowerShell 7.6.6
  • Install/channel: desktop app present alongside CLI; opencode shim at C:\Users\...\AppData\Roaming\npm\opencode.cmd
  • Active plugins: D:/@Data/MCP Server/opencode-dcp/node_modules/@tarquinen/opencode-dcp

Reproduction

Intermittent. From a working shell with the service healthy:

  1. Start the desktop app so the background service is running. Confirm with opencode service status — it reports http://127.0.0.1:49374, and the desktop main.log shows v2 CLI background service ready { port: '49374' }.

  2. From PowerShell, run opencode mcp list.

  3. Roughly half the time the command fails:

    PS C:\Windows\System32> opencode mcp list
    Error: Timed out waiting for the background service to start
        at <anonymous> (B:/~BUN/root/chunk-gsfq8agx.js:3:5692)
        at service.ensure (B:/~BUN/root/chunk-stx5n0x4.js:2:746)
        at service.ensure (definition) (B:/~BUN/root/chunk-gsfq8agx.js:3:3955)
        at cli.mcp.list (B:/~BUN/root/chunk-s87fe5kt.js:49:15321)
        at cli.mcp.list (definition) (B:/~BUN/root/chunk-stx5n0x4.js:2:696)
    

    Note the prompt: the failure was hit from C:\Windows\System32.

  4. Instead of the timeout, the same command from C:\Windows\System32 sometimes reports No MCP servers configured instead — despite the running service having all 11 servers connected. The same command from D:\@Data\MDCx and from C:\Users\ZhouHan reported all 11 as connected in every attempt.

  5. Re-running from C:\Windows\System32 with OPENCODE_LOG_LEVEL=DEBUG then succeeded and listed all 11 servers as connected.

Expected Behavior

If a healthy background service is already listening, opencode mcp list should connect to it and report its status, regardless of the current working directory. Global config at ~/.config/opencode/opencode.jsonc is documented to apply to every project for the user, so a directory outside the project tree should not change the result.

Actual Behavior

The CLI intermittently concludes that no healthy service exists. It then spawns one or more short-lived opencode-cli.exe serve --service processes that:

  • are visible for only a few seconds,
  • have zero child processes,
  • listen on no port at all,
  • and exit on their own without logging anything to the desktop app's main.log.

Observed during a failure window: PID 2572 (13:39:42) with children 9804 (13:41:23) and 26096 (13:41:33), all gone by the next command, plus PID 25128 (13:41:38, 166 MB) also appearing with serve --service. Throughout this, the real service was healthy on 127.0.0.1:49374 with 19 MCP children and ~1.2 GB working set.

Because those spawned instances bind no port, they can never become ready, and service.ensure eventually times out.

Additional Context

Service registration carries no endpoint. ~/.config/opencode/service.json contains only:

{
  "password": "<redacted>"
}

There is no port and no pid. opencode service get returns {}. ~/.local/share/opencode/ contains only opencode.db (48 MB) and its WAL/SHM files — no service record. So the CLI must derive the port some other way; the port was 49374 on both observed service starts (13:22:33 and 13:33:08), which suggests deterministic derivation rather than a random assignment.

The service is authenticated. An unauthenticated request to the running service is rejected:

Invoke-WebRequest http://127.0.0.1:49374/api/info   ->   HTTP 401 Unauthorized
opencode api get /api/info                             ->   {"version":"2.0.19","pid":24836,...}

So any port-probing health check gets a 401, and a client that does not have the password cannot distinguish "service is up" from "wrong port".

Working directory sensitivity. Config discovery walks from the current directory up through its ancestors. From C:\Windows\System32 that walk reaches C:\Windows and C:\ and stops, never reaching C:\Users\<name>, so ~/.config/opencode/opencode.jsonc is not in the discovered set. This matches the No MCP servers configured outcome, but since the DEBUG run from the same directory succeeded, it is a race or ordering issue rather than purely deterministic path behavior. OPENCODE_DISABLE_PROJECT_CONFIG=1 is set in the environment.

Related: this churn looks like the trigger for orphaned MCP subprocess accumulation — see #52020.

Logs: ~/.local/share/opencode/log/ is empty (no opencode.log), so no server-side lifecycle logs were available. Desktop logs are under %APPDATA%\ai.opencode.desktop\logs\<timestamp>\.

Activity

  1. github-actions commented on Sep 29, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

  2. opencodejr commented on Oct 28, 2026

    @opencodejr
    Contributor

    Thanks for the detailed report. I could reproduce the No MCP servers configured part, on 2.0.19 and on the latest dev (86ce19d).

    It doesn't depend on which directory you run from. The first opencode mcp list from a directory the running service hasn't seen before comes back empty, and later runs from the same directory list the servers. So C:\Windows\System32 most likely failed because the service hadn't seen it yet, and your DEBUG re-run worked because it was the second call. The script below reproduces it with a global config that defines one MCP server: it starts the service and runs mcp list three times in each of three new directories. The first call in each directory is empty.

    This looks like the same problem as #54192 (MCP handlers read an empty registry for directories the service hasn't loaded yet). #50710 reports the same empty list.

    I couldn't reproduce the Timed out waiting for the background service to start error or the extra port-less serve --service processes on Linux. That part seems to need Windows with the desktop app, where the CLI and desktop can register the service in different state directories (see #56708 and #58389). A maintainer with that setup will need to check it.

    Reproduction script (repro.sh)
    #!/usr/bin/env bash
    # Reproduces: `opencode mcp list` prints "No MCP servers configured" on the first
    # call from each new working directory, although the global config defines an MCP server.
    # Set OC_DEV=/path/to/checkout to run from source instead of `opencode` on PATH.
    set -u
    oc() {
      if [ -n "${OC_DEV:-}" ]; then
        bun --conditions=browser --preload="$OC_DEV/packages/tui/node_modules/@opentui/solid/scripts/preload.js" "$OC_DEV/packages/cli/src/index.ts" "$@"
      else opencode "$@"; fi
    }
    mkdir -p ~/.config/opencode
    cat > ~/.config/opencode/opencode.jsonc <<'JSON'
    { "mcp": { "dummy": { "type": "local", "command": ["node","-e","setInterval(()=>{},1000)"] } } }
    JSON
    oc service stop >/dev/null 2>&1
    if [ -n "${OC_DEV:-}" ]; then
      # From source, the auto-spawned service lacks the JSX preload (see #58981), so start it by hand.
      (cd /tmp && oc serve --service >/tmp/oc-service.log 2>&1 &)
      sleep 10
    else
      oc service start
    fi
    oc service status
    for n in 1 2 3; do
      d=$(mktemp -d)
      for i in 1 2 3; do echo "$d run $i: $( (cd "$d" && timeout 60 bash -c "$(declare -f oc); OC_DEV=${OC_DEV:-}; oc mcp list" 2>&1) | head -1)"; done
    done

    Run it: bash repro.sh

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions