crashpoint-ios-mcp
README.md
# CrashPoint iOS MCP
A **TypeScript MCP (Model Context Protocol) server** that wraps the CrashPoint iOS crash analysis pipeline as MCP tools. Use it with Claude Desktop, Cursor, and other MCP clients to export, symbolicate, analyze, and report iOS/macOS crash logs — all through natural language.
Also includes a standalone **CLI** (`crashpoint-ios-cli`) for scheduled runs without an AI client.
---
## What It Does
CrashPoint iOS MCP gives your AI assistant the ability to:
1. **Export** `.crash` files from Xcode Organizer `.xccrashpoint` bundles
2. **Save** Apptics crash data as `.crash` files for unified processing
3. **Symbolicate** crashes using Xcode's `symbolicatecrash` tool and your `.dSYM` bundle
4. **Analyze & group** symbolicated crashes by unique signature, device, iOS version, and app version
5. **Track fixes** locally so your team can mark crash types as resolved
6. **Notify Zoho Cliq** with crash report summaries via webhook
7. **Report to Zoho Projects** — prepare structured bug data for creation/updates
8. **Run the full pipeline** end-to-end with Apptics, Cliq, and Zoho Projects integration
---
## Prerequisites
- **macOS** (required for Xcode's `symbolicatecrash` and `dwarfdump`)
- **Node.js 18+**
- **Xcode CLI tools** (`xcode-select --install`)
- A `.dSYM` bundle for your app
- Xcode Organizer crash data (`.xccrashpoint` files)
---
## Installation
```bash
git clone https://github.com/maanasa-s-5539/CrashPoint-IOS-MCP.git
cd CrashPoint-IOS-MCP
npm install
npm run build
```
---
## Configuration
Copy `crashpoint.config.example.json` from the repo root to `<ParentHolderFolder>/crashpoint.config.json` and fill in your values:
```bash
cp crashpoint.config.example.json /path/to/ParentHolderFolder/crashpoint.config.json
```
This JSON config file is the **single source of truth** for all user configuration — you only need to edit this one file. The `.mcp.json` (used by Claude CLI for the automation pipeline) and the launchd `.plist` (for scheduled daily runs) are **auto-generated** from it by `setup_folders` and by `run_crash_pipeline.sh` on first run.
When both the JSON config file and environment variables provide the same key, **environment variables win** — values in `process.env` override values from the JSON config file. This means MCP client `env` blocks (or a `.env` file used as a fallback) can always override the JSON config.
### Complete `crashpoint.config.json` example
```json
{
"CRASH_ANALYSIS_PARENT": "/path/to/ParentHolderFolder",
"CLAUDE_CLI_PATH": "/Users/name/.local/bin/claude",
"DSYM_PATH": "/path/to/MyApp.app.dSYM",
"MASTER_BRANCH_PATH": "/path/to/master",
"DEV_BRANCH_PATH": "/path/to/dev",
"CRASH_INPUT_DIR": "",
"CRASH_VERSIONS": "1.0.0",
"CRASH_DATE_OFFSET": "4",
"CRASH_NUM_DAYS": "1",
"SCHEDULED_RUN_TIME": "11:00",
"APP_DISPLAY_NAME": "MyApp",
"APPTICS_MCP_NAME": "apptics-mcp",
"APPTICS_PORTAL_ID": "12345",
"APPTICS_PROJECT_ID": "67890",
"APPTICS_APP_NAME": "MyApp",
"ZOHO_CLIQ_WEBHOOK_URL": "https://cliq.zoho.in/...",
"ZOHO_PROJECTS_PORTAL_ID": "12345",
"ZOHO_PROJECTS_PROJECT_ID": "67890",
"ZOHO_BUG_STATUS_OPEN": "status-id-open",
"ZOHO_BUG_STATUS_FIXED": "status-id-fixed",
"ZOHO_BUG_SEVERITY_SHOWSTOPPER": "severity-id-showstopper",
"ZOHO_BUG_SEVERITY_CRITICAL": "severity-id-critical",
"ZOHO_BUG_SEVERITY_MAJOR": "severity-id-major",
"ZOHO_BUG_SEVERITY_MINOR": "severity-id-minor",
"ZOHO_BUG_SEVERITY_NONE": "severity-id-none",
"ZOHO_BUG_APP_VERSION": "field-name",
"ZOHO_BUG_NUM_OF_OCCURRENCES": "field-name"
}
```
### Config key reference
| Key | Description |
|---|---|
| `CRASH_ANALYSIS_PARENT` | Path to your ParentHolderFolder |
| `CLAUDE_CLI_PATH` | Absolute path to the Claude CLI binary (e.g. `~/.local/bin/claude`) |
| `DSYM_PATH` | Path to `MyApp.dSYM` bundle — needed for symbolication |
| `MASTER_BRANCH_PATH` | Path to master/live branch checkout (creates `CurrentMasterLiveBranch` symlink) |
| `DEV_BRANCH_PATH` | Path to dev branch checkout (creates `CurrentDevelopmentBranch` symlink) |
| `CRASH_INPUT_DIR` | Override directory searched for `.xccrashpoint` files |
| `CRASH_VERSIONS` | Comma-separated version filter for exports |
| `CRASH_DATE_OFFSET` | Days ago to target for daily run (default: `"3"`) |
| `CRASH_NUM_DAYS` | Number of days to process in the crash window (1–180, default: `"1"`) |
| `SCHEDULED_RUN_TIME` | Time of day for the scheduled launchd pipeline run in HH:MM 24-hour format, where HH is 0–23 and MM is 0–59 (default: `"11:00"`) |
| `APP_DISPLAY_NAME` | App name shown in pipeline prompts and Cliq notifications |
| `APPTICS_MCP_NAME` | Name of your Apptics MCP server (`claude mcp list`) — also provides Zoho Projects tools (`list_bugs`, `create_bug`, `update_bug`) |
| `ZOHO_CLIQ_WEBHOOK_URL` | Webhook URL for Zoho Cliq crash notifications |
| `ZOHO_PROJECTS_PORTAL_ID` | Zoho Projects portal ID |
| `ZOHO_PROJECTS_PROJECT_ID` | Zoho Projects project ID |
| `APPTICS_PORTAL_ID` | Apptics portal ID (`zsoid`) |
| `APPTICS_PROJECT_ID` | Apptics project ID |
| `APPTICS_APP_NAME` | App name as it appears in Apptics |
| `ZOHO_BUG_STATUS_OPEN` | Status ID for "Open" bugs in Zoho Projects |
| `ZOHO_BUG_STATUS_FIXED` | Status ID for "Fixed" bugs in Zoho Projects |
| `ZOHO_BUG_SEVERITY_SHOWSTOPPER` | Severity ID for Showstopper (≥50 occurrences) |
| `ZOHO_BUG_SEVERITY_CRITICAL` | Severity ID for Critical (≥20 occurrences) |
| `ZOHO_BUG_SEVERITY_MAJOR` | Severity ID for Major (≥5 occurrences) |
| `ZOHO_BUG_SEVERITY_MINOR` | Severity ID for Minor (≥2 occurrences) |
| `ZOHO_BUG_SEVERITY_NONE` | Severity ID for None (<2 occurrences) |
| `ZOHO_BUG_APP_VERSION` | Custom field name for app version on bug items |
| `ZOHO_BUG_NUM_OF_OCCURRENCES` | Custom field name for occurrence count on bug items |
### MCP Client Configuration
All MCP clients use the same JSON block — only the config file path differs.
**Block to add:**
```json
{
"mcpServers": {
"crashpoint-ios": {
"command": "npx",
"args": [
"-p",
"github:maanasa-s-5539/CrashPoint-IOS-MCP",
"crashpoint-ios-core"
],
"env": {
"CRASH_INPUT_DIR": "/path/to/Xcode/Products/com.example.myapp/Crashes/Points",
"CRASH_ANALYSIS_PARENT": "/path/to/ParentHolderFolder"
}
}
}
}
```
**Where to put it:**
| Client | Config file | Where in the file |
|---|---|---|
| Claude Desktop (macOS) | `~/Library/Application Support/Claude/claude_desktop_config.json` | Top-level `mcpServers` object |
| Claude CLI (Claude Code) | `~/.claude.json` | Top-level `mcpServers` object (not inside `projects`) so it is visible from any folder |
| Cursor | `.cursor/mcp.json` in your project root | Top-level `mcpServers` object |
If the chosen file already contains an `mcpServers` object, add the `"crashpoint-ios": { ... }` entry inside the existing object instead of duplicating the key.
Replace `/path/to/...` with real absolute paths on your machine. `CRASH_ANALYSIS_PARENT` is required; `CRASH_INPUT_DIR` is optional and only needed when overriding the default Xcode crash input location.
All other values (paths, app name, etc.) are read automatically from `crashpoint.config.json`.
Restart Claude Desktop, Cursor, or start a new `claude` CLI session after saving the file.
---
## Environment Variables
Only `CRASH_ANALYSIS_PARENT` is required as an environment variable — it tells the server where to find `crashpoint.config.json`. All other settings live in that config file.
Environment variables can still override any key from `crashpoint.config.json` (env always wins) if you need per-client overrides via MCP client `env` blocks.
---
## Quick Start
There are **two ways** to run the CrashPoint pipeline. Choose the path that fits your workflow:
---
### Path A: Claude Desktop / Cursor (zero manual setup)
The MCP tools automatically create the entire workspace on the **very first run** — no `setup` command needed beforehand.
1. **Clone & build the repo** (or install via npx — see [Installation](#installation) above).
2. **Create your ParentHolderFolder** and place a filled-in `crashpoint.config.json` inside it (see [Configuration](#configuration) above).
3. **Configure your MCP client** with `CRASH_ANALYSIS_PARENT` pointing to your ParentHolderFolder (see the Cursor / Claude Desktop block in [Configuration](#configuration) above).
4. **Ask Claude to call `run_full_pipeline`** — on the very first call, the MCP server detects that the workspace doesn't exist yet and automatically runs setup (creating all folders, copying prompt templates, generating `run_crash_pipeline.sh` with your real paths, and writing `.mcp.json`). No prior setup step is needed.
> **That's it.** After the first `run_full_pipeline` (or `run_basic_pipeline`) call, the full workspace is ready and every subsequent call works without any additional configuration.
---
### Path B: Terminal bash script (one-time setup required first)
The bash script at `ParentHolderFolder/Automation/run_crash_pipeline.sh` **does not exist** until a setup command generates it. The repo contains only a template (`automation/run_crash_pipeline.sh`) with `<REPLACE_WITH_...>` placeholders. The setup command replaces those placeholders with your real paths automatically — you never need to edit them manually.
```bash
# 1. Clone and build the repo
git clone https://github.com/maanasa-s-5539/CrashPoint-IOS-MCP.git
cd CrashPoint-IOS-MCP
npm install
npm run build
# 2. Create your ParentHolderFolder and fill in crashpoint.config.json
mkdir -p /path/to/ParentHolderFolder
cp crashpoint.config.example.json /path/to/ParentHolderFolder/crashpoint.config.json
# Edit /path/to/ParentHolderFolder/crashpoint.config.json with your real values
# 3. Run the setup command once — creates the folder structure AND generates
# run_crash_pipeline.sh with your real paths automatically filled in
CRASH_ANALYSIS_PARENT=/path/to/ParentHolderFolder node dist/cli.js setup
# 4. Run the generated script (placeholders already replaced — no manual editing needed)
bash /path/to/ParentHolderFolder/Automation/run_crash_pipeline.sh
```
> **Note:** The auto-setup block inside the generated bash script (which calls `node dist/cli.js setup` if folders are missing) is a **safety net for subsequent runs** — for example if folders were accidentally deleted. It is not the mechanism for the initial bootstrap. Step 3 above is the required first-time step.
---
## Folder Structure
CrashPoint iOS MCP uses a `ParentHolderFolder` to organize crash data:
```
ParentHolderFolder/ ← CRASH_ANALYSIS_PARENT
├── crashpoint.config.json ← Single source of truth for all configuration
├── .mcp.json ← Auto-generated (do not edit manually)
├── MainCrashLogsFolder/
│ ├── XCodeCrashLogs/ ← Exported .crash files from Xcode Organizer
│ ├── AppticsCrashLogs/ ← Apptics SDK crash logs
│ └── OtherCrashLogs/ ← Other crash logs
├── SymbolicatedCrashLogsFolder/ ← Symbolicated .crash files
├── AnalyzedReportsFolder/ ← JSON + CSV analysis reports
├── StateMaintenance/ ← Processed manifest + fix tracking
└── Automation/ ← Pipeline scripts, prompts, and logs
├── run_crash_pipeline.sh ← Generated by setup (placeholders auto-replaced)
├── daily_crash_pipeline_prompt_phase1.md
├── daily_crash_pipeline_prompt_phase2.md
└── ScheduledRunLogs/
```
**Using Claude Desktop / Cursor (MCP path):** The folder structure is created automatically on the first call to `run_full_pipeline` or `run_basic_pipeline` — no manual setup step needed. The MCP server also generates `Automation/run_crash_pipeline.sh` with your real paths filled in as part of this auto-setup.
**Using the terminal bash script:** Run `CRASH_ANALYSIS_PARENT=/path/to/ParentHolderFolder node dist/cli.js setup` once to create the folder structure and generate `Automation/run_crash_pipeline.sh` with your real paths. After that, run `bash /path/to/ParentHolderFolder/Automation/run_crash_pipeline.sh`. You can also run `setup_folders` in Claude Desktop / Cursor to do the same thing interactively.
---
## Available MCP Tools
| # | Tool | Description |
|---|---|---|
| 1 | `setup_folders` | Create the complete folder structure, generate `.mcp.json` + launchd plist, scaffold automation scripts (phase1 + phase2 prompts + shell script), and create symlinks — all in one command. Recommended for full control (symlinks, launchd plist, etc.). Note: `run_basic_pipeline` and `run_full_pipeline` will auto-run setup on first invocation if the workspace hasn't been initialized yet |
| 2 | `export_crashes` | Export `.crash` files from `.xccrashpoint` packages to `MainCrashLogsFolder/XCodeCrashLogs`. Add `dryRun: true` to preview without writing |
| 3 | `save_apptics_crashes` | Save crash data fetched from the Apptics Zoho MCP as `.crash` files in `AppticsCrashLogs/`. Uses `UniqueMessageID` in filenames for idempotency |
| 4 | `symbolicate_batch` | Symbolicate crash files. Pass optional `file` param for a single file, or batch-process all of `MainCrashLogsFolder` (XCodeCrashLogs, AppticsCrashLogs, OtherCrashLogs) |
| 5 | `verify_dsym` | Validate a `.dSYM` bundle and check if its UUIDs match those in crash files from `MainCrashLogsFolder` |
| 6 | `analyze_crashes` | Group & deduplicate crashes by signature; includes fix status. Always auto-generates JSON + CSV reports in `AnalyzedReportsFolder` |
| 7 | `fix_status` | Unified fix tracking: `action='set'` to mark fixed/unfixed, `action='unset'` to clear, `action='list'` to view all |
| 8 | `run_basic_pipeline` | Run the basic pipeline: export → symbolicate → analyze. Automatically initializes the workspace on first run if `setup_folders` hasn't been run yet |
| 9 | `run_full_pipeline` | Run the full pipeline with Zoho integration: export → symbolicate → analyze. Returns `nextSteps` flags (`notifyCliq`, `reportToProjects`) for follow-up actions. Automatically initializes the workspace on first run if `setup_folders` hasn't been run yet |
| 10 | `notify_cliq` | Send crash report summary to a Zoho Cliq channel via incoming webhook |
| 11 | `prepare_project_bugs` | Prepare structured bug data from crash reports for Zoho Projects submission (titles, descriptions, severity, custom fields) |
| 12 | `clean_old_crashes` | Delete `.crash`/`.ips` files older than a given date across all crash directories |
| 13 | `cleanup_reports` | Delete analyzed report files (`.json`/`.csv`) in `AnalyzedReportsFolder` that are older than a given date |
| 14 | `cleanup_all` | Remove all crash files and reports in one go. Supports `dryRun`, `keepReports`, and `keepManifests` flags |
For detailed parameter documentation, see [Tool Parameters](docs/TOOL_PARAMETERS.md).
---
## Standalone CLI
The CLI lets you run the crash analysis pipeline without an MCP client (useful for scheduled runs):
```bash
# Delete crash files older than a given date
node dist/cli.js clean --before-date 2026-03-01
# Delete analyzed report files in AnalyzedReportsFolder older than a given date
node dist/cli.js cleanup-reports --before-date 2026-03-01
# Create folder structure with symlinks
node dist/cli.js setup --master-branch /path/to/master --dev-branch /path/to/dev --dsym /path/to/MyApp.dSYM
# Validate a dSYM bundle and check UUID matches against crashes in MainCrashLogsFolder
node dist/cli.js verify-dsym
node dist/cli.js verify-dsym --crash-dir /path/to/MainCrashLogsFolder/XCodeCrashLogs/ --dsym /path/to/MyApp.dSYM
# Export crash logs from Xcode Organizer
node dist/cli.js export
# Export crashes filtered by date range
node dist/cli.js export --start-date 2026-03-01 --end-date 2026-03-20
# Symbolicate all crash files in MainCrashLogsFolder (XCodeCrashLogs, AppticsCrashLogs, OtherCrashLogs)
node dist/cli.js batch
# Symbolicate a single crash file
node dist/cli.js batch --file /path/to/crash.crash
# Analyze crashes and print JSON report (also auto-saves JSON + CSV to AnalyzedReportsFolder)
node dist/cli.js analyze
# Manage fix statuses (unified command)
node dist/cli.js fix-status --action set --signature "EXC_BAD_ACCESS SIGSEGV" --note "Fixed in PR #42"
node dist/cli.js fix-status --action unset --signature "EXC_BAD_ACCESS SIGSEGV"
node dist/cli.js fix-status --action list
# Run basic pipeline (export → symbolicate → analyze)
node dist/cli.js pipeline
# Remove all crash files and reports in one go
node dist/cli.js cleanup # delete everything
node dist/cli.js cleanup --keep-reports # only delete crash files, preserve reports
node dist/cli.js cleanup --keep-manifests # preserve processed manifests
```
---
## Fix Tracking
Crash fix statuses are stored in `{CRASH_ANALYSIS_PARENT}/StateMaintenance/fix_status.json` (local only, gitignored).
```json
{
"EXC_BAD_ACCESS||MyApp -[ViewController load]||...": {
"fixed": true,
"note": "Fixed in PR #42",
"updatedAt": "2026-03-22T16:00:00.000Z"
}
}
```
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues