xcode-mcp-server 1.3.15__tar.gz → 1.3.16b2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- xcode_mcp_server-1.3.16b2/PKG-INFO +44 -0
- xcode_mcp_server-1.3.16b2/README.md +25 -0
- xcode_mcp_server-1.3.16b2/pyproject.toml +37 -0
- xcode_mcp_server-1.3.16b2/xcode_mcp_server/__init__.py +42 -0
- xcode_mcp_server-1.3.16b2/xcode_mcp_server/__main__.py +6 -0
- xcode_mcp_server-1.3.15/.github/workflows/claude-code.yml +0 -78
- xcode_mcp_server-1.3.15/.github/workflows/claude-self-review.yml +0 -69
- xcode_mcp_server-1.3.15/CLAUDE.md +0 -220
- xcode_mcp_server-1.3.15/PKG-INFO +0 -201
- xcode_mcp_server-1.3.15/README.md +0 -177
- xcode_mcp_server-1.3.15/TODO.md +0 -282
- xcode_mcp_server-1.3.15/__PUBLIC_REPO +0 -0
- xcode_mcp_server-1.3.15/_venv-setup.sh +0 -27
- xcode_mcp_server-1.3.15/deploy-beta.sh +0 -143
- xcode_mcp_server-1.3.15/deploy.sh +0 -120
- xcode_mcp_server-1.3.15/dev.sh +0 -66
- xcode_mcp_server-1.3.15/info.sh +0 -37
- xcode_mcp_server-1.3.15/pyproject.toml +0 -46
- xcode_mcp_server-1.3.15/requirements.txt +0 -3
- xcode_mcp_server-1.3.15/run_local_for_claude.sh +0 -12
- xcode_mcp_server-1.3.15/scripts/cleanup_tests.sh +0 -34
- xcode_mcp_server-1.3.15/scripts/create_projects.py +0 -373
- xcode_mcp_server-1.3.15/scripts/create_real_projects.py +0 -302
- xcode_mcp_server-1.3.15/scripts/create_spm_projects.sh +0 -260
- xcode_mcp_server-1.3.15/scripts/create_xcode_projects.sh +0 -251
- xcode_mcp_server-1.3.15/scripts/run_all_tests.sh +0 -89
- xcode_mcp_server-1.3.15/scripts/setup_test_projects.sh +0 -209
- xcode_mcp_server-1.3.15/scripts/setup_tests.sh +0 -83
- xcode_mcp_server-1.3.15/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp/Assets.xcassets/AccentColor.colorset/Contents.json +0 -11
- xcode_mcp_server-1.3.15/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -35
- xcode_mcp_server-1.3.15/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp/Assets.xcassets/Contents.json +0 -6
- xcode_mcp_server-1.3.15/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp/ContentView.swift +0 -24
- xcode_mcp_server-1.3.15/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp/iosEmptySwiftUIAppApp.swift +0 -17
- xcode_mcp_server-1.3.15/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp.xcodeproj/project.pbxproj +0 -337
- xcode_mcp_server-1.3.15/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- xcode_mcp_server-1.3.15/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- xcode_mcp_server-1.3.15/test_projects/fromXcode/iosEmptySwiftUIApp/iosEmptySwiftUIApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- xcode_mcp_server-1.3.15/test_projects/fromXcode/macosEmptyCommandLineApp/macosEmptyCommandLineApp/main.swift +0 -11
- xcode_mcp_server-1.3.15/test_projects/fromXcode/macosEmptyCommandLineApp/macosEmptyCommandLineApp.xcodeproj/project.pbxproj +0 -300
- xcode_mcp_server-1.3.15/test_projects/fromXcode/macosEmptyCommandLineApp/macosEmptyCommandLineApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- xcode_mcp_server-1.3.15/test_projects/fromXcode/macosEmptyCommandLineApp/macosEmptyCommandLineApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- xcode_mcp_server-1.3.15/test_projects/fromXcode/macosEmptyCommandLineApp/macosEmptyCommandLineApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- xcode_mcp_server-1.3.15/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp/Assets.xcassets/AccentColor.colorset/Contents.json +0 -11
- xcode_mcp_server-1.3.15/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -58
- xcode_mcp_server-1.3.15/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp/Assets.xcassets/Contents.json +0 -6
- xcode_mcp_server-1.3.15/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp/ContentView.swift +0 -24
- xcode_mcp_server-1.3.15/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp/macosEmptySwiftUIAppApp.swift +0 -17
- xcode_mcp_server-1.3.15/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp.xcodeproj/project.pbxproj +0 -336
- xcode_mcp_server-1.3.15/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- xcode_mcp_server-1.3.15/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- xcode_mcp_server-1.3.15/test_projects/fromXcode/macosEmptySwiftUIApp/macosEmptySwiftUIApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- xcode_mcp_server-1.3.15/test_projects/templates/BrokenApp/BrokenApp/main.swift +0 -17
- xcode_mcp_server-1.3.15/test_projects/templates/BrokenApp/BrokenApp.xcodeproj/project.pbxproj +0 -300
- xcode_mcp_server-1.3.15/test_projects/templates/BrokenApp/BrokenApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- xcode_mcp_server-1.3.15/test_projects/templates/BrokenApp/BrokenApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- xcode_mcp_server-1.3.15/test_projects/templates/BrokenApp/BrokenApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- xcode_mcp_server-1.3.15/test_projects/templates/ConsoleApp/ConsoleApp/main.swift +0 -31
- xcode_mcp_server-1.3.15/test_projects/templates/ConsoleApp/ConsoleApp.xcodeproj/project.pbxproj +0 -300
- xcode_mcp_server-1.3.15/test_projects/templates/ConsoleApp/ConsoleApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- xcode_mcp_server-1.3.15/test_projects/templates/ConsoleApp/ConsoleApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- xcode_mcp_server-1.3.15/test_projects/templates/ConsoleApp/ConsoleApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- xcode_mcp_server-1.3.15/test_projects/templates/SimpleApp/SimpleApp/main.swift +0 -11
- xcode_mcp_server-1.3.15/test_projects/templates/SimpleApp/SimpleApp.xcodeproj/project.pbxproj +0 -300
- xcode_mcp_server-1.3.15/test_projects/templates/SimpleApp/SimpleApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- xcode_mcp_server-1.3.15/test_projects/templates/SimpleApp/SimpleApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- xcode_mcp_server-1.3.15/test_projects/templates/SimpleApp/SimpleApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- xcode_mcp_server-1.3.15/test_projects/templates/SwiftUITestApp/SwiftUITestApp/Assets.xcassets/AccentColor.colorset/Contents.json +0 -11
- xcode_mcp_server-1.3.15/test_projects/templates/SwiftUITestApp/SwiftUITestApp/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -58
- xcode_mcp_server-1.3.15/test_projects/templates/SwiftUITestApp/SwiftUITestApp/Assets.xcassets/Contents.json +0 -6
- xcode_mcp_server-1.3.15/test_projects/templates/SwiftUITestApp/SwiftUITestApp/ContentView.swift +0 -27
- xcode_mcp_server-1.3.15/test_projects/templates/SwiftUITestApp/SwiftUITestApp/macosEmptySwiftUIAppApp.swift +0 -17
- xcode_mcp_server-1.3.15/test_projects/templates/SwiftUITestApp/SwiftUITestApp.xcodeproj/project.pbxproj +0 -336
- xcode_mcp_server-1.3.15/test_projects/templates/SwiftUITestApp/SwiftUITestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- xcode_mcp_server-1.3.15/test_projects/templates/SwiftUITestApp/SwiftUITestApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- xcode_mcp_server-1.3.15/test_projects/templates/SwiftUITestApp/SwiftUITestApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- xcode_mcp_server-1.3.15/test_projects/templates/iOSTestApp/iOSTestApp/Assets.xcassets/AccentColor.colorset/Contents.json +0 -11
- xcode_mcp_server-1.3.15/test_projects/templates/iOSTestApp/iOSTestApp/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -35
- xcode_mcp_server-1.3.15/test_projects/templates/iOSTestApp/iOSTestApp/Assets.xcassets/Contents.json +0 -6
- xcode_mcp_server-1.3.15/test_projects/templates/iOSTestApp/iOSTestApp/ContentView.swift +0 -24
- xcode_mcp_server-1.3.15/test_projects/templates/iOSTestApp/iOSTestApp/iosEmptySwiftUIAppApp.swift +0 -17
- xcode_mcp_server-1.3.15/test_projects/templates/iOSTestApp/iOSTestApp.xcodeproj/project.pbxproj +0 -337
- xcode_mcp_server-1.3.15/test_projects/templates/iOSTestApp/iOSTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- xcode_mcp_server-1.3.15/test_projects/templates/iOSTestApp/iOSTestApp.xcodeproj/project.xcworkspace/xcuserdata/andrew.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- xcode_mcp_server-1.3.15/test_projects/templates/iOSTestApp/iOSTestApp.xcodeproj/xcuserdata/andrew.xcuserdatad/xcschemes/xcschememanagement.plist +0 -19
- xcode_mcp_server-1.3.15/tests/debug_build.py +0 -39
- xcode_mcp_server-1.3.15/tests/debug_test.py +0 -122
- xcode_mcp_server-1.3.15/tests/test_basic.py +0 -180
- xcode_mcp_server-1.3.15/tests/test_build.py +0 -222
- xcode_mcp_server-1.3.15/tests/test_build_log_parser.py +0 -217
- xcode_mcp_server-1.3.15/tests/test_fixed.py +0 -276
- xcode_mcp_server-1.3.15/tests/test_manifest_wait.py +0 -385
- xcode_mcp_server-1.3.15/tests/test_minimal.py +0 -216
- xcode_mcp_server-1.3.15/tests/test_run_guard.py +0 -159
- xcode_mcp_server-1.3.15/tests/test_runner.py +0 -238
- xcode_mcp_server-1.3.15/tests/test_xcresult_wait.py +0 -104
- xcode_mcp_server-1.3.15/xcode_mcp_server/__init__.py +0 -12
- xcode_mcp_server-1.3.15/xcode_mcp_server/__main__.py +0 -7
- xcode_mcp_server-1.3.15/xcode_mcp_server/cli.py +0 -135
- xcode_mcp_server-1.3.15/xcode_mcp_server/config_manager.py +0 -492
- xcode_mcp_server-1.3.15/xcode_mcp_server/config_ui.py +0 -538
- xcode_mcp_server-1.3.15/xcode_mcp_server/exceptions.py +0 -20
- xcode_mcp_server-1.3.15/xcode_mcp_server/security.py +0 -298
- xcode_mcp_server-1.3.15/xcode_mcp_server/server.py +0 -80
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/__init__.py +0 -32
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/build_project.py +0 -424
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/clean_project.py +0 -76
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/create_project.py +0 -133
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/debug_list_notification_history.py +0 -69
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/get_active_run_destination.py +0 -145
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/get_build_errors.py +0 -109
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/get_build_results.py +0 -134
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/get_directory_listing.py +0 -133
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/get_directory_tree.py +0 -195
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/get_latest_test_results.py +0 -120
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/get_project_schemes.py +0 -88
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/get_runtime_output.py +0 -83
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/get_xcode_projects.py +0 -352
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/list_booted_simulators.py +0 -61
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/list_mac_app_windows.py +0 -146
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/list_project_tests.py +0 -240
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/list_run_destinations.py +0 -117
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/list_running_mac_apps.py +0 -113
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/run_project_tests.py +0 -381
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/run_project_unmonitored.py +0 -83
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/run_project_until_terminated.py +0 -210
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/run_project_with_user_interaction.py +0 -305
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/set_run_destination.py +0 -90
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/stop_project.py +0 -69
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/take_app_screenshot.py +0 -115
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/take_simulator_screenshot.py +0 -110
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/take_window_screenshot.py +0 -121
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/take_xcode_screenshot.py +0 -115
- xcode_mcp_server-1.3.15/xcode_mcp_server/tools/version.py +0 -64
- xcode_mcp_server-1.3.15/xcode_mcp_server/utils/__init__.py +0 -1
- xcode_mcp_server-1.3.15/xcode_mcp_server/utils/applescript.py +0 -439
- xcode_mcp_server-1.3.15/xcode_mcp_server/utils/build_log_parser.py +0 -787
- xcode_mcp_server-1.3.15/xcode_mcp_server/utils/decode_active_destination.swift +0 -104
- xcode_mcp_server-1.3.15/xcode_mcp_server/utils/decode_xcode_recents.swift +0 -47
- xcode_mcp_server-1.3.15/xcode_mcp_server/utils/paths.py +0 -14
- xcode_mcp_server-1.3.15/xcode_mcp_server/utils/project_templates.py +0 -666
- xcode_mcp_server-1.3.15/xcode_mcp_server/utils/run_guard.py +0 -87
- xcode_mcp_server-1.3.15/xcode_mcp_server/utils/screenshot.py +0 -180
- xcode_mcp_server-1.3.15/xcode_mcp_server/utils/xcodebuild_query.py +0 -341
- xcode_mcp_server-1.3.15/xcode_mcp_server/utils/xcresult.py +0 -996
- {xcode_mcp_server-1.3.15 → xcode_mcp_server-1.3.16b2}/.gitignore +0 -0
- {xcode_mcp_server-1.3.15 → xcode_mcp_server-1.3.16b2}/LICENSE +0 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: xcode-mcp-server
|
|
3
|
+
Version: 1.3.16b2
|
|
4
|
+
Summary: RENAMED to drews-xcode-mcp - this compatibility package forwards to it
|
|
5
|
+
Project-URL: Homepage, https://github.com/drewster99/drews-xcode-mcp
|
|
6
|
+
Project-URL: Repository, https://github.com/drewster99/drews-xcode-mcp
|
|
7
|
+
Project-URL: Issues, https://github.com/drewster99/drews-xcode-mcp/issues
|
|
8
|
+
Author-email: Andrew Benson <db@nuclearcyborg.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: mcp,server,xcode
|
|
12
|
+
Classifier: Development Status :: 7 - Inactive
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Requires-Dist: drews-xcode-mcp==1.3.16b2
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# xcode-mcp-server → drews-xcode-mcp
|
|
21
|
+
|
|
22
|
+
**This package has been renamed to [drews-xcode-mcp](https://pypi.org/project/drews-xcode-mcp/).**
|
|
23
|
+
|
|
24
|
+
With several projects named "xcode-mcp-server" in the wild — and Xcode itself now
|
|
25
|
+
shipping a built-in MCP server — the old name had become ambiguous.
|
|
26
|
+
|
|
27
|
+
Nothing breaks: installing this package pulls in `drews-xcode-mcp` and forwards the
|
|
28
|
+
`xcode-mcp-server` command to it, so existing MCP client configurations keep working.
|
|
29
|
+
Your settings carry over automatically (`~/.xcode-mcp-server` is renamed to
|
|
30
|
+
`~/.drews-xcode-mcp` on first run), and `XCODEMCP_ALLOWED_FOLDERS` works as before.
|
|
31
|
+
|
|
32
|
+
When convenient, update your MCP configuration to run `drews-xcode-mcp` instead.
|
|
33
|
+
For Claude Code:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
claude mcp remove xcode-mcp-server
|
|
37
|
+
claude mcp add --scope user --transport stdio -- drews-xcode-mcp `which uvx` drews-xcode-mcp
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
(If you have tool-permission allowlists tied to the old server name, you can keep
|
|
41
|
+
the old name instead — replace the first `drews-xcode-mcp` after `--` (the server
|
|
42
|
+
key) with `xcode-mcp-server`, leaving the package name at the end unchanged.)
|
|
43
|
+
|
|
44
|
+
Source, documentation, and issues: https://github.com/drewster99/drews-xcode-mcp
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# xcode-mcp-server → drews-xcode-mcp
|
|
2
|
+
|
|
3
|
+
**This package has been renamed to [drews-xcode-mcp](https://pypi.org/project/drews-xcode-mcp/).**
|
|
4
|
+
|
|
5
|
+
With several projects named "xcode-mcp-server" in the wild — and Xcode itself now
|
|
6
|
+
shipping a built-in MCP server — the old name had become ambiguous.
|
|
7
|
+
|
|
8
|
+
Nothing breaks: installing this package pulls in `drews-xcode-mcp` and forwards the
|
|
9
|
+
`xcode-mcp-server` command to it, so existing MCP client configurations keep working.
|
|
10
|
+
Your settings carry over automatically (`~/.xcode-mcp-server` is renamed to
|
|
11
|
+
`~/.drews-xcode-mcp` on first run), and `XCODEMCP_ALLOWED_FOLDERS` works as before.
|
|
12
|
+
|
|
13
|
+
When convenient, update your MCP configuration to run `drews-xcode-mcp` instead.
|
|
14
|
+
For Claude Code:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
claude mcp remove xcode-mcp-server
|
|
18
|
+
claude mcp add --scope user --transport stdio -- drews-xcode-mcp `which uvx` drews-xcode-mcp
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
(If you have tool-permission allowlists tied to the old server name, you can keep
|
|
22
|
+
the old name instead — replace the first `drews-xcode-mcp` after `--` (the server
|
|
23
|
+
key) with `xcode-mcp-server`, leaving the package name at the end unchanged.)
|
|
24
|
+
|
|
25
|
+
Source, documentation, and issues: https://github.com/drewster99/drews-xcode-mcp
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "xcode-mcp-server"
|
|
7
|
+
# The version and the drews-xcode-mcp pin below are rewritten in lockstep by
|
|
8
|
+
# deploy.sh so every release of the renamed package ships a matching shim.
|
|
9
|
+
version = "1.3.16b2"
|
|
10
|
+
description = "RENAMED to drews-xcode-mcp - this compatibility package forwards to it"
|
|
11
|
+
readme = "README.md"
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
license = {text = "MIT"}
|
|
14
|
+
authors = [
|
|
15
|
+
{name = "Andrew Benson", email = "db@nuclearcyborg.com"},
|
|
16
|
+
]
|
|
17
|
+
keywords = ["mcp", "xcode", "server"]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 7 - Inactive",
|
|
20
|
+
"Intended Audience :: Developers",
|
|
21
|
+
"License :: OSI Approved :: MIT License",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"drews-xcode-mcp==1.3.16b2",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
xcode-mcp-server = "xcode_mcp_server:main"
|
|
30
|
+
|
|
31
|
+
[tool.hatch.build.targets.wheel]
|
|
32
|
+
packages = ["xcode_mcp_server"]
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://github.com/drewster99/drews-xcode-mcp"
|
|
36
|
+
Repository = "https://github.com/drewster99/drews-xcode-mcp"
|
|
37
|
+
Issues = "https://github.com/drewster99/drews-xcode-mcp/issues"
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Compatibility shim: the xcode-mcp-server package is now drews-xcode-mcp.
|
|
2
|
+
|
|
3
|
+
Installing this package pulls in drews-xcode-mcp and forwards the old
|
|
4
|
+
`xcode-mcp-server` command to it, so existing MCP client configurations keep
|
|
5
|
+
working unchanged. New configurations should invoke `drews-xcode-mcp` directly.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
# Read by the renamed server so it can surface migration guidance to the
|
|
12
|
+
# client when it was launched through this legacy package name.
|
|
13
|
+
LEGACY_PACKAGE_ENVIRONMENT_VARIABLE = "XCODE_MCP_LEGACY_PACKAGE_NAME"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def main():
|
|
17
|
+
"""Forward the legacy xcode-mcp-server command to drews-xcode-mcp."""
|
|
18
|
+
os.environ[LEGACY_PACKAGE_ENVIRONMENT_VARIABLE] = "xcode-mcp-server"
|
|
19
|
+
# stderr only: stdout carries the MCP protocol stream and must stay clean.
|
|
20
|
+
print(
|
|
21
|
+
"NOTE: The 'xcode-mcp-server' package has been renamed to 'drews-xcode-mcp'.\n"
|
|
22
|
+
" This compatibility package keeps existing configurations working,\n"
|
|
23
|
+
" but please update your MCP configuration to run 'drews-xcode-mcp'.\n"
|
|
24
|
+
" Details: https://github.com/drewster99/drews-xcode-mcp",
|
|
25
|
+
file=sys.stderr,
|
|
26
|
+
)
|
|
27
|
+
from drews_xcode_mcp import main as run_renamed_server
|
|
28
|
+
return run_renamed_server()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def __getattr__(name):
|
|
32
|
+
# __version__ is resolved lazily (PEP 562) rather than imported at module
|
|
33
|
+
# scope: importing this shim must never pull in drews_xcode_mcp before
|
|
34
|
+
# main() has set the legacy environment variable, because server.py reads
|
|
35
|
+
# that variable at import time.
|
|
36
|
+
if name == "__version__":
|
|
37
|
+
from drews_xcode_mcp import __version__
|
|
38
|
+
return __version__
|
|
39
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
__all__ = ["main", "__version__"]
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
name: Claude Code
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_dispatch:
|
|
5
|
-
issue_comment:
|
|
6
|
-
types: [created]
|
|
7
|
-
pull_request_review_comment:
|
|
8
|
-
types: [created]
|
|
9
|
-
issues:
|
|
10
|
-
types: [opened, assigned]
|
|
11
|
-
pull_request_review:
|
|
12
|
-
types: [submitted]
|
|
13
|
-
|
|
14
|
-
jobs:
|
|
15
|
-
claude:
|
|
16
|
-
if: |
|
|
17
|
-
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
18
|
-
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
19
|
-
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
|
20
|
-
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) ||
|
|
21
|
-
(github.event_name == 'issues' && github.event.action == 'assigned' && github.event.assignee.login == 'claude[bot]')
|
|
22
|
-
runs-on: ubuntu-latest
|
|
23
|
-
permissions:
|
|
24
|
-
contents: write
|
|
25
|
-
pull-requests: write
|
|
26
|
-
issues: write
|
|
27
|
-
id-token: write
|
|
28
|
-
actions: read
|
|
29
|
-
steps:
|
|
30
|
-
- name: Checkout repository
|
|
31
|
-
uses: actions/checkout@v4
|
|
32
|
-
with:
|
|
33
|
-
fetch-depth: 1
|
|
34
|
-
|
|
35
|
-
- name: Set up global Claude config
|
|
36
|
-
env:
|
|
37
|
-
GH_TOKEN: ${{ secrets.CROSS_REPO_PAT }}
|
|
38
|
-
run: |
|
|
39
|
-
mkdir -p ~/.claude
|
|
40
|
-
gh api repos/drewster99/dev-ops/contents/claude-rules/base.md \
|
|
41
|
-
--jq '.content' | base64 -d > ~/.claude/CLAUDE.md
|
|
42
|
-
echo "" >> ~/.claude/CLAUDE.md
|
|
43
|
-
gh api repos/drewster99/dev-ops/contents/claude-rules/ci.md \
|
|
44
|
-
--jq '.content' | base64 -d >> ~/.claude/CLAUDE.md
|
|
45
|
-
|
|
46
|
-
- name: Run Claude Code
|
|
47
|
-
id: claude
|
|
48
|
-
uses: anthropics/claude-code-action@v1
|
|
49
|
-
with:
|
|
50
|
-
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
51
|
-
additional_permissions: |
|
|
52
|
-
actions: read
|
|
53
|
-
|
|
54
|
-
- name: Auto-create PR if Claude pushed a branch
|
|
55
|
-
if: github.event_name == 'issues' || (github.event_name == 'issue_comment' && !github.event.issue.pull_request)
|
|
56
|
-
env:
|
|
57
|
-
GH_TOKEN: ${{ github.token }}
|
|
58
|
-
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
|
59
|
-
run: |
|
|
60
|
-
git fetch origin --no-tags
|
|
61
|
-
BRANCH=$(git branch -r --list "origin/claude/issue-${ISSUE_NUMBER}-*" | head -1 | xargs)
|
|
62
|
-
if [ -z "$BRANCH" ]; then
|
|
63
|
-
echo "No Claude branch found for issue #${ISSUE_NUMBER}, skipping PR creation."
|
|
64
|
-
exit 0
|
|
65
|
-
fi
|
|
66
|
-
LOCAL_BRANCH="${BRANCH#origin/}"
|
|
67
|
-
EXISTING_PR=$(gh pr list --head "$LOCAL_BRANCH" --json number --jq '.[0].number' 2>/dev/null)
|
|
68
|
-
if [ -n "$EXISTING_PR" ]; then
|
|
69
|
-
echo "PR #${EXISTING_PR} already exists for branch ${LOCAL_BRANCH}."
|
|
70
|
-
exit 0
|
|
71
|
-
fi
|
|
72
|
-
echo "Creating PR from ${LOCAL_BRANCH} for issue #${ISSUE_NUMBER}..."
|
|
73
|
-
PR_BODY=$(printf 'Resolves #%s\n\nAuto-generated by Claude Code from issue #%s.' "$ISSUE_NUMBER" "$ISSUE_NUMBER")
|
|
74
|
-
gh pr create \
|
|
75
|
-
--head "$LOCAL_BRANCH" \
|
|
76
|
-
--title "$(gh issue view "$ISSUE_NUMBER" --json title --jq .title)" \
|
|
77
|
-
--body "$PR_BODY" \
|
|
78
|
-
|| echo "PR creation failed -- Claude may not have pushed commits."
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
name: Claude Self-Review
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
pull_request:
|
|
5
|
-
types: [opened, synchronize]
|
|
6
|
-
|
|
7
|
-
jobs:
|
|
8
|
-
self-review:
|
|
9
|
-
runs-on: ubuntu-latest
|
|
10
|
-
permissions:
|
|
11
|
-
contents: write
|
|
12
|
-
pull-requests: write
|
|
13
|
-
issues: write
|
|
14
|
-
id-token: write
|
|
15
|
-
steps:
|
|
16
|
-
- name: Check review iteration count
|
|
17
|
-
id: check-iterations
|
|
18
|
-
env:
|
|
19
|
-
GH_TOKEN: ${{ github.token }}
|
|
20
|
-
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
21
|
-
run: |
|
|
22
|
-
MAX_REVIEWS=3
|
|
23
|
-
COUNT=$(gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \
|
|
24
|
-
--jq '[.[] | select(.user.login == "github-actions[bot]" and (.body | contains("Self-review pass"))) ] | length')
|
|
25
|
-
echo "review_count=$COUNT" >> "$GITHUB_OUTPUT"
|
|
26
|
-
if [ "$COUNT" -ge "$MAX_REVIEWS" ]; then
|
|
27
|
-
echo "skip=true" >> "$GITHUB_OUTPUT"
|
|
28
|
-
echo "Reached max self-review iterations ($MAX_REVIEWS). Skipping."
|
|
29
|
-
else
|
|
30
|
-
echo "skip=false" >> "$GITHUB_OUTPUT"
|
|
31
|
-
echo "Self-review pass $((COUNT + 1)) of $MAX_REVIEWS"
|
|
32
|
-
fi
|
|
33
|
-
|
|
34
|
-
- name: Checkout repository
|
|
35
|
-
if: steps.check-iterations.outputs.skip != 'true'
|
|
36
|
-
uses: actions/checkout@v4
|
|
37
|
-
with:
|
|
38
|
-
fetch-depth: 1
|
|
39
|
-
ref: ${{ github.head_ref }}
|
|
40
|
-
|
|
41
|
-
- name: Set up global Claude config
|
|
42
|
-
if: steps.check-iterations.outputs.skip != 'true'
|
|
43
|
-
env:
|
|
44
|
-
GH_TOKEN: ${{ secrets.CROSS_REPO_PAT }}
|
|
45
|
-
run: |
|
|
46
|
-
mkdir -p ~/.claude
|
|
47
|
-
gh api repos/drewster99/dev-ops/contents/claude-rules/base.md \
|
|
48
|
-
--jq '.content' | base64 -d > ~/.claude/CLAUDE.md
|
|
49
|
-
echo "" >> ~/.claude/CLAUDE.md
|
|
50
|
-
gh api repos/drewster99/dev-ops/contents/claude-rules/ci.md \
|
|
51
|
-
--jq '.content' | base64 -d >> ~/.claude/CLAUDE.md
|
|
52
|
-
|
|
53
|
-
- name: Self-review and fix
|
|
54
|
-
if: steps.check-iterations.outputs.skip != 'true'
|
|
55
|
-
uses: anthropics/claude-code-action@v1
|
|
56
|
-
with:
|
|
57
|
-
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
58
|
-
prompt: |
|
|
59
|
-
Self-review pass ${{ steps.check-iterations.outputs.review_count }} of 3.
|
|
60
|
-
|
|
61
|
-
You opened this PR. Review your own work before a human sees it.
|
|
62
|
-
|
|
63
|
-
1. Re-read every changed file. Check for bugs, edge cases, missing error handling.
|
|
64
|
-
2. Verify code style matches CLAUDE.md and existing patterns in this repo.
|
|
65
|
-
3. Look for security issues (injection, hardcoded secrets, unsafe operations).
|
|
66
|
-
4. If you find problems, fix them and push to this branch.
|
|
67
|
-
5. After fixing, re-review your fixes.
|
|
68
|
-
6. Add a PR comment starting with "Self-review pass N:" summarizing findings and any fixes made.
|
|
69
|
-
7. If everything looks clean, say so. Don't make changes for the sake of making changes.
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
-
|
|
5
|
-
## Project Overview
|
|
6
|
-
|
|
7
|
-
This is the Xcode MCP Server - a Model Context Protocol (MCP) server that enables AI assistants to interact with Xcode projects. It provides tools for building, running, and managing Xcode projects/workspaces programmatically through AppleScript.
|
|
8
|
-
|
|
9
|
-
## Development Commands
|
|
10
|
-
|
|
11
|
-
### Local Development
|
|
12
|
-
```bash
|
|
13
|
-
# Quick start with dev script (sets up conda env and runs MCP Inspector)
|
|
14
|
-
./dev.sh
|
|
15
|
-
|
|
16
|
-
# Manual setup: Test the server locally with MCP Inspector
|
|
17
|
-
export XCODEMCP_ALLOWED_FOLDERS=/Users/username/Projects
|
|
18
|
-
mcp dev xcode_mcp_server/__main__.py
|
|
19
|
-
|
|
20
|
-
# Run the server directly
|
|
21
|
-
python -m xcode_mcp_server
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
### Testing in-progress changes through the real MCP path
|
|
25
|
-
|
|
26
|
-
Two MCP servers are registered against this repo:
|
|
27
|
-
|
|
28
|
-
- **`xcode-mcp-server`** — the *deployed* build (`uvx xcode-mcp-server==<version>`).
|
|
29
|
-
It runs the published PyPI/beta release, NOT your working tree. Editing source
|
|
30
|
-
here does nothing to it until you `./deploy.sh` and switch versions.
|
|
31
|
-
- **`xcode-mcp-local-dev-server`** — runs your **live local source** via
|
|
32
|
-
`run_local_for_claude.sh` (`cd` into the repo, then `python -m xcode_mcp_server`).
|
|
33
|
-
Use this to test uncommitted changes without deploying. (Note: the canonical
|
|
34
|
-
repo path `~/cursor/xcode-mcp-server` and `~/Documents/ncc_source/cursor/xcode-mcp-server`
|
|
35
|
-
are the same directory via symlink.)
|
|
36
|
-
|
|
37
|
-
**Critical freshness rule:** a Claude instance spawns the dev-server process once,
|
|
38
|
-
when it first connects, and Python imports each module once per process. So the
|
|
39
|
-
dev-server bound to a *running* Claude session is **frozen at that session's
|
|
40
|
-
start** — editing source afterward does NOT update it. Per-tool-call does not
|
|
41
|
-
re-import; only a brand-new server process picks up edits.
|
|
42
|
-
|
|
43
|
-
To test the latest source after editing, pick one:
|
|
44
|
-
|
|
45
|
-
1. **Spawn a fresh Claude instance from bash** (best for end-to-end MCP-path
|
|
46
|
-
testing — each invocation starts its own dev-server process = current source):
|
|
47
|
-
```bash
|
|
48
|
-
claude -p "Call mcp__xcode-mcp-local-dev-server__list_project_tests with
|
|
49
|
-
project_path=... and report the result verbatim." \
|
|
50
|
-
--allowedTools "mcp__xcode-mcp-local-dev-server__list_project_tests"
|
|
51
|
-
```
|
|
52
|
-
2. **Call the tool function directly via `python3 -c`** (fastest for iterating on
|
|
53
|
-
tool logic; imports fresh source each run, but bypasses FastMCP/serialization):
|
|
54
|
-
```bash
|
|
55
|
-
python3 -c "
|
|
56
|
-
import xcode_mcp_server.security as sec
|
|
57
|
-
sec.ALLOWED_FOLDERS = {'/path/allowed'}
|
|
58
|
-
from xcode_mcp_server.tools.<tool_module> import <tool_fn>
|
|
59
|
-
fn = getattr(<tool_fn>, 'fn', <tool_fn>) # unwrap the FastMCP tool
|
|
60
|
-
print(fn('/path/to/Project.xcodeproj'))
|
|
61
|
-
"
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Do NOT trust the dev-server tools exposed in your *current* session to reflect
|
|
65
|
-
edits you just made — they reflect the source as of when this session connected.
|
|
66
|
-
|
|
67
|
-
**Confirming the running server matches your edits.** When running from a source
|
|
68
|
-
checkout, the `version` tool appends a source fingerprint, e.g.
|
|
69
|
-
`Xcode MCP Server version 1.3.14b1 (dev source e5f07eab)`. The hash is a SHA-256
|
|
70
|
-
of all `.py` files in the package, computed at import — so it identifies the
|
|
71
|
-
source the process actually loaded. Deployed (uvx) builds have no `.git` and omit
|
|
72
|
-
the suffix. To verify a server is running your current code, compare its reported
|
|
73
|
-
hash to the on-disk hash:
|
|
74
|
-
```bash
|
|
75
|
-
python3 -c "
|
|
76
|
-
import hashlib, os
|
|
77
|
-
d = hashlib.sha256()
|
|
78
|
-
for root, dirs, files in os.walk('xcode_mcp_server'):
|
|
79
|
-
dirs[:] = sorted(x for x in dirs if x != '__pycache__')
|
|
80
|
-
for n in sorted(files):
|
|
81
|
-
if n.endswith('.py'):
|
|
82
|
-
with open(os.path.join(root, n), 'rb') as h: d.update(h.read())
|
|
83
|
-
print(d.hexdigest()[:8])
|
|
84
|
-
"
|
|
85
|
-
```
|
|
86
|
-
If the `version` tool's hash differs from this, the server is running stale code
|
|
87
|
-
(start a fresh Claude instance). If they match, it is your current source.
|
|
88
|
-
|
|
89
|
-
### Testing
|
|
90
|
-
```bash
|
|
91
|
-
# Run tests using the test runner framework
|
|
92
|
-
python tests/test_basic.py # Basic functionality tests
|
|
93
|
-
python tests/test_build.py # Build operation tests
|
|
94
|
-
python tests/test_runner.py # Test infrastructure
|
|
95
|
-
|
|
96
|
-
# Tests automatically:
|
|
97
|
-
# - Set up isolated working directory (test_projects/working/)
|
|
98
|
-
# - Copy template projects from test_projects/templates/
|
|
99
|
-
# - Configure ALLOWED_FOLDERS to working directory
|
|
100
|
-
# - Clean up after execution
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
### Build and Deploy
|
|
104
|
-
```bash
|
|
105
|
-
# Deploy to PyPI (increments version, builds, and uploads)
|
|
106
|
-
./deploy.sh
|
|
107
|
-
|
|
108
|
-
# Manual version increment
|
|
109
|
-
hatch version patch # 1.2.0 -> 1.2.1
|
|
110
|
-
hatch version minor # 1.2.0 -> 1.3.0
|
|
111
|
-
hatch version major # 1.2.0 -> 2.0.0
|
|
112
|
-
|
|
113
|
-
# Build distribution manually
|
|
114
|
-
python -m build
|
|
115
|
-
|
|
116
|
-
# Install locally for testing
|
|
117
|
-
pip install -e .
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
### Testing with uvx
|
|
121
|
-
```bash
|
|
122
|
-
# Run the published version
|
|
123
|
-
uvx xcode-mcp-server
|
|
124
|
-
|
|
125
|
-
# Run with specific allowed folders
|
|
126
|
-
XCODEMCP_ALLOWED_FOLDERS=/path/to/projects uvx xcode-mcp-server
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
## Architecture
|
|
130
|
-
|
|
131
|
-
### Core Components
|
|
132
|
-
|
|
133
|
-
1. **Main Entry Point** (`xcode_mcp_server/__init__.py`)
|
|
134
|
-
- Handles command-line argument parsing
|
|
135
|
-
- Manages allowed folder configuration from environment and CLI args
|
|
136
|
-
- Validates security settings before server startup
|
|
137
|
-
|
|
138
|
-
2. **MCP Server Implementation** (`xcode_mcp_server/server.py` and `xcode_mcp_server/tools/`)
|
|
139
|
-
- Built with FastMCP framework
|
|
140
|
-
- Implements 24 MCP tools for Xcode interaction:
|
|
141
|
-
- **Project discovery**: `version`, `get_xcode_projects`
|
|
142
|
-
- **File system**: `get_directory_tree`, `get_directory_listing`
|
|
143
|
-
- **Build operations**: `get_project_schemes`, `build_project`, `clean_project`, `stop_project`, `get_build_errors`
|
|
144
|
-
- **Runtime**: `run_project_with_user_interaction`, `run_project_until_terminated`, `run_project_unmonitored`, `get_runtime_output`
|
|
145
|
-
- **Testing**: `list_project_tests`, `run_project_tests`, `get_latest_test_results`
|
|
146
|
-
- **Screenshots**: `take_xcode_screenshot`, `take_simulator_screenshot`, `take_window_screenshot`, `take_app_screenshot`
|
|
147
|
-
- **System info**: `list_booted_simulators`, `list_running_mac_apps`, `list_mac_app_windows`
|
|
148
|
-
- **Debug**: `debug_list_notification_history`
|
|
149
|
-
|
|
150
|
-
### Security Model
|
|
151
|
-
|
|
152
|
-
The server implements path-based security:
|
|
153
|
-
- **ALLOWED_FOLDERS**: Set of validated absolute paths where access is permitted
|
|
154
|
-
- Paths are validated for: absolute paths, existence, directory type, no '..' components
|
|
155
|
-
- Default to $HOME if no folders specified
|
|
156
|
-
- Every tool call validates the project path against allowed folders
|
|
157
|
-
|
|
158
|
-
### AppleScript Integration
|
|
159
|
-
|
|
160
|
-
All Xcode interactions use AppleScript via `osascript`:
|
|
161
|
-
- Opens projects/workspaces in Xcode
|
|
162
|
-
- Waits for workspace loading (60-second timeout)
|
|
163
|
-
- Handles build/run/clean operations
|
|
164
|
-
- Extracts build errors from Xcode's UI
|
|
165
|
-
|
|
166
|
-
### Error Handling
|
|
167
|
-
|
|
168
|
-
Custom exception hierarchy:
|
|
169
|
-
- `XCodeMCPError`: Base exception class
|
|
170
|
-
- `AccessDeniedError`: Path access violations
|
|
171
|
-
- `InvalidParameterError`: Invalid input parameters
|
|
172
|
-
|
|
173
|
-
## Key Implementation Details
|
|
174
|
-
|
|
175
|
-
- **Notifications**: Optional macOS notifications for tool invocations (--show-notifications flag)
|
|
176
|
-
- **Scheme Handling**: Active scheme detection with fallback to scheme list
|
|
177
|
-
- **Build Output**: Captures first 25 lines of build errors for concise feedback
|
|
178
|
-
- **Path Normalization**: Removes trailing slashes, validates absolute paths
|
|
179
|
-
- **Spotlight Integration**: Uses `mdfind` for efficient project discovery across allowed folders
|
|
180
|
-
|
|
181
|
-
## Version Management
|
|
182
|
-
|
|
183
|
-
Version is stored in `xcode_mcp_server/__init__.py` and managed by hatch. The `deploy.sh` script automatically increments the patch version, but you can manually control it with:
|
|
184
|
-
```bash
|
|
185
|
-
hatch version patch # Increment patch version
|
|
186
|
-
hatch version minor # Increment minor version
|
|
187
|
-
hatch version major # Increment major version
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
## Important Implementation Details
|
|
191
|
-
|
|
192
|
-
### Internal Helper Functions
|
|
193
|
-
- **`get_frontmost_project()`**: Not exposed as MCP tool; retrieves the currently open Xcode project path from frontmost window
|
|
194
|
-
- **`extract_console_logs_from_xcresult()`**: Parses .xcresult bundles to extract runtime console output as structured JSON
|
|
195
|
-
- **`extract_build_errors_and_warnings()`**: Filters build logs to show only errors/warnings as structured JSON (configurable via `include_warnings` parameter)
|
|
196
|
-
- **`extract_test_results_from_xcresult()`**: Parses .xcresult test bundles to extract concise test results with failure details
|
|
197
|
-
- **`wait_for_xcresult_after_timestamp()`**: Polls for new .xcresult files after a run starts, with timeout
|
|
198
|
-
- **`find_xcresult_for_project()`**: Locates the most recent .xcresult bundle for a project (runtime logs)
|
|
199
|
-
- **`find_xcresult_bundle()`**: Locates the most recent .xcresult bundle for a project (test logs)
|
|
200
|
-
- **`validate_and_normalize_project_path()`**: Ensures paths are absolute, exist, and are allowed by security policy
|
|
201
|
-
- **`escape_applescript_string()`**: Properly escapes strings for safe AppleScript execution
|
|
202
|
-
|
|
203
|
-
### Operational Behavior
|
|
204
|
-
- **Scheme Selection**: When no scheme is specified in `build_project`, the active scheme is used automatically
|
|
205
|
-
- **Debug Output**: Server prints debug information to stderr for troubleshooting
|
|
206
|
-
- **Workspace Loading**: All operations wait for Xcode workspace to fully load before proceeding (60-second timeout)
|
|
207
|
-
- **Build Log Filtering**: Build failures return structured JSON with errors/warnings (up to 25 lines) and full log path
|
|
208
|
-
- **Test Result Filtering**: Test results return structured JSON with summary and only failed test details; passing tests are counted but not detailed
|
|
209
|
-
- **Warning Control**: Global `BUILD_WARNINGS_ENABLED` and `BUILD_WARNINGS_FORCED` flags control warning display; can be overridden per-tool with `include_warnings` parameter
|
|
210
|
-
- **Notifications**: Optional macOS notifications via `osascript` (controlled by `NOTIFICATIONS_ENABLED` global flag)
|
|
211
|
-
|
|
212
|
-
### xcresult Management
|
|
213
|
-
The server relies heavily on Xcode's .xcresult bundles for extracting build, runtime, and test information:
|
|
214
|
-
- **Runtime logs**: Located in `~/Library/Developer/Xcode/DerivedData/*/Logs/Launch/`
|
|
215
|
-
- **Test results**: Located in `~/Library/Developer/Xcode/DerivedData/*/Logs/Test/`
|
|
216
|
-
- Parsed using `xcrun xcresulttool` with appropriate subcommands
|
|
217
|
-
- Timestamped checking prevents reading stale results
|
|
218
|
-
- **Runtime output**: Console logs extracted from `actionsInvocationRecord` → `actions` → `actionResult` → `logRef` paths, returned as structured JSON with errors/warnings prioritized
|
|
219
|
-
- **Test results**: Test tree parsed recursively to extract pass/fail counts and failure details, returned as concise structured JSON (10-50x smaller than raw xcresult output)
|
|
220
|
-
- **Build errors**: Filtered using regex patterns, returned as structured JSON with full log path for deep analysis
|