# v4.0.0 Monolith Refactor Plan

**Status**: Complete
**Target**: v4.0.0
**Started**: 2026-02-27
**Completed**: 2026-02-28

## Problem

`GhidraMCPPlugin.java` is 16,945 lines containing 149 HTTP endpoints and 257 private helper methods. `HeadlessEndpointHandler.java` duplicates ~6,000 lines of the same business logic for headless mode. This makes the codebase difficult to navigate, test, and extend.

## Solution

Extract shared business logic into 10 service classes under `com.xebyte.core`. The plugin becomes a ~1,200-line thin orchestrator (server lifecycle + endpoint wiring). The headless handler shrinks to ~300 lines. No HTTP paths, parameter names, or response formats change.

## Architecture

### Before
```
GhidraMCPPlugin.java (16,945 lines)  ──>  HTTP Server (149 endpoints)
HeadlessEndpointHandler.java (6,452 lines)  ──>  HTTP Server (173 endpoints)
                                    ~6,000 lines duplicated
```

### After
```
GhidraMCPPlugin.java (~1,200 lines)     ──>  HTTP Server (149 endpoints)
    └── delegates to shared services          │
HeadlessEndpointHandler.java (~300 lines) ──>  HTTP Server (173 endpoints)
    └── delegates to shared services          │
                                              │
core/                                         │
├── ServiceUtils.java (~500 lines)       shared utilities
├── ListingService.java (~700 lines)     18 endpoints
├── FunctionService.java (~900 lines)    16 endpoints
├── SymbolLabelService.java (~500 lines) 12 endpoints
├── CommentService.java (~400 lines)     6 endpoints
├── XrefCallGraphService.java (~600 lines) 9 endpoints
├── DataTypeService.java (~900 lines)    22 endpoints
├── AnalysisService.java (~900 lines)    12 endpoints
├── DocumentationHashService.java (~700 lines) 10 endpoints
├── MalwareSecurityService.java (~700 lines) 8 endpoints
├── ProgramScriptService.java (~600 lines) 12 endpoints
└── BinaryComparisonService.java (~1,047 lines) 5 endpoints (already exists)
```

## Key Design Decisions

1. **Instance-based services with constructor injection** — Services receive `ProgramProvider` + `ThreadingStrategy` via constructor. Reuses existing abstractions that already work in GUI (`SwingThreadingStrategy`) and headless (`DirectThreadingStrategy`) modes.

2. **Keep `server.createContext()` pattern** — The existing endpoint registration pattern is proven and grep-friendly. No new routing framework needed.

3. **Services return JSON strings** — Same as today. No `Response` sealed interface or serialization library changes.

4. **GUI-only endpoints stay in plugin** — `getCurrentAddress()` and `getCurrentFunction()` use `CodeViewerService` which has no headless equivalent.

## Service Breakdown

| Service | Lines | Endpoints | Key Methods |
|---|---|---|---|
| `ServiceUtils` | ~500 | — | `escapeJson`, `paginateList`, `resolveDataType`, `getFunctionForAddress`, `isAutoGeneratedName`, `programError` |
| `ListingService` | ~700 | 18 | `list_methods`, `list_classes`, `list_segments`, `list_imports`, `list_exports`, `list_namespaces`, `list_data_items`, `list_functions`, `list_strings`, `list_globals` |
| `FunctionService` | ~900 | 16 | `decompile_function`, `rename_function`, `set_function_prototype`, `set_local_variable_type`, `batch_decompile`, `batch_rename_function_components` |
| `SymbolLabelService` | ~500 | 12 | `create_label`, `rename_label`, `delete_label`, `batch_create_labels`, `rename_data`, `rename_global_variable` |
| `CommentService` | ~400 | 6 | `set_decompiler_comment`, `set_plate_comment`, `batch_set_comments`, `clear_function_comments` |
| `XrefCallGraphService` | ~600 | 9 | `get_xrefs_to`, `get_xrefs_from`, `get_function_xrefs`, `get_bulk_xrefs`, `get_function_call_graph`, `analyze_call_graph` |
| `DataTypeService` | ~900 | 22 | `list_data_types`, `create_struct`, `create_enum`, `apply_data_type`, `modify_struct_field`, `get_struct_layout`, `search_data_types` |
| `AnalysisService` | ~900 | 12 | `analyze_function_completeness`, `batch_analyze_completeness`, `analyze_control_flow`, `find_dead_code`, `list_analyzers`, `run_analysis` |
| `DocumentationHashService` | ~700 | 10 | `get_function_hash`, `get_function_documentation`, `apply_function_documentation`, `propagate_documentation` |
| `MalwareSecurityService` | ~700 | 8 | `find_anti_analysis_techniques`, `detect_malware_behaviors`, `analyze_api_call_chains`, `extract_iocs_with_context` |
| `ProgramScriptService` | ~600 | 12 | `save_program`, `list_open_programs`, `switch_program`, `run_script`, `set_bookmark`, `read_memory` |

## Phased Execution

Each phase is independently buildable and testable.

| Phase | Service(s) | Lines Moved | Plugin Size After |
|---|---|---|---|
| 0 | ServiceUtils + ProgramProvider wiring | 500 (utilities) | 16,445 |
| 1 | ListingService | 700 | 15,745 |
| 2 | CommentService + SymbolLabelService | 900 | 14,845 |
| 3 | FunctionService | 2,500 | 12,345 |
| 4 | XrefCallGraphService + DataTypeService | 2,800 | 9,545 |
| 5 | AnalysisService + DocumentationHashService | 3,200 | 6,345 |
| 6 | MalwareSecurityService + ProgramScriptService | 3,200 | 3,145 |
| 7 | HeadlessEndpointHandler consolidation | -6,152 (dedup) | — |
| 8 | Cleanup + documentation | — | ~1,200 |

## Threading Migration Pattern

The key migration for write operations:

```java
// BEFORE (manual SwingUtilities + transaction in GhidraMCPPlugin.java):
SwingUtilities.invokeAndWait(() -> {
    int tx = program.startTransaction("Rename function");
    boolean success = false;
    try {
        function.setName(newName, SourceType.USER_DEFINED);
        success = true;
    } finally {
        program.endTransaction(tx, success);
    }
});

// AFTER (delegated to ThreadingStrategy in service):
return threadingStrategy.executeWrite(program, "Rename function", () -> {
    function.setName(newName, SourceType.USER_DEFINED);
    return "{\"status\": \"success\"}";
});
```

`SwingThreadingStrategy.executeWrite()` handles EDT dispatch, transaction start/commit/rollback, and event flushing automatically.

## Impact

| Metric | Before | After |
|---|---|---|
| `GhidraMCPPlugin.java` | 16,945 lines | ~1,200 lines |
| `HeadlessEndpointHandler.java` | 6,452 lines | ~300 lines |
| Duplicated code | ~6,000 lines | 0 |
| Total Java lines | ~24,400 | ~10,350 |
| Largest file | 16,945 lines | ~1,200 lines |

## What Does NOT Change

- HTTP endpoint paths and parameters
- JSON response formats
- MCP bridge (`bridge_mcp_ghidra.py`) — all 180 tools unchanged
- `endpoints.json` test catalog
- `ProgramProvider`/`ThreadingStrategy` interfaces
- `BinaryComparisonService` (already extracted)
- Static singleton HTTP server pattern (multi-window support)

## Not Included (Future Work)

- `Response` sealed interface for type-safe returns (v5.0)
- JSON serialization library (Gson/Jackson) (v5.0)
- Declarative endpoint routing (unnecessary for current needs)
