
Axiom Xcode Mcp
- 888 installs
- 1.1k repo stars
- Updated August 3, 2026
- charleswiltgen/axiom
axiom-xcode-mcp is a Mobile Development skill that connects Claude, Cursor, or Codex to Xcode via the official MCP bridge for developers who need reliable access to 20 IDE tools without connection or permission failures.
About
axiom-xcode-mcp is the charleswiltgen/axiom skill suite for Xcode MCP setup, tool reference, workflow patterns, and troubleshooting. Xcode 26.3 ships an MCP server accessible through xcrun mcpbridge, exposing 20 IDE tools—including XcodeRead, BuildProject, RunTests, and RenderPreview—to external AI clients. The skill mandates use for any Xcode MCP interaction: first-time setup, mcpbridge configuration, tool invocation, and fixing permission or connection errors. Developers reach for axiom-xcode-mcp when automating iOS builds from Cursor, running XCTest via agent, or rendering SwiftUI previews without manual Xcode clicking. MIT-licensed guidance covers workflow patterns that prevent the common MCP handshake and entitlement headaches.
- Mandatory routing logic that directs every Xcode MCP request to the correct specialized skill
- Covers first-time setup, xcrun mcpbridge configuration, and client-specific settings for Claude Code, Cursor, Codex, VS
- Includes workflow patterns such as BuildFix loop and TestFix loop when using MCP tools
- Handles troubleshooting for connection refused, no windows, permission dialogs, multi-Xcode targeting and schema complia
- Guarantees you use the right skill for any of the 20 Xcode MCP tools including file ops, build, test and preview
Axiom Xcode Mcp by the numbers
- 888 all-time installs (skills.sh)
- +33 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #1,241 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/charleswiltgen/axiom --skill axiom-xcode-mcpAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 888 |
|---|---|
| repo stars | ★ 1.1k |
| Security audit | 3 / 3 scanners passed |
| Last updated | August 3, 2026 |
| Repository | charleswiltgen/axiom ↗ |
How do you connect AI agents to Xcode MCP?
Reliably connect Claude, Cursor or Codex to Xcode via the official MCP bridge and use its 20 IDE tools without connection or permission headaches.
Who is it for?
iOS and macOS developers using Claude, Cursor, or Codex who need documented setup and workflows for Xcode 26.3's 20-tool MCP server.
Skip if: Android Studio or cross-platform Flutter workflows without Xcode, or teams not running Xcode 26.3 with mcpbridge support.
When should I use this skill?
The user mentions Xcode MCP, xcrun mcpbridge, XcodeRead, BuildProject, RunTests, RenderPreview, or Xcode connection errors from an AI client.
What you get
Working mcpbridge configuration, successful Xcode MCP tool calls, build and test results, and SwiftUI preview renders from the agent client.
- MCP bridge configuration
- Build and test automation
By the numbers
- Xcode 26.3 ships the official MCP server
- Exposes 20 IDE tools via xcrun mcpbridge
Files
Xcode MCP
You MUST use this skill for ANY Xcode MCP interaction — setup, tool usage, workflow patterns, or troubleshooting.
Xcode ships an MCP server (xcrun mcpbridge, available since Xcode 26.3) that exposes 20 IDE tools to external AI clients. Xcode 27 adds an explicit "Allow external agents to use Xcode tools" gate, the run-agent launch path, and an agent-extension model (custom MCP servers, skills, plug-ins). This skill suite covers setup, tool reference, workflow patterns, and troubleshooting.
When to Use
Use this skill when:
- Setting up Xcode MCP for the first time
- Configuring
xcrun mcpbridgefor any MCP client - Using any Xcode MCP tool (file ops, build, test, preview)
- Building, testing, or previewing via MCP tools
- Troubleshooting mcpbridge connection issues
- Window/tab targeting questions
- Permission dialog confusion
Routing Logic
1. Setup/Connection → xcode-mcp-setup
Triggers:
- First-time Xcode MCP setup
- Client-specific config (Claude Code, Cursor, Codex, VS Code, Gemini CLI)
- Connection errors ("Connection refused", "No windows")
- Permission dialog confusion
- Multi-Xcode targeting (
MCP_XCODE_PID) - Schema compliance issues with strict clients
- Giving external agents access to Xcode (Intelligence settings gate)
- Launching an agent via Xcode config (
xcrun mcpbridge run-agent) - Exporting Xcode's skill bundles (
run-agent skills export) - Extending Xcode's agent (per-agent config files, MCP servers, plug-ins)
Read: skills/xcode-mcp-setup.md
---
2. Using Tools & Workflows → xcode-mcp-tools
Triggers:
- How to build/test/preview via MCP
- Workflow patterns (BuildFix loop, TestFix loop)
- Tool gotchas and anti-patterns
- Window/tab targeting strategy
- When to use MCP tools vs CLI (
xcodebuild) - Destructive operation safety (
XcodeRM,XcodeMV)
Read: skills/xcode-mcp-tools.md
---
3. Tool API Reference → xcode-mcp-ref
Triggers:
- Specific tool parameters and schemas
- Input/output format for a tool
- "How does XcodeGrep work?"
- "What params does BuildProject take?"
- Tool category listing
Read: skills/xcode-mcp-ref.md
---
Decision Tree
digraph xcode_mcp_router {
rankdir=TB;
"User has Xcode MCP question" [shape=ellipse];
"Setup or connection?" [shape=diamond];
"Using tools or workflows?" [shape=diamond];
"Need specific tool params?" [shape=diamond];
"xcode-mcp-setup" [shape=box];
"xcode-mcp-tools" [shape=box];
"xcode-mcp-ref" [shape=box];
"User has Xcode MCP question" -> "Setup or connection?";
"Setup or connection?" -> "xcode-mcp-setup" [label="yes"];
"Setup or connection?" -> "Using tools or workflows?" [label="no"];
"Using tools or workflows?" -> "xcode-mcp-tools" [label="yes"];
"Using tools or workflows?" -> "Need specific tool params?" [label="no"];
"Need specific tool params?" -> "xcode-mcp-ref" [label="yes"];
"Need specific tool params?" -> "xcode-mcp-tools" [label="general question"];
}Anti-Rationalization
| Thought | Reality |
|---|---|
| "I'll just use xcodebuild directly" | MCP gives IDE state, diagnostics, previews, and navigator issues that CLI doesn't expose |
| "I already know how to set up MCP" | Client configs differ. Permission dialog behavior is specific. Check setup skill. |
| "I can figure out the tool params" | Tool schemas have required fields and gotchas. Check ref skill. |
| "Tab identifiers are obvious" | Most tools fail silently without correct tabIdentifier. Tools skill explains targeting. |
| "This is just file reading, I'll use Read tool" | XcodeRead sees Xcode's project view including generated files and resolved packages |
Conflict Resolution (vs Other Routers)
| Domain | Owner | Why |
|---|---|---|
| MCP-specific interaction (mcpbridge, MCP tools, tab identifiers) | xcode-mcp | MCP protocol and tool-specific |
| Xcode environment (Derived Data, zombie processes, simulators) | axiom-build | Environment diagnostics, not MCP |
| Apple's bundled documentation (for-LLM guides/diagnostics) | apple-docs | Bundled docs, not MCP tool |
DocumentationSearch MCP tool usage specifically | xcode-mcp | MCP tool invocation |
| Build failures diagnosed via CLI | axiom-build | Traditional build debugging |
| Build failures diagnosed via MCP tools | xcode-mcp | MCP workflow patterns |
Example Invocations
User: "How do I set up Xcode MCP with Claude Code?" -> Read: skills/xcode-mcp-setup.md
User: "How do I build my project using MCP tools?" -> Read: skills/xcode-mcp-tools.md
User: "What parameters does BuildProject take?" -> Read: skills/xcode-mcp-ref.md
User: "My mcpbridge connection keeps failing" -> Read: skills/xcode-mcp-setup.md
User: "How do I target a specific Xcode window?" -> Read: skills/xcode-mcp-tools.md
User: "Can I render SwiftUI previews via MCP?" -> Read: skills/xcode-mcp-tools.md (workflow), then skills/xcode-mcp-ref.md (params)
User: "Cursor can't parse Xcode's MCP responses" -> Read: skills/xcode-mcp-setup.md (schema compliance section)
Resources
References: skills/xcode-mcp-setup.md, skills/xcode-mcp-tools.md, skills/xcode-mcp-ref.md, skills/axe-ref.md
AXe Reference (iOS Simulator UI Automation)
AXe is a CLI tool for interacting with iOS Simulators using Apple's Accessibility APIs and HID functionality. Single binary, no daemon required.
Installation
brew install cameroncooke/axe/axe
# Verify installation
axe --versionCritical Best Practice: describe_ui First
ALWAYS run `describe_ui` before UI interactions. Never guess coordinates from screenshots.
Best practice: Use describe-ui to get precise element coordinates prior to using x/y parameters (don't guess from screenshots).
# 1. FIRST: Get the UI tree with frame coordinates
axe describe-ui --udid $UDID
# 2. THEN: Tap by accessibility ID (preferred)
axe tap --id "loginButton" --udid $UDID
# 3. OR: Tap by label
axe tap --label "Login" --udid $UDID
# 4. LAST RESORT: Tap by coordinates from describe-ui output
axe tap -x 200 -y 400 --udid $UDIDPriority order for targeting elements: 1. --id (accessibilityIdentifier) - most stable 2. --label (accessibility label) - stable but may change with localization 3. -x -y coordinates from describe-ui - fragile, use only when no identifier
Core Concept: Accessibility-First
AXe's key advantage: Tap elements by accessibility identifier or label, not just coordinates.
# Coordinate-based (fragile - breaks with layout changes)
axe tap -x 200 -y 400 --udid $UDID
# Accessibility-based (stable - survives UI changes)
axe tap --id "loginButton" --udid $UDID
axe tap --label "Login" --udid $UDIDAlways prefer `--id` or `--label` over coordinates.
Getting the Simulator UDID
AXe requires the simulator UDID for most commands:
# Get booted simulator UDID
UDID=$(xcrun simctl list devices -j | jq -r '.devices | to_entries[] | .value[] | select(.state == "Booted") | .udid' | head -1)
# List all simulators
axe list-simulatorsTouch & Tap Commands
Tap by Accessibility Identifier (Recommended)
# Tap element with accessibilityIdentifier
axe tap --id "loginButton" --udid $UDID
# Tap element with accessibility label
axe tap --label "Submit" --udid $UDIDTap by Coordinates
# Basic tap
axe tap -x 200 -y 400 --udid $UDID
# Tap with timing controls
axe tap -x 200 -y 400 --pre-delay 0.5 --post-delay 0.3 --udid $UDID
# Long press: use touch with --down --up --delay (tap has no hold option)
axe touch -x 200 -y 400 --down --up --delay 1.0 --udid $UDIDLow-Level Touch Events
# Touch down (finger press)
axe touch -x 200 -y 400 --down --udid $UDID
# Touch up (finger release)
axe touch -x 200 -y 400 --up --udid $UDID
# Both in one call (tap)
axe touch -x 200 -y 400 --down --up --udid $UDID
# Long press (hold duration in seconds)
axe touch -x 200 -y 400 --down --up --delay 1.0 --udid $UDIDSwipe & Gesture Commands
Custom Swipe
# Swipe from point A to point B
axe swipe --start-x 200 --start-y 600 --end-x 200 --end-y 200 --udid $UDID
# Swipe with duration (slower = more visible)
axe swipe --start-x 200 --start-y 600 --end-x 200 --end-y 200 --duration 0.5 --udid $UDIDGesture Presets
# Scrolling
axe gesture scroll-up --udid $UDID # Scroll content up (swipe down)
axe gesture scroll-down --udid $UDID # Scroll content down (swipe up)
axe gesture scroll-left --udid $UDID
axe gesture scroll-right --udid $UDID
# Edge swipes (navigation)
axe gesture swipe-from-left-edge --udid $UDID # Back navigation
axe gesture swipe-from-right-edge --udid $UDID
axe gesture swipe-from-top-edge --udid $UDID # Notification Center
axe gesture swipe-from-bottom-edge --udid $UDID # Home indicator/Control CenterText Input
Type Text
# Type text (element must be focused)
axe type "user@example.com" --udid $UDID
# Type a longer string
axe type "password123" --udid $UDID
# Type from stdin
echo "Hello World" | axe type --stdin --udid $UDID
# Type from file
axe type --file /tmp/input.txt --udid $UDIDKeyboard Keys
# Press specific key by HID keycode
axe key 40 --udid $UDID # Return/Enter
# Common keycodes:
# 40 = Return/Enter
# 41 = Escape
# 42 = Backspace/Delete
# 43 = Tab
# 44 = Space
# 79 = Right Arrow
# 80 = Left Arrow
# 81 = Down Arrow
# 82 = Up Arrow
# Key sequence with timing (comma-separated keycodes, required --keycodes label)
axe key-sequence --keycodes 40,43,40 --delay 0.2 --udid $UDIDHardware Buttons
# Home button
axe button home --udid $UDID
# Lock/Power button
axe button lock --udid $UDID
# Long press power (shutdown dialog)
axe button lock --duration 3.0 --udid $UDID
# Side button (iPhone X+)
axe button side-button --udid $UDID
# Siri
axe button siri --udid $UDID
# Apple Pay
axe button apple-pay --udid $UDIDScreenshots
# Screenshot to auto-named file
axe screenshot --udid $UDID
# Output: screenshot_2026-01-11_143052.png
# Screenshot to specific file
axe screenshot --output /tmp/my-screenshot.png --udid $UDID
# For piping, write to a file then redirect (no --stdout flag exists)
axe screenshot --output /tmp/shot.png --udid $UDID && cat /tmp/shot.png > screenshot.pngVideo Recording & Streaming
Record Video
# Start recording (Ctrl+C to stop)
axe record-video --output /tmp/recording.mp4 --udid $UDID
# Record with quality settings
axe record-video --output /tmp/recording.mp4 --quality high --udid $UDID
# Record with scale (reduce file size)
axe record-video --output /tmp/recording.mp4 --scale 0.5 --udid $UDIDStream Video
# Stream at 10 FPS (default)
axe stream-video --udid $UDID
# Stream at specific framerate (1-30 FPS)
axe stream-video --fps 30 --udid $UDID
# Stream formats
axe stream-video --format mjpeg --udid $UDID # MJPEG (default)
axe stream-video --format jpeg --udid $UDID # Individual JPEGs
axe stream-video --format ffmpeg --udid $UDID # FFmpeg compatible
axe stream-video --format bgra --udid $UDID # Raw BGRAUI Inspection (describe-ui)
Critical for finding accessibility identifiers and labels.
Full Screen UI Tree
# Get complete accessibility tree
axe describe-ui --udid $UDID
# Output includes:
# - Element type (Button, TextField, StaticText, etc.)
# - Accessibility identifier
# - Accessibility label
# - Frame (position and size)
# - Enabled/disabled statePoint-Specific UI Info
# Get element at specific coordinates
axe describe-ui --point 200,400 --udid $UDIDExample Output
{
"type": "Button",
"identifier": "loginButton",
"label": "Login",
"frame": {"x": 150, "y": 380, "width": 100, "height": 44},
"enabled": true,
"focused": false
}Common Workflows
Login Flow
UDID=$(xcrun simctl list devices -j | jq -r '.devices | to_entries[] | .value[] | select(.state == "Booted") | .udid' | head -1)
# Tap email field and type
axe tap --id "emailTextField" --udid $UDID
axe type "user@example.com" --udid $UDID
# Tap password field and type
axe tap --id "passwordTextField" --udid $UDID
axe type "password123" --udid $UDID
# Tap login button
axe tap --id "loginButton" --udid $UDID
# Wait and screenshot
sleep 2
axe screenshot --output /tmp/login-result.png --udid $UDIDDiscover Elements Before Automating
# 1. Get the UI tree
axe describe-ui --udid $UDID > /tmp/ui-tree.json
# 2. Find elements (search for identifiers)
cat /tmp/ui-tree.json | jq '.[] | select(.identifier != null) | {identifier, label, type}'
# 3. Use discovered identifiers in automation
axe tap --id "discoveredIdentifier" --udid $UDIDScroll to Find Element
# Scroll down until element appears (pseudo-code pattern)
for i in {1..5}; do
if axe describe-ui --udid $UDID | grep -q "targetElement"; then
axe tap --id "targetElement" --udid $UDID
break
fi
axe gesture scroll-down --udid $UDID
sleep 0.5
doneScreenshot on Error
# Automation with error capture
if ! axe tap --id "submitButton" --udid $UDID; then
axe screenshot --output /tmp/error-state.png --udid $UDID
axe describe-ui --udid $UDID > /tmp/error-ui-tree.json
echo "Failed to tap submitButton - see error-state.png"
fiTiming Controls
Most commands support timing options:
| Option | Description |
|---|---|
--pre-delay | Wait before action (seconds, tap) |
--post-delay | Wait after action (seconds, tap) |
--delay | Hold duration between down/up (touch) or between key presses (key-sequence) |
--duration | Button-press duration (button) or swipe duration (swipe) |
# Example with full timing control
axe tap --id "button" --pre-delay 0.5 --post-delay 0.3 --udid $UDIDAXe vs simctl
| Capability | simctl | AXe |
|---|---|---|
| Device lifecycle | ✅ | ❌ |
| Permissions | ✅ | ❌ |
| Push notifications | ✅ | ❌ |
| Status bar | ✅ | ❌ |
| Deep links | ✅ | ❌ |
| Screenshots | ✅ | ✅ (PNG) |
| Video recording | ✅ | ✅ (H.264) |
| Video streaming | ❌ | ✅ |
| UI tap/swipe | ❌ | ✅ |
| Type text | ❌ | ✅ |
| Hardware buttons | ❌ | ✅ |
| Accessibility tree | ❌ | ✅ |
Use both together: simctl for device control, AXe for UI automation.
Troubleshooting
Element Not Found
1. Run axe describe-ui to see available elements 2. Check element has accessibilityIdentifier set in code 3. Ensure element is visible (not off-screen)
Tap Doesn't Work
1. Check element is enabled ("enabled": true in describe-ui) 2. Try adding --pre-delay 0.5 for slow-loading UI 3. Verify correct UDID with axe list-simulators
Type Not Working
1. Ensure text field is focused first: axe tap --id "textField" 2. Check keyboard is visible 3. For unreliable input, split long strings into multiple axe type calls, or use --stdin/--file
Permission Denied
AXe uses private APIs - ensure you're running on a Mac with Xcode installed and proper entitlements.
Resources
GitHub: https://github.com/cameroncooke/AXe
Related: xcsentinel (build orchestration)
Skills: axiom-testing
Agents: simulator-tester, test-runner
Xcode MCP Tool Reference
Complete reference for all 20 tools exposed by Xcode's MCP server (xcrun mcpbridge).
Source: Xcode 26.3 tools/list response. Validated against Keith Smiley's gist (2025-07-15).
Critical: tabIdentifier is required by 18 of 20 tools. Always call XcodeListWindows first.
Discovery
XcodeListWindows
Returns open Xcode windows. Call this first to get tabIdentifier values.
- Parameters: None
- Returns:
{ message: string }— description of open windows - Notes: Only tool that does not require
tabIdentifier.
---
File Operations
XcodeRead
Read file contents (cat -n format, 600 lines default).
- Parameters:
tabIdentifier(string, required)filePath(string, required) — project-relative or absolutelimit(integer, optional) — max lines to returnoffset(integer, optional) — starting line number- Returns:
{ content, filePath, fileSize, linesRead, startLine, totalLines }
XcodeWrite
Create or overwrite a file. Automatically adds new files to the project structure.
- Parameters:
tabIdentifier(string, required)filePath(string, required)content(string, required)- Returns:
{ success, filePath, absolutePath, bytesWritten, linesWritten, wasExistingFile, message }
XcodeUpdate
Edit an existing file with text replacement.
- Parameters:
tabIdentifier(string, required)filePath(string, required)oldString(string, required) — text to findnewString(string, required) — replacement textreplaceAll(boolean, optional, default false) — replace all occurrences- Returns:
{ filePath, editsApplied, success, originalContentLength, modifiedContentLength, message } - Notes: Single replacement by default. Each
oldStringmust be unique unlessreplaceAllis true. Prefer over XcodeWrite for editing existing files.
XcodeGlob
Find files matching a wildcard pattern.
- Parameters:
tabIdentifier(string, required)pattern(string, optional, default**/*) — glob patternpath(string, optional) — directory to search within- Returns:
{ matches[], pattern, searchPath, truncated, totalFound, message }
XcodeGrep
Search file contents with regex.
- Parameters:
tabIdentifier(string, required)pattern(string, required) — regex patternglob(string, optional) — file pattern filterpath(string, optional) — directory scopetype(string, optional) — file type filterignoreCase(boolean, optional)multiline(boolean, optional)outputMode(enum, optional) —content,filesWithMatches,countlinesContext(integer, optional) — context lineslinesBefore(integer, optional)linesAfter(integer, optional)headLimit(integer, optional) — max resultsshowLineNumbers(boolean, optional)- Returns:
{ results[], pattern, searchPath, matchCount, truncated, message } - Notes: Mirrors ripgrep's interface. Use
outputModeto control result format.
XcodeLS
List directory contents.
- Parameters:
tabIdentifier(string, required)path(string, required)recursive(boolean, optional, default true)ignore(array of strings, optional) — patterns to skip- Returns:
{ items[], path }
XcodeMakeDir
Create a directory in the project.
- Parameters:
tabIdentifier(string, required)directoryPath(string, required)- Returns:
{ success, message, createdPath }
XcodeRM
Remove files or directories from project. Uses Trash by default.
- Parameters:
tabIdentifier(string, required)path(string, required)deleteFiles(boolean, optional, default true) — move to Trashrecursive(boolean, optional)- Returns:
{ removedPath, success, message }
XcodeMV
Move or copy files.
- Parameters:
tabIdentifier(string, required)sourcePath(string, required)destinationPath(string, required)operation(enum, optional) —moveorcopyoverwriteExisting(boolean, optional)- Returns:
{ success, operation, message, sourceOriginalPath, destinationFinalPath } - Notes: Can copy, not just move. May break imports — confirm with user.
---
Build & Test
BuildProject
Build the project and wait for completion.
- Parameters:
tabIdentifier(string, required)- Returns:
{ buildResult, elapsedTime, errors[] } - Notes: Each error has
classification,filePath,lineNumber,message.
GetBuildLog
Retrieve build log with optional filtering.
- Parameters:
tabIdentifier(string, required)severity(enum, optional) —remark,warning,errorpattern(string, optional) — regex filterglob(string, optional) — file pattern filter- Returns:
{ buildIsRunning, buildLogEntries[], buildResult, fullLogPath, truncated, totalFound } - Notes: Returns structured entries, not raw text. Each entry has
buildTaskandemittedIssues[].
RunAllTests
Run the full test suite from the active scheme's test plan.
- Parameters:
tabIdentifier(string, required)- Returns:
{ summary, counts, results[], schemeName, activeTestPlanName } - Notes:
countshastotal,passed,failed,skipped,expectedFailures,notRun. Each result hastargetName,identifier,displayName,state.
RunSomeTests
Run specific tests by identifier.
- Parameters:
tabIdentifier(string, required)tests(array, required) — each element:{ targetName: string, testIdentifier: string }- Returns: Same shape as RunAllTests
- Notes: Use
GetTestListto discover valid test identifiers.
GetTestList
List available tests from the active test plan.
- Parameters:
tabIdentifier(string, required)- Returns:
{ tests[], schemeName, activeTestPlanName } - Notes: Each test has
targetName,identifier,displayName,isEnabled,filePath,lineNumber,tags[].
---
Diagnostics
XcodeListNavigatorIssues
Get issues from Xcode's Issue Navigator.
- Parameters:
tabIdentifier(string, required)severity(enum, optional) —remark,warning,errorpattern(string, optional) — regex filterglob(string, optional) — file pattern filter- Returns:
{ issues[], truncated, totalFound, message } - Notes: Each issue has
message,severity,path,line,category,vitality(fresh/stale). Structured and deduplicated.
XcodeRefreshCodeIssuesInFile
Refresh diagnostics for a specific file.
- Parameters:
tabIdentifier(string, required)filePath(string, required)- Returns:
{ filePath, diagnosticsCount, content, success } - Notes: Triggers Xcode to re-analyze the file.
---
Execution & Rendering
ExecuteSnippet
Build and run a code snippet in the context of a source file.
- Parameters:
tabIdentifier(string, required)codeSnippet(string, required) — code to executesourceFilePath(string, required) — Swift file whose context the snippet runs in (has access to itsfileprivatedeclarations)timeout(integer, optional, default 120) — seconds- Returns:
{ executionResults }— console output from print statements - Notes: Not a generic REPL. Runs in the context of a specific file. No
languageparameter — Swift only.
RenderPreview
Render a SwiftUI preview snapshot.
- Parameters:
tabIdentifier(string, required)sourceFilePath(string, required) — Swift file with#PreviewpreviewDefinitionIndexInFile(integer, optional, default 0) — zero-based index of which#Previewto rendertimeout(integer, optional, default 120)- Returns:
{ previewSnapshotPath }— path to rendered image - Notes: Index-based, not name-based. First
#Previewin the file is index 0.
---
Search
DocumentationSearch
Search Apple Developer Documentation semantically.
- Parameters:
query(string, required)frameworks(array of strings, optional) — scope to specific frameworks- Returns:
{ documents[] }— each withtitle,uri,contents,score - Notes: Local semantic search (MLX-accelerated), not web search.
---
Quick Reference
| Category | Tools |
|---|---|
| Discovery | XcodeListWindows |
| File Read | XcodeRead, XcodeGlob, XcodeGrep, XcodeLS |
| File Write | XcodeWrite, XcodeUpdate, XcodeMakeDir |
| File Destructive | XcodeRM, XcodeMV |
| Build | BuildProject, GetBuildLog |
| Test | RunAllTests, RunSomeTests, GetTestList |
| Diagnostics | XcodeListNavigatorIssues, XcodeRefreshCodeIssuesInFile |
| Execution | ExecuteSnippet |
| Preview | RenderPreview |
| Search | DocumentationSearch |
Common Parameter Patterns
- `tabIdentifier` — Required by 18/20 tools. Always call
XcodeListWindowsfirst. - `filePath` — Used by XcodeRead, XcodeWrite, XcodeUpdate, XcodeRefreshCodeIssuesInFile. Project-relative or absolute.
- `path` — Used by XcodeLS, XcodeRM, XcodeGlob. Directory path.
- `directoryPath` — Used by XcodeMakeDir.
- `sourceFilePath` — Used by ExecuteSnippet, RenderPreview. Must be a Swift source file.
Resources
Skills: axiom-xcode-mcp (skills/xcode-mcp-setup.md), axiom-xcode-mcp (skills/xcode-mcp-tools.md)
Xcode MCP Setup
Prerequisites
- Xcode 26.3+ with MCP support
- macOS with Xcode installed and running
- At least one project/workspace open in Xcode
Step 1: Allow external agents in Xcode
Agents you launch outside Xcode (Claude Code, Codex in Terminal) reach your project through the MCP server Xcode provides. Authorize them first:
1. Open Xcode Settings (Cmd+,) 2. Select Intelligence in the sidebar 3. Under Model Context Protocol, turn on "Allow external agents to use Xcode tools"
Without this, xcrun mcpbridge connects but Xcode exposes no tools. Xcode alerts you when an external agent connects and when it's active, so you always know when an agent is driving your project.
Step 2: Connect Your MCP Client
Claude Code
claude mcp add --transport stdio xcode -- xcrun mcpbridgeVerify: claude mcp list should show xcode server.
Codex
codex mcp add xcode -- xcrun mcpbridgeCursor
Create or edit .cursor/mcp.json in your project root:
{
"mcpServers": {
"xcode": {
"command": "xcrun",
"args": ["mcpbridge"]
}
}
}Cursor-specific note: Cursor is a strict MCP client. Xcode's mcpbridge omits structuredContent when tools declare outputSchema, which violates the MCP spec. If Cursor rejects responses, use XcodeMCPWrapper as a proxy:
{
"mcpServers": {
"xcode": {
"command": "/path/to/XcodeMCPWrapper",
"args": []
}
}
}VS Code + GitHub Copilot
Create or edit .vscode/mcp.json:
{
"servers": {
"xcode": {
"type": "stdio",
"command": "xcrun",
"args": ["mcpbridge"]
}
}
}Gemini CLI
gemini mcp add xcode -- xcrun mcpbridgeStep 3: Verify Connection
After configuration, call XcodeListWindows (no parameters). You should see:
tabIdentifier: <uuid>, workspacePath: /path/to/YourProject.xcodeprojIf you see an empty list, ensure a project is open in Xcode.
Permission Dialog
When an MCP client first connects, Xcode shows a permission dialog:
- Identifies the connecting process by PID
- Asks to allow MCP tool access
- Must be approved in Xcode's UI (not terminal)
PID-based approval: Permission is granted per-process. If the client restarts (new PID), you'll see the dialog again. This is expected behavior.
Letting Xcode Launch the Agent (run-agent)
Instead of wiring the agent yourself (Step 2), have Xcode launch it with Xcode's own configuration — resolved binary path, auth tokens, environment, and the Xcode MCP tools, all injected for you. run-agent connects to the running Xcode (same MCP_XCODE_PID auto-detection as the bridge), fetches the agent's config, then execs the agent with full terminal access.
# Launch Claude Code, configured by the running Xcode
xcrun mcpbridge run-agent claude
# Pass args straight through to the agent
xcrun mcpbridge run-agent claude --model opus -p "fix the failing test"
# Print the resolved command without running it
xcrun mcpbridge run-agent --dry-run claude
# Launch without injecting Xcode's MCP tools
xcrun mcpbridge run-agent claude --no-xcode-toolsUse run-agent when you want one command that both authorizes and starts the agent against the open project, rather than maintaining a separate mcp add registration.
Exporting Xcode's Skill Bundles OS27
Xcode ships built-in skill bundles — the expertise it injects for tasks like localization and accessibility. Export every globally available SKILL.md bundle to disk to inspect what guidance Xcode's agent works from, or to reuse those bundles elsewhere:
xcrun mcpbridge run-agent skills export # writes ./xcode-skills
xcrun mcpbridge run-agent skills export --output-dir ~/skills --replace-existingMulti-Xcode Targeting
When multiple Xcode instances are running:
Auto-Detection (default)
mcpbridge auto-selects using this fallback: 1. If exactly one Xcode process is running → uses that 2. If multiple → uses the one matching xcode-select 3. If none → exits with error
Manual PID Selection
Set MCP_XCODE_PID to target a specific instance:
# Find Xcode PIDs
pgrep -x Xcode
# Claude Code with specific PID
claude mcp add --transport stdio xcode -- env MCP_XCODE_PID=12345 xcrun mcpbridgeSession ID (optional)
MCP_XCODE_SESSION_ID provides a stable UUID for tool sessions, useful when tracking interactions across reconnections.
Troubleshooting
digraph troubleshoot {
rankdir=TB;
"Connection failed?" [shape=diamond];
"tools/list empty?" [shape=diamond];
"Wrong project?" [shape=diamond];
"Repeated permission prompts?" [shape=diamond];
"Client rejects responses?" [shape=diamond];
"Check Xcode running + toggle on" [shape=box];
"Open a project in Xcode" [shape=box];
"Use MCP_XCODE_PID or check tab targeting" [shape=box];
"Expected: PID changes on restart" [shape=box];
"Use XcodeMCPWrapper proxy" [shape=box];
"Connection failed?" -> "Check Xcode running + toggle on" [label="refused/timeout"];
"Connection failed?" -> "tools/list empty?" [label="connects OK"];
"tools/list empty?" -> "Open a project in Xcode" [label="no tools"];
"tools/list empty?" -> "Wrong project?" [label="tools listed"];
"Wrong project?" -> "Use MCP_XCODE_PID or check tab targeting" [label="yes"];
"Wrong project?" -> "Repeated permission prompts?" [label="no"];
"Repeated permission prompts?" -> "Expected: PID changes on restart" [label="yes"];
"Repeated permission prompts?" -> "Client rejects responses?" [label="no"];
"Client rejects responses?" -> "Use XcodeMCPWrapper proxy" [label="strict client (Cursor)"];
}Common Issues
| Symptom | Cause | Fix |
|---|---|---|
| "Connection refused" | Xcode not running or MCP toggle off | Launch Xcode, enable MCP in Settings > Intelligence |
| tools/list returns empty | No project open, or permission not granted | Open a project, check for permission dialog in Xcode |
| Tools target wrong project | Multiple Xcode windows, wrong tab | Call XcodeListWindows, use correct tabIdentifier |
| Repeated permission prompts | Client restarted (new PID) | Expected behavior — approve each time |
| Cursor/strict client errors | Missing structuredContent in response | Use XcodeMCPWrapper as proxy |
| "No such command: mcpbridge" | Xcode < 26.3 | Update to Xcode 26.3+ |
| Slow/hanging tool calls | Large project indexing | Wait for Xcode indexing to complete |
Extending the Agent That Runs Inside Xcode
Agents you launch in Xcode — the coding assistant, or one started with run-agent — can be customized beyond Intelligence settings. These customizations affect only Xcode-launched agents, not external clients you wired in Step 2.
Per-agent config files live in subfolders of ~/Library/Developer/Xcode/CodingAssistant (a folder Xcode uses exclusively). Use them to set a default model, add your own MCP servers, or define skills:
~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig # Claude
~/Library/Developer/Xcode/CodingAssistant/codex # Codex
~/Library/Developer/Xcode/CodingAssistant/gemini # GeminiPermissions — Intelligence settings → Agents → Permissions. Add command-line tools under Allowed Commands; revoke tools under Allowed Tools. Anything you previously granted in the coding assistant appears here.
Built-in skills via slash commands — type / in the message field to list them. /plan enters plan mode (explore without editing code); /exit → /exit-plan leaves it. Xcode also invokes skills automatically from your prompt (e.g. a "translate" prompt triggers localization subagents).
Plug-ins — Intelligence settings → Agents → Plug-ins → Add Plug-in. A plug-in bundles additional subagents, MCP servers, and skills; "Add from URL" imports one, then you select which components to install.
Resources
Docs: /xcode/mcp-server, /xcode/giving-external-agents-access-to-xcode, /xcode/extending-and-customizing-agents, /xcode/coding-intelligence
WWDC: 2026-258, 2026-259
Skills: axiom-xcode-mcp (skills/xcode-mcp-tools.md), axiom-xcode-mcp (skills/xcode-mcp-ref.md)
Xcode MCP Tool Workflows
Core principle: Xcode MCP gives you programmatic IDE access. Use workflow loops, not isolated tool calls.
Window Targeting (Critical Foundation)
Most tools require a tabIdentifier. Always call `XcodeListWindows` first.
1. XcodeListWindows → list of (tabIdentifier, workspacePath) pairs
2. Match workspacePath to your project
3. Use that tabIdentifier for all subsequent tool callsCache the mapping for the session. Only re-fetch if:
- A tool call fails with an invalid tab identifier
- You opened/closed Xcode windows
- You switched projects
If `XcodeListWindows` returns empty: Xcode has no project open. Ask the user to open their project.
Workflow: BuildFix Loop
Iteratively build, diagnose, and fix until the project compiles.
1. BuildProject(tabIdentifier)
2. Check buildResult — if success, done
3. GetBuildLog(tabIdentifier) → parse errors
4. XcodeListNavigatorIssues(tabIdentifier) → canonical diagnostics
5. XcodeUpdate(file, fix) for each diagnostic
6. Go to step 1 (max 5 iterations)
7. If same error persists after 3 attempts → fall back to axiom-build (skills/xcode-debugging.md)Why `XcodeListNavigatorIssues` over build log parsing: The Issue Navigator provides structured, deduplicated diagnostics. Build logs contain raw compiler output with noise.
When to fall back to `axiom-build (skills/xcode-debugging.md)`: When the error is environmental (zombie processes, stale Derived Data, simulator issues) rather than code-level. MCP tools operate on code; environment issues need CLI diagnostics.
Workflow: TestFix Loop
Fast iteration on failing tests.
1. GetTestList(tabIdentifier) → discover available tests
2. RunSomeTests(tabIdentifier, [specific failing tests]) for fast iteration
3. Parse failures → identify code to fix
4. XcodeUpdate(file, fix) to patch code
5. Go to step 2 (max 5 iterations per test)
6. RunAllTests(tabIdentifier) as final verificationWhy `RunSomeTests` first: Running a single test takes seconds. Running all tests takes minutes. Iterate on the failing test, then verify the full suite once it passes.
Parsing test results: Look for testResult field in the response. Failed tests include failure messages with file paths and line numbers.
Workflow: PreviewVerify
Render SwiftUI previews and verify UI changes visually.
1. RenderPreview(tabIdentifier, sourceFilePath, previewDefinitionIndexInFile: 0) → image artifact
2. Review the rendered image for correctness
3. If making changes: XcodeUpdate → RenderPreview again
4. Compare before/after for regressionsUse cases: Verifying layout changes, checking dark mode appearance, confirming Liquid Glass effects render correctly.
Workflow: IssueTriage
Use Xcode's Issue Navigator as the canonical diagnostics source.
1. XcodeListNavigatorIssues(tabIdentifier) → all current issues
2. For specific files: XcodeRefreshCodeIssuesInFile(tabIdentifier, file)
3. Prioritize: errors > warnings > notes
4. Fix errors first, rebuild, re-checkWhy this over grep-for-errors: The Issue Navigator tracks live diagnostics including type-check errors, missing imports, and constraint issues that only Xcode's compiler frontend surfaces.
Workflow: DocumentationSearch
Query Apple's documentation corpus through MCP.
1. DocumentationSearch(query) → documentation results
2. Cross-reference with axiom-apple-docs for bundled Xcode guidesNote: DocumentationSearch searches Apple's online documentation and WWDC transcripts. For the 20 for-LLM guides bundled inside Xcode, use axiom-apple-docs instead.
File Operations via MCP
Reading and Writing
| Operation | Tool | Notes |
|---|---|---|
| Read file contents | XcodeRead | Sees Xcode's project view (generated files, resolved packages) |
| Create new file | XcodeWrite | Creates file — auto-adds to project structure |
| Edit existing file | XcodeUpdate | str_replace-style patches — safer than full rewrites |
| Search for files | XcodeGlob | Pattern matching within the project |
| Search file contents | XcodeGrep | Content search with line numbers |
| List directory | XcodeLS | Directory listing |
| Create directory | XcodeMakeDir | Creates directories |
Destructive Operations (Require Confirmation)
| Operation | Tool | Risk |
|---|---|---|
| Delete file/directory | XcodeRM | Moves to Trash by default (deleteFiles: true) — confirm with user |
| Move/rename file | XcodeMV | May break imports and references |
Always confirm destructive operations with the user before calling XcodeRM or XcodeMV.
When to Use MCP File Tools vs Standard Tools
| Scenario | Use MCP | Use Standard (Read/Write/Grep) |
|---|---|---|
| Files in the Xcode project view | Yes — includes generated/resolved files | May miss generated files |
| Files outside the project | No | Yes — standard tools work everywhere |
| Need build context (diagnostics after edit) | Yes — edit + rebuild in one workflow | No build integration |
| Simple file read/edit | Either works | Slightly faster (no MCP overhead) |
Code Snippets
Execute Swift Code
ExecuteSnippet(tabIdentifier, codeSnippet: "print(MyModel.self)", sourceFilePath: "Sources/MyModel.swift")Runs code in the context of a specific Swift file — has access to that file's fileprivate declarations. Not a generic REPL. No language parameter (Swift only).
Gotchas and Anti-Patterns
Tab Identifier Staleness
Tab identifiers become invalid when:
- Xcode window is closed and reopened
- Project is closed and reopened
- Xcode is restarted
Fix: Re-call XcodeListWindows to get fresh identifiers.
XcodeWrite vs XcodeUpdate
XcodeWrite— creates a new file. Fails if file exists (in some clients).XcodeUpdate— patches an existing file witholdString/newStringreplacement. One replacement per call (usereplaceAll: truefor all occurrences).
Common mistake: Using XcodeWrite to edit an existing file overwrites its entire contents. Use XcodeUpdate for edits.
Schema Compliance
Xcode's mcpbridge has a known MCP spec violation: it populates content but omits structuredContent when tools declare outputSchema. This breaks strict MCP clients (Cursor, some Zed configurations).
Workaround: Use XcodeMCPWrapper as a proxy for strict clients.
Build After File Changes
After XcodeUpdate, the project may need a build to surface new diagnostics. Don't assume edits are correct without rebuilding.
Anti-Rationalization
| Thought | Reality |
|---|---|
| "I'll just use xcodebuild" | MCP gives IDE state + navigator diagnostics + previews that CLI doesn't |
| "Read tool works fine for Xcode files" | XcodeRead sees Xcode's project view including generated files and resolved packages |
| "Skip tab identifier, I only have one project" | Most tools fail silently without tabIdentifier — always call XcodeListWindows first |
| "Run all tests every time" | RunSomeTests for iteration, RunAllTests for verification — saves minutes per cycle |
| "I'll parse the build log for errors" | XcodeListNavigatorIssues provides structured, deduplicated diagnostics |
| "XcodeWrite to update a file" | XcodeUpdate for edits. XcodeWrite creates/overwrites. Wrong tool = data loss. |
| "One tool call is enough" | Workflows (BuildFix, TestFix) use loops. Isolated calls miss the iteration pattern. |
Resources
Skills: axiom-xcode-mcp (skills/xcode-mcp-setup.md), axiom-xcode-mcp (skills/xcode-mcp-ref.md), axiom-build (skills/xcode-debugging.md)
Related skills
FAQ
How many tools does Xcode MCP expose?
The axiom-xcode-mcp skill documents Xcode 26.3's official MCP server via xcrun mcpbridge, which exposes 20 IDE tools including XcodeRead, BuildProject, RunTests, and RenderPreview for external AI clients.
Which AI clients does axiom-xcode-mcp support?
The axiom-xcode-mcp skill covers setup and troubleshooting for connecting Claude, Cursor, and Codex to Xcode through the official mcpbridge MCP server with workflow patterns for builds, tests, and previews.
Is Axiom Xcode Mcp safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.