xcode-cli 1.0.5 → 1.0.7

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.
package/src/mcpbridge.ts CHANGED
@@ -1,5 +1,5 @@
1
- #!/usr/bin/env node
2
- // @generated by xcode-mcp@1.0.0 on 2026-02-27T19:58:04.864Z. DO NOT EDIT.
1
+ #!/usr/bin/env bun
2
+ // @generated by xcode-cli@1.0.5 on 2026-03-09T13:46:00.959Z. DO NOT EDIT.
3
3
  import { Command } from 'commander';
4
4
  import { createRuntime, createServerProxy } from 'mcporter';
5
5
  import { createCallResult } from 'mcporter';
@@ -20,69 +20,47 @@ const embeddedServer = {
20
20
  }
21
21
  } as const;
22
22
  const embeddedSchemas = {
23
- "XcodeUpdate": {
23
+ "BuildProject": {
24
24
  "type": "object",
25
25
  "properties": {
26
- "filePath": {
27
- "description": "REQUIRED: The path to the file to modify within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift')",
28
- "type": "string"
29
- },
30
- "newString": {
31
- "description": "REQUIRED: The text to replace it with, must be different from oldString",
32
- "type": "string"
33
- },
34
- "oldString": {
35
- "description": "REQUIRED: The text to replace",
36
- "type": "string"
37
- },
38
- "replaceAll": {
39
- "description": "Replace all occurrences of oldString (default false)",
40
- "type": "boolean"
41
- },
42
26
  "tabIdentifier": {
43
27
  "description": "The workspace tab identifier",
44
28
  "type": "string"
45
29
  }
46
30
  },
47
31
  "required": [
48
- "tabIdentifier",
49
- "filePath",
50
- "oldString",
51
- "newString"
32
+ "tabIdentifier"
52
33
  ]
53
34
  },
54
- "XcodeMV": {
35
+ "GetTestList": {
55
36
  "type": "object",
56
37
  "properties": {
57
- "destinationPath": {
58
- "description": "Project navigator relative path for the destination (for move) or new name (for rename)",
59
- "type": "string"
60
- },
61
- "operation": {
62
- "description": "The type of move operation to perform",
63
- "enum": [
64
- "move",
65
- "copy"
66
- ],
67
- "type": "string"
68
- },
69
- "overwriteExisting": {
70
- "description": "Whether to overwrite existing files at the destination",
71
- "type": "boolean"
72
- },
73
- "sourcePath": {
74
- "description": "Project navigator relative path of the source item to move/rename",
75
- "type": "string"
76
- },
77
38
  "tabIdentifier": {
78
39
  "description": "The workspace tab identifier",
79
40
  "type": "string"
80
41
  }
81
42
  },
82
43
  "required": [
83
- "tabIdentifier",
84
- "sourcePath",
85
- "destinationPath"
44
+ "tabIdentifier"
45
+ ]
46
+ },
47
+ "DocumentationSearch": {
48
+ "type": "object",
49
+ "properties": {
50
+ "frameworks": {
51
+ "description": "Framework(s) to search in. Searches all frameworks if not specified.",
52
+ "items": {
53
+ "type": "string"
54
+ },
55
+ "type": "array"
56
+ },
57
+ "query": {
58
+ "description": "The search query",
59
+ "type": "string"
60
+ }
61
+ },
62
+ "required": [
63
+ "query"
86
64
  ]
87
65
  },
88
66
  "XcodeRead": {
@@ -110,65 +88,6 @@ const embeddedSchemas = {
110
88
  "filePath"
111
89
  ]
112
90
  },
113
- "RunSomeTests": {
114
- "type": "object",
115
- "properties": {
116
- "tabIdentifier": {
117
- "description": "The workspace tab identifier",
118
- "type": "string"
119
- },
120
- "tests": {
121
- "description": "Array of test specifiers to run. Each specifier contains 'targetName' and 'testIdentifier' fields. Use GetTestList action to discover available tests and their identifiers, then extract the 'targetName' and 'identifier' fields from the TestActionInfo results to construct TestActionSpecifier objects.",
122
- "items": {
123
- "properties": {
124
- "targetName": {
125
- "description": "The test target name",
126
- "type": "string"
127
- },
128
- "testIdentifier": {
129
- "description": "Test identifier in XCTestIdentifier format",
130
- "type": "string"
131
- }
132
- },
133
- "required": [
134
- "targetName",
135
- "testIdentifier"
136
- ],
137
- "type": "object"
138
- },
139
- "type": "array"
140
- }
141
- },
142
- "required": [
143
- "tabIdentifier",
144
- "tests"
145
- ]
146
- },
147
- "XcodeRM": {
148
- "type": "object",
149
- "properties": {
150
- "deleteFiles": {
151
- "description": "Also move the underlying files to Trash (defaults to true)",
152
- "type": "boolean"
153
- },
154
- "path": {
155
- "description": "The project path to remove (e.g., 'ProjectName/Sources/MyFile.swift')",
156
- "type": "string"
157
- },
158
- "recursive": {
159
- "description": "Remove directories and their contents recursively",
160
- "type": "boolean"
161
- },
162
- "tabIdentifier": {
163
- "description": "The workspace tab identifier",
164
- "type": "string"
165
- }
166
- },
167
- "required": [
168
- "tabIdentifier",
169
- "path"
170
- ]
171
- },
172
91
  "XcodeRefreshCodeIssuesInFile": {
173
92
  "type": "object",
174
93
  "properties": {
@@ -215,35 +134,6 @@ const embeddedSchemas = {
215
134
  "tabIdentifier"
216
135
  ]
217
136
  },
218
- "XcodeListWindows": {
219
- "type": "object",
220
- "properties": {},
221
- "required": []
222
- },
223
- "BuildProject": {
224
- "type": "object",
225
- "properties": {
226
- "tabIdentifier": {
227
- "description": "The workspace tab identifier",
228
- "type": "string"
229
- }
230
- },
231
- "required": [
232
- "tabIdentifier"
233
- ]
234
- },
235
- "RunAllTests": {
236
- "type": "object",
237
- "properties": {
238
- "tabIdentifier": {
239
- "description": "The workspace tab identifier",
240
- "type": "string"
241
- }
242
- },
243
- "required": [
244
- "tabIdentifier"
245
- ]
246
- },
247
137
  "XcodeWrite": {
248
138
  "type": "object",
249
139
  "properties": {
@@ -266,6 +156,11 @@ const embeddedSchemas = {
266
156
  "content"
267
157
  ]
268
158
  },
159
+ "XcodeListWindows": {
160
+ "type": "object",
161
+ "properties": {},
162
+ "required": []
163
+ },
269
164
  "XcodeGrep": {
270
165
  "type": "object",
271
166
  "properties": {
@@ -332,63 +227,67 @@ const embeddedSchemas = {
332
227
  "pattern"
333
228
  ]
334
229
  },
335
- "XcodeLS": {
230
+ "RunAllTests": {
336
231
  "type": "object",
337
232
  "properties": {
338
- "ignore": {
339
- "description": "Skip files/folders matching these patterns",
340
- "items": {
341
- "type": "string"
342
- },
343
- "type": "array"
344
- },
345
- "path": {
346
- "description": "The project path to browse (e.g., 'ProjectName/Sources/')",
347
- "type": "string"
348
- },
349
- "recursive": {
350
- "description": "Recursively list all files (truncated to 100 lines). Default: true",
351
- "type": "boolean"
352
- },
353
233
  "tabIdentifier": {
354
234
  "description": "The workspace tab identifier",
355
235
  "type": "string"
356
236
  }
357
237
  },
358
238
  "required": [
359
- "tabIdentifier",
360
- "path"
239
+ "tabIdentifier"
361
240
  ]
362
241
  },
363
- "DocumentationSearch": {
242
+ "ExecuteSnippet": {
364
243
  "type": "object",
365
244
  "properties": {
366
- "frameworks": {
367
- "description": "Framework(s) to search in. Searches all frameworks if not specified.",
368
- "items": {
369
- "type": "string"
370
- },
371
- "type": "array"
245
+ "codeSnippet": {
246
+ "description": "The code snippet that should be executed in the context of the specified file.",
247
+ "type": "string"
372
248
  },
373
- "query": {
374
- "description": "The search query",
249
+ "sourceFilePath": {
250
+ "description": "The path to a Swift source file within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift') whose context the code snippet will have access to (including `fileprivate` declarations).",
251
+ "type": "string"
252
+ },
253
+ "tabIdentifier": {
254
+ "description": "The workspace tab identifier.",
375
255
  "type": "string"
256
+ },
257
+ "timeout": {
258
+ "description": "The time in seconds to wait for the execution of the snippet to complete. Defaults to 120 seconds.",
259
+ "type": "integer"
376
260
  }
377
261
  },
378
262
  "required": [
379
- "query"
263
+ "tabIdentifier",
264
+ "codeSnippet",
265
+ "sourceFilePath"
380
266
  ]
381
267
  },
382
- "GetTestList": {
268
+ "RenderPreview": {
383
269
  "type": "object",
384
270
  "properties": {
271
+ "previewDefinitionIndexInFile": {
272
+ "description": "The zero based index of the #Preview macro or PreviewProvider struct definition in the source file counting from the top. Defaults to 0, i.e. the first one.",
273
+ "type": "integer"
274
+ },
275
+ "sourceFilePath": {
276
+ "description": "The path to the file within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift')",
277
+ "type": "string"
278
+ },
385
279
  "tabIdentifier": {
386
280
  "description": "The workspace tab identifier",
387
281
  "type": "string"
282
+ },
283
+ "timeout": {
284
+ "description": "The time in seconds to wait for the rendering of the preview to complete. Defaults to 120 seconds.",
285
+ "type": "integer"
388
286
  }
389
287
  },
390
288
  "required": [
391
- "tabIdentifier"
289
+ "tabIdentifier",
290
+ "sourceFilePath"
392
291
  ]
393
292
  },
394
293
  "XcodeGlob": {
@@ -411,36 +310,51 @@ const embeddedSchemas = {
411
310
  "tabIdentifier"
412
311
  ]
413
312
  },
414
- "XcodeListNavigatorIssues": {
313
+ "XcodeUpdate": {
415
314
  "type": "object",
416
315
  "properties": {
417
- "glob": {
418
- "description": "Glob to filter the returned issues. Will match against the 'path' field.",
316
+ "filePath": {
317
+ "description": "REQUIRED: The path to the file to modify within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift')",
419
318
  "type": "string"
420
319
  },
421
- "pattern": {
422
- "description": "Regex to filter the returned issues. Will match against the 'message' field.",
320
+ "newString": {
321
+ "description": "REQUIRED: The text to replace it with, must be different from oldString",
423
322
  "type": "string"
424
323
  },
425
- "severity": {
426
- "description": "Limit the returned issues to those that have the specified severity or higher. Valid values in order of decreasing severity are 'error', 'warning', 'remark'. Defaults to 'error'.",
324
+ "oldString": {
325
+ "description": "REQUIRED: The text to replace",
427
326
  "type": "string"
428
327
  },
328
+ "replaceAll": {
329
+ "description": "Replace all occurrences of oldString (default false)",
330
+ "type": "boolean"
331
+ },
429
332
  "tabIdentifier": {
430
333
  "description": "The workspace tab identifier",
431
334
  "type": "string"
432
335
  }
433
336
  },
434
337
  "required": [
435
- "tabIdentifier"
338
+ "tabIdentifier",
339
+ "filePath",
340
+ "oldString",
341
+ "newString"
436
342
  ]
437
343
  },
438
- "XcodeMakeDir": {
344
+ "XcodeRM": {
439
345
  "type": "object",
440
346
  "properties": {
441
- "directoryPath": {
442
- "description": "Project navigator relative path for the directory to create",
443
- "type": "string"
347
+ "deleteFiles": {
348
+ "description": "Also move the underlying files to Trash (defaults to true)",
349
+ "type": "boolean"
350
+ },
351
+ "path": {
352
+ "description": "The project path to remove (e.g., 'ProjectName/Sources/MyFile.swift')",
353
+ "type": "string"
354
+ },
355
+ "recursive": {
356
+ "description": "Remove directories and their contents recursively",
357
+ "type": "boolean"
444
358
  },
445
359
  "tabIdentifier": {
446
360
  "description": "The workspace tab identifier",
@@ -449,76 +363,168 @@ const embeddedSchemas = {
449
363
  },
450
364
  "required": [
451
365
  "tabIdentifier",
452
- "directoryPath"
366
+ "path"
453
367
  ]
454
368
  },
455
- "ExecuteSnippet": {
369
+ "RunSomeTests": {
456
370
  "type": "object",
457
371
  "properties": {
458
- "codeSnippet": {
459
- "description": "The code snippet that should be executed in the context of the specified file.",
372
+ "tabIdentifier": {
373
+ "description": "The workspace tab identifier",
460
374
  "type": "string"
461
375
  },
462
- "sourceFilePath": {
463
- "description": "The path to a Swift source file within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift') whose context the code snippet will have access to (including `fileprivate` declarations).",
376
+ "tests": {
377
+ "description": "Array of test specifiers to run. Each specifier contains 'targetName' and 'testIdentifier' fields. Use GetTestList action to discover available tests and their identifiers, then extract the 'targetName' and 'identifier' fields from the TestActionInfo results to construct TestActionSpecifier objects.",
378
+ "items": {
379
+ "properties": {
380
+ "targetName": {
381
+ "description": "The test target name",
382
+ "type": "string"
383
+ },
384
+ "testIdentifier": {
385
+ "description": "Test identifier in XCTestIdentifier format",
386
+ "type": "string"
387
+ }
388
+ },
389
+ "required": [
390
+ "targetName",
391
+ "testIdentifier"
392
+ ],
393
+ "type": "object"
394
+ },
395
+ "type": "array"
396
+ }
397
+ },
398
+ "required": [
399
+ "tabIdentifier",
400
+ "tests"
401
+ ]
402
+ },
403
+ "XcodeMV": {
404
+ "type": "object",
405
+ "properties": {
406
+ "destinationPath": {
407
+ "description": "Project navigator relative path for the destination (for move) or new name (for rename)",
464
408
  "type": "string"
465
409
  },
466
- "tabIdentifier": {
467
- "description": "The workspace tab identifier.",
410
+ "operation": {
411
+ "description": "The type of move operation to perform",
412
+ "enum": [
413
+ "move",
414
+ "copy"
415
+ ],
468
416
  "type": "string"
469
417
  },
470
- "timeout": {
471
- "description": "The time in seconds to wait for the execution of the snippet to complete. Defaults to 120 seconds.",
472
- "type": "integer"
418
+ "overwriteExisting": {
419
+ "description": "Whether to overwrite existing files at the destination",
420
+ "type": "boolean"
421
+ },
422
+ "sourcePath": {
423
+ "description": "Project navigator relative path of the source item to move/rename",
424
+ "type": "string"
425
+ },
426
+ "tabIdentifier": {
427
+ "description": "The workspace tab identifier",
428
+ "type": "string"
473
429
  }
474
430
  },
475
431
  "required": [
476
432
  "tabIdentifier",
477
- "codeSnippet",
478
- "sourceFilePath"
433
+ "sourcePath",
434
+ "destinationPath"
479
435
  ]
480
436
  },
481
- "RenderPreview": {
437
+ "XcodeLS": {
482
438
  "type": "object",
483
439
  "properties": {
484
- "previewDefinitionIndexInFile": {
485
- "description": "The zero based index of the #Preview macro or PreviewProvider struct definition in the source file counting from the top. Defaults to 0, i.e. the first one.",
486
- "type": "integer"
440
+ "ignore": {
441
+ "description": "Skip files/folders matching these patterns",
442
+ "items": {
443
+ "type": "string"
444
+ },
445
+ "type": "array"
487
446
  },
488
- "sourceFilePath": {
489
- "description": "The path to the file within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift')",
447
+ "path": {
448
+ "description": "The project path to browse (e.g., 'ProjectName/Sources/')",
490
449
  "type": "string"
491
450
  },
451
+ "recursive": {
452
+ "description": "Recursively list all files (truncated to 100 lines). Default: true",
453
+ "type": "boolean"
454
+ },
492
455
  "tabIdentifier": {
493
456
  "description": "The workspace tab identifier",
494
457
  "type": "string"
458
+ }
459
+ },
460
+ "required": [
461
+ "tabIdentifier",
462
+ "path"
463
+ ]
464
+ },
465
+ "XcodeMakeDir": {
466
+ "type": "object",
467
+ "properties": {
468
+ "directoryPath": {
469
+ "description": "Project navigator relative path for the directory to create",
470
+ "type": "string"
495
471
  },
496
- "timeout": {
497
- "description": "The time in seconds to wait for the rendering of the preview to complete. Defaults to 120 seconds.",
498
- "type": "integer"
472
+ "tabIdentifier": {
473
+ "description": "The workspace tab identifier",
474
+ "type": "string"
499
475
  }
500
476
  },
501
477
  "required": [
502
478
  "tabIdentifier",
503
- "sourceFilePath"
479
+ "directoryPath"
480
+ ]
481
+ },
482
+ "XcodeListNavigatorIssues": {
483
+ "type": "object",
484
+ "properties": {
485
+ "glob": {
486
+ "description": "Glob to filter the returned issues. Will match against the 'path' field.",
487
+ "type": "string"
488
+ },
489
+ "pattern": {
490
+ "description": "Regex to filter the returned issues. Will match against the 'message' field.",
491
+ "type": "string"
492
+ },
493
+ "severity": {
494
+ "description": "Limit the returned issues to those that have the specified severity or higher. Valid values in order of decreasing severity are 'error', 'warning', 'remark'. Defaults to 'error'.",
495
+ "type": "string"
496
+ },
497
+ "tabIdentifier": {
498
+ "description": "The workspace tab identifier",
499
+ "type": "string"
500
+ }
501
+ },
502
+ "required": [
503
+ "tabIdentifier"
504
504
  ]
505
505
  }
506
506
  } as const;
507
507
  const embeddedName = "mcpbridge";
508
508
  const embeddedDescription = "xcode-tools";
509
- const generatorInfo = "Generated by xcode-mcp@1.0.0 — https://github.com/steipete/mcporter";
509
+ const generatorInfo = "Generated by xcode-cli@1.0.5 — https://github.com/steipete/mcporter";
510
510
  const generatorTools = [
511
511
  {
512
- "name": "XcodeUpdate",
513
- "description": "Edits files in the Xcode project by replacing text content. Works on Xcode project structure paths, not filesystem paths. IMPORTANT: The tool will fail if filePath, oldString, or newString parameters are missing.",
514
- "usage": "XcodeUpdate --file-path <file-path> --new-string <new-string> --old-string <old-string> [--replace-all <replace-all:true|false>] --tab-identifier <tab-identifier> [--raw <json>]",
515
- "flags": "--file-path <file-path> --new-string <new-string> --old-string <old-string> [--replace-all <replace-all:true|false>] --tab-identifier <tab-identifier> [--raw <json>]"
512
+ "name": "BuildProject",
513
+ "description": "Builds an Xcode project and waits until the build completes.",
514
+ "usage": "BuildProject --tab-identifier <tab-identifier> [--raw <json>]",
515
+ "flags": "--tab-identifier <tab-identifier> [--raw <json>]"
516
516
  },
517
517
  {
518
- "name": "XcodeMV",
519
- "description": "Moves or renames files and directories in the project navigator with support for filesystem operations.",
520
- "usage": "XcodeMV --destination-path <destination-path> [--operation <operation:move|copy>] [--overwrite-existing <overwrite-existing:true|false>] --source-path <source-path> --tab-identifier <tab-identifier> [--raw <json>]",
521
- "flags": "--destination-path <destination-path> [--operation <operation:move|copy>] [--overwrite-existing <overwrite-existing:true|false>] --source-path <source-path> --tab-identifier <tab-identifier> [--raw <json>]"
518
+ "name": "GetTestList",
519
+ "description": "Gets all available tests from the active scheme's active test plan",
520
+ "usage": "GetTestList --tab-identifier <tab-identifier> [--raw <json>]",
521
+ "flags": "--tab-identifier <tab-identifier> [--raw <json>]"
522
+ },
523
+ {
524
+ "name": "DocumentationSearch",
525
+ "description": "Searches Apple Developer Documentation using semantic matching.",
526
+ "usage": "DocumentationSearch [--frameworks <frameworks:value1,value2>] --query <query> [--raw <json>]",
527
+ "flags": "[--frameworks <frameworks:value1,value2>] --query <query> [--raw <json>]"
522
528
  },
523
529
  {
524
530
  "name": "XcodeRead",
@@ -526,18 +532,6 @@ const generatorTools = [
526
532
  "usage": "XcodeRead --file-path <file-path> [--limit <limit:number>] [--offset <offset:number>] --tab-identifier <tab-identifier> [--raw <json>]",
527
533
  "flags": "--file-path <file-path> [--limit <limit:number>] [--offset <offset:number>] --tab-identifier <tab-identifier> [--raw <json>]"
528
534
  },
529
- {
530
- "name": "RunSomeTests",
531
- "description": "Runs specific tests using the active scheme's active test plan",
532
- "usage": "RunSomeTests --tab-identifier <tab-identifier> --tests <tests:value1,value2> [--raw <json>]",
533
- "flags": "--tab-identifier <tab-identifier> --tests <tests:value1,value2> [--raw <json>]"
534
- },
535
- {
536
- "name": "XcodeRM",
537
- "description": "Removes files and directories from the Xcode project structure and optionally deletes the underlying files from the filesystem.",
538
- "usage": "XcodeRM [--delete-files <delete-files:true|false>] --path <path> [--recursive <recursive:true|false>] --tab-identifier <tab-identifier> [--raw <json>]",
539
- "flags": "[--delete-files <delete-files:true|false>] --path <path> [--recursive <recursive:true|false>] --tab-identifier <tab-identifier> [--raw <json>]"
540
- },
541
535
  {
542
536
  "name": "XcodeRefreshCodeIssuesInFile",
543
537
  "description": "Retrieves current compiler diagnostics (errors, warnings, notes) for a file in the Xcode project. Returns formatted diagnostic information including severity levels and messages.",
@@ -550,6 +544,12 @@ const generatorTools = [
550
544
  "usage": "GetBuildLog [--glob <glob>] [--pattern <pattern>] [--severity <severity:remark|warning|error>] --tab-identifier <tab-identifier> [--raw <json>]",
551
545
  "flags": "[--glob <glob>] [--pattern <pattern>] [--severity <severity:remark|warning|error>] --tab-identifier <tab-identifier> [--raw <json>]"
552
546
  },
547
+ {
548
+ "name": "XcodeWrite",
549
+ "description": "Creates or overwrites files with content in the Xcode project. Works on Xcode project structure paths, not filesystem paths. Automatically adds new files to the project structure. Both filePath and content parameters are required.",
550
+ "usage": "XcodeWrite --content <content> --file-path <file-path> --tab-identifier <tab-identifier> [--raw <json>]",
551
+ "flags": "--content <content> --file-path <file-path> --tab-identifier <tab-identifier> [--raw <json>]"
552
+ },
553
553
  {
554
554
  "name": "XcodeListWindows",
555
555
  "description": "Lists the current Xcode windows and their workspace information",
@@ -557,10 +557,10 @@ const generatorTools = [
557
557
  "flags": "[--raw <json>]"
558
558
  },
559
559
  {
560
- "name": "BuildProject",
561
- "description": "Builds an Xcode project and waits until the build completes.",
562
- "usage": "BuildProject --tab-identifier <tab-identifier> [--raw <json>]",
563
- "flags": "--tab-identifier <tab-identifier> [--raw <json>]"
560
+ "name": "XcodeGrep",
561
+ "description": "Searches for text patterns in files within the Xcode project structure using regex. Works on Xcode project organization, not filesystem structure. CRITICAL: Must include a 'pattern' argument - this tool will fail without it.",
562
+ "usage": "XcodeGrep [--glob <glob>] [--head-limit <head-limit:number>] [--ignore-case <ignore-case:true|false>] --pattern <pattern> --tab-identifier <tab-identifier> [--raw <json>]",
563
+ "flags": "[--glob <glob>] [--head-limit <head-limit:number>] [--ignore-case <ignore-case:true|false>] --pattern <pattern> --tab-identifier <tab-identifier> [--raw <json>]"
564
564
  },
565
565
  {
566
566
  "name": "RunAllTests",
@@ -569,46 +569,52 @@ const generatorTools = [
569
569
  "flags": "--tab-identifier <tab-identifier> [--raw <json>]"
570
570
  },
571
571
  {
572
- "name": "XcodeWrite",
573
- "description": "Creates or overwrites files with content in the Xcode project. Works on Xcode project structure paths, not filesystem paths. Automatically adds new files to the project structure. Both filePath and content parameters are required.",
574
- "usage": "XcodeWrite --content <content> --file-path <file-path> --tab-identifier <tab-identifier> [--raw <json>]",
575
- "flags": "--content <content> --file-path <file-path> --tab-identifier <tab-identifier> [--raw <json>]"
572
+ "name": "ExecuteSnippet",
573
+ "description": "Builds and runs a snippet of code in the context of a specific file and waits until results are available. This tool is available for source files in targets that build applications, frameworks, libraries, or command line executables. The output consists of the console output generated by the `print` statements contained in the provided snippet.",
574
+ "usage": "ExecuteSnippet --code-snippet <code-snippet> --source-file-path <source-file-path> --tab-identifier <tab-identifier> [--timeout <timeout:number>] [--raw <json>]",
575
+ "flags": "--code-snippet <code-snippet> --source-file-path <source-file-path> --tab-identifier <tab-identifier> [--timeout <timeout:number>] [--raw <json>]"
576
576
  },
577
577
  {
578
- "name": "XcodeGrep",
579
- "description": "Searches for text patterns in files within the Xcode project structure using regex. Works on Xcode project organization, not filesystem structure. CRITICAL: Must include a 'pattern' argument - this tool will fail without it.",
580
- "usage": "XcodeGrep [--glob <glob>] [--head-limit <head-limit:number>] [--ignore-case <ignore-case:true|false>] --pattern <pattern> --tab-identifier <tab-identifier> [--raw <json>]",
581
- "flags": "[--glob <glob>] [--head-limit <head-limit:number>] [--ignore-case <ignore-case:true|false>] --pattern <pattern> --tab-identifier <tab-identifier> [--raw <json>]"
578
+ "name": "RenderPreview",
579
+ "description": "Builds and renders a Preview and waits until a snapshot of the resulting UI is available.",
580
+ "usage": "RenderPreview [--preview-definition-index-in-file <preview-definition-index-in-file:number>] --source-file-path <source-file-path> --tab-identifier <tab-identifier> [--timeout <timeout:number>] [--raw <json>]",
581
+ "flags": "[--preview-definition-index-in-file <preview-definition-index-in-file:number>] --source-file-path <source-file-path> --tab-identifier <tab-identifier> [--timeout <timeout:number>] [--raw <json>]"
582
582
  },
583
583
  {
584
- "name": "XcodeLS",
585
- "description": "Lists files and directories in the Xcode project structure at the specified path. Works on Xcode project organization, not filesystem structure.",
586
- "usage": "XcodeLS [--ignore <ignore:value1,value2>] --path <path> [--recursive <recursive:true|false>] --tab-identifier <tab-identifier> [--raw <json>]",
587
- "flags": "[--ignore <ignore:value1,value2>] --path <path> [--recursive <recursive:true|false>] --tab-identifier <tab-identifier> [--raw <json>]"
584
+ "name": "XcodeGlob",
585
+ "description": "Finds files in the Xcode project structure matching wildcard patterns. Works on Xcode project organization, not filesystem structure. Example patterns: '*.swift', '**/*.json', 'src/**/*.{swift,m}'. If no pattern is provided, defaults to '**/*' (all files).",
586
+ "usage": "XcodeGlob [--path <path>] [--pattern <pattern>] --tab-identifier <tab-identifier> [--raw <json>]",
587
+ "flags": "[--path <path>] [--pattern <pattern>] --tab-identifier <tab-identifier> [--raw <json>]"
588
588
  },
589
589
  {
590
- "name": "DocumentationSearch",
591
- "description": "Searches Apple Developer Documentation using semantic matching.",
592
- "usage": "DocumentationSearch [--frameworks <frameworks:value1,value2>] --query <query> [--raw <json>]",
593
- "flags": "[--frameworks <frameworks:value1,value2>] --query <query> [--raw <json>]"
590
+ "name": "XcodeUpdate",
591
+ "description": "Edits files in the Xcode project by replacing text content. Works on Xcode project structure paths, not filesystem paths. IMPORTANT: The tool will fail if filePath, oldString, or newString parameters are missing.",
592
+ "usage": "XcodeUpdate --file-path <file-path> --new-string <new-string> --old-string <old-string> [--replace-all <replace-all:true|false>] --tab-identifier <tab-identifier> [--raw <json>]",
593
+ "flags": "--file-path <file-path> --new-string <new-string> --old-string <old-string> [--replace-all <replace-all:true|false>] --tab-identifier <tab-identifier> [--raw <json>]"
594
594
  },
595
595
  {
596
- "name": "GetTestList",
597
- "description": "Gets all available tests from the active scheme's active test plan. Results are limited to 100 tests. The complete list is written to fullTestListPath in grep-friendly format. Use grep with keys like TEST_TARGET, TEST_IDENTIFIER, or TEST_FILE_PATH to find specific tests.",
598
- "usage": "GetTestList --tab-identifier <tab-identifier> [--raw <json>]",
599
- "flags": "--tab-identifier <tab-identifier> [--raw <json>]"
596
+ "name": "XcodeRM",
597
+ "description": "Removes files and directories from the Xcode project structure and optionally deletes the underlying files from the filesystem.",
598
+ "usage": "XcodeRM [--delete-files <delete-files:true|false>] --path <path> [--recursive <recursive:true|false>] --tab-identifier <tab-identifier> [--raw <json>]",
599
+ "flags": "[--delete-files <delete-files:true|false>] --path <path> [--recursive <recursive:true|false>] --tab-identifier <tab-identifier> [--raw <json>]"
600
600
  },
601
601
  {
602
- "name": "XcodeGlob",
603
- "description": "Finds files in the Xcode project structure matching wildcard patterns. Works on Xcode project organization, not filesystem structure. Example patterns: '*.swift', '**/*.json', 'src/**/*.{swift,m}'. If no pattern is provided, defaults to '**/*' (all files).",
604
- "usage": "XcodeGlob [--path <path>] [--pattern <pattern>] --tab-identifier <tab-identifier> [--raw <json>]",
605
- "flags": "[--path <path>] [--pattern <pattern>] --tab-identifier <tab-identifier> [--raw <json>]"
602
+ "name": "RunSomeTests",
603
+ "description": "Runs specific tests using the active scheme's active test plan",
604
+ "usage": "RunSomeTests --tab-identifier <tab-identifier> --tests <tests:value1,value2> [--raw <json>]",
605
+ "flags": "--tab-identifier <tab-identifier> --tests <tests:value1,value2> [--raw <json>]"
606
606
  },
607
607
  {
608
- "name": "XcodeListNavigatorIssues",
609
- "description": "Lists the currently known issues shown Xcode's Issue Navigator UI in the workspace. These issues include those that have been discovered since the last build, and also issues like package resolution problems and workspace configuration issues. You can filter the issues to include by file name, glob, or severity. Use this tool when you want to list all the users the user can see in the workspace UI.",
610
- "usage": "XcodeListNavigatorIssues [--glob <glob>] [--pattern <pattern>] [--severity <severity>] --tab-identifier <tab-identifier> [--raw <json>]",
611
- "flags": "[--glob <glob>] [--pattern <pattern>] [--severity <severity>] --tab-identifier <tab-identifier> [--raw <json>]"
608
+ "name": "XcodeMV",
609
+ "description": "Moves or renames files and directories in the project navigator with support for filesystem operations.",
610
+ "usage": "XcodeMV --destination-path <destination-path> [--operation <operation:move|copy>] [--overwrite-existing <overwrite-existing:true|false>] --source-path <source-path> --tab-identifier <tab-identifier> [--raw <json>]",
611
+ "flags": "--destination-path <destination-path> [--operation <operation:move|copy>] [--overwrite-existing <overwrite-existing:true|false>] --source-path <source-path> --tab-identifier <tab-identifier> [--raw <json>]"
612
+ },
613
+ {
614
+ "name": "XcodeLS",
615
+ "description": "Lists files and directories in the Xcode project structure at the specified path. Works on Xcode project organization, not filesystem structure.",
616
+ "usage": "XcodeLS [--ignore <ignore:value1,value2>] --path <path> [--recursive <recursive:true|false>] --tab-identifier <tab-identifier> [--raw <json>]",
617
+ "flags": "[--ignore <ignore:value1,value2>] --path <path> [--recursive <recursive:true|false>] --tab-identifier <tab-identifier> [--raw <json>]"
612
618
  },
613
619
  {
614
620
  "name": "XcodeMakeDir",
@@ -617,24 +623,18 @@ const generatorTools = [
617
623
  "flags": "--directory-path <directory-path> --tab-identifier <tab-identifier> [--raw <json>]"
618
624
  },
619
625
  {
620
- "name": "ExecuteSnippet",
621
- "description": "Builds and runs a snippet of code in the context of a specific file and waits until results are available. This tool is available for source files in targets that build applications, frameworks, libraries, or command line executables. The output consists of the console output generated by the `print` statements contained in the provided snippet.",
622
- "usage": "ExecuteSnippet --code-snippet <code-snippet> --source-file-path <source-file-path> --tab-identifier <tab-identifier> [--timeout <timeout:number>] [--raw <json>]",
623
- "flags": "--code-snippet <code-snippet> --source-file-path <source-file-path> --tab-identifier <tab-identifier> [--timeout <timeout:number>] [--raw <json>]"
624
- },
625
- {
626
- "name": "RenderPreview",
627
- "description": "Builds and renders a Preview and waits until a snapshot of the resulting UI is available.",
628
- "usage": "RenderPreview [--preview-definition-index-in-file <preview-definition-index-in-file:number>] --source-file-path <source-file-path> --tab-identifier <tab-identifier> [--timeout <timeout:number>] [--raw <json>]",
629
- "flags": "[--preview-definition-index-in-file <preview-definition-index-in-file:number>] --source-file-path <source-file-path> --tab-identifier <tab-identifier> [--timeout <timeout:number>] [--raw <json>]"
626
+ "name": "XcodeListNavigatorIssues",
627
+ "description": "Lists the currently known issues shown Xcode's Issue Navigator UI in the workspace. These issues include those that have been discovered since the last build, and also issues like package resolution problems and workspace configuration issues. You can filter the issues to include by file name, glob, or severity. Use this tool when you want to list all the users the user can see in the workspace UI.",
628
+ "usage": "XcodeListNavigatorIssues [--glob <glob>] [--pattern <pattern>] [--severity <severity>] --tab-identifier <tab-identifier> [--raw <json>]",
629
+ "flags": "[--glob <glob>] [--pattern <pattern>] [--severity <severity>] --tab-identifier <tab-identifier> [--raw <json>]"
630
630
  }
631
631
  ] as const;
632
632
  const embeddedMetadata = {
633
633
  "schemaVersion": 1,
634
- "generatedAt": "2026-02-27T19:58:04.864Z",
634
+ "generatedAt": "2026-03-09T13:46:00.959Z",
635
635
  "generator": {
636
- "name": "xcode-mcp",
637
- "version": "1.0.0"
636
+ "name": "xcode-cli",
637
+ "version": "1.0.5"
638
638
  },
639
639
  "server": {
640
640
  "name": "mcpbridge",
@@ -661,8 +661,8 @@ const embeddedMetadata = {
661
661
  "invocation": {
662
662
  "serverRef": "{\"name\":\"mcpbridge\",\"description\":\"xcode-tools\",\"command\":{\"kind\":\"stdio\",\"command\":\"xcrun\",\"args\":[\"mcpbridge\"]},\"source\":{\"kind\":\"local\",\"path\":\"<adhoc>\"}}",
663
663
  "configPath": "<adhoc>",
664
- "runtime": "node",
665
- "bundler": "rolldown",
664
+ "runtime": "bun",
665
+ "bundler": "bun",
666
666
  "outputPath": "./src/mcpbridge.ts",
667
667
  "timeoutMs": 30000,
668
668
  "minify": false
@@ -675,26 +675,26 @@ program.description(embeddedDescription);
675
675
  program.option('-t, --timeout <ms>', 'Call timeout in milliseconds', (value) => parseInt(value, 10), 30000);
676
676
  program.option('-o, --output <format>', 'Output format: text|markdown|json|raw', 'text');
677
677
  const commandSignatures: Record<string, string> = {
678
- "XcodeUpdate": "function XcodeUpdate(filePath: string, newString: string, oldString: string, replaceAll?: boolean, tabIdentifier: string): object;",
679
- "XcodeMV": "function XcodeMV(destinationPath: string, operation?: \"move\" | \"copy\", overwriteExisting?: boolean, sourcePath: string, tabIdentifier: string): object;",
678
+ "BuildProject": "function BuildProject(tabIdentifier: string): object;",
679
+ "GetTestList": "function GetTestList(tabIdentifier: string): object;",
680
+ "DocumentationSearch": "function DocumentationSearch(frameworks?: string[], query: string): object;",
680
681
  "XcodeRead": "function XcodeRead(filePath: string, limit?: number, offset?: number, tabIdentifier: string): object;",
681
- "RunSomeTests": "function RunSomeTests(tabIdentifier: string, tests: string[]): object;",
682
- "XcodeRM": "function XcodeRM(deleteFiles?: boolean, path: string, recursive?: boolean, tabIdentifier: string): object;",
683
682
  "XcodeRefreshCodeIssuesInFile": "function XcodeRefreshCodeIssuesInFile(filePath: string, tabIdentifier: string): object;",
684
683
  "GetBuildLog": "function GetBuildLog(glob?: string, pattern?: string, severity?: \"remark\" | \"warning\" | \"error\", tabIdentifier: string): object;",
685
- "XcodeListWindows": "function XcodeListWindows(): object;",
686
- "BuildProject": "function BuildProject(tabIdentifier: string): object;",
687
- "RunAllTests": "function RunAllTests(tabIdentifier: string): object;",
688
684
  "XcodeWrite": "function XcodeWrite(content: string, filePath: string, tabIdentifier: string): object;",
685
+ "XcodeListWindows": "function XcodeListWindows(): object;",
689
686
  "XcodeGrep": "function XcodeGrep(glob?: string, headLimit?: number, ignoreCase?: boolean, pattern: string, tabIdentifier: string): object;",
690
- "XcodeLS": "function XcodeLS(ignore?: string[], path: string, recursive?: boolean, tabIdentifier: string): object;",
691
- "DocumentationSearch": "function DocumentationSearch(frameworks?: string[], query: string): object;",
692
- "GetTestList": "function GetTestList(tabIdentifier: string): object;",
687
+ "RunAllTests": "function RunAllTests(tabIdentifier: string): object;",
688
+ "ExecuteSnippet": "function ExecuteSnippet(codeSnippet: string, sourceFilePath: string, tabIdentifier: string, timeout?: number): object;",
689
+ "RenderPreview": "function RenderPreview(previewDefinitionIndexInFile?: number, sourceFilePath: string, tabIdentifier: string, timeout?: number): object;",
693
690
  "XcodeGlob": "function XcodeGlob(path?: string, pattern?: string, tabIdentifier: string): object;",
694
- "XcodeListNavigatorIssues": "function XcodeListNavigatorIssues(glob?: string, pattern?: string, severity?: string, tabIdentifier: string): object;",
691
+ "XcodeUpdate": "function XcodeUpdate(filePath: string, newString: string, oldString: string, replaceAll?: boolean, tabIdentifier: string): object;",
692
+ "XcodeRM": "function XcodeRM(deleteFiles?: boolean, path: string, recursive?: boolean, tabIdentifier: string): object;",
693
+ "RunSomeTests": "function RunSomeTests(tabIdentifier: string, tests: string[]): object;",
694
+ "XcodeMV": "function XcodeMV(destinationPath: string, operation?: \"move\" | \"copy\", overwriteExisting?: boolean, sourcePath: string, tabIdentifier: string): object;",
695
+ "XcodeLS": "function XcodeLS(ignore?: string[], path: string, recursive?: boolean, tabIdentifier: string): object;",
695
696
  "XcodeMakeDir": "function XcodeMakeDir(directoryPath: string, tabIdentifier: string): object;",
696
- "ExecuteSnippet": "function ExecuteSnippet(codeSnippet: string, sourceFilePath: string, tabIdentifier: string, timeout?: number): object;",
697
- "RenderPreview": "function RenderPreview(previewDefinitionIndexInFile?: number, sourceFilePath: string, tabIdentifier: string, timeout?: number): object;"
697
+ "XcodeListNavigatorIssues": "function XcodeListNavigatorIssues(glob?: string, pattern?: string, severity?: string, tabIdentifier: string): object;"
698
698
  };
699
699
  program.configureHelp({
700
700
  commandTerm(cmd) {
@@ -705,51 +705,12 @@ program.configureHelp({
705
705
  program.showSuggestionAfterError(true);
706
706
 
707
707
  program
708
- .command("XcodeUpdate")
709
- .summary("XcodeUpdate --file-path <file-path> --new-string <new-string> --old-string <old-string> [--replace-all <replace-all:true|false>] --tab-identifier <tab-identifier> [--raw <json>]")
710
- .description("Edits files in the Xcode project by replacing text content. Works on Xcode project structure paths, not filesystem paths. IMPORTANT: The tool will fail if filePath, oldString, or newString parameters are missing.")
711
- .usage("--file-path <file-path> --new-string <new-string> --old-string <old-string> [--replace-all <replace-all:true|false>] --tab-identifier <tab-identifier> [--raw <json>]")
712
- .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
713
-
714
- .requiredOption("--file-path <file-path>", "REQUIRED: The path to the file to modify within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift') (example: /path/to/file.md)")
715
- .requiredOption("--new-string <new-string>", "REQUIRED: The text to replace it with, must be different from oldString")
716
- .requiredOption("--old-string <old-string>", "REQUIRED: The text to replace")
717
- .option("--replace-all <replace-all:true|false>", "Replace all occurrences of oldString (default false) (example: true)", (value) => value !== 'false')
718
- .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
719
- .action(async (cmdOpts) => {
720
- const globalOptions = program.opts();
721
- const runtime = await ensureRuntime();
722
- const serverName = embeddedName;
723
- const proxy = createServerProxy(runtime, serverName, {
724
- initialSchemas: embeddedSchemas,
725
- });
726
- try {
727
- const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
728
- if (cmdOpts.filePath !== undefined) args.filePath = cmdOpts.filePath;
729
- if (cmdOpts.newString !== undefined) args.newString = cmdOpts.newString;
730
- if (cmdOpts.oldString !== undefined) args.oldString = cmdOpts.oldString;
731
- if (cmdOpts.replaceAll !== undefined) args.replaceAll = cmdOpts.replaceAll;
732
- if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
733
- const call = (proxy.xcodeUpdate as any)(args);
734
- const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
735
- printResult(result, globalOptions.output ?? 'text');
736
- } finally {
737
- await runtime.close(serverName).catch(() => {});
738
- }
739
- })
740
- .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeUpdate(filePath: \"/path/to/file.md\", newStrin, ...)");
741
-
742
- program
743
- .command("XcodeMV")
744
- .summary("XcodeMV --destination-path <destination-path> [--operation <operation:move|copy>] [--overwrite-existing <overwrite-existing:true|false>] --source-path <source-path> --tab-identifier <tab-identifier> [--raw <json>]")
745
- .description("Moves or renames files and directories in the project navigator with support for filesystem operations.")
746
- .usage("--destination-path <destination-path> [--operation <operation:move|copy>] [--overwrite-existing <overwrite-existing:true|false>] --source-path <source-path> --tab-identifier <tab-identifier> [--raw <json>]")
708
+ .command("BuildProject")
709
+ .summary("BuildProject --tab-identifier <tab-identifier> [--raw <json>]")
710
+ .description("Builds an Xcode project and waits until the build completes.")
711
+ .usage("--tab-identifier <tab-identifier> [--raw <json>]")
747
712
  .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
748
713
 
749
- .requiredOption("--destination-path <destination-path>", "Project navigator relative path for the destination (for move) or new name (for rename) (example: /path/to/file.md)")
750
- .option("--operation <operation:move|copy>", "The type of move operation to perform (choices: move, copy; example: move)")
751
- .option("--overwrite-existing <overwrite-existing:true|false>", "Whether to overwrite existing files at the destination (example: true)", (value) => value !== 'false')
752
- .requiredOption("--source-path <source-path>", "Project navigator relative path of the source item to move/rename (example: /path/to/file.md)")
753
714
  .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
754
715
  .action(async (cmdOpts) => {
755
716
  const globalOptions = program.opts();
@@ -760,30 +721,23 @@ program
760
721
  });
761
722
  try {
762
723
  const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
763
- if (cmdOpts.destinationPath !== undefined) args.destinationPath = cmdOpts.destinationPath;
764
- if (cmdOpts.operation !== undefined) args.operation = cmdOpts.operation;
765
- if (cmdOpts.overwriteExisting !== undefined) args.overwriteExisting = cmdOpts.overwriteExisting;
766
- if (cmdOpts.sourcePath !== undefined) args.sourcePath = cmdOpts.sourcePath;
767
- if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
768
- const call = (proxy.xcodeMV as any)(args);
724
+ if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
725
+ const call = (proxy.buildProject as any)(args);
769
726
  const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
770
727
  printResult(result, globalOptions.output ?? 'text');
771
728
  } finally {
772
729
  await runtime.close(serverName).catch(() => {});
773
730
  }
774
731
  })
775
- .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeMV(destinationPath: \"/path/to/file.md\", opera, ...)");
732
+ .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.BuildProject(tabIdentifier: \"example-id\")");
776
733
 
777
734
  program
778
- .command("XcodeRead")
779
- .summary("XcodeRead --file-path <file-path> [--limit <limit:number>] [--offset <offset:number>] --tab-identifier <tab-identifier> [--raw <json>]")
780
- .description("Reads the contents of a file within the Xcode project organization. Returns content in cat -n format with line numbers. Supports reading up to 600 lines by default with optional offset and limit parameters for large files.")
781
- .usage("--file-path <file-path> [--limit <limit:number>] [--offset <offset:number>] --tab-identifier <tab-identifier> [--raw <json>]")
735
+ .command("GetTestList")
736
+ .summary("GetTestList --tab-identifier <tab-identifier> [--raw <json>]")
737
+ .description("Gets all available tests from the active scheme's active test plan")
738
+ .usage("--tab-identifier <tab-identifier> [--raw <json>]")
782
739
  .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
783
740
 
784
- .requiredOption("--file-path <file-path>", "The path to the file within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift') (example: /path/to/file.md)")
785
- .option("--limit <limit:number>", "The number of lines to read (only provide if the file is too large to read at once) (example: 1)", (value) => parseFloat(value))
786
- .option("--offset <offset:number>", "The line number to start reading from (only provide if the file is too large to read at once) (example: 1)", (value) => parseFloat(value))
787
741
  .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
788
742
  .action(async (cmdOpts) => {
789
743
  const globalOptions = program.opts();
@@ -794,28 +748,25 @@ program
794
748
  });
795
749
  try {
796
750
  const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
797
- if (cmdOpts.filePath !== undefined) args.filePath = cmdOpts.filePath;
798
- if (cmdOpts.limit !== undefined) args.limit = cmdOpts.limit;
799
- if (cmdOpts.offset !== undefined) args.offset = cmdOpts.offset;
800
- if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
801
- const call = (proxy.xcodeRead as any)(args);
751
+ if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
752
+ const call = (proxy.getTestList as any)(args);
802
753
  const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
803
754
  printResult(result, globalOptions.output ?? 'text');
804
755
  } finally {
805
756
  await runtime.close(serverName).catch(() => {});
806
757
  }
807
758
  })
808
- .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeRead(filePath: \"/path/to/file.md\", limit: 1, ...)");
759
+ .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.GetTestList(tabIdentifier: \"example-id\")");
809
760
 
810
761
  program
811
- .command("RunSomeTests")
812
- .summary("RunSomeTests --tab-identifier <tab-identifier> --tests <tests:value1,value2> [--raw <json>]")
813
- .description("Runs specific tests using the active scheme's active test plan")
814
- .usage("--tab-identifier <tab-identifier> --tests <tests:value1,value2> [--raw <json>]")
762
+ .command("DocumentationSearch")
763
+ .summary("DocumentationSearch [--frameworks <frameworks:value1,value2>] --query <query> [--raw <json>]")
764
+ .description("Searches Apple Developer Documentation using semantic matching.")
765
+ .usage("[--frameworks <frameworks:value1,value2>] --query <query> [--raw <json>]")
815
766
  .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
816
767
 
817
- .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
818
- .requiredOption("--tests <tests:value1,value2>", "Array of test specifiers to run. Each specifier contains 'targetName' and 'testIdentifier' fields. Use GetTestList action to discover available tests and their identifiers, then extract the 'targetName' and 'identifier' fields from the TestActionInfo results to construct TestActionSpecifier objects. (example: value1,value2)", (value) => value.split(',').map((v) => v.trim()))
768
+ .option("--frameworks <frameworks:value1,value2>", "Framework(s) to search in. Searches all frameworks if not specified. (example: value1,value2)", (value) => value.split(',').map((v) => v.trim()))
769
+ .requiredOption("--query <query>", "The search query")
819
770
  .action(async (cmdOpts) => {
820
771
  const globalOptions = program.opts();
821
772
  const runtime = await ensureRuntime();
@@ -825,27 +776,27 @@ program
825
776
  });
826
777
  try {
827
778
  const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
828
- if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
829
- if (cmdOpts.tests !== undefined) args.tests = cmdOpts.tests;
830
- const call = (proxy.runSomeTests as any)(args);
779
+ if (cmdOpts.frameworks !== undefined) args.frameworks = cmdOpts.frameworks;
780
+ if (cmdOpts.query !== undefined) args.query = cmdOpts.query;
781
+ const call = (proxy.documentationSearch as any)(args);
831
782
  const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
832
783
  printResult(result, globalOptions.output ?? 'text');
833
784
  } finally {
834
785
  await runtime.close(serverName).catch(() => {});
835
786
  }
836
787
  })
837
- .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.RunSomeTests(tabIdentifier: \"example-id\", tests: [, ...)");
788
+ .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.DocumentationSearch(frameworks: [\"value1\", \"value2, ...)");
838
789
 
839
790
  program
840
- .command("XcodeRM")
841
- .summary("XcodeRM [--delete-files <delete-files:true|false>] --path <path> [--recursive <recursive:true|false>] --tab-identifier <tab-identifier> [--raw <json>]")
842
- .description("Removes files and directories from the Xcode project structure and optionally deletes the underlying files from the filesystem.")
843
- .usage("[--delete-files <delete-files:true|false>] --path <path> [--recursive <recursive:true|false>] --tab-identifier <tab-identifier> [--raw <json>]")
791
+ .command("XcodeRead")
792
+ .summary("XcodeRead --file-path <file-path> [--limit <limit:number>] [--offset <offset:number>] --tab-identifier <tab-identifier> [--raw <json>]")
793
+ .description("Reads the contents of a file within the Xcode project organization. Returns content in cat -n format with line numbers. Supports reading up to 600 lines by default with optional offset and limit parameters for large files.")
794
+ .usage("--file-path <file-path> [--limit <limit:number>] [--offset <offset:number>] --tab-identifier <tab-identifier> [--raw <json>]")
844
795
  .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
845
796
 
846
- .option("--delete-files <delete-files:true|false>", "Also move the underlying files to Trash (defaults to true) (example: true)", (value) => value !== 'false')
847
- .requiredOption("--path <path>", "The project path to remove (e.g., 'ProjectName/Sources/MyFile.swift') (example: /path/to/file.md)")
848
- .option("--recursive <recursive:true|false>", "Remove directories and their contents recursively (example: true)", (value) => value !== 'false')
797
+ .requiredOption("--file-path <file-path>", "The path to the file within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift') (example: /path/to/file.md)")
798
+ .option("--limit <limit:number>", "The number of lines to read (only provide if the file is too large to read at once) (example: 1)", (value) => parseFloat(value))
799
+ .option("--offset <offset:number>", "The line number to start reading from (only provide if the file is too large to read at once) (example: 1)", (value) => parseFloat(value))
849
800
  .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
850
801
  .action(async (cmdOpts) => {
851
802
  const globalOptions = program.opts();
@@ -856,18 +807,18 @@ program
856
807
  });
857
808
  try {
858
809
  const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
859
- if (cmdOpts.deleteFiles !== undefined) args.deleteFiles = cmdOpts.deleteFiles;
860
- if (cmdOpts.path !== undefined) args.path = cmdOpts.path;
861
- if (cmdOpts.recursive !== undefined) args.recursive = cmdOpts.recursive;
810
+ if (cmdOpts.filePath !== undefined) args.filePath = cmdOpts.filePath;
811
+ if (cmdOpts.limit !== undefined) args.limit = cmdOpts.limit;
812
+ if (cmdOpts.offset !== undefined) args.offset = cmdOpts.offset;
862
813
  if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
863
- const call = (proxy.xcodeRM as any)(args);
814
+ const call = (proxy.xcodeRead as any)(args);
864
815
  const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
865
816
  printResult(result, globalOptions.output ?? 'text');
866
817
  } finally {
867
818
  await runtime.close(serverName).catch(() => {});
868
819
  }
869
820
  })
870
- .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeRM(deleteFiles: true, path: \"/path/to/file.md, ...)");
821
+ .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeRead(filePath: \"/path/to/file.md\", limit: 1, ...)");
871
822
 
872
823
  program
873
824
  .command("XcodeRefreshCodeIssuesInFile")
@@ -931,6 +882,37 @@ program
931
882
  })
932
883
  .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.GetBuildLog(severity: \"remark\", tabIdentifier: \"ex, ...)");
933
884
 
885
+ program
886
+ .command("XcodeWrite")
887
+ .summary("XcodeWrite --content <content> --file-path <file-path> --tab-identifier <tab-identifier> [--raw <json>]")
888
+ .description("Creates or overwrites files with content in the Xcode project. Works on Xcode project structure paths, not filesystem paths. Automatically adds new files to the project structure. Both filePath and content parameters are required.")
889
+ .usage("--content <content> --file-path <file-path> --tab-identifier <tab-identifier> [--raw <json>]")
890
+ .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
891
+
892
+ .requiredOption("--content <content>", "REQUIRED: The content to write to the file")
893
+ .requiredOption("--file-path <file-path>", "REQUIRED: The path to the file within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift') (example: /path/to/file.md)")
894
+ .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (required) (example: example-id)")
895
+ .action(async (cmdOpts) => {
896
+ const globalOptions = program.opts();
897
+ const runtime = await ensureRuntime();
898
+ const serverName = embeddedName;
899
+ const proxy = createServerProxy(runtime, serverName, {
900
+ initialSchemas: embeddedSchemas,
901
+ });
902
+ try {
903
+ const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
904
+ if (cmdOpts.content !== undefined) args.content = cmdOpts.content;
905
+ if (cmdOpts.filePath !== undefined) args.filePath = cmdOpts.filePath;
906
+ if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
907
+ const call = (proxy.xcodeWrite as any)(args);
908
+ const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
909
+ printResult(result, globalOptions.output ?? 'text');
910
+ } finally {
911
+ await runtime.close(serverName).catch(() => {});
912
+ }
913
+ })
914
+ .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeWrite(content: \"value\", filePath: \"/path/to/f, ...)");
915
+
934
916
  program
935
917
  .command("XcodeListWindows")
936
918
  .summary("XcodeListWindows [--raw <json>]")
@@ -958,13 +940,25 @@ program
958
940
  .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeListWindows()");
959
941
 
960
942
  program
961
- .command("BuildProject")
962
- .summary("BuildProject --tab-identifier <tab-identifier> [--raw <json>]")
963
- .description("Builds an Xcode project and waits until the build completes.")
964
- .usage("--tab-identifier <tab-identifier> [--raw <json>]")
943
+ .command("XcodeGrep")
944
+ .summary("XcodeGrep [--glob <glob>] [--head-limit <head-limit:number>] [--ignore-case <ignore-case:true|false>] --pattern <pattern> --tab-identifier <tab-identifier> [--raw <json>]")
945
+ .description("Searches for text patterns in files within the Xcode project structure using regex. Works on Xcode project organization, not filesystem structure. CRITICAL: Must include a 'pattern' argument - this tool will fail without it.")
946
+ .usage("[--glob <glob>] [--head-limit <head-limit:number>] [--ignore-case <ignore-case:true|false>] --pattern <pattern> --tab-identifier <tab-identifier> [--raw <json>]")
965
947
  .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
966
948
 
949
+ .option("--glob <glob>", "Only search files matching this pattern")
950
+ .option("--head-limit <head-limit:number>", "Stop after N results (example: 1)", (value) => parseFloat(value))
951
+ .option("--ignore-case <ignore-case:true|false>", "Ignore case when matching (example: true)", (value) => value !== 'false')
952
+ .option("--lines-after <lines-after:number>", "Show N lines after each match for context (example: 1)", (value) => parseFloat(value))
953
+ .option("--lines-before <lines-before:number>", "Show N lines before each match for context (example: 1)", (value) => parseFloat(value))
954
+ .option("--lines-context <lines-context:number>", "Show N lines both before and after each match (example: 1)", (value) => parseFloat(value))
955
+ .option("--multiline <multiline:true|false>", "Allow patterns to span multiple lines (example: true)", (value) => value !== 'false')
956
+ .option("--output-mode <output-mode:content|filesWithMatches|count>", "What to return: content, files_with_matches, or count (default: files_with_matches) (choices: content, filesWithMatches, count; example: content)")
957
+ .option("--path <path>", "Where to search - file or directory in project (defaults to root) (example: /path/to/file.md)")
958
+ .requiredOption("--pattern <pattern>", "Text to search for using regex. REQUIRED: Must include a 'pattern' argument - this tool will fail without it.")
959
+ .option("--show-line-numbers <show-line-numbers:true|false>", "Show line numbers with results (content mode only) (example: true)", (value) => value !== 'false')
967
960
  .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
961
+ .option("--type <type>", "Shortcut for common file types (swift, js, py, etc.)")
968
962
  .action(async (cmdOpts) => {
969
963
  const globalOptions = program.opts();
970
964
  const runtime = await ensureRuntime();
@@ -974,15 +968,28 @@ program
974
968
  });
975
969
  try {
976
970
  const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
977
- if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
978
- const call = (proxy.buildProject as any)(args);
971
+ if (cmdOpts.glob !== undefined) args.glob = cmdOpts.glob;
972
+ if (cmdOpts.headLimit !== undefined) args.headLimit = cmdOpts.headLimit;
973
+ if (cmdOpts.ignoreCase !== undefined) args.ignoreCase = cmdOpts.ignoreCase;
974
+ if (cmdOpts.linesAfter !== undefined) args.linesAfter = cmdOpts.linesAfter;
975
+ if (cmdOpts.linesBefore !== undefined) args.linesBefore = cmdOpts.linesBefore;
976
+ if (cmdOpts.linesContext !== undefined) args.linesContext = cmdOpts.linesContext;
977
+ if (cmdOpts.multiline !== undefined) args.multiline = cmdOpts.multiline;
978
+ if (cmdOpts.outputMode !== undefined) args.outputMode = cmdOpts.outputMode;
979
+ if (cmdOpts.path !== undefined) args.path = cmdOpts.path;
980
+ if (cmdOpts.pattern !== undefined) args.pattern = cmdOpts.pattern;
981
+ if (cmdOpts.showLineNumbers !== undefined) args.showLineNumbers = cmdOpts.showLineNumbers;
982
+ if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
983
+ if (cmdOpts.type !== undefined) args.type = cmdOpts.type;
984
+ const call = (proxy.xcodeGrep as any)(args);
979
985
  const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
980
986
  printResult(result, globalOptions.output ?? 'text');
981
987
  } finally {
982
988
  await runtime.close(serverName).catch(() => {});
983
989
  }
984
990
  })
985
- .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.BuildProject(tabIdentifier: \"example-id\")");
991
+ .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeGrep(headLimit: 1, ignoreCase: true, pattern:, ...)")
992
+ .addHelpText('afterAll', () => '\n' + "// optional (8): linesAfter, linesBefore, linesContext, multiline, outputMode, ..." + '\n');
986
993
 
987
994
  program
988
995
  .command("RunAllTests")
@@ -1012,15 +1019,16 @@ program
1012
1019
  .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.RunAllTests(tabIdentifier: \"example-id\")");
1013
1020
 
1014
1021
  program
1015
- .command("XcodeWrite")
1016
- .summary("XcodeWrite --content <content> --file-path <file-path> --tab-identifier <tab-identifier> [--raw <json>]")
1017
- .description("Creates or overwrites files with content in the Xcode project. Works on Xcode project structure paths, not filesystem paths. Automatically adds new files to the project structure. Both filePath and content parameters are required.")
1018
- .usage("--content <content> --file-path <file-path> --tab-identifier <tab-identifier> [--raw <json>]")
1022
+ .command("ExecuteSnippet")
1023
+ .summary("ExecuteSnippet --code-snippet <code-snippet> --source-file-path <source-file-path> --tab-identifier <tab-identifier> [--timeout <timeout:number>] [--raw <json>]")
1024
+ .description("Builds and runs a snippet of code in the context of a specific file and waits until results are available. This tool is available for source files in targets that build applications, frameworks, libraries, or command line executables. The output consists of the console output generated by the `print` statements contained in the provided snippet.")
1025
+ .usage("--code-snippet <code-snippet> --source-file-path <source-file-path> --tab-identifier <tab-identifier> [--timeout <timeout:number>] [--raw <json>]")
1019
1026
  .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
1020
1027
 
1021
- .requiredOption("--content <content>", "REQUIRED: The content to write to the file")
1022
- .requiredOption("--file-path <file-path>", "REQUIRED: The path to the file within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift') (example: /path/to/file.md)")
1023
- .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (required) (example: example-id)")
1028
+ .requiredOption("--code-snippet <code-snippet>", "The code snippet that should be executed in the context of the specified file.")
1029
+ .requiredOption("--source-file-path <source-file-path>", "The path to a Swift source file within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift') whose context the code snippet will have access to (including `fileprivate` declarations). (example: /path/to/file.md)")
1030
+ .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier. (example: example-id)")
1031
+ .option("--timeout <timeout:number>", "The time in seconds to wait for the execution of the snippet to complete. Defaults to 120 seconds. (example: 1)", (value) => parseFloat(value))
1024
1032
  .action(async (cmdOpts) => {
1025
1033
  const globalOptions = program.opts();
1026
1034
  const runtime = await ensureRuntime();
@@ -1030,38 +1038,30 @@ program
1030
1038
  });
1031
1039
  try {
1032
1040
  const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
1033
- if (cmdOpts.content !== undefined) args.content = cmdOpts.content;
1034
- if (cmdOpts.filePath !== undefined) args.filePath = cmdOpts.filePath;
1041
+ if (cmdOpts.codeSnippet !== undefined) args.codeSnippet = cmdOpts.codeSnippet;
1042
+ if (cmdOpts.sourceFilePath !== undefined) args.sourceFilePath = cmdOpts.sourceFilePath;
1035
1043
  if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
1036
- const call = (proxy.xcodeWrite as any)(args);
1044
+ if (cmdOpts.timeout !== undefined) args.timeout = cmdOpts.timeout;
1045
+ const call = (proxy.executeSnippet as any)(args);
1037
1046
  const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
1038
1047
  printResult(result, globalOptions.output ?? 'text');
1039
1048
  } finally {
1040
1049
  await runtime.close(serverName).catch(() => {});
1041
1050
  }
1042
1051
  })
1043
- .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeWrite(content: \"value\", filePath: \"/path/to/f, ...)");
1052
+ .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.ExecuteSnippet(codeSnippet: \"value\", sourceFilePat, ...)");
1044
1053
 
1045
1054
  program
1046
- .command("XcodeGrep")
1047
- .summary("XcodeGrep [--glob <glob>] [--head-limit <head-limit:number>] [--ignore-case <ignore-case:true|false>] --pattern <pattern> --tab-identifier <tab-identifier> [--raw <json>]")
1048
- .description("Searches for text patterns in files within the Xcode project structure using regex. Works on Xcode project organization, not filesystem structure. CRITICAL: Must include a 'pattern' argument - this tool will fail without it.")
1049
- .usage("[--glob <glob>] [--head-limit <head-limit:number>] [--ignore-case <ignore-case:true|false>] --pattern <pattern> --tab-identifier <tab-identifier> [--raw <json>]")
1055
+ .command("RenderPreview")
1056
+ .summary("RenderPreview [--preview-definition-index-in-file <preview-definition-index-in-file:number>] --source-file-path <source-file-path> --tab-identifier <tab-identifier> [--timeout <timeout:number>] [--raw <json>]")
1057
+ .description("Builds and renders a Preview and waits until a snapshot of the resulting UI is available.")
1058
+ .usage("[--preview-definition-index-in-file <preview-definition-index-in-file:number>] --source-file-path <source-file-path> --tab-identifier <tab-identifier> [--timeout <timeout:number>] [--raw <json>]")
1050
1059
  .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
1051
1060
 
1052
- .option("--glob <glob>", "Only search files matching this pattern")
1053
- .option("--head-limit <head-limit:number>", "Stop after N results (example: 1)", (value) => parseFloat(value))
1054
- .option("--ignore-case <ignore-case:true|false>", "Ignore case when matching (example: true)", (value) => value !== 'false')
1055
- .option("--lines-after <lines-after:number>", "Show N lines after each match for context (example: 1)", (value) => parseFloat(value))
1056
- .option("--lines-before <lines-before:number>", "Show N lines before each match for context (example: 1)", (value) => parseFloat(value))
1057
- .option("--lines-context <lines-context:number>", "Show N lines both before and after each match (example: 1)", (value) => parseFloat(value))
1058
- .option("--multiline <multiline:true|false>", "Allow patterns to span multiple lines (example: true)", (value) => value !== 'false')
1059
- .option("--output-mode <output-mode:content|filesWithMatches|count>", "What to return: content, files_with_matches, or count (default: files_with_matches) (choices: content, filesWithMatches, count; example: content)")
1060
- .option("--path <path>", "Where to search - file or directory in project (defaults to root) (example: /path/to/file.md)")
1061
- .requiredOption("--pattern <pattern>", "Text to search for using regex. REQUIRED: Must include a 'pattern' argument - this tool will fail without it.")
1062
- .option("--show-line-numbers <show-line-numbers:true|false>", "Show line numbers with results (content mode only) (example: true)", (value) => value !== 'false')
1061
+ .option("--preview-definition-index-in-file <preview-definition-index-in-file:number>", "The zero based index of the #Preview macro or PreviewProvider struct definition in the source file counting from the top. Defaults to 0, i.e. the first one. (example: 1)", (value) => parseFloat(value))
1062
+ .requiredOption("--source-file-path <source-file-path>", "The path to the file within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift') (example: /path/to/file.md)")
1063
1063
  .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
1064
- .option("--type <type>", "Shortcut for common file types (swift, js, py, etc.)")
1064
+ .option("--timeout <timeout:number>", "The time in seconds to wait for the rendering of the preview to complete. Defaults to 120 seconds. (example: 1)", (value) => parseFloat(value))
1065
1065
  .action(async (cmdOpts) => {
1066
1066
  const globalOptions = program.opts();
1067
1067
  const runtime = await ensureRuntime();
@@ -1071,39 +1071,28 @@ program
1071
1071
  });
1072
1072
  try {
1073
1073
  const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
1074
- if (cmdOpts.glob !== undefined) args.glob = cmdOpts.glob;
1075
- if (cmdOpts.headLimit !== undefined) args.headLimit = cmdOpts.headLimit;
1076
- if (cmdOpts.ignoreCase !== undefined) args.ignoreCase = cmdOpts.ignoreCase;
1077
- if (cmdOpts.linesAfter !== undefined) args.linesAfter = cmdOpts.linesAfter;
1078
- if (cmdOpts.linesBefore !== undefined) args.linesBefore = cmdOpts.linesBefore;
1079
- if (cmdOpts.linesContext !== undefined) args.linesContext = cmdOpts.linesContext;
1080
- if (cmdOpts.multiline !== undefined) args.multiline = cmdOpts.multiline;
1081
- if (cmdOpts.outputMode !== undefined) args.outputMode = cmdOpts.outputMode;
1082
- if (cmdOpts.path !== undefined) args.path = cmdOpts.path;
1083
- if (cmdOpts.pattern !== undefined) args.pattern = cmdOpts.pattern;
1084
- if (cmdOpts.showLineNumbers !== undefined) args.showLineNumbers = cmdOpts.showLineNumbers;
1074
+ if (cmdOpts.previewDefinitionIndexInFile !== undefined) args.previewDefinitionIndexInFile = cmdOpts.previewDefinitionIndexInFile;
1075
+ if (cmdOpts.sourceFilePath !== undefined) args.sourceFilePath = cmdOpts.sourceFilePath;
1085
1076
  if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
1086
- if (cmdOpts.type !== undefined) args.type = cmdOpts.type;
1087
- const call = (proxy.xcodeGrep as any)(args);
1077
+ if (cmdOpts.timeout !== undefined) args.timeout = cmdOpts.timeout;
1078
+ const call = (proxy.renderPreview as any)(args);
1088
1079
  const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
1089
1080
  printResult(result, globalOptions.output ?? 'text');
1090
1081
  } finally {
1091
1082
  await runtime.close(serverName).catch(() => {});
1092
1083
  }
1093
1084
  })
1094
- .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeGrep(headLimit: 1, ignoreCase: true, pattern:, ...)")
1095
- .addHelpText('afterAll', () => '\n' + "// optional (8): linesAfter, linesBefore, linesContext, multiline, outputMode, ..." + '\n');
1085
+ .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.RenderPreview(previewDefinitionIndexInFile: 1, sou, ...)");
1096
1086
 
1097
1087
  program
1098
- .command("XcodeLS")
1099
- .summary("XcodeLS [--ignore <ignore:value1,value2>] --path <path> [--recursive <recursive:true|false>] --tab-identifier <tab-identifier> [--raw <json>]")
1100
- .description("Lists files and directories in the Xcode project structure at the specified path. Works on Xcode project organization, not filesystem structure.")
1101
- .usage("[--ignore <ignore:value1,value2>] --path <path> [--recursive <recursive:true|false>] --tab-identifier <tab-identifier> [--raw <json>]")
1088
+ .command("XcodeGlob")
1089
+ .summary("XcodeGlob [--path <path>] [--pattern <pattern>] --tab-identifier <tab-identifier> [--raw <json>]")
1090
+ .description("Finds files in the Xcode project structure matching wildcard patterns. Works on Xcode project organization, not filesystem structure. Example patterns: '*.swift', '**/*.json', 'src/**/*.{swift,m}'. If no pattern is provided, defaults to '**/*' (all files).")
1091
+ .usage("[--path <path>] [--pattern <pattern>] --tab-identifier <tab-identifier> [--raw <json>]")
1102
1092
  .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
1103
1093
 
1104
- .option("--ignore <ignore:value1,value2>", "Skip files/folders matching these patterns (example: value1,value2)", (value) => value.split(',').map((v) => v.trim()))
1105
- .requiredOption("--path <path>", "The project path to browse (e.g., 'ProjectName/Sources/') (example: /path/to/file.md)")
1106
- .option("--recursive <recursive:true|false>", "Recursively list all files (truncated to 100 lines). Default: true (example: true)", (value) => value !== 'false')
1094
+ .option("--path <path>", "Which project directory to search in (optional, defaults to root) (example: /path/to/file.md)")
1095
+ .option("--pattern <pattern>", "File matching pattern using wildcards (* ** ? [abc] {swift,m}). Examples: '*.swift', '**/*.json', 'src/**/*.{swift,m}'. Defaults to '**/*' if not provided.")
1107
1096
  .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
1108
1097
  .action(async (cmdOpts) => {
1109
1098
  const globalOptions = program.opts();
@@ -1114,28 +1103,30 @@ program
1114
1103
  });
1115
1104
  try {
1116
1105
  const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
1117
- if (cmdOpts.ignore !== undefined) args.ignore = cmdOpts.ignore;
1118
- if (cmdOpts.path !== undefined) args.path = cmdOpts.path;
1119
- if (cmdOpts.recursive !== undefined) args.recursive = cmdOpts.recursive;
1106
+ if (cmdOpts.path !== undefined) args.path = cmdOpts.path;
1107
+ if (cmdOpts.pattern !== undefined) args.pattern = cmdOpts.pattern;
1120
1108
  if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
1121
- const call = (proxy.xcodeLS as any)(args);
1109
+ const call = (proxy.xcodeGlob as any)(args);
1122
1110
  const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
1123
1111
  printResult(result, globalOptions.output ?? 'text');
1124
1112
  } finally {
1125
1113
  await runtime.close(serverName).catch(() => {});
1126
1114
  }
1127
1115
  })
1128
- .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeLS(ignore: [\"value1\", \"value2\"], path: \"/path, ...)");
1116
+ .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeGlob(path: \"/path/to/file.md\", tabIdentifier:, ...)");
1129
1117
 
1130
1118
  program
1131
- .command("DocumentationSearch")
1132
- .summary("DocumentationSearch [--frameworks <frameworks:value1,value2>] --query <query> [--raw <json>]")
1133
- .description("Searches Apple Developer Documentation using semantic matching.")
1134
- .usage("[--frameworks <frameworks:value1,value2>] --query <query> [--raw <json>]")
1119
+ .command("XcodeUpdate")
1120
+ .summary("XcodeUpdate --file-path <file-path> --new-string <new-string> --old-string <old-string> [--replace-all <replace-all:true|false>] --tab-identifier <tab-identifier> [--raw <json>]")
1121
+ .description("Edits files in the Xcode project by replacing text content. Works on Xcode project structure paths, not filesystem paths. IMPORTANT: The tool will fail if filePath, oldString, or newString parameters are missing.")
1122
+ .usage("--file-path <file-path> --new-string <new-string> --old-string <old-string> [--replace-all <replace-all:true|false>] --tab-identifier <tab-identifier> [--raw <json>]")
1135
1123
  .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
1136
1124
 
1137
- .option("--frameworks <frameworks:value1,value2>", "Framework(s) to search in. Searches all frameworks if not specified. (example: value1,value2)", (value) => value.split(',').map((v) => v.trim()))
1138
- .requiredOption("--query <query>", "The search query")
1125
+ .requiredOption("--file-path <file-path>", "REQUIRED: The path to the file to modify within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift') (example: /path/to/file.md)")
1126
+ .requiredOption("--new-string <new-string>", "REQUIRED: The text to replace it with, must be different from oldString")
1127
+ .requiredOption("--old-string <old-string>", "REQUIRED: The text to replace")
1128
+ .option("--replace-all <replace-all:true|false>", "Replace all occurrences of oldString (default false) (example: true)", (value) => value !== 'false')
1129
+ .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
1139
1130
  .action(async (cmdOpts) => {
1140
1131
  const globalOptions = program.opts();
1141
1132
  const runtime = await ensureRuntime();
@@ -1145,24 +1136,30 @@ program
1145
1136
  });
1146
1137
  try {
1147
1138
  const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
1148
- if (cmdOpts.frameworks !== undefined) args.frameworks = cmdOpts.frameworks;
1149
- if (cmdOpts.query !== undefined) args.query = cmdOpts.query;
1150
- const call = (proxy.documentationSearch as any)(args);
1139
+ if (cmdOpts.filePath !== undefined) args.filePath = cmdOpts.filePath;
1140
+ if (cmdOpts.newString !== undefined) args.newString = cmdOpts.newString;
1141
+ if (cmdOpts.oldString !== undefined) args.oldString = cmdOpts.oldString;
1142
+ if (cmdOpts.replaceAll !== undefined) args.replaceAll = cmdOpts.replaceAll;
1143
+ if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
1144
+ const call = (proxy.xcodeUpdate as any)(args);
1151
1145
  const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
1152
1146
  printResult(result, globalOptions.output ?? 'text');
1153
1147
  } finally {
1154
1148
  await runtime.close(serverName).catch(() => {});
1155
1149
  }
1156
1150
  })
1157
- .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.DocumentationSearch(frameworks: [\"value1\", \"value2, ...)");
1151
+ .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeUpdate(filePath: \"/path/to/file.md\", newStrin, ...)");
1158
1152
 
1159
1153
  program
1160
- .command("GetTestList")
1161
- .summary("GetTestList --tab-identifier <tab-identifier> [--raw <json>]")
1162
- .description("Gets all available tests from the active scheme's active test plan. Results are limited to 100 tests. The complete list is written to fullTestListPath in grep-friendly format. Use grep with keys like TEST_TARGET, TEST_IDENTIFIER, or TEST_FILE_PATH to find specific tests.")
1163
- .usage("--tab-identifier <tab-identifier> [--raw <json>]")
1154
+ .command("XcodeRM")
1155
+ .summary("XcodeRM [--delete-files <delete-files:true|false>] --path <path> [--recursive <recursive:true|false>] --tab-identifier <tab-identifier> [--raw <json>]")
1156
+ .description("Removes files and directories from the Xcode project structure and optionally deletes the underlying files from the filesystem.")
1157
+ .usage("[--delete-files <delete-files:true|false>] --path <path> [--recursive <recursive:true|false>] --tab-identifier <tab-identifier> [--raw <json>]")
1164
1158
  .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
1165
1159
 
1160
+ .option("--delete-files <delete-files:true|false>", "Also move the underlying files to Trash (defaults to true) (example: true)", (value) => value !== 'false')
1161
+ .requiredOption("--path <path>", "The project path to remove (e.g., 'ProjectName/Sources/MyFile.swift') (example: /path/to/file.md)")
1162
+ .option("--recursive <recursive:true|false>", "Remove directories and their contents recursively (example: true)", (value) => value !== 'false')
1166
1163
  .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
1167
1164
  .action(async (cmdOpts) => {
1168
1165
  const globalOptions = program.opts();
@@ -1173,26 +1170,28 @@ program
1173
1170
  });
1174
1171
  try {
1175
1172
  const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
1176
- if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
1177
- const call = (proxy.getTestList as any)(args);
1173
+ if (cmdOpts.deleteFiles !== undefined) args.deleteFiles = cmdOpts.deleteFiles;
1174
+ if (cmdOpts.path !== undefined) args.path = cmdOpts.path;
1175
+ if (cmdOpts.recursive !== undefined) args.recursive = cmdOpts.recursive;
1176
+ if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
1177
+ const call = (proxy.xcodeRM as any)(args);
1178
1178
  const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
1179
1179
  printResult(result, globalOptions.output ?? 'text');
1180
1180
  } finally {
1181
1181
  await runtime.close(serverName).catch(() => {});
1182
1182
  }
1183
1183
  })
1184
- .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.GetTestList(tabIdentifier: \"example-id\")");
1184
+ .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeRM(deleteFiles: true, path: \"/path/to/file.md, ...)");
1185
1185
 
1186
1186
  program
1187
- .command("XcodeGlob")
1188
- .summary("XcodeGlob [--path <path>] [--pattern <pattern>] --tab-identifier <tab-identifier> [--raw <json>]")
1189
- .description("Finds files in the Xcode project structure matching wildcard patterns. Works on Xcode project organization, not filesystem structure. Example patterns: '*.swift', '**/*.json', 'src/**/*.{swift,m}'. If no pattern is provided, defaults to '**/*' (all files).")
1190
- .usage("[--path <path>] [--pattern <pattern>] --tab-identifier <tab-identifier> [--raw <json>]")
1187
+ .command("RunSomeTests")
1188
+ .summary("RunSomeTests --tab-identifier <tab-identifier> --tests <tests:value1,value2> [--raw <json>]")
1189
+ .description("Runs specific tests using the active scheme's active test plan")
1190
+ .usage("--tab-identifier <tab-identifier> --tests <tests:value1,value2> [--raw <json>]")
1191
1191
  .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
1192
1192
 
1193
- .option("--path <path>", "Which project directory to search in (optional, defaults to root) (example: /path/to/file.md)")
1194
- .option("--pattern <pattern>", "File matching pattern using wildcards (* ** ? [abc] {swift,m}). Examples: '*.swift', '**/*.json', 'src/**/*.{swift,m}'. Defaults to '**/*' if not provided.")
1195
1193
  .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
1194
+ .requiredOption("--tests <tests:value1,value2>", "Array of test specifiers to run. Each specifier contains 'targetName' and 'testIdentifier' fields. Use GetTestList action to discover available tests and their identifiers, then extract the 'targetName' and 'identifier' fields from the TestActionInfo results to construct TestActionSpecifier objects. (example: value1,value2)", (value) => value.split(',').map((v) => v.trim()))
1196
1195
  .action(async (cmdOpts) => {
1197
1196
  const globalOptions = program.opts();
1198
1197
  const runtime = await ensureRuntime();
@@ -1202,28 +1201,28 @@ program
1202
1201
  });
1203
1202
  try {
1204
1203
  const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
1205
- if (cmdOpts.path !== undefined) args.path = cmdOpts.path;
1206
- if (cmdOpts.pattern !== undefined) args.pattern = cmdOpts.pattern;
1207
- if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
1208
- const call = (proxy.xcodeGlob as any)(args);
1204
+ if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
1205
+ if (cmdOpts.tests !== undefined) args.tests = cmdOpts.tests;
1206
+ const call = (proxy.runSomeTests as any)(args);
1209
1207
  const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
1210
1208
  printResult(result, globalOptions.output ?? 'text');
1211
1209
  } finally {
1212
1210
  await runtime.close(serverName).catch(() => {});
1213
1211
  }
1214
1212
  })
1215
- .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeGlob(path: \"/path/to/file.md\", tabIdentifier:, ...)");
1213
+ .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.RunSomeTests(tabIdentifier: \"example-id\", tests: [, ...)");
1216
1214
 
1217
1215
  program
1218
- .command("XcodeListNavigatorIssues")
1219
- .summary("XcodeListNavigatorIssues [--glob <glob>] [--pattern <pattern>] [--severity <severity>] --tab-identifier <tab-identifier> [--raw <json>]")
1220
- .description("Lists the currently known issues shown Xcode's Issue Navigator UI in the workspace. These issues include those that have been discovered since the last build, and also issues like package resolution problems and workspace configuration issues. You can filter the issues to include by file name, glob, or severity. Use this tool when you want to list all the users the user can see in the workspace UI.")
1221
- .usage("[--glob <glob>] [--pattern <pattern>] [--severity <severity>] --tab-identifier <tab-identifier> [--raw <json>]")
1216
+ .command("XcodeMV")
1217
+ .summary("XcodeMV --destination-path <destination-path> [--operation <operation:move|copy>] [--overwrite-existing <overwrite-existing:true|false>] --source-path <source-path> --tab-identifier <tab-identifier> [--raw <json>]")
1218
+ .description("Moves or renames files and directories in the project navigator with support for filesystem operations.")
1219
+ .usage("--destination-path <destination-path> [--operation <operation:move|copy>] [--overwrite-existing <overwrite-existing:true|false>] --source-path <source-path> --tab-identifier <tab-identifier> [--raw <json>]")
1222
1220
  .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
1223
1221
 
1224
- .option("--glob <glob>", "Glob to filter the returned issues. Will match against the 'path' field.")
1225
- .option("--pattern <pattern>", "Regex to filter the returned issues. Will match against the 'message' field.")
1226
- .option("--severity <severity>", "Limit the returned issues to those that have the specified severity or higher. Valid values in order of decreasing severity are 'error', 'warning', 'remark'. Defaults to 'error'.")
1222
+ .requiredOption("--destination-path <destination-path>", "Project navigator relative path for the destination (for move) or new name (for rename) (example: /path/to/file.md)")
1223
+ .option("--operation <operation:move|copy>", "The type of move operation to perform (choices: move, copy; example: move)")
1224
+ .option("--overwrite-existing <overwrite-existing:true|false>", "Whether to overwrite existing files at the destination (example: true)", (value) => value !== 'false')
1225
+ .requiredOption("--source-path <source-path>", "Project navigator relative path of the source item to move/rename (example: /path/to/file.md)")
1227
1226
  .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
1228
1227
  .action(async (cmdOpts) => {
1229
1228
  const globalOptions = program.opts();
@@ -1234,27 +1233,30 @@ program
1234
1233
  });
1235
1234
  try {
1236
1235
  const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
1237
- if (cmdOpts.glob !== undefined) args.glob = cmdOpts.glob;
1238
- if (cmdOpts.pattern !== undefined) args.pattern = cmdOpts.pattern;
1239
- if (cmdOpts.severity !== undefined) args.severity = cmdOpts.severity;
1236
+ if (cmdOpts.destinationPath !== undefined) args.destinationPath = cmdOpts.destinationPath;
1237
+ if (cmdOpts.operation !== undefined) args.operation = cmdOpts.operation;
1238
+ if (cmdOpts.overwriteExisting !== undefined) args.overwriteExisting = cmdOpts.overwriteExisting;
1239
+ if (cmdOpts.sourcePath !== undefined) args.sourcePath = cmdOpts.sourcePath;
1240
1240
  if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
1241
- const call = (proxy.xcodeListNavigatorIssues as any)(args);
1241
+ const call = (proxy.xcodeMV as any)(args);
1242
1242
  const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
1243
1243
  printResult(result, globalOptions.output ?? 'text');
1244
1244
  } finally {
1245
1245
  await runtime.close(serverName).catch(() => {});
1246
1246
  }
1247
1247
  })
1248
- .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeListNavigatorIssues(tabIdentifier: \"example-id\")");
1248
+ .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeMV(destinationPath: \"/path/to/file.md\", opera, ...)");
1249
1249
 
1250
1250
  program
1251
- .command("XcodeMakeDir")
1252
- .summary("XcodeMakeDir --directory-path <directory-path> --tab-identifier <tab-identifier> [--raw <json>]")
1253
- .description("Creates directories and groups in the Xcode project structure.")
1254
- .usage("--directory-path <directory-path> --tab-identifier <tab-identifier> [--raw <json>]")
1251
+ .command("XcodeLS")
1252
+ .summary("XcodeLS [--ignore <ignore:value1,value2>] --path <path> [--recursive <recursive:true|false>] --tab-identifier <tab-identifier> [--raw <json>]")
1253
+ .description("Lists files and directories in the Xcode project structure at the specified path. Works on Xcode project organization, not filesystem structure.")
1254
+ .usage("[--ignore <ignore:value1,value2>] --path <path> [--recursive <recursive:true|false>] --tab-identifier <tab-identifier> [--raw <json>]")
1255
1255
  .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
1256
1256
 
1257
- .requiredOption("--directory-path <directory-path>", "Project navigator relative path for the directory to create (example: /path/to/file.md)")
1257
+ .option("--ignore <ignore:value1,value2>", "Skip files/folders matching these patterns (example: value1,value2)", (value) => value.split(',').map((v) => v.trim()))
1258
+ .requiredOption("--path <path>", "The project path to browse (e.g., 'ProjectName/Sources/') (example: /path/to/file.md)")
1259
+ .option("--recursive <recursive:true|false>", "Recursively list all files (truncated to 100 lines). Default: true (example: true)", (value) => value !== 'false')
1258
1260
  .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
1259
1261
  .action(async (cmdOpts) => {
1260
1262
  const globalOptions = program.opts();
@@ -1265,28 +1267,28 @@ program
1265
1267
  });
1266
1268
  try {
1267
1269
  const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
1268
- if (cmdOpts.directoryPath !== undefined) args.directoryPath = cmdOpts.directoryPath;
1270
+ if (cmdOpts.ignore !== undefined) args.ignore = cmdOpts.ignore;
1271
+ if (cmdOpts.path !== undefined) args.path = cmdOpts.path;
1272
+ if (cmdOpts.recursive !== undefined) args.recursive = cmdOpts.recursive;
1269
1273
  if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
1270
- const call = (proxy.xcodeMakeDir as any)(args);
1274
+ const call = (proxy.xcodeLS as any)(args);
1271
1275
  const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
1272
1276
  printResult(result, globalOptions.output ?? 'text');
1273
1277
  } finally {
1274
1278
  await runtime.close(serverName).catch(() => {});
1275
1279
  }
1276
1280
  })
1277
- .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeMakeDir(directoryPath: \"/path/to/file.md\", ta, ...)");
1281
+ .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeLS(ignore: [\"value1\", \"value2\"], path: \"/path, ...)");
1278
1282
 
1279
1283
  program
1280
- .command("ExecuteSnippet")
1281
- .summary("ExecuteSnippet --code-snippet <code-snippet> --source-file-path <source-file-path> --tab-identifier <tab-identifier> [--timeout <timeout:number>] [--raw <json>]")
1282
- .description("Builds and runs a snippet of code in the context of a specific file and waits until results are available. This tool is available for source files in targets that build applications, frameworks, libraries, or command line executables. The output consists of the console output generated by the `print` statements contained in the provided snippet.")
1283
- .usage("--code-snippet <code-snippet> --source-file-path <source-file-path> --tab-identifier <tab-identifier> [--timeout <timeout:number>] [--raw <json>]")
1284
+ .command("XcodeMakeDir")
1285
+ .summary("XcodeMakeDir --directory-path <directory-path> --tab-identifier <tab-identifier> [--raw <json>]")
1286
+ .description("Creates directories and groups in the Xcode project structure.")
1287
+ .usage("--directory-path <directory-path> --tab-identifier <tab-identifier> [--raw <json>]")
1284
1288
  .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
1285
1289
 
1286
- .requiredOption("--code-snippet <code-snippet>", "The code snippet that should be executed in the context of the specified file.")
1287
- .requiredOption("--source-file-path <source-file-path>", "The path to a Swift source file within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift') whose context the code snippet will have access to (including `fileprivate` declarations). (example: /path/to/file.md)")
1288
- .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier. (example: example-id)")
1289
- .option("--timeout <timeout:number>", "The time in seconds to wait for the execution of the snippet to complete. Defaults to 120 seconds. (example: 1)", (value) => parseFloat(value))
1290
+ .requiredOption("--directory-path <directory-path>", "Project navigator relative path for the directory to create (example: /path/to/file.md)")
1291
+ .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
1290
1292
  .action(async (cmdOpts) => {
1291
1293
  const globalOptions = program.opts();
1292
1294
  const runtime = await ensureRuntime();
@@ -1296,30 +1298,28 @@ program
1296
1298
  });
1297
1299
  try {
1298
1300
  const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
1299
- if (cmdOpts.codeSnippet !== undefined) args.codeSnippet = cmdOpts.codeSnippet;
1300
- if (cmdOpts.sourceFilePath !== undefined) args.sourceFilePath = cmdOpts.sourceFilePath;
1301
+ if (cmdOpts.directoryPath !== undefined) args.directoryPath = cmdOpts.directoryPath;
1301
1302
  if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
1302
- if (cmdOpts.timeout !== undefined) args.timeout = cmdOpts.timeout;
1303
- const call = (proxy.executeSnippet as any)(args);
1303
+ const call = (proxy.xcodeMakeDir as any)(args);
1304
1304
  const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
1305
1305
  printResult(result, globalOptions.output ?? 'text');
1306
1306
  } finally {
1307
1307
  await runtime.close(serverName).catch(() => {});
1308
1308
  }
1309
1309
  })
1310
- .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.ExecuteSnippet(codeSnippet: \"value\", sourceFilePat, ...)");
1310
+ .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeMakeDir(directoryPath: \"/path/to/file.md\", ta, ...)");
1311
1311
 
1312
1312
  program
1313
- .command("RenderPreview")
1314
- .summary("RenderPreview [--preview-definition-index-in-file <preview-definition-index-in-file:number>] --source-file-path <source-file-path> --tab-identifier <tab-identifier> [--timeout <timeout:number>] [--raw <json>]")
1315
- .description("Builds and renders a Preview and waits until a snapshot of the resulting UI is available.")
1316
- .usage("[--preview-definition-index-in-file <preview-definition-index-in-file:number>] --source-file-path <source-file-path> --tab-identifier <tab-identifier> [--timeout <timeout:number>] [--raw <json>]")
1313
+ .command("XcodeListNavigatorIssues")
1314
+ .summary("XcodeListNavigatorIssues [--glob <glob>] [--pattern <pattern>] [--severity <severity>] --tab-identifier <tab-identifier> [--raw <json>]")
1315
+ .description("Lists the currently known issues shown Xcode's Issue Navigator UI in the workspace. These issues include those that have been discovered since the last build, and also issues like package resolution problems and workspace configuration issues. You can filter the issues to include by file name, glob, or severity. Use this tool when you want to list all the users the user can see in the workspace UI.")
1316
+ .usage("[--glob <glob>] [--pattern <pattern>] [--severity <severity>] --tab-identifier <tab-identifier> [--raw <json>]")
1317
1317
  .option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
1318
1318
 
1319
- .option("--preview-definition-index-in-file <preview-definition-index-in-file:number>", "The zero based index of the #Preview macro or PreviewProvider struct definition in the source file counting from the top. Defaults to 0, i.e. the first one. (example: 1)", (value) => parseFloat(value))
1320
- .requiredOption("--source-file-path <source-file-path>", "The path to the file within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift') (example: /path/to/file.md)")
1319
+ .option("--glob <glob>", "Glob to filter the returned issues. Will match against the 'path' field.")
1320
+ .option("--pattern <pattern>", "Regex to filter the returned issues. Will match against the 'message' field.")
1321
+ .option("--severity <severity>", "Limit the returned issues to those that have the specified severity or higher. Valid values in order of decreasing severity are 'error', 'warning', 'remark'. Defaults to 'error'.")
1321
1322
  .requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
1322
- .option("--timeout <timeout:number>", "The time in seconds to wait for the rendering of the preview to complete. Defaults to 120 seconds. (example: 1)", (value) => parseFloat(value))
1323
1323
  .action(async (cmdOpts) => {
1324
1324
  const globalOptions = program.opts();
1325
1325
  const runtime = await ensureRuntime();
@@ -1329,18 +1329,18 @@ program
1329
1329
  });
1330
1330
  try {
1331
1331
  const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
1332
- if (cmdOpts.previewDefinitionIndexInFile !== undefined) args.previewDefinitionIndexInFile = cmdOpts.previewDefinitionIndexInFile;
1333
- if (cmdOpts.sourceFilePath !== undefined) args.sourceFilePath = cmdOpts.sourceFilePath;
1332
+ if (cmdOpts.glob !== undefined) args.glob = cmdOpts.glob;
1333
+ if (cmdOpts.pattern !== undefined) args.pattern = cmdOpts.pattern;
1334
+ if (cmdOpts.severity !== undefined) args.severity = cmdOpts.severity;
1334
1335
  if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
1335
- if (cmdOpts.timeout !== undefined) args.timeout = cmdOpts.timeout;
1336
- const call = (proxy.renderPreview as any)(args);
1336
+ const call = (proxy.xcodeListNavigatorIssues as any)(args);
1337
1337
  const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
1338
1338
  printResult(result, globalOptions.output ?? 'text');
1339
1339
  } finally {
1340
1340
  await runtime.close(serverName).catch(() => {});
1341
1341
  }
1342
1342
  })
1343
- .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.RenderPreview(previewDefinitionIndexInFile: 1, sou, ...)");
1343
+ .addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeListNavigatorIssues(tabIdentifier: \"example-id\")");
1344
1344
 
1345
1345
  program
1346
1346
  .command('__mcporter_inspect', { hidden: true })