Forward ghidra()/ghidra_tools() to the shared read-only Ghidra MCP server
Every agent reaches GhidrAssistMCP through Harbor's own MCP server, so no per-host configuration is needed. Configured by ghidra_url in [reverse]; long decompiles are polled; also 'harbor re ghidra <tool> <json>'.
This commit is contained in:
1 parent
3f6df88f95
commit
7ed914ebdb
4 files changed
+186
-6
No files matched your search
+34
-1
@@ -35,7 +35,9 @@ review queue, presence and stop flags. Protocol:
|
||||
9. A correction is send(..., corrects=<id of your earlier message>).
|
||||
10. Before your session ends or your allowance runs out, write handoff(): finished, in flight, next.
|
||||
11. To read the original machine code use re_disassemble, re_xrefs, re_bytes and re_lookup: they read the project's
|
||||
own image with the team's current names, so do not write your own disassembler or offset maths."""
|
||||
own image with the team's current names, so do not write your own disassembler or offset maths.
|
||||
For Ghidra's view (decompiler, p-code, stack frames, struct field references, types) use ghidra_tools() once,
|
||||
then ghidra(tool, arguments): one shared read-only Ghidra session holding the team's annotations."""
|
||||
|
||||
KindName = Literal["note", "question", "answer", "request", "finding", "retraction", "decision", "status", "handoff"]
|
||||
Importance = Literal["normal", "high", "urgent"]
|
||||
@@ -484,6 +486,37 @@ def re_lookup(target: str) -> dict:
|
||||
return _re(lambda r: r.lookup(target))
|
||||
|
||||
|
||||
_ghidra = {}
|
||||
|
||||
|
||||
def _gh(fn):
|
||||
try:
|
||||
h = harbor()
|
||||
g = _ghidra.get(h.project.name)
|
||||
if g is None:
|
||||
from .reverse import Ghidra
|
||||
g = _ghidra[h.project.name] = Ghidra(h.project.reverse)
|
||||
return fn(g)
|
||||
except (HarborError, projects.ProjectError) as error:
|
||||
raise ToolError(str(error)) from None
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def ghidra_tools() -> list:
|
||||
"""The tools of the team's shared Ghidra session (GhidrAssistMCP, read-only, the curated project with every
|
||||
applied annotation): name, description and arguments. Call them with ghidra(tool, arguments)."""
|
||||
return _gh(lambda g: g.tools())
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def ghidra(tool: str, arguments: dict | None = None) -> str:
|
||||
"""Run one tool in the shared read-only Ghidra session, e.g. ghidra('get_code', {'function': 'GetFogLevel',
|
||||
'format': 'decompiler'}), ghidra('get_function_stack_layout', {'function_name_or_address': '0x4ADC70'}),
|
||||
ghidra('struct', {'action': 'field_xrefs', ...}). Long decompiles are waited for. Renames, retypes and other
|
||||
changes are refused: names and types change through annotations/ and land on main."""
|
||||
return _gh(lambda g: g.call(tool, arguments or {}))
|
||||
|
||||
|
||||
def _report_in():
|
||||
"""Tell Harbor this agent's app has its tools running: at start, then every 5 minutes while the app keeps the
|
||||
server open (updates the connection only, not the agent's last-seen time)."""
|
||||
|
||||
Reference in new issue
Block a user