betterBinaryMCP

A TypeScript MCP server for Hopper Disassembler. It preserves 31 familiar Hopper operations and adds 8 reverse-engineering workflows for Swift, Objective-C, decompilation, call graphs, cross-references, and binary summaries.

The server uses the modular @modelcontextprotocol/server@2.0.0-beta.3 SDK.

Architecture

MCP client ← stdio → TypeScript MCP server ← Unix socket → owned Python bridge → Hopper.app

src/main.ts owns configuration and lifetimes. src/hopper/ lazily launches Hopper on the first Hopper-dependent tool and correlates bounded bridge messages, so lengthy analysis does not block the MCP handshake. bridge/hopper_bridge.py runs inside Hopper and calls its public Python API. Hopper's bundled MCP server is not executed or required.

Requirements

  • Node.js 20 or newer
  • Hopper Disassembler 6+ on macOS
  • A binary or Hopper database to analyze

Accessibility permission is not required. Specify loader arguments for archives that would otherwise show an architecture chooser.

Install and Build

npm ci
npm run build

MCP Configuration

Build the project, then configure your MCP client with an absolute path:

{
  "mcpServers": {
    "betterBinaryMCP": {
      "command": "node",
      "args": ["/absolute/path/to/betterBinaryMCP/dist/main.js"],
      "env": {
        "HOPPER_TARGET_PATH": "/absolute/path/to/binary"
      }
    }
  }
}

Run it directly with npm start after building. Stdout is reserved for MCP protocol messages; diagnostics use stderr.

The Hopper launcher defaults to:

/Applications/Hopper Disassembler.app/Contents/MacOS/hopper

Override it with HOPPER_LAUNCHER_PATH. Set HOPPER_TARGET_KIND=database for .hop files. HOPPER_LOADER_ARGS_JSON accepts documented launcher arguments before the target; for an Apple FAT binary, for example:

["-l", "FAT", "--aarch64", "-l", "Mach-O"]

Enhanced Tools

Tool Purpose
binary_overview Summarize documents, segments, procedures, and strings
swift_classes Find Swift _TtC class symbols
get_objc_classes Find Objective-C class labels
get_objc_protocols Find Objective-C and Swift protocol labels
batch_decompile Decompile up to 20 procedures concurrently
get_call_graph Traverse callers or callees to depth 1–5
analyze_swift_types Categorize Swift classes, structs, enums, protocols, and extensions
find_xrefs_to_name Resolve a name and retrieve cross-references

Development

npm run typecheck
npm run lint
npm run format:check
npm test
npm run check

npm test builds first. Tests cover all 39 contracts, every handler through a beta.3 MCP client, bridge failures, concurrency, strict boundary parsing, and the compiled stdio runtime.

Run the real-Hopper verifier with a representative binary and any required loader options:

HOPPER_TARGET_PATH=/path/to/binary \
HOPPER_LOADER_ARGS_JSON='["-l","Mach-O","--aarch64"]' \
npm run verify:hopper

It asserts the exact 39-tool inventory, document access, binary_overview, segment reads, a one-procedure bounded decompile, clean protocol output, and absence of Hopper's bundled MCP process.

Troubleshooting

If startup times out, verify the target path and reproduce the generated loader chain with Hopper's hopper launcher. A visible loader or save dialog prevents the post-analysis bridge from starting; supply explicit loader/CPU options or close the stale dialog. Granting Accessibility access will not fix this.

batch_decompile accepts at most 20 addresses, and get_call_graph accepts depths from 1 through 5.

License

MIT

Languages
TypeScript 88.5%
JavaScript 6.8%
Python 1.8%
HTML 1.5%
Java 0.9%
Other 0.4%