Add quick start: config generator script and onboarding docs

This commit is contained in:
morluto 2026-07-12 03:30:31 +08:00
parent d0d609dd2b
commit 6f2afc2d18
4 changed files with 99 additions and 20 deletions

View File

@ -14,6 +14,7 @@ The server is a layered ESM TypeScript application. Dependencies flow inward: `d
- `src/server/`: MCP request translation. `createServer.ts` assembles the MCP server, `registerOfficialTools.ts`/`registerEnhancedTools.ts` register each tool set, `toolResult.ts` maps `Result` values to MCP content.
- `tests/`: Vitest suite. `tests/fixtures/` holds the fake launcher and fake Hopper bridge used as production seams.
- `scripts/verify-real-hopper.mjs`: real-Hopper end-to-end verifier.
- `scripts/print-mcp-config.mjs`: prints a ready-to-paste MCP server config with absolute paths filled in (`npm run config:print -- /path/to/binary`).
## Build, Test, and Development Commands
@ -25,6 +26,7 @@ The server is a layered ESM TypeScript application. Dependencies flow inward: `d
- `npm run format:check`: verify Prettier formatting.
- `npm run check`: run typecheck, lint, format:check, and tests.
- `npm run verify:hopper`: build and run the real-Hopper verifier (requires a binary).
- `npm run config:print -- /path/to/binary`: print a ready-to-paste MCP server config with absolute paths.
- `HOPPER_TARGET_PATH=/path/to/binary npm start`: launch Hopper and run the built stdio MCP server.
## Configuration & Environment Variables

View File

@ -2,7 +2,47 @@
A TypeScript MCP server for [Hopper Disassembler](https://www.hopperapp.com/). 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.
## Quick Start
```bash
git clone <repo-url> && cd betterBinaryMCP
npm ci && npm run build
```
Generate a ready-to-paste MCP config with absolute paths filled in:
```bash
npm run config:print -- /path/to/your/binary
```
Paste the output into your MCP client config (Claude Desktop, Cursor, etc.) and restart the client. That's it — the 39 tools are now available.
```bash
# For a .hop database:
npm run config:print -- /path/to/file.hop --kind database
# For a FAT binary that needs loader args:
npm run config:print -- /path/to/binary --loader-args '["-l","Mach-O","--aarch64"]'
```
### Set up with your agent
Paste this prompt into Claude, Cursor, or any MCP-capable agent to have it do the setup for you:
> I want to connect betterBinaryMCP (a Hopper Disassembler MCP server) to this client.
>
> 1. Clone the repo and run `npm ci && npm run build`.
> 2. Run `npm run config:print -- /path/to/my/binary` to generate the MCP server config.
> 3. Paste the output into this client's MCP config and restart.
> 4. Verify the 39 tools are listed.
## Prerequisites
- **Node.js 20+** — `node --version`
- **Hopper Disassembler 6+** on macOS — ships at `/Applications/Hopper Disassembler.app/`
- **A binary or Hopper database** to analyze
Accessibility permission is **not** required. Specify loader arguments for archives that would otherwise show an architecture chooser.
## Architecture
@ -18,24 +58,9 @@ The codebase is a layered ESM TypeScript application. Dependencies flow inward:
- `src/application/` composes official operations into the 8 enhanced tools.
- `src/domain/` holds pure parsers and the tagged error algebra; `src/contracts/` declares the caller-visible tool schemas.
## Requirements
## Manual MCP Configuration
- 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
```bash
npm ci
npm run build
```
## MCP Configuration
Build the project, then configure your MCP client with an absolute path:
If you prefer to write the config by hand, build the project and use absolute paths:
```json
{
@ -51,7 +76,7 @@ Build the project, then configure your MCP client with an absolute path:
}
```
Run it directly with `npm start` after building. Stdout is reserved for MCP protocol messages; diagnostics use stderr.
Stdout is reserved for MCP protocol messages; diagnostics use stderr.
### Environment Variables

View File

@ -20,7 +20,8 @@
"test": "vitest run",
"test:watch": "vitest",
"typecheck": "tsc --noEmit",
"verify:hopper": "npm run build && node scripts/verify-real-hopper.mjs"
"verify:hopper": "npm run build && node scripts/verify-real-hopper.mjs",
"config:print": "node scripts/print-mcp-config.mjs"
},
"dependencies": {
"@modelcontextprotocol/server": "2.0.0-beta.3",

51
scripts/print-mcp-config.mjs Executable file
View File

@ -0,0 +1,51 @@
#!/usr/bin/env node
/**
* Print a ready-to-paste MCP server config with absolute paths filled in.
*
* Usage:
* node scripts/print-mcp-config.mjs /path/to/binary
* node scripts/print-mcp-config.mjs /path/to/binary --kind database
* node scripts/print-mcp-config.mjs /path/to/binary --loader-args '["-l","Mach-O","--aarch64"]'
*/
import { resolve } from "node:path";
import { fileURLToPath } from "node:url";
const targetPath = process.argv[2];
if (!targetPath) {
process.stderr.write(
"Usage: node scripts/print-mcp-config.mjs <target-path> [--kind executable|database] [--loader-args JSON]\n",
);
process.exit(1);
}
const flags = process.argv.slice(3);
const kind = readFlag(flags, "--kind") ?? "executable";
const loaderArgs = readFlag(flags, "--loader-args");
const serverPath = resolve(
fileURLToPath(new URL("..", import.meta.url)),
"dist/main.js",
);
const env = {
HOPPER_TARGET_PATH: resolve(targetPath),
HOPPER_TARGET_KIND: kind,
};
if (loaderArgs) env.HOPPER_LOADER_ARGS_JSON = loaderArgs;
const config = {
mcpServers: {
betterBinaryMCP: {
command: "node",
args: [serverPath],
env,
},
},
};
process.stdout.write(`${JSON.stringify(config, null, 2)}\n`);
function readFlag(args, name) {
const i = args.indexOf(name);
return i !== -1 ? args[i + 1] : undefined;
}