Skip to content

synapse-todo-board: MCP error -32000 on startup after switching bundle image from local to remote registry #80

@Ovaculos

Description

@Ovaculos

Summary

After changing the synapse-todo-board bundle configuration from a local Docker registry address to the remote GitHub Container Registry image (ghcr.io/nimblebraininc/synapse-todo-board), the bundle fails to start on runtime boot. The web UI shows no entry for the bundle. Switching back to the local image address resolves the issue.

Repro

The full repro steps are not fully characterized. What is known:

  1. synapse-todo-board is installed and working with a local Docker registry image address.
  2. The bundle manifest or workspace config is updated to reference the remote image (e.g., ghcr.io/nimblebraininc/synapse-todo-board:latest).
  3. Runtime is restarted.
  4. Bundle fails to start; no sidebar entry appears.

Observed in Docker logs:

platform-1  | [bundles] Starting @nimblebraininc/synapse-todo-board...
platform-1  | [workspace-runtime] Failed to start synapse-todo-board in ws_usr_default: MCP error -32000: Connection closed
platform-1  | [workspace-runtime] Started 0/1 bundles in 444ms (concurrency=4)
platform-1  | [nimblebrain] Runtime ready.

What is known

  • The runtime reaches the bundle start step — [bundles] Starting is logged before the failure.
  • The MCP error -32000: Connection closed error originates from the MCP client transport after the subprocess exits or fails to establish the handshake within the 30-second connect timeout (src/tools/mcp-source.ts:110).
  • The bundle starts successfully at the same version with a local registry image. Only the image address changed.
  • No additional stderr from the Docker subprocess is surfaced in the platform logs.

Suspected causes

The Connection closed error typically means the spawned subprocess exited before completing the MCP initialization handshake. For a Docker-based bundle, likely candidates are:

  1. Image pull failureghcr.io/nimblebraininc/synapse-todo-board requires authentication or the image does not exist at the referenced tag. docker run exits non-zero before the MCP server starts.
  2. Silent pull timeout — Image pull exceeds the 30-second MCP connect timeout (src/tools/mcp-source.ts:110), causing the client to abort even if the image pull eventually succeeds.
  3. Platform difference — The remote image targets a different architecture or base OS than the local build, causing the container to exit immediately on launch.

Why this is hard to diagnose

The platform pipes subprocess stderr but does not forward it to the platform log or the web UI at bundle startup time. Connection closed is the only signal that reaches the operator. There is no indication of whether Docker pulled the image, failed authentication, or the container itself crashed.

See also #13 — bundle health is not surfaced in the web UI at all, compounding the diagnostic gap.

What would help

  • Capturing and logging Docker subprocess stderr during the startup attempt (at least on failure)
  • Distinguishing between "subprocess never started" and "subprocess started but MCP handshake timed out"
  • If the failure is a pull timeout, increasing or making the MCP connect timeout configurable for image-heavy bundles

Key files

  • src/bundles/startup.ts:160–189mpak.prepareServer() call + subprocess spawn
  • src/tools/mcp-source.ts:70–134 — MCP stdio transport setup, 30s timeout, error handling
  • src/tools/mcp-source.ts:122–134 — generic connection error catch (no stderr forwarded)

Metadata

Metadata

Assignees

No one assigned

    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