Skip to content

Route pylink-square-mcp through a persistent J-Link Remote Server - #53

Merged
emrainey merged 2 commits into
developfrom
issue-52
Aug 11, 2026
Merged

Route pylink-square-mcp through a persistent J-Link Remote Server#53
emrainey merged 2 commits into
developfrom
issue-52

Conversation

@emrainey

Copy link
Copy Markdown
Owner

Closes #52

Problem

The pylink-square MCP server crashes periodically. Every tool call created a
fresh pylink.JLink(), opened USB, connected, and discarded it — repeated
J-Link DLL load / USB connect-disconnect churn inside a long-lived process.

Change

All 13 J-Link tools now connect through a persistent localhost J-Link
Remote Server
(default 127.0.0.1:19020) instead of opening USB per call.
mcp_server.py launches the daemon on startup when nothing is listening and
intentionally leaves it running across MCP restarts.

  • jlink_connection.py (new): shared --remote-host/--remote-port/--direct
    args + connect() via jlink.open(ip_addr="host:port") with direct-USB
    fallback.
  • All tool scripts converted to the shared helper.
  • mcp_server.py: ensure_remote_server() spawns
    JLinkRemoteServer -Port <port> [-USB <serial>]; every handler routes
    through it with --remote-host/--remote-port; new
    --device/--speed/--remote-port/--usb-serial CLI with JLINK_MCP_* env
    fallbacks.
  • README + gotcha + .gitignore for the server logs.

Verification

  • Live through the tunnel: debug_target, run_for --seconds 2,
    rtt_read --continuous 4 all connect/read correctly.
  • MCP restart detects the already-running daemon.
  • Host LLVM build + all 18 unit tests pass; no C++ sources touched
    (cross presets unaffected; CI will still validate).

…er (#52)

Stabilize the pylink-square MCP server (crashes caused by repeated J-Link
DLL load / USB connect-disconnect on every tool call) by connecting all
J-Link tools through a persistent localhost J-Link Remote Server on port
19020, and have mcp_server.py launch that daemon when it isn't listening.

AI-authored (deepseek-v4-flash-free, 4k context) — researched SEgger KB,
designed/implemented:
- jlink_connection.py: shared --remote-host/--remote-port/--direct args and
  a connect() that opens via jlink.open(ip_addr=host:port) with direct-USB
  fallback.
- Converted all 13 J-Link tool scripts to the shared helper.
- mcp_server.py: spawns JLinkRemoteServer -Port <port> [-USB <serial>] on
  startup if not already listening (persists across MCP restarts), routes
  every tool call through it via --remote-host/--remote-port; added
  --device/--speed/--remote-port/--usb-serial with JLINK_MCP_* env fallbacks.
- .gitignore/gotcha/PLAN/README docs.

Human review: chose the localhost-server default, confirmed port 19020,
provided the Remote Server launch options, and requested serial numbers not
appear in examples/commits.

Verified live on hardware through the tunnel: debug_target, run_for,
rtt_read --continuous. Host LLVM build + all 18 unit tests pass; no C++
sources touched.
@emrainey
emrainey merged commit a02aef7 into develop Aug 11, 2026
4 checks passed
@emrainey
emrainey deleted the issue-52 branch August 11, 2026 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant