← Blog
2026-09-22

Getting the Most Out of Xcode MCP

Xcode's MCP server and the CLI are both good tools for an agent working on an iOS app. Here's what each one is good at, with measured token counts, so you can pick one or mix them.

TL;DR

Xcode's MCP server, shipped in Xcode 26.3 and still there in Xcode 27, is a fine default. If you're happy with it, keep it. If you want to trim context, send the questions an agent asks constantly (a build setting, a named test run, a symbol search) to xcodebuild, xcrun simctl and grep, and keep MCP for what it does better: filtered string catalogs, directory listings, compiler flags, crash logs, device automation, and anything with no CLI equivalent. See Apple's Xcode 27 release notes for what's changed.

What I measured

Thirteen query pairs, CLI vs MCP, run against four apps: Rain Check (a small app of mine), WordPress-iOS, Signal-iOS and Firefox for iOS. All four are live clones, and every number is from an actual run, nothing extrapolated. Every CLI number is filtered: -quiet, piped, grepped. Tokens were counted with tiktoken1. A dash means I couldn't measure it, not zero2.

QueryAppCLIMCPNote
One build setting's valueRain Check811,946CLI wins everywhere; MCP has no per-key filter anywhere. Firefox: 450 settings, 11,995 tokens unfiltered vs. 13 grepped, ~923×. Narrower than Rain Check's ~1,493×, but still three to four orders of magnitude on every app
WordPress-iOS1412,558
Signal-iOS1212,064
Firefox for iOS1311,995
Find a symbol in one fileRain Check2467CLI wins everywhere it runs
WordPress-iOS1459
Signal-iOS951
Firefox for iOS2049
Read a 21-line file rangeRain Check217402CLI wins everywhere it runs
WordPress-iOS142312
Signal-iOS104277
Firefox for iOS149316
Full clean build, success onlyRain Check5164CLI wins on the three that build. Firefox's CLI build succeeded; MCP's BuildProject failed on package resolution (see Method). A capability gap, not a cost gap
WordPress-iOS577
Signal-iOS577
Firefox for iOS5—
List schemesRain Check237154Flips per app depending on what "list schemes" actually costs each side: Signal-iOS's CocoaPods has no Swift package graph to resolve, so CLI wins there; Firefox's 34 schemes (Client project plus BrowserKit) cost CLI less than MCP's more heavily annotated response
WordPress-iOS1,294427
Signal-iOS147283
Firefox for iOS8061,103
Run one named testRain Check937,259CLI numbers assume you already know the exact identifier, which flatters CLI: on WordPress-iOS, -only-testing: took two failed attempts by hand (wrong scope, wrong test plan) before a clean 7-token pass line; MCP's GetTestList gave the exact targetName/identifier pair and RunSomeTests worked first try, at the cost of that separate discovery call (see the day-long tally below the table). Firefox's CLI number is big, but that's what it measured: its first test-target build let a full pass of Swift 6 concurrency warnings through -quiet before the pass/fail line. MCP couldn't attempt it, same package-resolution failure as the build row
WordPress-iOS7338
Signal-iOS106339
Firefox for iOS19,006—
List targets (name + type)Rain Check78310CLI wins everywhere it runs; Signal-iOS's 8 targets cost MCP nearly as much as WordPress-iOS's 16, and Firefox's 23 targets cost more still
WordPress-iOS92952
Signal-iOS37622
Firefox for iOS1081,358
Find *ViewController.swift filesRain Check4885Flips on two of three bigger apps: WordPress-iOS (154 matches) and Signal-iOS (257, using its own *Controller.swift convention) favor MCP's truncated, metadata-light list over CLI's full paths. Firefox flips back: 192 matches, but its longer nested paths (BrowserKit sub-packages) make CLI's raw list cheaper than MCP's JSON wrapper plus package-dependency metadata
WordPress-iOS2,2872,071
Signal-iOS3,9401,756
Firefox for iOS1,3621,849
ls a directory (comparable file count)Rain Check1,389227Not a fair fight anywhere: ls -la dumps metadata nobody asked for. Dirs picked for ~42-54 files each: WordPress-iOS 44, Signal-iOS's SignalServiceKit/Contacts 47, Firefox's Client/Frontend/Browser 54
WordPress-iOS1,505253
Signal-iOS1,598283
Firefox for iOS1,8151,027
One file's compiler flagsRain Check41586There's no dedicated CLI command for this on any app. The workaround is grepping OTHER_SWIFT_FLAGS out of the same unfiltered build-settings dump row 1 already paid for. Cheap when that dump is small (Signal-iOS), expensive when it isn't (WordPress-iOS's dump has deep DerivedData module-map paths baked in). Firefox's dash here is my miss, not an impossibility: its build succeeded, so the dump existed, I just didn't capture it before cleaning up the clone. Its file had no per-file flags set at all, and even that empty MCP answer still cost 83 tokens of wrapping JSON
WordPress-iOS26588
Signal-iOS5488
Firefox for iOS—83
Translation state of a .xcstrings catalogRain Check475,528359Neither Signal-iOS nor Firefox has a single .xcstrings file — both still use older localization formats (95 .strings files on Signal-iOS alone; Firefox uses .strings/.xliff). That's how those projects are set up, not a hole in my search
WordPress-iOS8,37557
Signal-iOS——
Firefox for iOS——
List run destinationsRain Check125–452651Flips per app. The CLI cost tracks how many devices and simulators were registered on the machine when I measured, which was fewer for Signal-iOS than for WordPress-iOS. On Firefox it flips the other way: MCP's grouped, flagged listing beats CLI's raw destination dump
WordPress-iOS1,461726
Signal-iOS465875
Firefox for iOS982813
Build failure (one compile error)Rain Check140204–434Nearly a tie on WordPress-iOS: its error surfaced in 13 separate filtered error: lines (one syntax mistake cascades into repeated diagnostics across a large shared module), closing most of the usual CLI advantage. Signal-iOS's throwaway error was a single clean type mismatch. Firefox's MCP side never reached the injected error, same package-resolution failure as its build row
WordPress-iOS626648
Signal-iOS36141
Firefox for iOS43—

Over a day, the two unfiltered calls are what add up. I modeled 12 fix/verify cycles shaped like my Rain Check work: defaulting to MCP cost 181,750 tokens, CLI-first cost 16,429, about 11×, a gap of 165,321 tokens a day. On WordPress-iOS, which is over twice the size, live calls gave 10.4× at 30 cycles a day, so the gap doesn't grow much with the codebase. The cost that matters is context, not dollars: one build-setting call alone is 6% of a 200k window.

Where MCP is the better pick

Where the CLI is the better pick

One caveat if you're on a large SPM-heavy app: on Firefox for iOS, every read-only MCP call worked, but BuildProject and RunSomeTests failed on package resolution where plain xcodebuild in the same clone built fine. Worth checking on your own project before picking a default.

Mixing them

My CLAUDE.md used to say "prefer the Xcode MCP tools for anything they cover." It now says: CLI and grep for build settings, named test runs and symbol searches; MCP for anything with a filter, structured output, or no CLI equivalent; quiet output by default; batch edits before building. If you'd rather stay MCP-only, the one habit worth changing is not calling GetTestList before every run. Write the identifier by hand, or grep the file it writes to disk.

Most public comparisons3 measure MCP against unfiltered xcodebuild output, where MCP wins easily. Against filtered CLI it's closer, and it depends on the question. Either one is a reasonable default. Pick whichever fits how you work and borrow the other where it's cheaper.

Your mix of calls will differ from mine, so don't take these numbers as yours. The full dataset (all 13 queries across all four apps) is the table above. I'll publish the scripts too, so you can point them at your own repo.

  1. tiktoken's cl100k_base encoding, not Anthropic's real tokenizer, so treat the ratios as the result and the absolute numbers as approximate. ↩
  2. Firefox's MCP build path fails on its own package graph, and two of the four apps predate the .xcstrings format. ↩
  3. Sentry, XcodeBuildMCP, this walkthrough. ↩