- Python 92.4%
- Nix 7.3%
- Shell 0.3%
| .gitignore | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
| run | ||
| server.py | ||
| test_server.py | ||
Persistent Rizin MCP server
This MCP server keeps each opened binary in a long-lived rizin -q0 subprocess and can checkpoint
analysis for later MCP processes. Checkpoints are keyed by the binary's SHA-256, so an unchanged
binary can restore its analysis while a changed binary starts fresh.
It uses only the Python standard library. The Nix package supplies both Python and Rizin at runtime. The flake provides x86-64 and ARM outputs for Linux and macOS.
Run with Nix
nix run "git+https://git.kunet.dev/wslop/rizin-mcp"
The process speaks MCP over standard input/output and normally runs under an MCP host. Build and test the complete package with:
nix flake check "git+https://git.kunet.dev/wslop/rizin-mcp"
Register with Codex
codex mcp add rizin -- nix run "git+https://git.kunet.dev/wslop/rizin-mcp"
Then add a long tool timeout to the generated ~/.codex/config.toml entry so aaa is not cut off
by Codex's 60-second default:
[mcp_servers.rizin]
tool_timeout_sec = 7200
Recommended configuration:
[mcp_servers.rizin]
command = "nix"
args = ["run", "git+https://git.kunet.dev/wslop/rizin-mcp"]
tool_timeout_sec = 7200
default_tools_approval_mode = "approve"
Restart the Codex session after registration. Live analysis remains resident for the lifetime of the MCP process; SHA-keyed checkpoints provide reuse after that process exits.
Typical workflow
- Always call
rizin_acquirewith the DLL path, sessionserver, and required analysisaaa. - If it returns
state: ready, reuse the resident or restored analysis without runningaaa. - If it returns
state: analysis_required, callrizin_analyzewith levelaaa, followed byrizin_checkpoint. - Reuse
rizin_commandfor the rest of the session. Prefer JSON commands such asaflj,isj,axtj, andpdfj, withparse_jsonenabled. - Checkpoint again after meaningful renames, flags, comments, types, or other analysis changes.
rizin_acquire reports source: resident, checkpoint, or fresh, along with the available and
required analysis levels. Multiple named sessions can remain open at once (for example, server
and client). The binary is opened read-only.
Checkpoints default to ~/.rizin-mcp/checkpoints. Set RIZIN_MCP_STATE_DIR to choose another
cross-platform location. A checkpoint created by a different Rizin version is reported as
incompatible rather than loaded automatically; allow_incompatible can override that safeguard.
Rizin shell escapes are rejected by default. Set RIZIN_MCP_ALLOW_SHELL=1 in the MCP server's
environment only if that behavior is explicitly needed. The default command timeout is one hour;
override it with RIZIN_MCP_TIMEOUT_SECONDS or per rizin_command call.
Manual smoke test
Every stdio MCP message is one line of JSON:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"smoke","version":"1"}}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
| nix run "git+https://git.kunet.dev/wslop/rizin-mcp"