[GH-ISSUE #5272] feat(mcp): hold several Ghidra targets open concurrently in one server #3219

Open
opened 2026-10-31 00:37:58 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @goncalompontes on GitHub (Oct 19, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/5272

Title

feat(mcp): hold several Ghidra targets open concurrently in one server

Problem

One MCP server holds one active binary target. Opening another target drains and replaces the current one (BinarySession, #openWithinTransition). A large game with many DLLs therefore has to be analysed one module at a time, even though each Ghidra analysis is its own JVM and the provider already serialises work per program.

The single lifecycle lock sits in the application layer. The parallelism is available below it.

Analysis tools accept no target selector, and Rizin, GDB, Cutter, and the Rizin debugger each retire the active binary session in a shared server.

Proposal

  • A BinaryTargetRegistry with one slot per open target, each with its own lifecycle lock. Work on different targets runs concurrently; work on one target stays serial.
  • open_binary returns an opaque target_id. A reopen of the same digest and profile returns the same id. keep_others_open (default false) keeps today's replace behaviour.
  • An optional target_id on target-bound tools. Absent means the current target, so single-target clients are unchanged.
  • Caps: REA_MAX_OPEN_TARGETS (default 4) and REA_MAX_CONCURRENT_ANALYSES (default 2), with explicit capacity refusals and a FIFO queue.
  • A batch CLI on the same registry (rea analyze a.dll b.dll --concurrency N) as a later slice.
  • #1048 and #3751 (pre-analysed projects; repeated analysis cost), #2358 and #2150 (existing-project wiring), #3817 (persistent project open; overlaps #2358), #3531 (project cache).
  • The analysis-jobs draft in the companion issue covers background jobs, which run in these slots.

Design

Design draft: docs/specs/multi-target-sessions/spec.md on design/analysis-jobs (uncommitted). It lists three open questions: whether Rizin, GDB, Cutter, and the debugger should keep retiring every slot (O1); whether slots need a client owner for shared HTTP servers (O2); and whether cross-target queries should follow in a later spec (O5).

Scope check

This is the largest contract change so far, because every target-bound tool gains a field. Per CONTRIBUTING.md, a maintainer scope decision is needed before implementation.

Verification plan

Refactor guard: the existing BinarySession tests pass unchanged. Then unit tests for caps and routing, an MCP stdio boundary test with two fakeGhidra targets, and a real Ghidra 12.1.4 Linux run that compares concurrent and serial analysis of two real PEs, recording wall time and peak RSS.

Originally created by @goncalompontes on GitHub (Oct 19, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5272 ## Title feat(mcp): hold several Ghidra targets open concurrently in one server ## Problem One MCP server holds one active binary target. Opening another target drains and replaces the current one (`BinarySession`, `#openWithinTransition`). A large game with many DLLs therefore has to be analysed one module at a time, even though each Ghidra analysis is its own JVM and the provider already serialises work per program. The single lifecycle lock sits in the application layer. The parallelism is available below it. Analysis tools accept no target selector, and Rizin, GDB, Cutter, and the Rizin debugger each retire the active binary session in a shared server. ## Proposal - A `BinaryTargetRegistry` with one slot per open target, each with its own lifecycle lock. Work on different targets runs concurrently; work on one target stays serial. - `open_binary` returns an opaque `target_id`. A reopen of the same digest and profile returns the same id. `keep_others_open` (default `false`) keeps today's replace behaviour. - An optional `target_id` on target-bound tools. Absent means the current target, so single-target clients are unchanged. - Caps: `REA_MAX_OPEN_TARGETS` (default 4) and `REA_MAX_CONCURRENT_ANALYSES` (default 2), with explicit `capacity` refusals and a FIFO queue. - A batch CLI on the same registry (`rea analyze a.dll b.dll --concurrency N`) as a later slice. ## Related - #1048 and #3751 (pre-analysed projects; repeated analysis cost), #2358 and #2150 (existing-project wiring), #3817 (persistent project open; overlaps #2358), #3531 (project cache). - The analysis-jobs draft in the companion issue covers background jobs, which run in these slots. ## Design Design draft: `docs/specs/multi-target-sessions/spec.md` on `design/analysis-jobs` (uncommitted). It lists three open questions: whether Rizin, GDB, Cutter, and the debugger should keep retiring every slot (O1); whether slots need a client owner for shared HTTP servers (O2); and whether cross-target queries should follow in a later spec (O5). ## Scope check This is the largest contract change so far, because every target-bound tool gains a field. Per CONTRIBUTING.md, a maintainer scope decision is needed before implementation. ## Verification plan Refactor guard: the existing `BinarySession` tests pass unchanged. Then unit tests for caps and routing, an MCP stdio boundary test with two `fakeGhidra` targets, and a real Ghidra 12.1.4 Linux run that compares concurrent and serial analysis of two real PEs, recording wall time and peak RSS.
Author
Owner

@goncalompontes commented on GitHub (Oct 19, 2026):

Design draft is now visible: multi-target spec and tasks. It is committed at 219535a95 on the fork branch design/analysis-jobs. The companion background-jobs design is here, and it runs inside the slots defined in this one. Feedback welcome, especially on O1 (shared-server retirement rule) and O2 (slot ownership).

<!-- gh-comment-id:6273083827 --> @goncalompontes commented on GitHub (Oct 19, 2026): Design draft is now visible: [multi-target spec](https://github.com/goncalompontes/rea/blob/219535a95/docs/specs/multi-target-sessions/spec.md) and [tasks](https://github.com/goncalompontes/rea/blob/219535a95/docs/specs/multi-target-sessions/tasks.md). It is committed at `219535a95` on the fork branch [`design/analysis-jobs`](https://github.com/goncalompontes/rea/tree/design/analysis-jobs). The companion background-jobs design is [here](https://github.com/goncalompontes/rea/blob/219535a95/docs/specs/analysis-jobs/spec.md), and it runs inside the slots defined in this one. Feedback welcome, especially on O1 (shared-server retirement rule) and O2 (slot ownership).
Author
Owner

@goncalompontes commented on GitHub (Oct 19, 2026):

Draft implementation is up: https://github.com/morluto/rea/pull/5283. It adds the target registry, target_id routing for official analysis tools, the open/analysis caps, and the start queue. The design and remaining slices are in docs/specs/multi-target-sessions/.

<!-- gh-comment-id:6274857079 --> @goncalompontes commented on GitHub (Oct 19, 2026): Draft implementation is up: https://github.com/morluto/rea/pull/5283. It adds the target registry, target_id routing for official analysis tools, the open/analysis caps, and the start queue. The design and remaining slices are in docs/specs/multi-target-sessions/.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3219
No description provided.