Skip to content

ruby attach across a container boundary can bind no breakpoints: localfs is silently overridden, localfsMap is inert #499

Description

@debugmcpdev

Corrected 2026-08-26. The first version of this issue claimed localfsMap verified breakpoints that never fire, and that localfs: true was a working workaround. Both observations came from a re-used rdbg --open target that an earlier client had already set a breakpoint on — rdbg keeps its breakpoint table across client disconnects, so the later attach inherited a binding it never made. Re-run against a fresh target, nothing works. The body below is the corrected finding.

Summary

A containerised mcp-debugger attaching to a rdbg outside the container cannot bind any line breakpoint, and both levers that are supposed to fix that are inert:

  • localfs is advertised in supportedAttachKeys, but transformAttachConfig overwrites the caller's value after spreading it, so localfs: true is silently discarded — and it produces no warning, because the key is present both before and after the transform (only its value changed), so it is neither "dropped" nor "forwarded unknown".
  • localfsMap (both directions) leaves the breakpoint unbound.
  • docs/ruby/README.md's primary remedy — "prefer target-side paths" — cannot work while localfs is false, no matter how correct the path is.

The code

packages/adapter-ruby/src/ruby-debug-adapter.ts:

const {, localfsMap, ...rest } = config as Record<string, unknown>;

const attachConfig: RubyAttachConfig = {
  ...rest,                            // caller's localfs lands here…
  
  localfs: this.isLocalHost(host),    // …and is overwritten here};

adapterConfig is merged over the attach config before transformAttachConfig (session-manager-operations.ts:2712, issue #336), so a caller-supplied localfs reaches rest and is then discarded.

Experiment (fresh target)

Host: Windows 11, Ruby 3.4, rdbg --open --port 5693 --host 0.0.0.0 --nonstop examples/ruby/long_running.rb. Nothing else had ever attached to this process. Server: mcp-debugger:local 0.24.2 in Docker, attaching via host.docker.internal.

# adapterConfig breakpoint path result
1 localfsMap: "C:/…/mcp-debugger:/workspace" /workspace/…/long_running.rb:12 verified: false + is not available
2 localfsMap: "/workspace:C:/…/mcp-debugger" /workspace/…/long_running.rb:12 verified: false + is not available
3 localfs: true C:/…/long_running.rb:12 (target-side) verified: false + is not available

Control, same fixture and line, server on the host with host: 127.0.0.1 (so isLocalHostlocalfs: true): verified: true, breakpoint hits, locals read (counter, squared, message).

Everything else about the cross-boundary attach works: connect, pause, get_stack_trace, list_threads, get_local_variables, evaluate_expression, detach (target survives). Only breakpoint binding is unreachable.

Note on localfsMap's format on Windows targets

rdbg parses localfsMap as colon-separated remote:local pairs. Every path on a Windows debuggee contains a drive-letter colon (C:/Users/…), so the pair is ambiguous by construction. Even if the flag were reaching rdbg usefully, there may be no way to express a Windows-target mapping in it. Worth checking before treating localfsMap as the answer here.

Suggested

Scope

mcp-debugger:local 0.24.2, Docker image, both the Streamable HTTP and SSE transports (same server core). Found during a full /testdebugger everything sweep.

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