Skip to main content

Crate ghidra_mcp

Crate ghidra_mcp 

Source
Expand description

The agent-agnostic half of the Ghidra MCP stack.

Everything here is shared by every agent’s plugin: the MCP server and its 19 tools, the worker lifecycle glue, the config contract, and the embedded GhidraMcpWorker.java and driver skill. An agent plugin contributes only a binary that calls cli::dispatch, plus its own manifest and skills.

Modules§

cli
The argv-level entry point every agent’s plugin binary dispatches into.
config
Server configuration + static validation (spec §7). Precedence: CLI flag > env var > config file > built-in default. Validation happens BEFORE any worker boot so a misconfig surfaces as a clean onboarding error, not a boot crash-loop. bootstrap_program is required (the worker cannot boot without a valid -process program — M0 spike D1).
execute
The request engine (spec §4.3/§4.4/§4.7/§5): the ordered pipeline every tool call runs through. Returns either a worker result Value (plus a snapshot of the active canonicalizer for the caller to canonicalize addresses) or a structured ErrorEnvelope.
logging
Server logging: a per-instance, size-bounded, owner-only file log — never stdout (spec §5). stdout is the MCP JSON-RPC channel; any byte there corrupts the protocol. The 128-bit connection token is NEVER passed to a log macro anywhere in the server (enforced by review, not code).
paths
Filesystem locations for the server: the ghidra-mcp data dir, the per-version worker-script dir, and the per-instance log path (spec §5). Base dir = $GHIDRA_MCP_HOME, else %USERPROFILE%/$HOME + “.ghidra-mcp”, else the system temp dir. No external dir crate (keeps the deny gate small).
poison
Bounded poison-set (spec §4.3): remembers (tool, selector) pairs that reproducibly crashed the worker, so an identical later request is rejected up-front without a third/fourth respawn. Bounded LRU (evicts oldest) so a stubborn agent spamming distinct payloads can’t grow it without limit.
server
MCP stdio server (lands across Tasks 12-15 of the M1a “Crucible” plan).
skill_asset
Embed the driver skill (skill/SKILL.md) in the binary so an agent plugin can regenerate its committed copy from the shipped binary (single source of truth — no skill drift). The ship-guard test below fails the build if the embedded content is stubbed, emptied, or truncated rather than the authored driver skill.
state
Server state: the single worker held behind an async mutex, its active attachment + address canonicalizer, the poison set, and a permit semaphore. Lazy single-flight boot (spec §5); strict inner<outer timeouts (spec §4.7); transparent crash respawn (spec §4.3) lives in execute.rs.
tools
MCP tool handlers (spec §3). Each maps a worker result Value into the client-facing shape, then canonicalizes every address string through the attached program’s AddressCanonicalizer (spec §6). Domain errors become CallToolResult{isError:true} with the ErrorEnvelope as text (spec §4.2).
worker_asset
Embed the worker .java in the binary and extract it to a per-user script dir at boot, keyed by content hash so the extracted copy always matches the compiled binary (spec §12). Only the thin-slice extraction primitive; the §6 extraction-integrity hardening (0700/0600, ownership, symlink guards) is layered in a later milestone.

Functions§

worker_asset_extract
Extract the embedded worker script into dir. Returns the script path; IO failures (full disk, read-only temp dir) are returned, never panicked — the shipped boot-smoke path calls this on a real filesystem.