import { ProbeFactoryConfig } from "../probe/factory"; export declare class JLinkMcpServer { private server; private processManager; private probe; private gdb; private rttClient; private telnetProxy; constructor(probeConfig?: ProbeFactoryConfig, rttPort?: number, telnetConfig?: { listenPort?: number; sourceHost?: string; sourcePort?: number; }, gdbPath?: string); /** * Returns an MCP error response if device is not configured, or null if OK. * Call at the top of any tool handler that talks to hardware. */ private requireDevice; private registerTools; /** * Render a probe/GDB result as text, preferring the most specific thing we * have: parsed output, then raw output, then the error the layer below * produced, and only then a generic fallback. * * The layer below often knows exactly what went wrong — "Target is running; * GDB cannot accept commands until it stops" — and dropping that in favour * of "Could not read memory" hands the caller a dead end. Observed on * hardware: reading during a run returned the generic string while the * client had produced an actionable one. */ private static resultText; /** * Drop every breakpoint before a session ends. * * Best-effort and never fatal: failing to tidy up must not stop the caller * disconnecting. Returns a note to append to the tool's reply so the action * is visible rather than silent. */ private clearDebugState; /** * Run a probe-CLI operation that needs exclusive access to the probe, and * put any live GDB session back afterwards. * * flash and erase must spawn JLinkExe — GDB has no equivalent for writing a * .hex — and a J-Link serves one client at a time. Doing that alongside a * running GDB server evicts the server: the child GDB stays alive attached * to a dead socket, and the caller only finds out when their next command * fails for reasons that look nothing like "your flash did this". * * So take the session down deliberately, do the work, and bring it back. * Every step is reported: silently losing a debug session is the bug, and * silently restoring one would only be a quieter version of the same * problem. If the restore fails the caller is told exactly what state they * are in rather than left to discover it. */ private withGdbSessionRestored; /** * Attach our GDB client when the server is running without one. * * The J-Link GDB Server halts the core on attach and holds it, and it also * hosts the RTT telnet port — so anything using RTT needs the server up. * But CPU-control routing keys off whether a *client* is connected, so a * server with no client is the one configuration where every halt, reset, * step and read spawns a competing JLinkExe and evicts the server. RTT dies * with it, and the target is left halted with nothing driving it. * * That is reachable from the documented happy path: start_debug_session * brings up the server and RTT, and the next reset kills the stream. * * Connecting a client puts everything back on one channel. The alternative * — bracketing each call with a server stop and restart, as flash does — * would drop the RTT stream on every single control operation, which is a * worse answer to the same question. */ private ensureGdbSession; /** * Connect RTT to a target that is actually executing. * * Two things have to be true before RTT produces anything, and both are * easy to get wrong independently: * * - The core must be running. The GDB server halts it on attach and holds * it, so anything that brings the server up has stopped the firmware. * - The firmware must have reached the point where it builds its RTT * control block. The probe finds that block by scanning RAM when RTT * connects, and does not retry — connect too early and RTT is silent * forever, with no error anywhere. * * The failure is silent in both directions: the up channel produces nothing * and the down channel swallows commands, so it reads as "RTT is broken" * rather than "the target was not running yet". This has now been fixed * twice in two different call sites; it lives in one place so there is not * a third. */ private connectRttToRunningTarget; private registerResources; private registerPrompts; startStdio(): Promise; dispose(): void; } //# sourceMappingURL=server.d.ts.map