Malspark

Tools

radare2

The r2 static provider: r2mcp over stdio.

The r2 static provider attaches r2mcp, radare2's MCP server, over stdio. It is a generic MCP provider with radare2-specific defaults, and like it, it degrades: a missing r2mcp costs the run its tools and is named in the run summary, rather than failing the job.

Install and connect

r2pm -ci r2mcp
core.static.provider     = r2
core.static.r2.enabled   = true
core.static.r2.binary_path = r2mcp

Where r2mcp is looked for

r2pm -ci r2mcp installs under radare2's own prefix and does not touch PATH, so the provider resolves the name when it starts. A value with a directory in it is used as it is; a bare name is looked up on the worker's PATH, then in $R2PM_BINDIR, $R2PM_PREFIX/bin and radare2/prefix/bin under the user's data directory ($XDG_DATA_HOME, else ~/.local/share). Nothing past those is guessed. Not found, the log names every place looked, and the run summary carries static provider 'r2' unavailable: … with the remedy. Setting binary_path to the executable's absolute path is the sure way. See Where r2mcp is looked for.

The mirror directory

r2 reads the sample from a copy the worker makes under the samples directory: core.static.r2.work_dir, r2-work by default (one directory name, as for every server). A value stored as core.static.r2.mirror_dir by an earlier release is read as this setting, by its last segment. The copy is hardened like every mirror — a 0o700 directory, a 0o600 file — and removed when the job ends.

The mirror directory may not be hidden

radare2 rejects any path with a /. segment, so an r2mcp handed a sample under a hidden directory answers "Failed to open file." to every call. The setting refuses a hidden segment and says why.

The r2 analyst is handed the mirror and only the mirror. No analyst's chunk carries the worker's own copy (its staging path, under a hidden directory); the static role's family classifier reads that from the agent. A path argument that spells the worker's copy in full is replaced with the mirror before the call, as the bare file name always was. Before the analyst's loop, the r2 provider opens the mirror in r2mcp's session with r2mcp's own open_file (R2StaticProvider.open_sample), as the Ghidra provider loads its program, so a listing tool called first is answered rather than refused; a failed early open is logged and changes nothing else. A failed open_file names the path it tried and the mirror radare2 can open, and r2mcp's open-first refusal, whether written as a reply or raised as a protocol error, names the mirror in its remediation.

The same directory is how r2mcp on another host can read the sample through a shared volume; see Tool servers on another host.

One tool, one analyst

The importable all-tools team runs all_tools_static_r2 with static_provider: "r2" beside two other static analysts, each reading a tool of its own. See An all-tools team.

What its tools are read as

The platform ships no table of r2mcp's tools. Each one is read from what r2mcp lists, by its verb, its object and its arguments' role words. The block says once that its tools run nothing, reach no network and send nothing (default_effects). Its sample_open names analyze as its analysis step, with no open tool, because the provider opens the sample itself. analyse_effects says that step emulates the sample's code at analysis level 2 and above, where r2mcp runs aaa. When r2mcp is started with -r, run_command runs whatever command it is given, so it declares no effect. See A decompiler's or disassembler's tools read from what it lists.

Edit on GitHub

On this page