Example prompts

Eleven things you can type to an agent that has the server registered, with the tools each one triggers. The first four build in complexity; the rest are there for when you need them.

Start here

1. The minimal loop

“Set a breakpoint at TFoo.Bar and show me the locals when it’s hit.”

launch_debuggee (or launch_from_config) → set_breakpoint at the source line → continue_and_waitget_locals.

The shortest useful session, and the one everything else is a variation on. If the agent guesses the file name wrong, get_source_files gives it the spelling set_breakpoint expects.

2. Crash triage

“Launch Foo.exe and tell me why it’s crashing.”

launch_debuggeeset_exception_filters(["unhandled"]) (usually already the default) → continue_and_wait → on the stop, get_exception_details and get_call_stack — or get_compact_debug_snapshot for state, exception, top frames and top-frame locals in one call.

3. Watching a value evolve

“Set a breakpoint at TOrderProcessor.ProcessBatch, run to it, then step over 10 times and show me Order.Total after each step.”

set_breakpointcontinue_and_wait → then ten times: step_over followed by evaluate_expression("Order.Total").

4. Attach and ask

“Attach to the already-running MyApp.exe, tell me exactly where it’s stopped right now, and evaluate Customer.Orders.Count.”

attach_to_process(processName="MyApp.exe")get_current_source_locationevaluate_expression("Customer.Orders.Count").

If more than one instance is running the attach fails and lists the candidates with their command lines, so the agent can pick a pid rather than guess.

Finding out who wrote that

5. A field that keeps getting corrupted

“Watch TCustomer(FCustomer).FBalance and tell me which thread writes it and what the old and new values are each time.”

set_data_breakpoint(expression="TCustomer(FCustomer).FBalance", size=8, access="write")continue_and_wait, repeatedly. On each hit, dataBreakpointDescription in the snapshot names the old value, the new value and the writing thread directly — no manual diffing.

Watch a field or a global, not a bare local — a local is refused over MCP, because its address is only valid while its frame lives. See the tool reference.

6. Checking the slot budget

“Watch the global ActiveConnection for both reads and writes, then show me how many of the 4 hardware watchpoint slots are still free.”

set_data_breakpoint(expression="ActiveConnection", size=8, access="readWrite")list_data_breakpoints, which reports the slot each watchpoint holds.

Worth knowing before you ask: readWrite also fires on plain writes. There is no watch-reads-only mode on x86 or x64.

Below the source level

7. Registers and instructions at a crash

“Run until it crashes with an access violation, then show me the registers and the instructions around the crash point.”

set_exception_filters(["av"])continue_and_waitget_registers and disassemble(address=<crash RIP>, count=20).

8. Reading a structure by hand

“Evaluate Self.FBuffer to get its address, then dump the first 64 bytes and tell me what the header fields look like.”

evaluate_expression("Self.FBuffer") — or @Self.FBuffer for the address explicitly — → read_memory(address, count=64), which returns hex plus little-endian integer views.

Bigger targets

9. Which package exports this?

“Launch Hydra2.exe, wait for the business-logic packages to load, and tell me which BPL exports TInvoiceEngine.Calculate.”

launch_from_configcontinue_and_wait until the packages are loaded → get_loaded_modules, checking each module’s symbol state and loaded debug-info formats → cross-reference with get_source_files, or with a breakpoint that resolves against the right module.

10. Quieting handled exceptions

“I keep getting interrupted by EFileNotFound that the app catches itself. Only stop me on exceptions that actually crash the program.”

set_exception_filters(filters=["unhandled"]) — turns off the first-chance delphi, av and all breaks and leaves only the second-chance stop. For anything finer-grained than a whole category, the rule engine in launch.json is the right tool; see Exception handling.

Finishing cleanly

11. Detach, do not kill

“When you’re done inspecting, detach cleanly — don’t kill the process, it’s attached, not launched by you.”

detach_debugger, not terminate_debuggee. Detaching leaves the process running, which is the default for an attached session.

This prompt exists to teach one distinction. Breakpoints are INT3 bytes patched into the target, and only the debugger that planted them can put the originals back. A clean detach does that; an agent that kills the session instead leaves those bytes behind, and the program later dies with a mystifying External exception 80000003 that nothing connects back to the debugging session. See chapter 10.

Two things not to ask for

Neither of these exists over MCP, however reasonably an agent might attempt them: Set Next Statement, and writing a variable by name. Mutating state over MCP means write_memory or set_register and nothing else. Both are available in the VS Code debugger — see chapter 5.