AgentStack
MCP verified MIT Self-run

Hopper Mcp

mcp-shmsr-hopper-mcp · by shmsr

let's dig in with hopper disassembler

No reviews yet
0 installs
0 views
view→install

Install

$ agentstack add mcp-shmsr-hopper-mcp

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution Used
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Hopper Mcp? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Hopper MCP

An MCP server that gives an LLM client structured, transaction-safe access to Hopper-derived reverse-engineering snapshots without putting the disassembler in the model's context window.

The production rewrite is crates/hopper-mcpd. It owns MCP stdio, snapshot indexing, query, resources, prompts, local transactions, persistence, Rust-side live ingest orchestration, and the versioned hopper-wire backend boundary. The JavaScript server is retained as a migration reference and live-export bridge until the native/private backend fully replaces it.

The public analysis surface is Hopper-native. It does not expose local otool, nm, strings, or codesign fallback tools; if Hopper has not analyzed or exported evidence, the server reports that gap instead of fabricating local heuristics.

Current Rust Scope

  • open_session loads a Hopper-derived JSON snapshot into the indexed Rust store.
  • ingest_current_hopper exercises the backend boundary with either the mock backend or a configured private hopper-wire Unix-socket agent.
  • ingest_live_hopper is exposed by the Rust daemon and delegates safe Hopper Python export to the Node live bridge.
  • Snapshot read tools cover list/search/resolve/procedure/xrefs/containing function queries.
  • Analysis tools cover graph slices, deep function summaries, fingerprints, similarity, diffs, and query DSL.
  • Resources and prompts are exposed through MCP resources/* and prompts/*.
  • Local transactions support rename, comment, and inline comment changes with preview/commit/rollback.
  • hopper-wire pins the daemon-to-agent JSON contract with versioned request/response types.
  • agents/hopper-agent builds an Objective-C++ Unix-socket agent artifact that speaks the hopper-wire handshake, current-document, and procedure-list protocol.
  • agents/hopper-tool-plugin builds a signed Hopper Tool Plugin bundle that can expose the same hopper-wire protocol from inside Hopper using the official Hopper SDK.

Private Hopper live extraction is implemented on the daemon side as a fail-closed hopper-wire Unix-socket client and on the native side as packaged Objective-C++ agents. Today, non-fixture hopper-agent mode bridges real Hopper evidence through Hopper's bundled MCP subprocess and returns structured errors when Hopper has no current document. HopperMCPAgent.hopperTool is the direct in-Hopper plugin path and is built from the official SDK. The plugin now publishes a Foundation bridge service keyed off the configured plugin socket path, and hopper-agent --plugin-service auto can expose that service through the existing hopper-wire Unix socket contract. Hopper will only live-load that plugin when it is signed with a real Apple codesigning identity; ad-hoc signatures are sufficient for packaging smoke but are not sufficient evidence of live plugin acceptance. hopper-agent --fixture is only for tests/package smoke, so fixture data cannot be mistaken for live Hopper evidence.

Requirements

  • macOS
  • Rust toolchain
  • Node.js 20+ for npm wrappers, migration-reference tests, and the v1 live-export bridge
  • Hopper.app installed for live ingest tests and workflows

Install

git clone  hopper-mcp
cd hopper-mcp
npm install
npm run build:rust
npm run doctor
npm run test:rust
npm test

Add To A Client

Replace /abs/path/to/hopper-mcp with the absolute path to your clone.

Claude Code

claude mcp add -s user hopper -- cargo run --manifest-path /abs/path/to/hopper-mcp/Cargo.toml -p hopper-mcpd --

Codex CLI

codex mcp add hopper -- cargo run --manifest-path /abs/path/to/hopper-mcp/Cargo.toml -p hopper-mcpd --

Cursor / Claude Desktop / generic MCP

{
  "mcpServers": {
    "hopper": {
      "command": "cargo",
      "args": ["run", "--manifest-path", "/abs/path/to/hopper-mcp/Cargo.toml", "-p", "hopper-mcpd", "--"],
      "env": {}
    }
  }
}

MCP Inspector

npx @modelcontextprotocol/inspector cargo run --manifest-path /abs/path/to/hopper-mcp/Cargo.toml -p hopper-mcpd --

Workflows

Load A Hopper Snapshot

// open_session
{
  "session": {
    "sessionId": "calculator",
    "binary": {
      "name": "Calculator",
      "format": "hopper-snapshot",
      "arch": "arm64"
    },
    "functions": {
      "0x100003f50": {
        "name": "_main",
        "size": 96,
        "callees": ["0x100004010"]
      }
    }
  }
}

The Rust daemon normalizes addresses and indexes functions, resources, names, strings, comments, call edges, and transaction state from the snapshot.

Exercise The Backend Boundary

// ingest_current_hopper
{ "backend": "mock" }

The mock backend returns a minimal live-{documentId} session and proves the daemon-to-agent seam. To require a configured native/private agent, set HOPPER_MCP_PRIVATE_AGENT_SOCKET and call:

// ingest_current_hopper
{ "backend": "private" }

The private path connects to the Unix socket, performs a hopper-wire versioned handshake, requests the current document and procedure list, and fails closed if the socket is missing, the wire version is rejected, Hopper reports no current document, or the configured backend is not private. backend: "auto" uses whichever backend the daemon was configured with; it does not silently switch evidence quality. By default, hopper-agent uses Hopper's bundled HopperMCPServer as its real evidence source; pass --official-mcp-command PATH to test against an alternate command.

SIP-Off Private Backend Power Mode

This is a separate lane from the signed public Hopper Tool Plugin path. Select it explicitly with:

// ingest_current_hopper
{ "backend": "private" }

Diagnose the configured private lane before ingesting with backend_status or backend_diagnostics. A healthy private backend reports backend: "private", backendMode: "injected_private", and readiness: "ready".

For host preflight, run:

cargo run -p hopper-mcpd -- doctor --require-private-host

That check is intended only for a designated SIP-disabled host. In code it passes when csrutil status reports SIP disabled, or when HOPPER_MCP_ASSUME_SIP_DISABLED=1 is set for controlled runners where host detection is unavailable. Override the probe command with --csrutil-command PATH or HOPPER_MCP_CSRUTIL=PATH in controlled environments.

Validate the full private lane only on a designated SIP-disabled Hopper host:

npm run --silent release:check:private-backend

The private-backend gate runs doctor --require-private-host, builds hopper-agent plus the Foundation-only Hopper Tool Plugin, installs the plugin bundle, opens a real target through the proven live-export Hopper path, then verifies private socket handshake, current document, and procedure list via scripts/private-backend-runtime.mjs. The default probe uses a temporary HOPPER_MCP_PRIVATE_AGENT_SOCKET and lets the Hopper Tool Plugin host the private socket server directly inside Hopper; the custom launcher path remains only for synthetic test fixtures. Success in this lane does not prove the signed public Hopper Tool Plugin path. The self-hosted live CI workflow stores the resulting JSON as reports/release-check-private-backend.json and uploads it as part of the hopper-release-gate-reports artifact bundle.

The abandoned DYLD_INSERT_LIBRARIES injection experiment is not part of the supported production path and is not shipped as a public build target.

Ingest A Live Hopper Export

// ingest_live_hopper
{
  "executable_path": "/bin/echo",
  "timeout_ms": 90000,
  "max_functions": 20,
  "max_strings": 50,
  "close_after_export": true
}

The Rust daemon invokes the live bridge, ingests the normalized Hopper session into the Rust store, and returns session, launch, and diagnostics. Universal Mach-O inputs are launched with Hopper's FAT loader chain to avoid the manual architecture picker. close_after_export defaults to false; set it to true for throwaway agent/test runs where the Hopper document should be cleaned up after export.

Live ingest is intentionally capped so one MCP call cannot monopolize the daemon indefinitely: `timeoutms returns transactionId queue(kind: rename | comment | inlinecomment) previewtransaction -> review queued operations committransaction -> applies atomically to the local Rust store rollback_transaction -> discards queued operations


## Tool Surface

The Rust daemon exposes strict schemas for every tool. Unknown arguments are rejected at runtime.

| Group | Tools |
|---|---|
| Meta / backend | `capabilities`, `backend_status`, `backend_diagnostics` |
| Lifecycle / ingest | `open_session`, `ingest_current_hopper`, `ingest_live_hopper` |
| Snapshot reads | `procedure`, `search`, `list`, `xrefs`, `containing_function`, `resolve`, `query`, `analyze_function_deep`, `get_graph_slice` |
| Transactions | `begin_transaction`, `queue`, `preview_transaction`, `commit_transaction`, `rollback_transaction` |
| Analysis | `compute_fingerprints`, `find_similar_functions`, `diff_sessions` |

Discriminator-style tools (`procedure`, `search`, `list`, `queue`) take a `kind:` or `field:` argument that selects the variant.

**Resources** - `hopper://session/current`, `hopper://binary/metadata`, `hopper://functions`, `hopper://strings`, `hopper://names`, and `hopper://transactions/pending`.

**Prompts** - `function_triage`, `hypothesis_workspace`.

## Rust Commands

```bash
npm run start:rust
npm run doctor
npm run doctor:json
npm run package:release
npm run package:release:ad-hoc
npm run package:release:check
npm run package:verify -- dist/hopper-mcp-0.1.0-darwin-arm64.tar.gz
npm run package:smoke -- dist/hopper-mcp-0.1.0-darwin-arm64.tar.gz
npm run package:notarize -- dist/hopper-mcp-0.1.0-darwin-arm64.tar.gz
npm run fetch:hopper-sdk
npm run build:agent
npm run build:hopper-plugin
npm run hopper-plugin:service-name -- --socket /tmp/hopper-plugin.sock
npm run hopper-plugin:identities
npm run hopper-plugin:install
npm run hopper-plugin:probe
npm run cleanup:hopper-state
npm run test:agent
npm run build:rust
npm run check:rust
npm run fmt:rust
npm run clippy:rust
npm run test:rust
npm run test:live
npm run test:live:corpus:dry-run
npm run test:live:corpus
npm run test:live:corpus:large-apps
npm run release:check
npm run release:check:live
npm run release:check:private-backend
npm run release:check:internal
npm run release:check:internal-soak
npm run release:check:plugin-live
npm run release:check:distribution
npm run release:check:public-release
npm run release:check:public

Production readiness in this repo is split into two explicit profiles:

  • internal: non-live verification, live Hopper verification, and the SIP-off

private-backend lane on a designated Hopper runner

  • internal-soak: the full internal profile plus the optional large-app live

corpus soak

  • public: signed plugin acceptance, signed distribution packaging, and

notarized public release

Use the profile wrappers below when your claim is about one complete release profile rather than a single gate.

Non-live CI release gate:

npm run release:check

The non-live gate now emits structured JSON with a phase field and runs JS syntax/tests, Rust formatting, cargo clippy with warnings denied, Rust tests, doctor checks, and package release verification. For machine parsing, prefer npm run --silent release:check. The GitHub-hosted CI job stores the resulting JSON as reports/release-check.json and uploads it as the hopper-nonlive-release-gate-report artifact.

Full local release gate on a macOS machine with Hopper installed and Automation permission:

npm run release:check:live

The live gate now starts with a doctor preflight that hard-requires Hopper on the current machine, then opens throwaway Hopper documents, ingests them, verifies the official write-back path with HOPPER_MCP_ENABLE_OFFICIAL_WRITES=1 plus confirm_live_write=true, closes the documents without saving, and runs the default live corpus with its content/performance budgets. Before test:live and before the live corpus run, the wrapper clears any existing GUI Hopper process and unsets HOPPER_MCP_PLUGIN_SOCKET so stale interactive Hopper state cannot poison the release gate. Cleanup failures are fatal on otherwise-successful runs, so the gate will not return green if Hopper still persists after a phase completes. The gate emits structured JSON with a phase field so Hopper-readiness failures are distinguishable from failures in the non-live gate, live suite, or live corpus. For machine parsing, prefer npm run --silent release:check:live. The self-hosted live CI workflow stores the resulting JSON as reports/release-check-live.json and uploads it as part of the hopper-release-gate-reports artifact bundle. That workflow now also runs npm run --silent cleanup:hopper-state as a final if: always() step, stores reports/cleanup-hopper-state.json, and clears any leftover Hopper GUI processes plus HOPPER_MCP_PLUGIN_SOCKET from the runner before the job ends.

Internal/private production profile on the designated Hopper runner:

npm run release:check:internal

This wrapper runs release:check, release:check:live, and release:check:private-backend in order and returns structured JSON with profile: "internal". A green result here means the repo is production-ready for internal/private Hopper use on the designated runner. It does not satisfy the signed public-release requirements below.

Extended internal/private soak profile on a designated heavy-app workstation:

npm run release:check:internal-soak

This wrapper runs release:check:internal and then the optional heavyweight live corpus manifest from corpus/live-large-apps.json. That manifest records the large-app stability lane used during hardening and keeps each target optional, so machines without Capture One, Chrome, VS Code, Safari, Resolve, Photoshop, or a usable Xcode bundle will skip those entries instead of failing the soak run.

Signed in-Hopper plugin gate on a macOS machine with Hopper installed and a real Apple developer signing identity:

npm run release:check:plugin-live

This gate fails fast on missing codesigning identities, then runs the end-to-end plugin probe so the signed HopperMCPAgent.hopperTool path is validated as a first-class release step rather than an ad hoc manual command. Before probing, the wrapper clears any existing Hopper GUI process and unsets HOPPER_MCP_PLUGIN_SOCKET so stale interactive state cannot poison the signed plugin acceptance run. Cleanup failures are fatal on otherwise-successful runs, so the gate will not return green if Hopper still persists afterward. The gate now emits structured JSON with a phase field so CI and release operators can distinguish a signing-readiness failure from a probe failure. For machine parsing, prefer npm run --silent release:check:plugin-live. The self-hosted live CI workflow stores the resulting JSON as reports/release-check-plugin-live.json and uploads it as part of the hopper-release-gate-reports artifact bundle.

If you only need the signing preflight without touching Hopper, run:

npm run doctor:plugin-live

Signed distribution gate on a macOS machine with a real signing identity:

npm run release:check:distribution

This runs the non-live release gate and then requires a real signed distribution artifact build via npm run package:release. The gate emits structured JSON with a phase field so failures in the non-live gate are distinguishable from signed packaging failures. It now starts with a doctor preflight that hard-requires a Developer ID Application distribution identity and a clean git worktree so misconfigured release hosts fail before spending time in the non-live gate. For mac

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.