Hi yall. I was needing to integrate jeb more deeply with the powerful AI tools and I found that i needed to have an extra tool that JEB still dosnt provide
run_jeb_script
Disclaimer: this whole project was vibe coded Im not gonna lie to you. I just cared about the result and how to improve my rev eng workflow. Let me know if you find issues or proposals and I will be happy to help.
I hope you can get some value out of this at least the idea.
JEB 5.40 ships with an MCP server (File → Start/Stop the MCP Server).
It works, but it exposes a fixed list of 20 tools and provides no way to run arbitrary code.
If the model needs something not on that list, you're stuck.
This small autorun script (JebMcpRunScript.py) goes into:
< JebHome >\scripts\
It registers a
21st tool, named
run_jeb_script, directly on JEB’s MCP server.
The model gets full access to JEB’s Python API — no bridge, no sidecar, same SSE endpoint, just one extra tool.
------------------------------------------------------------
The 20 Built‑In Tools (Reference)
Code:
get_project_information project name, artifacts, units
list_units / get_unit_description walk the project tree
list_code_items / list_code_strings items and strings of a code unit
get_type_information resolve a type
decompile_code_item class/method to pseudo-code
get_disassembly_snippet disasm around an address
list_cross_references xrefs to an address
list_apk_resources / get_apk_text_artifact APK resource access
find_dynamic_library locate a .so loaded by DEX
list_comments / set_comments inline comment R/W
rename_code_items / rename_pseudo_code_variables renaming
bulk_auto_rename_dex_items bulk de-obfuscation
create_dex_package / move_dex_item_to_package DEX package ops
get_ui_fragment_information current UI selection
Great for common tasks.
Useless the moment you want something like:
find every call to Cipher.getInstance("DES") and dump them as JSON
That’s not a tool — that’s a script.
------------------------------------------------------------
What `run_jeb_script` Does
Input:
Code:
{ "code": "string" }
The code runs inside JEB’s Jython 2.7 environment with these globals:
Code:
ctx IClientContext
engctx IEnginesContext
prj first IRuntimeProject (or None)
If the code is a bare expression, its value is returned.
If it’s a block, assign to
result.
print() output is captured.
Example: find all callsites of System.exit
Code:
from com.pnfsoftware.jeb.core import RuntimeProjectUtil
from com.pnfsoftware.jeb.core.units.code.android import IDexUnit
dex = RuntimeProjectUtil.findUnitsByType(prj, IDexUnit, False)[0]
hits = []
for m in dex.getMethods():
for ins in (m.getInstructions() or []):
if 'System;->exit' in ins.format(None):
hits.append('%s @ 0x%x' % (m.getSignature(False), ins.getOffset()))
result = hits
------------------------------------------------------------
Setup
Copy the script:
Code:
copy JebMcpRunScript.py C:\JEB\scripts\
Restart JEB. Console should show:
Code:
JEB MCP server: http://localhost:8425/mcp
Located McpSyncServer via field:bD.GJ
Registered tool "run_jeb_script" on JEB MCP server.
Register with Claude Code:
Code:
claude mcp add --transport sse --scope user jeb http://localhost:8425/mcp
Or add to .mcp.json:
Code:
{
"mcpServers": {
"jeb": { "type": "sse", "url": "http://localhost:8425/mcp" }
}
}
Check with /mcp — you should see
21 tools.
------------------------------------------------------------
Optional: Feed Claude the JEB API Docs
JEB ships:
Code:
C:\JEB\doc\apidoc_md.zip
Extract:
Code:
mkdir .jeb-docs
cd .jeb-docs
unzip C:\JEB\doc\apidoc_md.zip
Add to CLAUDE.md:
Code:
The JEB Python API reference is in .jeb-docs/.
Consult it before writing run_jeb_script calls.
------------------------------------------------------------
How the Tool Is Attached (The Interesting Part)
McpSyncServer.addTool(SyncToolSpecification) exists in the embedded SDK.
We just need to locate the live instance — but it’s private, obfuscated, and renamed every release.
The script tries 5 strategies (fallback order):
1. Public getters (getMcpServer, getServer, …)
2. Declared field by
type io.modelcontextprotocol.server.McpSyncServer
3. Same, but for McpAsyncServer, wrapped into a sync server
4. Bounded BFS through reachable fields/collections
(depth ≤ 4, ≤ 20k visits, skipping JDK/Jetty)
5. Static‑field scan on JebMcpServerInstance
Each candidate is validated via:
- isInstance using the classloader
- presence of addTool(SyncToolSpecification)
The winning strategy is logged; failures are logged too for debugging future JEB changes.
------------------------------------------------------------
Caveats
Code:
- Toggling MCP via menu spawns a new server → re-run the script.
- Engines config must have LoadPythonPlugins = true (default in 5.40).
- MCP tool calls run on a worker thread; UI work must use ctx.runOnUiThread().
- Security: this is arbitrary code execution on localhost. Same trust model as JEB’s own MCP.
------------------------------------------------------------
CPython 3 Note
JEB 5.40 adds Java Embedded Python (CPython 3.x).
Jython 2.7 remains default and is what runs at autorun stage.
This plugin stays on Jython for now; CPython dispatch could be added later.
------------------------------------------------------------
Troubleshooting
Code:
Autorun doesn't fire:
Enable LoadPythonPlugins in bin\jeb-engines.cfg
Port 8425 already taken:
JEB auto-increments; check console for actual port
Tool disappears after toggling MCP:
Run File → Scripts → JebMcpRunScript again
"Could not locate McpSyncServer":
JEB internals changed; console logs show which strategies failed
------------------------------------------------------------
Uninstall
Code:
del C:\JEB\scripts\JebMcpRunScript.py
Restart JEB — MCP server returns to 20 tools.
------------------------------------------------------------
Folder Contents
Code:
JebMcpRunScript.py ← drop into <JebHome>\scripts\
apidoc_md.zip ← JEB’s Python API docs
README.MD