Lightweight MCP server for Ghidra-based reverse engineering with iOS, Linux, and game file support
Project description
pyghidra-lite
Lightweight MCP server for Ghidra-based reverse engineering. Focused toolset with smart backend features.
Quick Links
- ๐ฆ PyPI Package
- ๐ MCP Release Guide
- ๐ Issue Tracker
- ๐ค Contributing
- ๐ Security Policy
Design Philosophy
- Focused tool surface: Core tools plus capability-specific extensions
- Rich metadata: Functions include
refs_in,refs_out,has_strings,is_libraryfor prioritization - Stable IDs: Content-addressed
unit_idandstable_idsurvive renames - Analysis profiles:
fast/default/deeptradeoff without changing tools - Container detection: APK/IPA/AppImage detection hooks (extraction TODO)
- Per-binary projects: Each binary gets its own Ghidra project for multi-agent parallelism
- Persistent analysis: Shared cache persists across agent suspend/resume cycles
Requirements
- Ghidra 11.x installed
GHIDRA_INSTALL_DIRenvironment variable set to Ghidra installation path- Python 3.11+
Installation
cd pyghidra-lite
uv pip install -e .
Usage
As MCP Server (Claude Code)
Out of the box (stdio transport, automatic session isolation):
Add to .mcp.json in your project root (or ~/.claude.json for global):
{
"mcpServers": {
"pyghidra-lite": {
"command": "pyghidra-lite",
"args": ["--allow-any-path"]
}
}
}
Each agent automatically gets its own isolated session. No conflicts, no manual setup required!
With path restrictions (recommended for production):
{
"mcpServers": {
"pyghidra-lite": {
"command": "pyghidra-lite",
"args": [
"--allow-path", "/home/user/binaries",
"--allow-path", "/opt/apps"
]
}
}
}
With development installation:
{
"mcpServers": {
"pyghidra-lite": {
"command": "uv",
"args": [
"run",
"--directory",
"/path/to/pyghidra-lite",
"pyghidra-lite",
"--allow-any-path"
]
}
}
}
Command Line
# Start server (binaries imported via MCP tools)
uv run pyghidra-lite --allow-path /path/to/binaries
# Pre-load binaries with fast profile
uv run pyghidra-lite --profile fast --allow-path /path/to/binaries /path/to/app.apk
# Use custom project location
uv run pyghidra-lite --project-dir /tmp/ghidra-projects --project-name myproject --allow-path /path/to/binaries
Multi-Agent Usage
pyghidra-lite works out of the box with multiple agents using per-binary projects:
~/.local/share/pyghidra-lite/
โโโ projects/
โโโ abc123def456/ # Binary 1's project
โ โโโ abc123def456.gpr
โ โโโ abc123def456.rep/
โโโ 789ghi012jkl/ # Binary 2's project
โโโ 789ghi012jkl.gpr
โโโ 789ghi012jkl.rep/
Benefits:
- โ No configuration needed - just add to MCP config
- โ Persistent analysis - work survives agent suspend/resume
- โ Shared cache - all agents share analysis results
- โ Parallel analysis - different binaries analyzed simultaneously
- โ Minimal disk usage - each binary analyzed once, shared by all
- โ ๏ธ Same-binary locking - only locks when 2+ agents work on identical binary
When locks occur:
- Two agents analyzing the exact same binary (same content hash) simultaneously
- Does NOT lock when agents work on different binaries
- Rare in practice - agents typically work on different files or at different times
SSE Transport (Optional):
SSE transport is available but not required. Both stdio and SSE use the same shared project structure:
# Optional: Start SSE server for reduced process overhead
pyghidra-lite --transport sse --port 8001 --allow-any-path
SSE benefits: Single server process instead of one per agent, slightly less memory usage.
Import Policy (Multi-client)
import_binary is allowlisted by default for multi-client safety.
- Allow specific roots:
--allow-path /path/to/binaries(repeatable) orPYGHIDRA_LITE_ALLOWED_PATHS(pathsep-separated). - Allow any path (unsafe):
--allow-any-pathorPYGHIDRA_LITE_ALLOW_ANY_PATH=1.
Tools
Token-efficient defaults: list_functions, list_exports, swift_functions, and elf_symbols return compact output by default.
Pass compact=false to request full metadata.
Import (3)
| Tool | Description |
|---|---|
import_binary |
Import binary or container with profile selection |
delete_binary |
Remove from project |
reanalyze |
Re-run with different profile |
Discovery (4)
| Tool | Description |
|---|---|
list_binaries |
List all binaries with status |
list_functions |
Functions with metadata (sortable by refs) |
list_imports |
Imports with capability tags |
list_exports |
Exported symbols |
Analysis (8)
| Tool | Description |
|---|---|
get_function_info |
Function metadata and callers/callees |
disassemble |
Assembly for a function |
decompile |
Pseudo-C with callees and strings |
batch_decompile |
Decompile multiple functions efficiently |
get_xrefs |
Who calls/uses this |
get_callees |
What this function calls |
call_graph |
Call graph with configurable depth |
memory_map |
Memory layout with permissions |
Search (2)
| Tool | Description |
|---|---|
search_strings |
Strings with xrefs |
search_symbols |
Symbol name search |
Data (2)
| Tool | Description |
|---|---|
read_bytes |
Raw memory |
read_string |
Null-terminated string |
ELF (4)
| Tool | Description |
|---|---|
elf_info |
ELF structure summary |
elf_sections |
ELF sections |
elf_symbols |
ELF symbols |
elf_got_plt |
GOT/PLT entries |
Mach-O (3)
| Tool | Description |
|---|---|
macho_info |
Mach-O structure summary |
macho_segments |
Segments and sections |
macho_dylibs |
Linked dylibs |
Swift (4)
| Tool | Description |
|---|---|
swift_functions |
Swift functions (demangled) |
swift_types |
Swift types from metadata |
swift_decompile |
Swift decompile with demangled callees |
demangle |
Swift symbol demangling |
Objective-C (3)
| Tool | Description |
|---|---|
objc_classes |
Objective-C classes |
objc_methods |
Objective-C methods |
objc_decompile |
Objective-C method decompile |
Hermes (3)
| Tool | Description |
|---|---|
hermes_info |
Hermes bundle summary |
hermes_components |
React component names |
hermes_endpoints |
API endpoints/URLs |
Analysis Profiles
| Profile | Use Case |
|---|---|
fast |
Quick triage, minimal decompiler analysis |
default |
Balanced analysis |
deep |
Full analysis for obfuscated code |
# Import with fast profile for triage
import_binary("/path/to/app.apk", profile="fast")
# Re-analyze specific binary with deep profile
reanalyze("libnative.so", profile="deep")
Container Detection
Container extraction is not yet implemented. import_binary currently expects a direct
binary path; container detection helpers are in place for future extraction work.
Function Metadata
list_functions returns prioritization hints:
FunctionInfo(
name="decrypt_data",
address="0x1234",
stable_id="a1b2c3...", # Survives renames
size=256,
refs_in=47, # Many callers = important
refs_out=3, # Few callees = leaf function
has_strings=True, # References literals
is_library=False, # Not known stdlib
is_thunk=False, # Not a wrapper
)
Sort by refs_in to find important functions, refs_out to find orchestrators.
Import Capability Tags
list_imports tags imports with capabilities:
ImportInfo(
name="SSL_read",
library="libssl.so",
tags=["crypto", "network"], # Auto-detected
)
Tags: crypto, network, file, process, memory, jni
Provenance
All results include provenance for reproducibility:
Provenance(
unit_id="abc123...",
profile=AnalysisProfile.DEFAULT,
ghidra_version="11.4.3",
tool_version="0.1.0",
)
Project Structure
All agents share a common per-binary project structure:
~/.local/share/pyghidra-lite/
โโโ projects/
โโโ abc123def456/ # Binary 1 (unit_id = SHA256 hash)
โ โโโ abc123def456.gpr # Ghidra project file
โ โโโ abc123def456.rep/ # Analysis repository
โโโ 789ghi012jkl/ # Binary 2 (unit_id)
โโโ 789ghi012jkl.gpr
โโโ 789ghi012jkl.rep/
Key features:
- Content-addressed: Binary identified by SHA256 hash of contents
- Shared analysis: All agents see the same analysis results
- Persistent: Analysis survives agent restarts and suspend/resume
- Per-binary locking: Each binary has independent lock
- No duplication: Same binary analyzed once, shared by all
When is analysis reused?
- Same binary file (identical content) โ always reuses existing analysis
- Different binary โ gets its own project, analyzes independently
- Binary modified โ new hash, new analysis (old analysis preserved)
Cleanup:
To remove old analysis:
# Remove all analyzed binaries
rm -rf ~/.local/share/pyghidra-lite/projects
# Remove specific binary (find by partial hash)
rm -rf ~/.local/share/pyghidra-lite/projects/abc123*
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyghidra_lite-0.1.1.tar.gz.
File metadata
- Download URL: pyghidra_lite-0.1.1.tar.gz
- Upload date:
- Size: 108.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7b1ed447c81b96fa7fb9286c8eb6ccff78d0de59dabb7b39d4a831fa778ea1f8
|
|
| MD5 |
dcf03c17f51aaee9380f122e582cdbe8
|
|
| BLAKE2b-256 |
29e11816f945a65379daac6c23f53628cc45c2b163b6593b480d66770c6d8e9e
|
Provenance
The following attestation bundles were made for pyghidra_lite-0.1.1.tar.gz:
Publisher:
publish.yml on johnzfitch/pyghidra-lite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyghidra_lite-0.1.1.tar.gz -
Subject digest:
7b1ed447c81b96fa7fb9286c8eb6ccff78d0de59dabb7b39d4a831fa778ea1f8 - Sigstore transparency entry: 869026203
- Sigstore integration time:
-
Permalink:
johnzfitch/pyghidra-lite@f82cae20cd23081b25ce8e7167bda049e470174b -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/johnzfitch
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f82cae20cd23081b25ce8e7167bda049e470174b -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyghidra_lite-0.1.1-py3-none-any.whl.
File metadata
- Download URL: pyghidra_lite-0.1.1-py3-none-any.whl
- Upload date:
- Size: 51.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f83eeade0815f64b4e56852b3f7540f49cad815671d17c56aedd58e6fac778fe
|
|
| MD5 |
83e4c125258bc693751d2064ae3d3ae2
|
|
| BLAKE2b-256 |
21a836feadbc927eeb922a47ba16f48eaa68dd015b311431218af6374a80470f
|
Provenance
The following attestation bundles were made for pyghidra_lite-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on johnzfitch/pyghidra-lite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyghidra_lite-0.1.1-py3-none-any.whl -
Subject digest:
f83eeade0815f64b4e56852b3f7540f49cad815671d17c56aedd58e6fac778fe - Sigstore transparency entry: 869026216
- Sigstore integration time:
-
Permalink:
johnzfitch/pyghidra-lite@f82cae20cd23081b25ce8e7167bda049e470174b -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/johnzfitch
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f82cae20cd23081b25ce8e7167bda049e470174b -
Trigger Event:
release
-
Statement type: