diff --git a/README.md b/README.md
index 94ae7cad..d2d38c8f 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@ Add XcodeBuildMCP to your MCP client configuration. Most clients use JSON config
```json
"XcodeBuildMCP": {
"command": "npx",
- "args": ["-y", "xcodebuildmcp@latest", "mcp"]
+ "args": ["-y", "xcodebuildmcp@beta", "mcp"]
}
```
@@ -26,7 +26,7 @@ Add XcodeBuildMCP to your MCP client configuration. Most clients use JSON config
"mcpServers": {
"XcodeBuildMCP": {
"command": "npx",
- "args": ["-y", "xcodebuildmcp@latest", "mcp"]
+ "args": ["-y", "xcodebuildmcp@beta", "mcp"]
}
}
}
@@ -34,7 +34,7 @@ Add XcodeBuildMCP to your MCP client configuration. Most clients use JSON config
Or use the quick install link:
- [](cursor://anysphere.cursor-deeplink/mcp/install?name=XcodeBuildMCP&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsInhjb2RlYnVpbGRtY3BAbGF0ZXN0IiwibWNwIl19)
+[](https://cursor.com/en-US/install-mcp?name=XcodeBuildMCP&config=eyJjb21tYW5kIjoibnB4IC15IHhjb2RlYnVpbGRtY3BAYmV0YSBtY3AifQ%3D%3D)
@@ -44,7 +44,7 @@ Add XcodeBuildMCP to your MCP client configuration. Most clients use JSON config
Run:
```bash
- claude mcp add XcodeBuildMCP -- npx -y xcodebuildmcp@latest mcp
+ claude mcp add XcodeBuildMCP -- npx -y xcodebuildmcp@beta mcp
```
@@ -55,14 +55,14 @@ Add XcodeBuildMCP to your MCP client configuration. Most clients use JSON config
Run:
```bash
- codex mcp add XcodeBuildMCP -- npx -y xcodebuildmcp@latest mcp
+ codex mcp add XcodeBuildMCP -- npx -y xcodebuildmcp@beta mcp
```
Or add to `~/.codex/config.toml`:
```toml
[mcp_servers.XcodeBuildMCP]
command = "npx"
- args = ["-y", "xcodebuildmcp@latest", "mcp"]
+ args = ["-y", "xcodebuildmcp@beta", "mcp"]
```
@@ -77,7 +77,7 @@ Add XcodeBuildMCP to your MCP client configuration. Most clients use JSON config
"mcpServers": {
"XcodeBuildMCP": {
"command": "npx",
- "args": ["-y", "xcodebuildmcp@latest", "mcp"]
+ "args": ["-y", "xcodebuildmcp@beta", "mcp"]
}
}
}
@@ -95,7 +95,7 @@ Add XcodeBuildMCP to your MCP client configuration. Most clients use JSON config
"servers": {
"XcodeBuildMCP": {
"command": "npx",
- "args": ["-y", "xcodebuildmcp@latest", "mcp"]
+ "args": ["-y", "xcodebuildmcp@beta", "mcp"]
}
}
}
@@ -103,8 +103,8 @@ Add XcodeBuildMCP to your MCP client configuration. Most clients use JSON config
Or use the quick install links:
- [
](https://insiders.vscode.dev/redirect/mcp/install?name=XcodeBuildMCP&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22xcodebuildmcp%40latest%22%2C%22mcp%22%5D%7D)
- [
](https://insiders.vscode.dev/redirect/mcp/install?name=XcodeBuildMCP&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22xcodebuildmcp%40latest%22%2C%22mcp%22%5D%7D&quality=insiders)
+ [](https://cursor.com/en-US/install-mcp?name=XcodeBuildMCP&config=eyJjb21tYW5kIjoibnB4IC15IHhjb2RlYnVpbGRtY3BAYmV0YSBtY3AifQ%3D%3D)
+ [](vscode-insiders:mcp/install?%7B%22name%22%3A%22XcodeBuildMCP%22%2C%22type%22%3A%22stdio%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22xcodebuildmcp%40beta%22%2C%22mcp%22%5D%7D)
@@ -118,7 +118,7 @@ Add XcodeBuildMCP to your MCP client configuration. Most clients use JSON config
"mcpServers": {
"XcodeBuildMCP": {
"command": "npx",
- "args": ["-y", "xcodebuildmcp@latest", "mcp"]
+ "args": ["-y", "xcodebuildmcp@beta", "mcp"]
}
}
}
@@ -136,7 +136,7 @@ Add XcodeBuildMCP to your MCP client configuration. Most clients use JSON config
"mcpServers": {
"XcodeBuildMCP": {
"command": "npx",
- "args": ["-y", "xcodebuildmcp@latest", "mcp"]
+ "args": ["-y", "xcodebuildmcp@beta", "mcp"]
}
}
}
@@ -160,9 +160,10 @@ When configuring a client manually, ensure the command includes the `mcp` subcom
XcodeBuildMCP now includes an optional agent skill. Some clients (e.g., Cursor, Claude Code) hide MCP tool schemas behind search/progressive disclosure, which can reduce tool discovery and usage. The skill provides a concise overview of available tools to counter that. If your client already exposes tools up front, you likely don’t need it; only use it if your agent isn’t reaching for XcodeBuildMCP tools.
-To install, replace `` with your client (cursor, claude, codex):
+To install, download and run the installer in a terminal, then choose your client when prompted:
```bash
-curl -fsSL https://raw.githubusercontent.com/cameroncooke/XcodeBuildMCP/main/scripts/install-skill.sh | bash -s -- --
+curl -fsSL https://raw.githubusercontent.com/cameroncooke/XcodeBuildMCP/main/scripts/install-skill.sh -o install-skill.sh
+bash install-skill.sh
```
For further information on how to install the skill, see: [docs/SKILLS.md](docs/SKILLS.md)
@@ -182,7 +183,7 @@ XcodeBuildMCP provides a unified command-line interface. The `mcp` subcommand st
```bash
# Install globally
-npm install -g xcodebuildmcp
+npm install -g xcodebuildmcp@beta
# Start the MCP server (for MCP clients)
xcodebuildmcp mcp
@@ -191,7 +192,7 @@ xcodebuildmcp mcp
xcodebuildmcp tools
# Build for simulator
-xcodebuildmcp build-sim --scheme MyApp --project-path ./MyApp.xcodeproj
+xcodebuildmcp simulator build-sim --scheme MyApp --project-path ./MyApp.xcodeproj
```
The CLI uses a per-workspace daemon for stateful operations (log capture, debugging, etc.) that auto-starts when needed. See [docs/CLI.md](docs/CLI.md) for full documentation.
diff --git a/docs/CLI.md b/docs/CLI.md
index 9f9b2c60..89f4ca7a 100644
--- a/docs/CLI.md
+++ b/docs/CLI.md
@@ -1,36 +1,139 @@
# XcodeBuildMCP CLI
-`xcodebuildmcp` is a unified command-line interface that provides both the MCP server and direct tool access. Use `xcodebuildmcp mcp` to start the MCP server, or invoke tools directly from your terminal.
+`xcodebuildmcp` is a unified command-line interface that provides both an MCP server and direct tool access via a first-class CLI.
+
+Use `xcodebuildmcp` CLI to invoke tools or start the MCP server by passing the `mcp` argument.
## Installation
```bash
# Install globally
-npm install -g xcodebuildmcp
+npm install -g xcodebuildmcp@beta
# Or run via npx
-npx xcodebuildmcp --help
+npx xcodebuildmcp@beta --help
```
## Quick Start
```bash
-# Start MCP server (for MCP clients like Claude, Cursor, etc.)
-xcodebuildmcp mcp
-
# List available tools
xcodebuildmcp tools
-# Build for simulator
+# View CLI help
+xcodebuildmcp --help
+
+# View tool help
+xcodebuildmcp --help
+```
+
+## Tool Options
+
+Each tool supports `--help` for detailed options:
+
+```bash
+xcodebuildmcp simulator build-sim --help
+```
+
+Common patterns:
+
+```bash
+# Pass options as flags
xcodebuildmcp simulator build-sim --scheme MyApp --project-path ./MyApp.xcodeproj
-# List simulators
-xcodebuildmcp simulator list-sims
+# Pass complex options as JSON
+xcodebuildmcp simulator build-sim --json '{"scheme": "MyApp", "projectPath": "./MyApp.xcodeproj"}'
-# Run tests
-xcodebuildmcp simulator test-sim --scheme MyApp --simulator-name "iPhone 17 Pro"
+# Control output format
+xcodebuildmcp simulator list-sims --output json
```
+## Examples
+
+### Build and Run Workflow
+
+```bash
+# Discover projects
+xcodebuildmcp simulator discover-projs
+
+# List schemes
+xcodebuildmcp simulator list-schemes --project-path ./MyApp.xcodeproj
+
+# Build
+xcodebuildmcp simulator build-sim --scheme MyApp --project-path ./MyApp.xcodeproj
+
+# Boot simulator
+xcodebuildmcp simulator boot-sim --simulator-name "iPhone 17 Pro"
+
+# Install and launch
+xcodebuildmcp simulator install-app-sim --simulator-id --app-path ./build/MyApp.app
+
+xcodebuildmcp simulator launch-app-sim --simulator-id --bundle-id com.example.MyApp
+
+# Or... build and run in a single command
+xcodebuildmcp simulator build-run-sim --scheme MyApp --project-path ./MyApp.xcodeproj
+```
+
+### Log Capture Workflow
+
+```bash
+# Start log capture
+xcodebuildmcp logging start-sim-log-cap --simulator-id --bundle-id com.example.MyApp
+
+> Log capture started successfully. Session ID: 51e2142a-1a99-442a-af01-0586540043df.
+
+# Stop and retrieve logs
+xcodebuildmcp logging stop-sim-log-cap --session-id
+```
+
+### Testing
+
+```bash
+# Run all tests
+xcodebuildmcp simulator test-sim --scheme MyAppTests --project-path ./MyApp.xcodeproj
+
+# Run with specific simulator
+xcodebuildmcp simulator test-sim --scheme MyAppTests --simulator-name "iPhone 17 Pro"
+```
+
+For a full list of workflows and tools, see [TOOLS-CLI.md](TOOLS-CLI.md).
+
+## Configuration
+
+The CLI respects the same configuration as the MCP server:
+
+```yaml
+# .xcodebuildmcp/config.yaml
+sessionDefaults:
+ scheme: MyApp
+ projectPath: ./MyApp.xcodeproj
+ simulatorName: iPhone 17 Pro
+
+enabledWorkflows:
+ - simulator
+ - project-discovery
+```
+
+See [CONFIGURATION.md](CONFIGURATION.md) for the full schema.
+
+## Environment Variables
+
+| Variable | Description |
+|----------|-------------|
+| `XCODEBUILDMCP_SOCKET` | Override socket path for all commands |
+| `XCODEBUILDMCP_DISABLE_SESSION_DEFAULTS` | Disable session defaults |
+
+## CLI vs MCP Mode
+
+| Feature | CLI (`xcodebuildmcp `) | MCP (`xcodebuildmcp mcp`) |
+|---------|------------------------------|---------------------------|
+| Invocation | Direct terminal | MCP client (Claude, etc.) |
+| Session state | Per-workspace daemon | In-process |
+| Use case | Scripts, CI, manual | AI-assisted development |
+| Configuration | Same config.yaml | Same config.yaml |
+
+Both share the same underlying tool implementations.
+
## Per-Workspace Daemon
The CLI uses a per-workspace daemon architecture for stateful operations (log capture, video recording, debugging). Each workspace gets its own daemon instance.
@@ -95,36 +198,15 @@ Daemons:
Total: 2 (1 running, 1 stale)
```
-## Global Options
-
-| Option | Description |
-|--------|-------------|
-| `--socket ` | Override the daemon socket path (hidden) |
-| `--daemon` | Force daemon execution for stateless tools (hidden) |
-| `--no-daemon` | Disable daemon usage; stateful tools will fail |
-| `-h, --help` | Show help |
-| `-v, --version` | Show version |
-
-## Tool Options
+### Opting Out of Daemon
-Each tool supports `--help` for detailed options:
+If you want to disable daemon auto-start (stateful tools will error):
```bash
-xcodebuildmcp simulator build-sim --help
+xcodebuildmcp build-sim --no-daemon --scheme MyApp
```
-Common patterns:
-
-```bash
-# Pass options as flags
-xcodebuildmcp simulator build-sim --scheme MyApp --project-path ./MyApp.xcodeproj
-
-# Pass complex options as JSON
-xcodebuildmcp simulatorbuild-sim --json '{"scheme": "MyApp", "projectPath": "./MyApp.xcodeproj"}'
-
-# Control output format
-xcodebuildmcp simulator list-sims --output json
-```
+This is useful for CI environments or when you want explicit control.
## Stateful vs Stateless Tools
@@ -132,7 +214,7 @@ xcodebuildmcp simulator list-sims --output json
Most tools run directly without the daemon:
- `build-sim`, `test-sim`, `clean`
- `list-sims`, `list-schemes`, `discover-projs`
-- `boot-sim`, `install-app-sim`, `launch-app-sim`
+- `boot-sim`, `install-app-sim`, `launch-app-sim` etc.
### Stateful Tools (require daemon)
Some tools maintain state and route through the daemon:
@@ -143,95 +225,15 @@ Some tools maintain state and route through the daemon:
When you invoke a stateful tool, the daemon auto-starts if needed.
-## Opting Out of Daemon
-
-If you want to disable daemon auto-start (stateful tools will error):
-
-```bash
-xcodebuildmcp build-sim --no-daemon --scheme MyApp
-```
-
-This is useful for CI environments or when you want explicit control.
-
-## Configuration
-
-The CLI respects the same configuration as the MCP server:
-
-```yaml
-# .xcodebuildmcp/config.yaml
-sessionDefaults:
- scheme: MyApp
- projectPath: ./MyApp.xcodeproj
- simulatorName: iPhone 17 Pro
-
-enabledWorkflows:
- - simulator
- - project-discovery
-```
-
-See [CONFIGURATION.md](CONFIGURATION.md) for the full schema.
-
-## Environment Variables
-
-| Variable | Description |
-|----------|-------------|
-| `XCODEBUILDMCP_SOCKET` | Override socket path for all commands |
-| `XCODEBUILDMCP_DISABLE_SESSION_DEFAULTS` | Disable session defaults |
-
-## Examples
-
-### Build and Run Workflow
-
-```bash
-# Discover projects
-xcodebuildmcp simulatordiscover-projs
-
-# List schemes
-xcodebuildmcp simulatordiscover list-schemes --project-path ./MyApp.xcodeproj
-
-# Build
-xcodebuildmcp simulator build-sim --scheme MyApp --project-path ./MyApp.xcodeproj
-
-# Boot simulator
-xcodebuildmcp simulator boot-sim --simulator-name "iPhone 17 Pro"
-
-# Install and launch
-xcodebuildmcp simulator install-app-sim --simulator-id --app-path ./build/MyApp.app
-xcodebuildmcp simulator launch-app-sim --simulator-id --bundle-id com.example.MyApp
-```
-
-### Log Capture Workflow
-
-```bash
-# Start log capture (daemon auto-starts)
-xcodebuildmcp logging start-sim-log-cap --simulator-id --bundle-id com.example.MyApp
-
-# ... use your app ...
-
-# Stop and retrieve logs
-xcodebuildmcp logging stop-sim-log-cap --session-id
-```
-
-### Testing
-
-```bash
-# Run all tests
-xcodebuildmcp simulator test-sim --scheme MyAppTests --project-path ./MyApp.xcodeproj
-
-# Run with specific simulator
-xcodebuildmcp simulator test-sim --scheme MyAppTests --simulator-name "iPhone 17 Pro"
-```
-
-## CLI vs MCP Mode
-
-| Feature | CLI (`xcodebuildmcp `) | MCP (`xcodebuildmcp mcp`) |
-|---------|------------------------------|---------------------------|
-| Invocation | Direct terminal | MCP client (Claude, etc.) |
-| Session state | Per-workspace daemon | In-process |
-| Use case | Scripts, CI, manual | AI-assisted development |
-| Configuration | Same config.yaml | Same config.yaml |
+## Global Options
-Both share the same underlying tool implementations.
+| Option | Description |
+|--------|-------------|
+| `--socket ` | Override the daemon socket path (hidden) |
+| `--daemon` | Force daemon execution for stateless tools (hidden) |
+| `--no-daemon` | Disable daemon usage; stateful tools will fail |
+| `-h, --help` | Show help |
+| `-v, --version` | Show version |
## Troubleshooting
@@ -264,4 +266,4 @@ The socket directory (`~/.xcodebuildmcp/daemons/`) should have mode 0700. If you
```bash
chmod 700 ~/.xcodebuildmcp
chmod -R 700 ~/.xcodebuildmcp/daemons
-```
+```
\ No newline at end of file
diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md
index cbb66a3b..3473e767 100644
--- a/docs/GETTING_STARTED.md
+++ b/docs/GETTING_STARTED.md
@@ -12,7 +12,7 @@ XcodeBuildMCP provides a unified CLI with two modes:
| Command | Use Case |
|---------|----------|
| `xcodebuildmcp mcp` | Start MCP server for AI-assisted development |
-| `xcodebuildmcp ` | Direct terminal usage, scripts, CI pipelines |
+| `xcodebuildmcp ` | Direct terminal usage, scripts, CI pipelines |
Both share the same tools and configuration.
@@ -25,7 +25,7 @@ Most MCP clients use JSON configuration. Add the following server entry to your
"command": "npx",
"args": [
"-y",
- "xcodebuildmcp@latest",
+ "xcodebuildmcp@beta",
"mcp"
]
}
@@ -35,13 +35,19 @@ Most MCP clients use JSON configuration. Add the following server entry to your
```bash
# Install globally
-npm install -g xcodebuildmcp
+npm install -g xcodebuildmcp@beta
# Verify installation
xcodebuildmcp --version
# List available tools
xcodebuildmcp tools
+
+# View CLI help
+xcodebuildmcp --help
+
+# View tool help
+xcodebuildmcp --help
```
See [CLI.md](CLI.md) for full CLI documentation.
@@ -63,7 +69,7 @@ Codex uses TOML for MCP configuration. Add this to `~/.codex/config.toml`:
```toml
[mcp_servers.XcodeBuildMCP]
command = "npx"
-args = ["-y", "xcodebuildmcp@latest", "mcp"]
+args = ["-y", "xcodebuildmcp@beta", "mcp"]
env = { "XCODEBUILDMCP_SENTRY_DISABLED" = "false" }
```
@@ -79,10 +85,10 @@ https://github.com/openai/codex/blob/main/docs/config.md#connecting-to-mcp-serve
### Claude Code CLI
```bash
# Add XcodeBuildMCP server to Claude Code
-claude mcp add XcodeBuildMCP -- npx -y xcodebuildmcp@latest mcp
+claude mcp add XcodeBuildMCP -- npx -y xcodebuildmcp@beta mcp
# Or with environment variables
-claude mcp add XcodeBuildMCP -e XCODEBUILDMCP_SENTRY_DISABLED=false -- npx -y xcodebuildmcp@latest mcp
+claude mcp add XcodeBuildMCP -e XCODEBUILDMCP_SENTRY_DISABLED=false -- npx -y xcodebuildmcp@beta mcp
```
Note: XcodeBuildMCP requests xcodebuild to skip macro validation to avoid Swift Macro build errors.
diff --git a/docs/TOOLS-CLI.md b/docs/TOOLS-CLI.md
new file mode 100644
index 00000000..5ebee8f2
--- /dev/null
+++ b/docs/TOOLS-CLI.md
@@ -0,0 +1,180 @@
+# XcodeBuildMCP CLI Tools Reference
+
+This document lists CLI tool names as exposed by `xcodebuildmcp `.
+
+XcodeBuildMCP provides 68 canonical tools organized into 12 workflow groups.
+
+## Workflow Groups
+
+### iOS Device Development (`device`)
+**Purpose**: Complete iOS development workflow for both .xcodeproj and .xcworkspace files targeting physical devices (iPhone, iPad, Apple Watch, Apple TV, Apple Vision Pro). Build, test, deploy, and debug apps on real hardware. (14 tools)
+
+- `build-device` - Build for device.
+- `clean` - Defined in Project Utilities workflow.
+- `discover-projs` - Defined in Project Discovery workflow.
+- `get-app-bundle-id` - Defined in Project Discovery workflow.
+- `get-device-app-path` - Get device built app path.
+- `install-app-device` - Install app on device.
+- `launch-app-device` - Launch app on device.
+- `list-devices` - List connected devices.
+- `list-schemes` - Defined in Project Discovery workflow.
+- `show-build-settings` - Defined in Project Discovery workflow.
+- `start-device-log-cap` - Defined in Log Capture & Management workflow.
+- `stop-app-device` - Stop device app.
+- `stop-device-log-cap` - Defined in Log Capture & Management workflow.
+- `test-device` - Test on device.
+
+
+
+### iOS Simulator Development (`simulator`)
+**Purpose**: Complete iOS development workflow for both .xcodeproj and .xcworkspace files targeting simulators. Build, test, deploy, and interact with iOS apps on simulators. (20 tools)
+
+- `boot-sim` - Boot iOS simulator.
+- `build-run-sim` - Build and run iOS sim.
+- `build-sim` - Build for iOS sim.
+- `clean` - Defined in Project Utilities workflow.
+- `discover-projs` - Defined in Project Discovery workflow.
+- `get-app-bundle-id` - Defined in Project Discovery workflow.
+- `get-sim-app-path` - Get sim built app path.
+- `install-app-sim` - Install app on sim.
+- `launch-app-logs-sim` - Launch sim app with logs.
+- `launch-app-sim` - Launch app on simulator.
+- `list-schemes` - Defined in Project Discovery workflow.
+- `list-sims` - List iOS simulators.
+- `open-sim` - Open Simulator app.
+- `record-sim-video` - Record sim video.
+- `screenshot` - Defined in UI Automation workflow.
+- `show-build-settings` - Defined in Project Discovery workflow.
+- `snapshot-ui` - Defined in UI Automation workflow.
+- `stop-app-sim` - Stop sim app.
+- `stop-sim-log-cap` - Defined in Log Capture & Management workflow.
+- `test-sim` - Test on iOS sim.
+
+
+
+### Log Capture & Management (`logging`)
+**Purpose**: Log capture and management tools for iOS simulators and physical devices. Start, stop, and analyze application and system logs during development and testing. (4 tools)
+
+- `start-device-log-cap` - Start device log capture.
+- `start-sim-log-cap` - Start sim log capture.
+- `stop-device-log-cap` - Stop device app and return logs.
+- `stop-sim-log-cap` - Stop sim app and return logs.
+
+
+
+### macOS Development (`macos`)
+**Purpose**: Complete macOS development workflow for both .xcodeproj and .xcworkspace files. Build, test, deploy, and manage macOS applications. (11 tools)
+
+- `build-macos` - Build macOS app.
+- `build-run-macos` - Build and run macOS app.
+- `clean` - Defined in Project Utilities workflow.
+- `discover-projs` - Defined in Project Discovery workflow.
+- `get-mac-app-path` - Get macOS built app path.
+- `get-mac-bundle-id` - Defined in Project Discovery workflow.
+- `launch-mac-app` - Launch macOS app.
+- `list-schemes` - Defined in Project Discovery workflow.
+- `show-build-settings` - Defined in Project Discovery workflow.
+- `stop-mac-app` - Stop macOS app.
+- `test-macos` - Test macOS target.
+
+
+
+### Project Discovery (`project-discovery`)
+**Purpose**: Discover and examine Xcode projects, workspaces, and Swift packages. Analyze project structure, schemes, build settings, and bundle information. (5 tools)
+
+- `discover-projs` - Scans a directory (defaults to workspace root) to find Xcode project (.xcodeproj) and workspace (.xcworkspace) files.
+- `get-app-bundle-id` - Extract bundle id from .app.
+- `get-mac-bundle-id` - Extract bundle id from macOS .app.
+- `list-schemes` - List Xcode schemes.
+- `show-build-settings` - Show build settings.
+
+
+
+### Project Scaffolding (`project-scaffolding`)
+**Purpose**: Tools for creating new iOS and macOS projects from templates. Bootstrap new applications with best practices, standard configurations, and modern project structures. (2 tools)
+
+- `scaffold-ios-project` - Scaffold iOS project.
+- `scaffold-macos-project` - Scaffold macOS project.
+
+
+
+### Project Utilities (`utilities`)
+**Purpose**: Essential project maintenance utilities for cleaning and managing existing projects. Provides clean operations for both .xcodeproj and .xcworkspace files. (1 tools)
+
+- `clean` - Clean build products.
+
+
+
+### Simulator Debugging (`debugging`)
+**Purpose**: Interactive iOS Simulator debugging tools: attach LLDB, manage breakpoints, inspect stack/variables, and run LLDB commands. (8 tools)
+
+- `debug-attach-sim` - Attach LLDB to sim app.
+- `debug-breakpoint-add` - Add breakpoint.
+- `debug-breakpoint-remove` - Remove breakpoint.
+- `debug-continue` - Continue debug session.
+- `debug-detach` - Detach debugger.
+- `debug-lldb-command` - Run LLDB command.
+- `debug-stack` - Get backtrace.
+- `debug-variables` - Get frame variables.
+
+
+
+### Simulator Management (`simulator-management`)
+**Purpose**: Tools for managing simulators from booting, opening simulators, listing simulators, stopping simulators, erasing simulator content and settings, and setting simulator environment options like location, network, statusbar and appearance. (8 tools)
+
+- `boot-sim` - Defined in iOS Simulator Development workflow.
+- `erase-sims` - Erase simulator.
+- `list-sims` - Defined in iOS Simulator Development workflow.
+- `open-sim` - Defined in iOS Simulator Development workflow.
+- `reset-sim-location` - Reset sim location.
+- `set-sim-appearance` - Set sim appearance.
+- `set-sim-location` - Set sim location.
+- `sim-statusbar` - Set sim status bar network.
+
+
+
+### Swift Package Manager (`swift-package`)
+**Purpose**: Swift Package Manager operations for building, testing, running, and managing Swift packages and dependencies. Complete SPM workflow support. (6 tools)
+
+- `swift-package-build` - swift package target build.
+- `swift-package-clean` - swift package clean.
+- `swift-package-list` - List SwiftPM processes.
+- `swift-package-run` - swift package target run.
+- `swift-package-stop` - Stop SwiftPM run.
+- `swift-package-test` - Run swift package target tests.
+
+
+
+### System Doctor (`doctor`)
+**Purpose**: Debug tools and system doctor for troubleshooting XcodeBuildMCP server, development environment, and tool availability. (1 tools)
+
+- `doctor` - MCP environment info.
+
+
+
+### UI Automation (`ui-automation`)
+**Purpose**: UI automation and accessibility testing tools for iOS simulators. Perform gestures, interactions, screenshots, and UI analysis for automated testing workflows. (11 tools)
+
+- `button` - Press simulator hardware button.
+- `gesture` - Simulator gesture preset.
+- `key-press` - Press key by keycode.
+- `key-sequence` - Press a sequence of keys by their keycodes.
+- `long-press` - Long press at coords.
+- `screenshot` - Capture screenshot.
+- `snapshot-ui` - Print view hierarchy with precise view coordinates (x, y, width, height) for visible elements.
+- `swipe` - Swipe between points.
+- `tap` - Tap coordinate or element.
+- `touch` - Touch down/up at coords.
+- `type-text` - Type text.
+
+
+
+## Summary Statistics
+
+- **Canonical Tools**: 68
+- **Total Tools**: 91
+- **Workflow Groups**: 12
+
+---
+
+*This documentation is automatically generated by `scripts/update-tools-docs.ts` from the tools manifest. Last updated: 2026-02-03T12:43:04.479Z UTC*
diff --git a/docs/TOOLS.md b/docs/TOOLS.md
index 8d187c5d..e979dc14 100644
--- a/docs/TOOLS.md
+++ b/docs/TOOLS.md
@@ -1,34 +1,55 @@
-# XcodeBuildMCP Tools Reference
+# XcodeBuildMCP MCP Tools Reference
-XcodeBuildMCP provides 72 tools organized into 14 workflow groups for comprehensive Apple development workflows.
+This document lists MCP tool names as exposed to MCP clients. XcodeBuildMCP provides 72 canonical tools organized into 14 workflow groups for comprehensive Apple development workflows.
## Workflow Groups
### iOS Device Development (`device`)
-**Purpose**: Complete iOS development workflow for both .xcodeproj and .xcworkspace files targeting physical devices (iPhone, iPad, Apple Watch, Apple TV, Apple Vision Pro). Build, test, deploy, and debug apps on real hardware. (7 tools)
+**Purpose**: Complete iOS development workflow for both .xcodeproj and .xcworkspace files targeting physical devices (iPhone, iPad, Apple Watch, Apple TV, Apple Vision Pro). Build, test, deploy, and debug apps on real hardware. (14 tools)
- `build_device` - Build for device.
+- `clean` - Defined in Project Utilities workflow.
+- `discover_projs` - Defined in Project Discovery workflow.
+- `get_app_bundle_id` - Defined in Project Discovery workflow.
- `get_device_app_path` - Get device built app path.
- `install_app_device` - Install app on device.
- `launch_app_device` - Launch app on device.
- `list_devices` - List connected devices.
+- `list_schemes` - Defined in Project Discovery workflow.
+- `show_build_settings` - Defined in Project Discovery workflow.
+- `start_device_log_cap` - Defined in Log Capture & Management workflow.
- `stop_app_device` - Stop device app.
+- `stop_device_log_cap` - Defined in Log Capture & Management workflow.
- `test_device` - Test on device.
+
+
+
### iOS Simulator Development (`simulator`)
-**Purpose**: Complete iOS development workflow for both .xcodeproj and .xcworkspace files targeting simulators. Build, test, deploy, and interact with iOS apps on simulators. (12 tools)
+**Purpose**: Complete iOS development workflow for both .xcodeproj and .xcworkspace files targeting simulators. Build, test, deploy, and interact with iOS apps on simulators. (20 tools)
- `boot_sim` - Boot iOS simulator.
- `build_run_sim` - Build and run iOS sim.
- `build_sim` - Build for iOS sim.
+- `clean` - Defined in Project Utilities workflow.
+- `discover_projs` - Defined in Project Discovery workflow.
+- `get_app_bundle_id` - Defined in Project Discovery workflow.
- `get_sim_app_path` - Get sim built app path.
- `install_app_sim` - Install app on sim.
- `launch_app_logs_sim` - Launch sim app with logs.
- `launch_app_sim` - Launch app on simulator.
+- `list_schemes` - Defined in Project Discovery workflow.
- `list_sims` - List iOS simulators.
- `open_sim` - Open Simulator app.
- `record_sim_video` - Record sim video.
+- `screenshot` - Defined in UI Automation workflow.
+- `show_build_settings` - Defined in Project Discovery workflow.
+- `snapshot_ui` - Defined in UI Automation workflow.
- `stop_app_sim` - Stop sim app.
+- `stop_sim_log_cap` - Defined in Log Capture & Management workflow.
- `test_sim` - Test on iOS sim.
+
+
+
### Log Capture & Management (`logging`)
**Purpose**: Log capture and management tools for iOS simulators and physical devices. Start, stop, and analyze application and system logs during development and testing. (4 tools)
@@ -36,15 +57,26 @@ XcodeBuildMCP provides 72 tools organized into 14 workflow groups for comprehens
- `start_sim_log_cap` - Start sim log capture.
- `stop_device_log_cap` - Stop device app and return logs.
- `stop_sim_log_cap` - Stop sim app and return logs.
+
+
+
### macOS Development (`macos`)
-**Purpose**: Complete macOS development workflow for both .xcodeproj and .xcworkspace files. Build, test, deploy, and manage macOS applications. (6 tools)
+**Purpose**: Complete macOS development workflow for both .xcodeproj and .xcworkspace files. Build, test, deploy, and manage macOS applications. (11 tools)
- `build_macos` - Build macOS app.
- `build_run_macos` - Build and run macOS app.
+- `clean` - Defined in Project Utilities workflow.
+- `discover_projs` - Defined in Project Discovery workflow.
- `get_mac_app_path` - Get macOS built app path.
+- `get_mac_bundle_id` - Defined in Project Discovery workflow.
- `launch_mac_app` - Launch macOS app.
+- `list_schemes` - Defined in Project Discovery workflow.
+- `show_build_settings` - Defined in Project Discovery workflow.
- `stop_mac_app` - Stop macOS app.
- `test_macos` - Test macOS target.
+
+
+
### Project Discovery (`project-discovery`)
**Purpose**: Discover and examine Xcode projects, workspaces, and Swift packages. Analyze project structure, schemes, build settings, and bundle information. (5 tools)
@@ -53,21 +85,33 @@ XcodeBuildMCP provides 72 tools organized into 14 workflow groups for comprehens
- `get_mac_bundle_id` - Extract bundle id from macOS .app.
- `list_schemes` - List Xcode schemes.
- `show_build_settings` - Show build settings.
+
+
+
### Project Scaffolding (`project-scaffolding`)
**Purpose**: Tools for creating new iOS and macOS projects from templates. Bootstrap new applications with best practices, standard configurations, and modern project structures. (2 tools)
- `scaffold_ios_project` - Scaffold iOS project.
- `scaffold_macos_project` - Scaffold macOS project.
+
+
+
### Project Utilities (`utilities`)
**Purpose**: Essential project maintenance utilities for cleaning and managing existing projects. Provides clean operations for both .xcodeproj and .xcworkspace files. (1 tools)
- `clean` - Clean build products.
+
+
+
### session-management (`session-management`)
**Purpose**: Manage session defaults for project/workspace paths, scheme, configuration, simulatorName/simulatorId, deviceId, useLatestOS, arch, suppressWarnings, derivedDataPath, preferXcodebuild, platform, and bundleId. Defaults can be seeded from .xcodebuildmcp/config.yaml at startup. (3 tools)
- `session_clear_defaults` - Clear session defaults.
- `session_set_defaults` - Set the session defaults, should be called at least once to set tool defaults.
- `session_show_defaults` - Show session defaults.
+
+
+
### Simulator Debugging (`debugging`)
**Purpose**: Interactive iOS Simulator debugging tools: attach LLDB, manage breakpoints, inspect stack/variables, and run LLDB commands. (8 tools)
@@ -79,14 +123,23 @@ XcodeBuildMCP provides 72 tools organized into 14 workflow groups for comprehens
- `debug_lldb_command` - Run LLDB command.
- `debug_stack` - Get backtrace.
- `debug_variables` - Get frame variables.
+
+
+
### Simulator Management (`simulator-management`)
-**Purpose**: Tools for managing simulators from booting, opening simulators, listing simulators, stopping simulators, erasing simulator content and settings, and setting simulator environment options like location, network, statusbar and appearance. (5 tools)
+**Purpose**: Tools for managing simulators from booting, opening simulators, listing simulators, stopping simulators, erasing simulator content and settings, and setting simulator environment options like location, network, statusbar and appearance. (8 tools)
+- `boot_sim` - Defined in iOS Simulator Development workflow.
- `erase_sims` - Erase simulator.
+- `list_sims` - Defined in iOS Simulator Development workflow.
+- `open_sim` - Defined in iOS Simulator Development workflow.
- `reset_sim_location` - Reset sim location.
- `set_sim_appearance` - Set sim appearance.
- `set_sim_location` - Set sim location.
- `sim_statusbar` - Set sim status bar network.
+
+
+
### Swift Package Manager (`swift-package`)
**Purpose**: Swift Package Manager operations for building, testing, running, and managing Swift packages and dependencies. Complete SPM workflow support. (6 tools)
@@ -96,10 +149,16 @@ XcodeBuildMCP provides 72 tools organized into 14 workflow groups for comprehens
- `swift_package_run` - swift package target run.
- `swift_package_stop` - Stop SwiftPM run.
- `swift_package_test` - Run swift package target tests.
+
+
+
### System Doctor (`doctor`)
**Purpose**: Debug tools and system doctor for troubleshooting XcodeBuildMCP server, development environment, and tool availability. (1 tools)
- `doctor` - MCP environment info.
+
+
+
### UI Automation (`ui-automation`)
**Purpose**: UI automation and accessibility testing tools for iOS simulators. Perform gestures, interactions, screenshots, and UI analysis for automated testing workflows. (11 tools)
@@ -114,16 +173,22 @@ XcodeBuildMCP provides 72 tools organized into 14 workflow groups for comprehens
- `tap` - Tap coordinate or element.
- `touch` - Touch down/up at coords.
- `type_text` - Type text.
-### workflow-discovery (`workflow-discovery`)
-**Purpose**: workflow-discovery related tools (1 tools)
+
+
+
+### Workflow Discovery (`workflow-discovery`)
+**Purpose**: Manage the workflows that are enabled and disabled. (1 tools)
- `manage_workflows` - Workflows are groups of tools exposed by XcodeBuildMCP. By default, not all workflows (and therefore tools) are enabled; only simulator tools are enabled by default. Some workflows are mandatory and can't be disabled. Available workflows: ${availableWorkflows}
+
+
## Summary Statistics
-- **Total Tools**: 72 canonical tools + 22 re-exports = 94 total
+- **Canonical Tools**: 72
+- **Total Tools**: 95
- **Workflow Groups**: 14
---
-*This documentation is automatically generated by `scripts/update-tools-docs.ts` using static analysis. Last updated: 2026-02-02*
+*This documentation is automatically generated by `scripts/update-tools-docs.ts` from the tools manifest. Last updated: 2026-02-03T12:43:04.479Z UTC*
diff --git a/package.json b/package.json
index b957435b..cb0fc662 100644
--- a/package.json
+++ b/package.json
@@ -17,10 +17,11 @@
"scripts": {
"build": "npm run build:tsup && npx smithery build --transport stdio",
"dev": "npm run generate:version && npm run generate:loaders && npx smithery dev",
- "build:tsup": "npm run generate:version && npm run generate:loaders && tsup",
+ "build:tsup": "npm run generate:version && npm run generate:loaders && tsup && npm run generate:tools-manifest",
"dev:tsup": "npm run build:tsup && tsup --watch",
"generate:version": "npx tsx scripts/generate-version.ts",
"generate:loaders": "npx tsx scripts/generate-loaders.ts",
+ "generate:tools-manifest": "npx tsx scripts/generate-tools-manifest.ts",
"bundle:axe": "scripts/bundle-axe.sh",
"lint": "eslint 'src/**/*.{js,ts}'",
"lint:fix": "eslint 'src/**/*.{js,ts}' --fix",
diff --git a/scripts/analysis/tools-analysis.ts b/scripts/analysis/tools-analysis.ts
index 0ee43f53..036d5ad3 100644
--- a/scripts/analysis/tools-analysis.ts
+++ b/scripts/analysis/tools-analysis.ts
@@ -42,6 +42,9 @@ export interface ToolInfo {
path: string;
relativePath: string;
description: string;
+ cliName?: string;
+ originWorkflow?: string;
+ stateful?: boolean;
isCanonical: boolean;
}
@@ -68,11 +71,72 @@ export interface StaticAnalysisResult {
stats: AnalysisStats;
}
+type ExtractStringOptions = {
+ allowFallback: boolean;
+};
+
+function extractStringValue(
+ sourceFile: SourceFile,
+ node: Node,
+ options: ExtractStringOptions = { allowFallback: false },
+): string | null {
+ if (isStringLiteral(node)) {
+ return node.text;
+ }
+
+ if (isTemplateExpression(node) || isNoSubstitutionTemplateLiteral(node)) {
+ let text = node.getFullText(sourceFile).trim();
+ if (text.startsWith('`') && text.endsWith('`')) {
+ text = text.slice(1, -1);
+ }
+ return text;
+ }
+
+ if (!options.allowFallback) {
+ return null;
+ }
+
+ const fullText = node.getFullText(sourceFile).trim();
+ let cleaned = fullText;
+ if (
+ (cleaned.startsWith('"') && cleaned.endsWith('"')) ||
+ (cleaned.startsWith("'") && cleaned.endsWith("'"))
+ ) {
+ cleaned = cleaned.slice(1, -1);
+ }
+ return cleaned.replace(/\s+/g, ' ').trim();
+}
+
+function extractBooleanValue(node: Node): boolean | null {
+ if (node.kind === SyntaxKind.TrueKeyword) {
+ return true;
+ }
+ if (node.kind === SyntaxKind.FalseKeyword) {
+ return false;
+ }
+ return null;
+}
+
+function getCodeLines(content: string): string[] {
+ const contentWithoutBlockComments = content.replace(/\/\*[\s\S]*?\*\//g, '');
+
+ return contentWithoutBlockComments
+ .split('\n')
+ .map((line) => line.split('//')[0].trim())
+ .filter((line) => line.length > 0);
+}
+
/**
* Extract the description from a tool's default export using TypeScript AST
*/
-function extractToolDescription(sourceFile: SourceFile): string {
+function extractToolMetadata(sourceFile: SourceFile): {
+ description: string;
+ cliName?: string;
+ stateful?: boolean;
+} {
let description: string | null = null;
+ let cliName: string | null = null;
+ let stateful: boolean | null = null;
function visit(node: Node): void {
let objectExpression: ObjectLiteralExpression | null = null;
@@ -86,43 +150,36 @@ function extractToolDescription(sourceFile: SourceFile): string {
}
if (objectExpression) {
- // Found export default { ... }, now look for description property
+ // Found export default { ... }, now look for description and CLI metadata
for (const property of objectExpression.properties) {
- if (
- isPropertyAssignment(property) &&
- isIdentifier(property.name) &&
- property.name.text === 'description'
- ) {
- // Extract the description value
- if (isStringLiteral(property.initializer)) {
- // This is the most common case - simple string literal
- description = property.initializer.text;
- } else if (
- isTemplateExpression(property.initializer) ||
- isNoSubstitutionTemplateLiteral(property.initializer)
- ) {
- // Handle template literals - get the raw text and clean it
- description = property.initializer.getFullText(sourceFile).trim();
- // Remove surrounding backticks
- if (description.startsWith('`') && description.endsWith('`')) {
- description = description.slice(1, -1);
+ if (!isPropertyAssignment(property) || !isIdentifier(property.name)) {
+ continue;
+ }
+
+ if (property.name.text === 'description') {
+ description = extractStringValue(sourceFile, property.initializer, {
+ allowFallback: true,
+ });
+ continue;
+ }
+
+ if (property.name.text === 'cli' && isObjectLiteralExpression(property.initializer)) {
+ for (const cliProperty of property.initializer.properties) {
+ if (!isPropertyAssignment(cliProperty) || !isIdentifier(cliProperty.name)) {
+ continue;
}
- } else {
- // Handle any other expression (multiline strings, computed values)
- const fullText = property.initializer.getFullText(sourceFile).trim();
- // This covers cases where the description spans multiple lines
- // Remove surrounding quotes and normalize whitespace
- let cleaned = fullText;
- if (
- (cleaned.startsWith('"') && cleaned.endsWith('"')) ||
- (cleaned.startsWith("'") && cleaned.endsWith("'"))
- ) {
- cleaned = cleaned.slice(1, -1);
+
+ if (cliProperty.name.text === 'name') {
+ cliName = extractStringValue(sourceFile, cliProperty.initializer, {
+ allowFallback: true,
+ });
+ continue;
+ }
+
+ if (cliProperty.name.text === 'stateful') {
+ stateful = extractBooleanValue(cliProperty.initializer);
}
- // Collapse multiple whitespaces and newlines into single spaces
- description = cleaned.replace(/\s+/g, ' ').trim();
}
- return; // Found description, stop looking
}
}
}
@@ -136,7 +193,11 @@ function extractToolDescription(sourceFile: SourceFile): string {
throw new Error('Could not extract description from tool export default object');
}
- return description;
+ return {
+ description,
+ cliName: cliName ?? undefined,
+ stateful: stateful ?? undefined,
+ };
}
/**
@@ -144,19 +205,7 @@ function extractToolDescription(sourceFile: SourceFile): string {
*/
function isReExportFile(filePath: string): boolean {
const content = fs.readFileSync(filePath, 'utf-8');
-
- // Remove comments and empty lines, then check for re-export pattern
- // First remove multi-line comments
- const contentWithoutBlockComments = content.replace(/\/\*[\s\S]*?\*\//g, '');
-
- const cleanedLines = contentWithoutBlockComments
- .split('\n')
- .map((line) => {
- // Remove inline comments but preserve the code before them
- const codeBeforeComment = line.split('//')[0].trim();
- return codeBeforeComment;
- })
- .filter((line) => line.length > 0);
+ const cleanedLines = getCodeLines(content);
// Should have exactly one line: export { default } from '...';
if (cleanedLines.length !== 1) {
@@ -167,6 +216,42 @@ function isReExportFile(filePath: string): boolean {
return /^export\s*{\s*default\s*}\s*from\s*['"][^'"]+['"];?\s*$/.test(exportLine);
}
+function getReExportTargetInfo(filePath: string): { filePath: string; workflow: string } | null {
+ const content = fs.readFileSync(filePath, 'utf-8');
+ const cleanedLines = getCodeLines(content);
+
+ if (cleanedLines.length !== 1) {
+ return null;
+ }
+
+ const match = cleanedLines[0].match(/export\s*{\s*default\s*}\s*from\s*['"]([^'"]+)['"];?\s*$/);
+ if (!match) {
+ return null;
+ }
+
+ let targetFilePath = path.resolve(path.dirname(filePath), match[1]);
+ if (!path.extname(targetFilePath)) {
+ targetFilePath += '.ts';
+ }
+
+ if (!targetFilePath.startsWith(toolsDir)) {
+ throw new Error(
+ `Re-export target for ${path.relative(projectRoot, filePath)} is outside tools directory: ${targetFilePath}`,
+ );
+ }
+
+ if (!fs.existsSync(targetFilePath)) {
+ throw new Error(
+ `Re-export target for ${path.relative(projectRoot, filePath)} does not exist: ${targetFilePath}`,
+ );
+ }
+
+ return {
+ filePath: targetFilePath,
+ workflow: path.basename(path.dirname(targetFilePath)),
+ };
+}
+
/**
* Get workflow metadata from index.ts file if it exists
*/
@@ -204,13 +289,16 @@ async function getWorkflowMetadata(
if (isPropertyAssignment(property) && isIdentifier(property.name)) {
const propertyName = property.name.text;
- if (propertyName === 'name' && isStringLiteral(property.initializer)) {
- workflowExport.name = property.initializer.text;
- } else if (
- propertyName === 'description' &&
- isStringLiteral(property.initializer)
- ) {
- workflowExport.description = property.initializer.text;
+ if (propertyName === 'name') {
+ const value = extractStringValue(sourceFile, property.initializer);
+ if (value) {
+ workflowExport.name = value;
+ }
+ } else if (propertyName === 'description') {
+ const value = extractStringValue(sourceFile, property.initializer);
+ if (value) {
+ workflowExport.description = value;
+ }
}
}
}
@@ -327,6 +415,9 @@ export async function getStaticToolAnalysis(): Promise {
const isReExport = isReExportFile(filePath);
let description = '';
+ let cliName: string | undefined;
+ let originWorkflow: string | undefined;
+ let stateful: boolean | undefined;
if (!isReExport) {
// Extract description from canonical tool using AST
@@ -334,13 +425,38 @@ export async function getStaticToolAnalysis(): Promise {
const content = fs.readFileSync(filePath, 'utf-8');
const sourceFile = createSourceFile(filePath, content, ScriptTarget.Latest, true);
- description = extractToolDescription(sourceFile);
+ const metadata = extractToolMetadata(sourceFile);
+ description = metadata.description;
+ cliName = metadata.cliName;
+ stateful = metadata.stateful;
canonicalCount++;
} catch (error) {
throw new Error(`Failed to extract description from ${relativePath}: ${error}`);
}
} else {
- description = '(Re-exported from shared workflow)';
+ const reExportInfo = getReExportTargetInfo(filePath);
+ if (!reExportInfo) {
+ throw new Error(`Failed to resolve re-export target for ${relativePath}`);
+ }
+
+ originWorkflow = reExportInfo.workflow;
+ try {
+ const targetContent = fs.readFileSync(reExportInfo.filePath, 'utf-8');
+ const targetSourceFile = createSourceFile(
+ reExportInfo.filePath,
+ targetContent,
+ ScriptTarget.Latest,
+ true,
+ );
+ const metadata = extractToolMetadata(targetSourceFile);
+ description = metadata.description;
+ cliName = metadata.cliName;
+ stateful = metadata.stateful;
+ } catch (error) {
+ throw new Error(
+ `Failed to extract description for re-export ${relativePath}: ${error as Error}`,
+ );
+ }
reExportCount++;
}
@@ -350,6 +466,9 @@ export async function getStaticToolAnalysis(): Promise {
path: filePath,
relativePath,
description,
+ cliName,
+ originWorkflow,
+ stateful,
isCanonical: !isReExport,
};
@@ -399,32 +518,6 @@ export async function getStaticToolAnalysis(): Promise {
};
}
-/**
- * Get only canonical tools (excluding re-exports) for documentation generation
- */
-export async function getCanonicalTools(): Promise {
- const analysis = await getStaticToolAnalysis();
- return analysis.tools.filter((tool) => tool.isCanonical);
-}
-
-/**
- * Get tools grouped by workflow for documentation generation
- */
-export async function getToolsByWorkflow(): Promise