# 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.
[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
[](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