mlua-probe
Lua debugger, test runner, and static analyzer for mlua — breakpoints, stepping, variable inspection, expression evaluation, a built-in test framework, and lint-style code checking.
Designed for programmatic access: attach to a running mlua::Lua instance and control it from any frontend (MCP server, DAP adapter, etc.).
Crates
| Crate | Description |
|---|---|
mlua-probe-core |
Core debug engine, test framework, and static checker |
mlua-probe-mcp |
MCP server binary (stdio transport) |
mlua-lspec |
Lua test framework for mlua (external dependency) |
mlua-check |
Lua static analysis engine (external dependency) |
Architecture
The engine uses a VM-thread blocking model:
- A Lua debug hook pauses the VM thread when a breakpoint or step condition is met
- While paused, inspection commands (locals, upvalues, evaluate) run on the VM thread — required because
lua_getlocaland friends are not thread-safe - A resume command (continue / step) unblocks the hook
┌──────────┐ commands ┌──────────────┐
│ Frontend │ ───────────────► │ Controller │
│ (MCP/..) │ ◄─────────────── │ │
└──────────┘ events └──────┬───────┘
│ mpsc
┌──────▼───────┐
│ Debug Engine │
│ (VM thread) │
└──────────────┘
Quick start
As a library
use *;
use ;
let lua = new;
let = new;
session.attach.unwrap;
controller.set_breakpoint.unwrap;
let handle = spawn;
let event = controller.wait_event.unwrap;
controller.continue_execution.unwrap;
let result = handle.join.unwrap.unwrap;
assert_eq!;
As an MCP server
Add to your MCP client configuration:
MCP tools
| Tool | Description |
|---|---|
debug_launch |
Launch a Lua debug session with source code |
set_breakpoint |
Set a breakpoint at source:line |
remove_breakpoint |
Remove a breakpoint by ID |
list_breakpoints |
List all breakpoints |
continue_execution |
Resume execution |
step_into |
Step into the next line |
step_over |
Step over (skip function bodies) |
step_out |
Step out of current function |
pause |
Request VM to pause |
wait_event |
Block until next debug event |
get_stack_trace |
Get current call stack |
get_locals |
Get local variables at a frame |
get_upvalues |
Get captured variables at a frame |
evaluate |
Evaluate a Lua expression |
get_state |
Get session state |
disconnect |
End debug session |
| Testing | |
test_launch |
Run Lua tests with the mlua-lspec framework and return structured results |
| Checking | |
check_launch |
Run static analysis on Lua code and return structured diagnostics |
Testing
The test_launch tool runs Lua test code with the mlua-lspec framework (describe/it/expect/spy) pre-loaded and returns structured JSON results (passed/failed counts and per-test details).
local describe, it, expect = lspec., lspec., lspec.
describe
The testing module is independent of the debug session. To debug a failing test, pass the same Lua code to debug_launch — breakpoints and stepping work inside test code as usual.
Static analysis
The check_launch tool runs mlua-check on Lua source code without executing it. It detects undefined variables, globals, and table fields, returning structured diagnostics (rule, severity, line, message).
-- check_launch will warn: undefined global 'unknown_func'
unknown_func
The checker uses the standard Lua 5.4 symbol table. For custom globals registered on a mlua::Lua instance, use the checking::framework::register API from Rust.
Requirements
- Rust 1.77+
- Lua 5.4 (vendored via mlua)
Contributing
Bug reports and feature requests are welcome — please open an issue. Pull requests are also appreciated.
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.