# xcsift-mcp

An MCP (Model Context Protocol) server that wraps [xcsift](https://github.com/ldomaradzki/xcsift), enabling AI coding assistants to parse Xcode build output into structured, token-efficient formats.

[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![MCP](https://img.shields.io/badge/MCP-Compatible-green.svg)](https://modelcontextprotocol.io)

## Overview

`xcsift-mcp` provides AI coding assistants (like Claude, OpenCode, Cursor, etc.) with tools to:

- **Parse** raw `xcodebuild` or `swift build/test` output into structured JSON or TOON format
- **Execute** build commands and get parsed results automatically
- **Extract** errors, warnings, test failures, and linker errors with file/line information
- **Analyze** code coverage from test runs

The output is optimized for token efficiency, with TOON format providing 30-60% fewer tokens compared to JSON.

## Installation

### Prerequisites

- Python 3.10+
- macOS (xcsift is macOS-only)
- [pipx](https://pipx.pypa.io/) (install via `brew install pipx`)

### Install from source

```bash
git clone https://github.com/johnnyclem/xcsift_mcp.git
cd xcsift_mcp
pipx install -e ".[dev]"
```

### Install via Homebrew

```bash
brew install johnnyclem/xcsift-mcp/xcsift-mcp
```

### xcsift Binary

The server will **automatically download** the `xcsift` binary from GitHub releases on first run if it's not already installed. The binary is cached in `~/.local/share/xcsift-mcp/bin/`.

You can also install it manually via Homebrew:

```bash
brew install xcsift
```

## Usage

### Running the Server

```bash
# Run with stdio transport (default, for Claude Desktop/OpenCode)
xcsift-mcp

# Run with HTTP transport (for debugging/web clients)
xcsift-mcp --transport http --port 8000
```

### Integration with AI Assistants

#### Claude Desktop

Add to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "xcsift": {
      "command": "xcsift-mcp"
    }
  }
}
```

#### OpenCode

Add to your `opencode.json` (or `opencode.jsonc`):

```json
{
  "mcp": {
    "xcsift": {
      "type": "local",
      "command": ["xcsift-mcp"]
    }
  }
}
```

Alternatively, run `opencode mcp add` and follow the interactive prompts.

#### Cursor

Add to your MCP configuration in Cursor settings, or add to `.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "xcsift": {
      "command": "xcsift-mcp"
    }
  }
}
```

## Available Tools

### Parsing Tools

| Tool | Description |
|------|-------------|
| `parse_xcodebuild_output` | Parse raw xcodebuild/swift output into JSON or TOON format |
| `extract_errors` | Extract only errors with file/line information |
| `extract_warnings` | Extract only warnings with file/line/type |
| `extract_test_failures` | Extract failed tests with assertion messages |
| `get_build_summary` | Get a quick summary with error/warning counts |

### Build Execution Tools

| Tool | Description |
|------|-------------|
| `xcodebuild` | Run xcodebuild and parse output automatically |
| `swift_build` | Run swift build for SPM projects |
| `swift_test` | Run swift test with optional coverage |
| `run_shell_build_command` | Run arbitrary build commands and parse output |

## Tool Parameters

### `parse_xcodebuild_output`

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `output` | string | required | Raw xcodebuild/swift output (use `2>&1` to capture stderr) |
| `format` | `"json"` \| `"toon"` | `"json"` | Output format |
| `include_warnings` | bool | `false` | Include detailed warnings list |
| `include_coverage` | bool | `false` | Include coverage data if available |

### `xcodebuild`

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `action` | `"build"` \| `"test"` \| `"clean"` \| `"analyze"` | `"build"` | Build action |
| `scheme` | string | none | Scheme to build |
| `project` | string | none | Path to .xcodeproj |
| `workspace` | string | none | Path to .xcworkspace |
| `destination` | string | none | Destination (e.g., `"platform=iOS Simulator,name=iPhone 15"`) |
| `configuration` | `"Debug"` \| `"Release"` | none | Build configuration |
| `enable_code_coverage` | bool | `false` | Enable coverage for tests |
| `output_format` | `"json"` \| `"toon"` | `"json"` | Output format |
| `timeout` | int | `600` | Timeout in seconds |

### `swift_build`

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `configuration` | `"debug"` \| `"release"` | `"debug"` | Build configuration |
| `package_path` | string | none | Path to Swift package |
| `target` | string | none | Specific target to build |
| `output_format` | `"json"` \| `"toon"` | `"json"` | Output format |
| `timeout` | int | `300` | Timeout in seconds |

### `swift_test`

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `package_path` | string | none | Path to Swift package |
| `filter_test` | string | none | Filter tests (e.g., `"MyTests.testFoo"`) |
| `enable_code_coverage` | bool | `false` | Enable coverage collection |
| `parallel` | bool | `true` | Run tests in parallel |
| `output_format` | `"json"` \| `"toon"` | `"json"` | Output format |
| `timeout` | int | `600` | Timeout in seconds |

## Example Usage

### Parse existing build output

```python
# In your AI assistant
result = parse_xcodebuild_output(
    output="<raw xcodebuild output>",
    format="toon",  # or "json"
    include_warnings=True
)
```

### Run build and get parsed results

```python
result = xcodebuild(
    action="build",
    scheme="MyApp",
    destination="platform=iOS Simulator,name=iPhone 15",
    output_format="json"
)
```

### Run tests with coverage

```python
result = swift_test(
    enable_code_coverage=True,
    output_format="toon"
)
```

### Extract just the errors

```python
errors = extract_errors(output="<raw xcodebuild output>")
# Returns: [{"file": "main.swift", "line": 15, "message": "..."}]
```

## Output Formats

### JSON Format

Standard structured JSON output:

```json
{
  "status": "failed",
  "summary": {
    "errors": 1,
    "warnings": 3,
    "failed_tests": 0,
    "linker_errors": 0,
    "build_time": "3.2s"
  },
  "errors": [
    {
      "file": "main.swift",
      "line": 15,
      "message": "use of undeclared identifier 'unknown'"
    }
  ],
  "warnings": [
    {
      "file": "view.swift",
      "line": 20,
      "message": "variable 'temp' was never used",
      "type": "compile"
    }
  ]
}
```

### TOON Format (Token-Optimized)

30-60% fewer tokens than JSON:

```
status: failed
summary:
  errors: 1
  warnings: 3
  failed_tests: 0
  linker_errors: 0
  build_time: 3.2s
errors[1]{file,line,message}:
  main.swift,15,"use of undeclared identifier 'unknown'"
warnings[1]{file,line,message,type}:
  view.swift,20,"variable 'temp' was never used","compile"
```

**When to use each format:**

- **JSON**: When you need to parse the output programmatically or integrate with other tools
- **TOON**: When sending to an LLM to reduce token usage and API costs

## Available Resources

| Resource URI | Description |
|--------------|-------------|
| `xcsift://version` | xcsift version and installation info |
| `xcsift://config-template` | Example .xcsift.toml configuration |
| `xcsift://output-formats` | Documentation about output formats |
| `xcsift://help` | Comprehensive help documentation |

## Available Prompts

| Prompt | Description | Arguments |
|--------|-------------|-----------|
| `analyze_build_failure` | Template for analyzing build failures | `errors`, `code_context` |
| `fix_compiler_errors` | Template for fixing Swift/ObjC compiler errors | `errors`, `file_content` |
| `improve_test_coverage` | Template for improving test coverage | `coverage_report`, `target_coverage` |
| `debug_test_failures` | Template for debugging test failures | `test_output`, `test_code` |
| `fix_linker_errors` | Template for fixing linker errors | `linker_errors`, `project_structure` |
| `analyze_build_performance` | Template for analyzing build performance | `build_info` |

## Development

### Running Tests

```bash
pytest
```

### Running Tests with Coverage

```bash
pytest --cov=xcsift_mcp
```

### Code Formatting

```bash
ruff format .
ruff check .
```

### Project Structure

```
xcsift_mcp/
├── src/xcsift_mcp/
│   ├── __init__.py           # Package init
│   ├── __main__.py           # Entry point
│   ├── server.py             # FastMCP server
│   ├── xcsift_installer.py   # Auto-download xcsift
│   ├── resources.py          # MCP resources
│   ├── prompts.py            # Prompt templates
│   └── tools/
│       ├── parse.py          # Parsing tools
│       └── build.py          # Build execution tools
├── tests/
│   ├── fixtures/             # Sample build outputs
│   └── test_*.py             # Test files
├── pyproject.toml
└── README.md
```

## Architecture

```
┌─────────────────────────────────────────────────────────────────┐
│                 AI Assistant (Claude, OpenCode, etc.)           │
└─────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────┐
│                     MCP Protocol (stdio/HTTP)                    │
└─────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────┐
│                     xcsift MCP Server (Python)                   │
│  ┌─────────────────┐  ┌──────────────────┐  ┌────────────────┐  │
│  │   Tools (9)     │  │  Resources (4)   │  │  Prompts (6)   │  │
│  │ - parse_output  │  │ - version        │  │ - analyze      │  │
│  │ - xcodebuild    │  │ - config         │  │ - fix_errors   │  │
│  │ - swift_build   │  │ - formats        │  │ - coverage     │  │
│  │ - swift_test    │  │ - help           │  │ - debug        │  │
│  └─────────────────┘  └──────────────────┘  └────────────────┘  │
└─────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────┐
│                     xcsift CLI (subprocess)                      │
└─────────────────────────────────────────────────────────────────┘
```

## Troubleshooting

### xcsift not found

If xcsift cannot be downloaded automatically, install it manually:

```bash
brew install xcsift
```

### Permission denied

Ensure the xcsift binary has execute permissions:

```bash
chmod +x ~/.local/share/xcsift-mcp/bin/xcsift
```

### Build timeout

Increase the timeout parameter for long builds:

```python
xcodebuild(scheme="MyApp", timeout=1200)  # 20 minutes
```

## License

MIT License - see [LICENSE](LICENSE) for details.

## Credits

- [xcsift](https://github.com/ldomaradzki/xcsift) - The Swift CLI tool that does the actual parsing
- [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) - Model Context Protocol implementation
