xcode-cli 1.0.5
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/LICENSE +21 -0
- package/README.md +151 -0
- package/bin/xcode-cli +19 -0
- package/bin/xcode-cli-ctl +19 -0
- package/package.json +41 -0
- package/skills/xcode-cli/SKILL.md +138 -0
- package/src/mcpbridge.ts +1624 -0
- package/src/xcode-ctl.ts +138 -0
- package/src/xcode-issues.ts +165 -0
- package/src/xcode-mcp.ts +483 -0
- package/src/xcode-output.ts +431 -0
- package/src/xcode-preview.ts +55 -0
- package/src/xcode-service.ts +278 -0
- package/src/xcode-skill.ts +52 -0
- package/src/xcode-test.ts +115 -0
- package/src/xcode-tree.ts +59 -0
- package/src/xcode-types.ts +28 -0
- package/src/xcode.ts +785 -0
package/src/mcpbridge.ts
ADDED
|
@@ -0,0 +1,1624 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @generated by xcode-mcp@1.0.0 on 2026-02-27T19:58:04.864Z. DO NOT EDIT.
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { createRuntime, createServerProxy } from 'mcporter';
|
|
5
|
+
import { createCallResult } from 'mcporter';
|
|
6
|
+
|
|
7
|
+
const embeddedServer = {
|
|
8
|
+
"name": "mcpbridge",
|
|
9
|
+
"description": "xcode-tools",
|
|
10
|
+
"command": {
|
|
11
|
+
"kind": "stdio",
|
|
12
|
+
"command": "xcrun",
|
|
13
|
+
"args": [
|
|
14
|
+
"mcpbridge"
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"source": {
|
|
18
|
+
"kind": "local",
|
|
19
|
+
"path": "<adhoc>"
|
|
20
|
+
}
|
|
21
|
+
} as const;
|
|
22
|
+
const embeddedSchemas = {
|
|
23
|
+
"XcodeUpdate": {
|
|
24
|
+
"type": "object",
|
|
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
|
+
"tabIdentifier": {
|
|
43
|
+
"description": "The workspace tab identifier",
|
|
44
|
+
"type": "string"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"required": [
|
|
48
|
+
"tabIdentifier",
|
|
49
|
+
"filePath",
|
|
50
|
+
"oldString",
|
|
51
|
+
"newString"
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
"XcodeMV": {
|
|
55
|
+
"type": "object",
|
|
56
|
+
"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
|
+
"tabIdentifier": {
|
|
78
|
+
"description": "The workspace tab identifier",
|
|
79
|
+
"type": "string"
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"required": [
|
|
83
|
+
"tabIdentifier",
|
|
84
|
+
"sourcePath",
|
|
85
|
+
"destinationPath"
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
"XcodeRead": {
|
|
89
|
+
"type": "object",
|
|
90
|
+
"properties": {
|
|
91
|
+
"filePath": {
|
|
92
|
+
"description": "The path to the file within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift')",
|
|
93
|
+
"type": "string"
|
|
94
|
+
},
|
|
95
|
+
"limit": {
|
|
96
|
+
"description": "The number of lines to read (only provide if the file is too large to read at once)",
|
|
97
|
+
"type": "integer"
|
|
98
|
+
},
|
|
99
|
+
"offset": {
|
|
100
|
+
"description": "The line number to start reading from (only provide if the file is too large to read at once)",
|
|
101
|
+
"type": "integer"
|
|
102
|
+
},
|
|
103
|
+
"tabIdentifier": {
|
|
104
|
+
"description": "The workspace tab identifier",
|
|
105
|
+
"type": "string"
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"required": [
|
|
109
|
+
"tabIdentifier",
|
|
110
|
+
"filePath"
|
|
111
|
+
]
|
|
112
|
+
},
|
|
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
|
+
"XcodeRefreshCodeIssuesInFile": {
|
|
173
|
+
"type": "object",
|
|
174
|
+
"properties": {
|
|
175
|
+
"filePath": {
|
|
176
|
+
"description": "The path to the file within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift')",
|
|
177
|
+
"type": "string"
|
|
178
|
+
},
|
|
179
|
+
"tabIdentifier": {
|
|
180
|
+
"description": "The workspace tab identifier",
|
|
181
|
+
"type": "string"
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
"required": [
|
|
185
|
+
"tabIdentifier",
|
|
186
|
+
"filePath"
|
|
187
|
+
]
|
|
188
|
+
},
|
|
189
|
+
"GetBuildLog": {
|
|
190
|
+
"type": "object",
|
|
191
|
+
"properties": {
|
|
192
|
+
"glob": {
|
|
193
|
+
"description": "Glob to filter the returned build log entries. Will match against the 'path' field of any emitted issues, as well as against the location of any build task.",
|
|
194
|
+
"type": "string"
|
|
195
|
+
},
|
|
196
|
+
"pattern": {
|
|
197
|
+
"description": "Regex to filter the returned build log entries. Will match against the 'message' field of any emitted issues, as well as the task description, command line, and console output of any build tasks.",
|
|
198
|
+
"type": "string"
|
|
199
|
+
},
|
|
200
|
+
"severity": {
|
|
201
|
+
"description": "Limit the output of build log entries to those that emitted issues of the specified severity or higher. Valid values in order of decreasing severity are 'error', 'warning', 'remark'. Defaults to 'error'.",
|
|
202
|
+
"enum": [
|
|
203
|
+
"remark",
|
|
204
|
+
"warning",
|
|
205
|
+
"error"
|
|
206
|
+
],
|
|
207
|
+
"type": "string"
|
|
208
|
+
},
|
|
209
|
+
"tabIdentifier": {
|
|
210
|
+
"description": "The workspace tab identifier",
|
|
211
|
+
"type": "string"
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
"required": [
|
|
215
|
+
"tabIdentifier"
|
|
216
|
+
]
|
|
217
|
+
},
|
|
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
|
+
"XcodeWrite": {
|
|
248
|
+
"type": "object",
|
|
249
|
+
"properties": {
|
|
250
|
+
"content": {
|
|
251
|
+
"description": "REQUIRED: The content to write to the file",
|
|
252
|
+
"type": "string"
|
|
253
|
+
},
|
|
254
|
+
"filePath": {
|
|
255
|
+
"description": "REQUIRED: The path to the file within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift')",
|
|
256
|
+
"type": "string"
|
|
257
|
+
},
|
|
258
|
+
"tabIdentifier": {
|
|
259
|
+
"description": "The workspace tab identifier (required)",
|
|
260
|
+
"type": "string"
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
"required": [
|
|
264
|
+
"tabIdentifier",
|
|
265
|
+
"filePath",
|
|
266
|
+
"content"
|
|
267
|
+
]
|
|
268
|
+
},
|
|
269
|
+
"XcodeGrep": {
|
|
270
|
+
"type": "object",
|
|
271
|
+
"properties": {
|
|
272
|
+
"glob": {
|
|
273
|
+
"description": "Only search files matching this pattern",
|
|
274
|
+
"type": "string"
|
|
275
|
+
},
|
|
276
|
+
"headLimit": {
|
|
277
|
+
"description": "Stop after N results",
|
|
278
|
+
"type": "integer"
|
|
279
|
+
},
|
|
280
|
+
"ignoreCase": {
|
|
281
|
+
"description": "Ignore case when matching",
|
|
282
|
+
"type": "boolean"
|
|
283
|
+
},
|
|
284
|
+
"linesAfter": {
|
|
285
|
+
"description": "Show N lines after each match for context",
|
|
286
|
+
"type": "integer"
|
|
287
|
+
},
|
|
288
|
+
"linesBefore": {
|
|
289
|
+
"description": "Show N lines before each match for context",
|
|
290
|
+
"type": "integer"
|
|
291
|
+
},
|
|
292
|
+
"linesContext": {
|
|
293
|
+
"description": "Show N lines both before and after each match",
|
|
294
|
+
"type": "integer"
|
|
295
|
+
},
|
|
296
|
+
"multiline": {
|
|
297
|
+
"description": "Allow patterns to span multiple lines",
|
|
298
|
+
"type": "boolean"
|
|
299
|
+
},
|
|
300
|
+
"outputMode": {
|
|
301
|
+
"description": "What to return: content, files_with_matches, or count (default: files_with_matches)",
|
|
302
|
+
"enum": [
|
|
303
|
+
"content",
|
|
304
|
+
"filesWithMatches",
|
|
305
|
+
"count"
|
|
306
|
+
],
|
|
307
|
+
"type": "string"
|
|
308
|
+
},
|
|
309
|
+
"path": {
|
|
310
|
+
"description": "Where to search - file or directory in project (defaults to root)",
|
|
311
|
+
"type": "string"
|
|
312
|
+
},
|
|
313
|
+
"pattern": {
|
|
314
|
+
"description": "Text to search for using regex. REQUIRED: Must include a 'pattern' argument - this tool will fail without it.",
|
|
315
|
+
"type": "string"
|
|
316
|
+
},
|
|
317
|
+
"showLineNumbers": {
|
|
318
|
+
"description": "Show line numbers with results (content mode only)",
|
|
319
|
+
"type": "boolean"
|
|
320
|
+
},
|
|
321
|
+
"tabIdentifier": {
|
|
322
|
+
"description": "The workspace tab identifier",
|
|
323
|
+
"type": "string"
|
|
324
|
+
},
|
|
325
|
+
"type": {
|
|
326
|
+
"description": "Shortcut for common file types (swift, js, py, etc.)",
|
|
327
|
+
"type": "string"
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
"required": [
|
|
331
|
+
"tabIdentifier",
|
|
332
|
+
"pattern"
|
|
333
|
+
]
|
|
334
|
+
},
|
|
335
|
+
"XcodeLS": {
|
|
336
|
+
"type": "object",
|
|
337
|
+
"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
|
+
"tabIdentifier": {
|
|
354
|
+
"description": "The workspace tab identifier",
|
|
355
|
+
"type": "string"
|
|
356
|
+
}
|
|
357
|
+
},
|
|
358
|
+
"required": [
|
|
359
|
+
"tabIdentifier",
|
|
360
|
+
"path"
|
|
361
|
+
]
|
|
362
|
+
},
|
|
363
|
+
"DocumentationSearch": {
|
|
364
|
+
"type": "object",
|
|
365
|
+
"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"
|
|
372
|
+
},
|
|
373
|
+
"query": {
|
|
374
|
+
"description": "The search query",
|
|
375
|
+
"type": "string"
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
"required": [
|
|
379
|
+
"query"
|
|
380
|
+
]
|
|
381
|
+
},
|
|
382
|
+
"GetTestList": {
|
|
383
|
+
"type": "object",
|
|
384
|
+
"properties": {
|
|
385
|
+
"tabIdentifier": {
|
|
386
|
+
"description": "The workspace tab identifier",
|
|
387
|
+
"type": "string"
|
|
388
|
+
}
|
|
389
|
+
},
|
|
390
|
+
"required": [
|
|
391
|
+
"tabIdentifier"
|
|
392
|
+
]
|
|
393
|
+
},
|
|
394
|
+
"XcodeGlob": {
|
|
395
|
+
"type": "object",
|
|
396
|
+
"properties": {
|
|
397
|
+
"path": {
|
|
398
|
+
"description": "Which project directory to search in (optional, defaults to root)",
|
|
399
|
+
"type": "string"
|
|
400
|
+
},
|
|
401
|
+
"pattern": {
|
|
402
|
+
"description": "File matching pattern using wildcards (* ** ? [abc] {swift,m}). Examples: '*.swift', '**/*.json', 'src/**/*.{swift,m}'. Defaults to '**/*' if not provided.",
|
|
403
|
+
"type": "string"
|
|
404
|
+
},
|
|
405
|
+
"tabIdentifier": {
|
|
406
|
+
"description": "The workspace tab identifier",
|
|
407
|
+
"type": "string"
|
|
408
|
+
}
|
|
409
|
+
},
|
|
410
|
+
"required": [
|
|
411
|
+
"tabIdentifier"
|
|
412
|
+
]
|
|
413
|
+
},
|
|
414
|
+
"XcodeListNavigatorIssues": {
|
|
415
|
+
"type": "object",
|
|
416
|
+
"properties": {
|
|
417
|
+
"glob": {
|
|
418
|
+
"description": "Glob to filter the returned issues. Will match against the 'path' field.",
|
|
419
|
+
"type": "string"
|
|
420
|
+
},
|
|
421
|
+
"pattern": {
|
|
422
|
+
"description": "Regex to filter the returned issues. Will match against the 'message' field.",
|
|
423
|
+
"type": "string"
|
|
424
|
+
},
|
|
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'.",
|
|
427
|
+
"type": "string"
|
|
428
|
+
},
|
|
429
|
+
"tabIdentifier": {
|
|
430
|
+
"description": "The workspace tab identifier",
|
|
431
|
+
"type": "string"
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
"required": [
|
|
435
|
+
"tabIdentifier"
|
|
436
|
+
]
|
|
437
|
+
},
|
|
438
|
+
"XcodeMakeDir": {
|
|
439
|
+
"type": "object",
|
|
440
|
+
"properties": {
|
|
441
|
+
"directoryPath": {
|
|
442
|
+
"description": "Project navigator relative path for the directory to create",
|
|
443
|
+
"type": "string"
|
|
444
|
+
},
|
|
445
|
+
"tabIdentifier": {
|
|
446
|
+
"description": "The workspace tab identifier",
|
|
447
|
+
"type": "string"
|
|
448
|
+
}
|
|
449
|
+
},
|
|
450
|
+
"required": [
|
|
451
|
+
"tabIdentifier",
|
|
452
|
+
"directoryPath"
|
|
453
|
+
]
|
|
454
|
+
},
|
|
455
|
+
"ExecuteSnippet": {
|
|
456
|
+
"type": "object",
|
|
457
|
+
"properties": {
|
|
458
|
+
"codeSnippet": {
|
|
459
|
+
"description": "The code snippet that should be executed in the context of the specified file.",
|
|
460
|
+
"type": "string"
|
|
461
|
+
},
|
|
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).",
|
|
464
|
+
"type": "string"
|
|
465
|
+
},
|
|
466
|
+
"tabIdentifier": {
|
|
467
|
+
"description": "The workspace tab identifier.",
|
|
468
|
+
"type": "string"
|
|
469
|
+
},
|
|
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"
|
|
473
|
+
}
|
|
474
|
+
},
|
|
475
|
+
"required": [
|
|
476
|
+
"tabIdentifier",
|
|
477
|
+
"codeSnippet",
|
|
478
|
+
"sourceFilePath"
|
|
479
|
+
]
|
|
480
|
+
},
|
|
481
|
+
"RenderPreview": {
|
|
482
|
+
"type": "object",
|
|
483
|
+
"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"
|
|
487
|
+
},
|
|
488
|
+
"sourceFilePath": {
|
|
489
|
+
"description": "The path to the file within the Xcode project organization (e.g., 'ProjectName/Sources/MyFile.swift')",
|
|
490
|
+
"type": "string"
|
|
491
|
+
},
|
|
492
|
+
"tabIdentifier": {
|
|
493
|
+
"description": "The workspace tab identifier",
|
|
494
|
+
"type": "string"
|
|
495
|
+
},
|
|
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"
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
"required": [
|
|
502
|
+
"tabIdentifier",
|
|
503
|
+
"sourceFilePath"
|
|
504
|
+
]
|
|
505
|
+
}
|
|
506
|
+
} as const;
|
|
507
|
+
const embeddedName = "mcpbridge";
|
|
508
|
+
const embeddedDescription = "xcode-tools";
|
|
509
|
+
const generatorInfo = "Generated by xcode-mcp@1.0.0 — https://github.com/steipete/mcporter";
|
|
510
|
+
const generatorTools = [
|
|
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>]"
|
|
516
|
+
},
|
|
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>]"
|
|
522
|
+
},
|
|
523
|
+
{
|
|
524
|
+
"name": "XcodeRead",
|
|
525
|
+
"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.",
|
|
526
|
+
"usage": "XcodeRead --file-path <file-path> [--limit <limit:number>] [--offset <offset:number>] --tab-identifier <tab-identifier> [--raw <json>]",
|
|
527
|
+
"flags": "--file-path <file-path> [--limit <limit:number>] [--offset <offset:number>] --tab-identifier <tab-identifier> [--raw <json>]"
|
|
528
|
+
},
|
|
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
|
+
{
|
|
542
|
+
"name": "XcodeRefreshCodeIssuesInFile",
|
|
543
|
+
"description": "Retrieves current compiler diagnostics (errors, warnings, notes) for a file in the Xcode project. Returns formatted diagnostic information including severity levels and messages.",
|
|
544
|
+
"usage": "XcodeRefreshCodeIssuesInFile --file-path <file-path> --tab-identifier <tab-identifier> [--raw <json>]",
|
|
545
|
+
"flags": "--file-path <file-path> --tab-identifier <tab-identifier> [--raw <json>]"
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
"name": "GetBuildLog",
|
|
549
|
+
"description": "Gets the log of the current or most recently finished build. You can choose which build log entries to include by specifying the severity of any issues emitted by the build task represented by the entry. You can also filter by message regex pattern or file glob pattern. The response also indicates whether the build is currently in progress.",
|
|
550
|
+
"usage": "GetBuildLog [--glob <glob>] [--pattern <pattern>] [--severity <severity:remark|warning|error>] --tab-identifier <tab-identifier> [--raw <json>]",
|
|
551
|
+
"flags": "[--glob <glob>] [--pattern <pattern>] [--severity <severity:remark|warning|error>] --tab-identifier <tab-identifier> [--raw <json>]"
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
"name": "XcodeListWindows",
|
|
555
|
+
"description": "Lists the current Xcode windows and their workspace information",
|
|
556
|
+
"usage": "XcodeListWindows [--raw <json>]",
|
|
557
|
+
"flags": "[--raw <json>]"
|
|
558
|
+
},
|
|
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>]"
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
"name": "RunAllTests",
|
|
567
|
+
"description": "Runs all tests from the active scheme's active test plan",
|
|
568
|
+
"usage": "RunAllTests --tab-identifier <tab-identifier> [--raw <json>]",
|
|
569
|
+
"flags": "--tab-identifier <tab-identifier> [--raw <json>]"
|
|
570
|
+
},
|
|
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>]"
|
|
576
|
+
},
|
|
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>]"
|
|
582
|
+
},
|
|
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>]"
|
|
588
|
+
},
|
|
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>]"
|
|
594
|
+
},
|
|
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>]"
|
|
600
|
+
},
|
|
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>]"
|
|
606
|
+
},
|
|
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>]"
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
"name": "XcodeMakeDir",
|
|
615
|
+
"description": "Creates directories and groups in the Xcode project structure.",
|
|
616
|
+
"usage": "XcodeMakeDir --directory-path <directory-path> --tab-identifier <tab-identifier> [--raw <json>]",
|
|
617
|
+
"flags": "--directory-path <directory-path> --tab-identifier <tab-identifier> [--raw <json>]"
|
|
618
|
+
},
|
|
619
|
+
{
|
|
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>]"
|
|
630
|
+
}
|
|
631
|
+
] as const;
|
|
632
|
+
const embeddedMetadata = {
|
|
633
|
+
"schemaVersion": 1,
|
|
634
|
+
"generatedAt": "2026-02-27T19:58:04.864Z",
|
|
635
|
+
"generator": {
|
|
636
|
+
"name": "xcode-mcp",
|
|
637
|
+
"version": "1.0.0"
|
|
638
|
+
},
|
|
639
|
+
"server": {
|
|
640
|
+
"name": "mcpbridge",
|
|
641
|
+
"source": {
|
|
642
|
+
"kind": "local",
|
|
643
|
+
"path": "<adhoc>"
|
|
644
|
+
},
|
|
645
|
+
"definition": {
|
|
646
|
+
"name": "mcpbridge",
|
|
647
|
+
"description": "xcode-tools",
|
|
648
|
+
"command": {
|
|
649
|
+
"kind": "stdio",
|
|
650
|
+
"command": "xcrun",
|
|
651
|
+
"args": [
|
|
652
|
+
"mcpbridge"
|
|
653
|
+
]
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
},
|
|
657
|
+
"artifact": {
|
|
658
|
+
"path": "",
|
|
659
|
+
"kind": "template"
|
|
660
|
+
},
|
|
661
|
+
"invocation": {
|
|
662
|
+
"serverRef": "{\"name\":\"mcpbridge\",\"description\":\"xcode-tools\",\"command\":{\"kind\":\"stdio\",\"command\":\"xcrun\",\"args\":[\"mcpbridge\"]},\"source\":{\"kind\":\"local\",\"path\":\"<adhoc>\"}}",
|
|
663
|
+
"configPath": "<adhoc>",
|
|
664
|
+
"runtime": "node",
|
|
665
|
+
"bundler": "rolldown",
|
|
666
|
+
"outputPath": "./src/mcpbridge.ts",
|
|
667
|
+
"timeoutMs": 30000,
|
|
668
|
+
"minify": false
|
|
669
|
+
}
|
|
670
|
+
} as const;
|
|
671
|
+
const artifactKind = determineArtifactKind();
|
|
672
|
+
const program = new Command();
|
|
673
|
+
program.name(embeddedName);
|
|
674
|
+
program.description(embeddedDescription);
|
|
675
|
+
program.option('-t, --timeout <ms>', 'Call timeout in milliseconds', (value) => parseInt(value, 10), 30000);
|
|
676
|
+
program.option('-o, --output <format>', 'Output format: text|markdown|json|raw', 'text');
|
|
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;",
|
|
680
|
+
"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
|
+
"XcodeRefreshCodeIssuesInFile": "function XcodeRefreshCodeIssuesInFile(filePath: string, tabIdentifier: string): object;",
|
|
684
|
+
"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
|
+
"XcodeWrite": "function XcodeWrite(content: string, filePath: string, tabIdentifier: string): object;",
|
|
689
|
+
"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;",
|
|
693
|
+
"XcodeGlob": "function XcodeGlob(path?: string, pattern?: string, tabIdentifier: string): object;",
|
|
694
|
+
"XcodeListNavigatorIssues": "function XcodeListNavigatorIssues(glob?: string, pattern?: string, severity?: string, tabIdentifier: string): object;",
|
|
695
|
+
"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;"
|
|
698
|
+
};
|
|
699
|
+
program.configureHelp({
|
|
700
|
+
commandTerm(cmd) {
|
|
701
|
+
const term = cmd.name();
|
|
702
|
+
return commandSignatures[term] ?? cmd.name();
|
|
703
|
+
},
|
|
704
|
+
});
|
|
705
|
+
program.showSuggestionAfterError(true);
|
|
706
|
+
|
|
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>]")
|
|
747
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
748
|
+
|
|
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
|
+
.requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
|
|
754
|
+
.action(async (cmdOpts) => {
|
|
755
|
+
const globalOptions = program.opts();
|
|
756
|
+
const runtime = await ensureRuntime();
|
|
757
|
+
const serverName = embeddedName;
|
|
758
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
759
|
+
initialSchemas: embeddedSchemas,
|
|
760
|
+
});
|
|
761
|
+
try {
|
|
762
|
+
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);
|
|
769
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
770
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
771
|
+
} finally {
|
|
772
|
+
await runtime.close(serverName).catch(() => {});
|
|
773
|
+
}
|
|
774
|
+
})
|
|
775
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeMV(destinationPath: \"/path/to/file.md\", opera, ...)");
|
|
776
|
+
|
|
777
|
+
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>]")
|
|
782
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
783
|
+
|
|
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
|
+
.requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
|
|
788
|
+
.action(async (cmdOpts) => {
|
|
789
|
+
const globalOptions = program.opts();
|
|
790
|
+
const runtime = await ensureRuntime();
|
|
791
|
+
const serverName = embeddedName;
|
|
792
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
793
|
+
initialSchemas: embeddedSchemas,
|
|
794
|
+
});
|
|
795
|
+
try {
|
|
796
|
+
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);
|
|
802
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
803
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
804
|
+
} finally {
|
|
805
|
+
await runtime.close(serverName).catch(() => {});
|
|
806
|
+
}
|
|
807
|
+
})
|
|
808
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeRead(filePath: \"/path/to/file.md\", limit: 1, ...)");
|
|
809
|
+
|
|
810
|
+
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>]")
|
|
815
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
816
|
+
|
|
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()))
|
|
819
|
+
.action(async (cmdOpts) => {
|
|
820
|
+
const globalOptions = program.opts();
|
|
821
|
+
const runtime = await ensureRuntime();
|
|
822
|
+
const serverName = embeddedName;
|
|
823
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
824
|
+
initialSchemas: embeddedSchemas,
|
|
825
|
+
});
|
|
826
|
+
try {
|
|
827
|
+
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);
|
|
831
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
832
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
833
|
+
} finally {
|
|
834
|
+
await runtime.close(serverName).catch(() => {});
|
|
835
|
+
}
|
|
836
|
+
})
|
|
837
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.RunSomeTests(tabIdentifier: \"example-id\", tests: [, ...)");
|
|
838
|
+
|
|
839
|
+
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>]")
|
|
844
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
845
|
+
|
|
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')
|
|
849
|
+
.requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
|
|
850
|
+
.action(async (cmdOpts) => {
|
|
851
|
+
const globalOptions = program.opts();
|
|
852
|
+
const runtime = await ensureRuntime();
|
|
853
|
+
const serverName = embeddedName;
|
|
854
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
855
|
+
initialSchemas: embeddedSchemas,
|
|
856
|
+
});
|
|
857
|
+
try {
|
|
858
|
+
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;
|
|
862
|
+
if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
|
|
863
|
+
const call = (proxy.xcodeRM as any)(args);
|
|
864
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
865
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
866
|
+
} finally {
|
|
867
|
+
await runtime.close(serverName).catch(() => {});
|
|
868
|
+
}
|
|
869
|
+
})
|
|
870
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeRM(deleteFiles: true, path: \"/path/to/file.md, ...)");
|
|
871
|
+
|
|
872
|
+
program
|
|
873
|
+
.command("XcodeRefreshCodeIssuesInFile")
|
|
874
|
+
.summary("XcodeRefreshCodeIssuesInFile --file-path <file-path> --tab-identifier <tab-identifier> [--raw <json>]")
|
|
875
|
+
.description("Retrieves current compiler diagnostics (errors, warnings, notes) for a file in the Xcode project. Returns formatted diagnostic information including severity levels and messages.")
|
|
876
|
+
.usage("--file-path <file-path> --tab-identifier <tab-identifier> [--raw <json>]")
|
|
877
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
878
|
+
|
|
879
|
+
.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)")
|
|
880
|
+
.requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
|
|
881
|
+
.action(async (cmdOpts) => {
|
|
882
|
+
const globalOptions = program.opts();
|
|
883
|
+
const runtime = await ensureRuntime();
|
|
884
|
+
const serverName = embeddedName;
|
|
885
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
886
|
+
initialSchemas: embeddedSchemas,
|
|
887
|
+
});
|
|
888
|
+
try {
|
|
889
|
+
const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
|
|
890
|
+
if (cmdOpts.filePath !== undefined) args.filePath = cmdOpts.filePath;
|
|
891
|
+
if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
|
|
892
|
+
const call = (proxy.xcodeRefreshCodeIssuesInFile as any)(args);
|
|
893
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
894
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
895
|
+
} finally {
|
|
896
|
+
await runtime.close(serverName).catch(() => {});
|
|
897
|
+
}
|
|
898
|
+
})
|
|
899
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeRefreshCodeIssuesInFile(filePath: \"/path/to/f, ...)");
|
|
900
|
+
|
|
901
|
+
program
|
|
902
|
+
.command("GetBuildLog")
|
|
903
|
+
.summary("GetBuildLog [--glob <glob>] [--pattern <pattern>] [--severity <severity:remark|warning|error>] --tab-identifier <tab-identifier> [--raw <json>]")
|
|
904
|
+
.description("Gets the log of the current or most recently finished build. You can choose which build log entries to include by specifying the severity of any issues emitted by the build task represented by the entry. You can also filter by message regex pattern or file glob pattern. The response also indicates whether the build is currently in progress.")
|
|
905
|
+
.usage("[--glob <glob>] [--pattern <pattern>] [--severity <severity:remark|warning|error>] --tab-identifier <tab-identifier> [--raw <json>]")
|
|
906
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
907
|
+
|
|
908
|
+
.option("--glob <glob>", "Glob to filter the returned build log entries. Will match against the 'path' field of any emitted issues, as well as against the location of any build task.")
|
|
909
|
+
.option("--pattern <pattern>", "Regex to filter the returned build log entries. Will match against the 'message' field of any emitted issues, as well as the task description, command line, and console output of any build tasks.")
|
|
910
|
+
.option("--severity <severity:remark|warning|error>", "Limit the output of build log entries to those that emitted issues of the specified severity or higher. Valid values in order of decreasing severity are 'error', 'warning', 'remark'. Defaults to 'error'. (choices: remark, warning, error; example: remark)")
|
|
911
|
+
.requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
|
|
912
|
+
.action(async (cmdOpts) => {
|
|
913
|
+
const globalOptions = program.opts();
|
|
914
|
+
const runtime = await ensureRuntime();
|
|
915
|
+
const serverName = embeddedName;
|
|
916
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
917
|
+
initialSchemas: embeddedSchemas,
|
|
918
|
+
});
|
|
919
|
+
try {
|
|
920
|
+
const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
|
|
921
|
+
if (cmdOpts.glob !== undefined) args.glob = cmdOpts.glob;
|
|
922
|
+
if (cmdOpts.pattern !== undefined) args.pattern = cmdOpts.pattern;
|
|
923
|
+
if (cmdOpts.severity !== undefined) args.severity = cmdOpts.severity;
|
|
924
|
+
if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
|
|
925
|
+
const call = (proxy.getBuildLog as any)(args);
|
|
926
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
927
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
928
|
+
} finally {
|
|
929
|
+
await runtime.close(serverName).catch(() => {});
|
|
930
|
+
}
|
|
931
|
+
})
|
|
932
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.GetBuildLog(severity: \"remark\", tabIdentifier: \"ex, ...)");
|
|
933
|
+
|
|
934
|
+
program
|
|
935
|
+
.command("XcodeListWindows")
|
|
936
|
+
.summary("XcodeListWindows [--raw <json>]")
|
|
937
|
+
.description("Lists the current Xcode windows and their workspace information")
|
|
938
|
+
.usage("[--raw <json>]")
|
|
939
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
940
|
+
|
|
941
|
+
.action(async (cmdOpts) => {
|
|
942
|
+
const globalOptions = program.opts();
|
|
943
|
+
const runtime = await ensureRuntime();
|
|
944
|
+
const serverName = embeddedName;
|
|
945
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
946
|
+
initialSchemas: embeddedSchemas,
|
|
947
|
+
});
|
|
948
|
+
try {
|
|
949
|
+
const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
|
|
950
|
+
|
|
951
|
+
const call = (proxy.xcodeListWindows as any)(args);
|
|
952
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
953
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
954
|
+
} finally {
|
|
955
|
+
await runtime.close(serverName).catch(() => {});
|
|
956
|
+
}
|
|
957
|
+
})
|
|
958
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeListWindows()");
|
|
959
|
+
|
|
960
|
+
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>]")
|
|
965
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
966
|
+
|
|
967
|
+
.requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
|
|
968
|
+
.action(async (cmdOpts) => {
|
|
969
|
+
const globalOptions = program.opts();
|
|
970
|
+
const runtime = await ensureRuntime();
|
|
971
|
+
const serverName = embeddedName;
|
|
972
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
973
|
+
initialSchemas: embeddedSchemas,
|
|
974
|
+
});
|
|
975
|
+
try {
|
|
976
|
+
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);
|
|
979
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
980
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
981
|
+
} finally {
|
|
982
|
+
await runtime.close(serverName).catch(() => {});
|
|
983
|
+
}
|
|
984
|
+
})
|
|
985
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.BuildProject(tabIdentifier: \"example-id\")");
|
|
986
|
+
|
|
987
|
+
program
|
|
988
|
+
.command("RunAllTests")
|
|
989
|
+
.summary("RunAllTests --tab-identifier <tab-identifier> [--raw <json>]")
|
|
990
|
+
.description("Runs all tests from the active scheme's active test plan")
|
|
991
|
+
.usage("--tab-identifier <tab-identifier> [--raw <json>]")
|
|
992
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
993
|
+
|
|
994
|
+
.requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
|
|
995
|
+
.action(async (cmdOpts) => {
|
|
996
|
+
const globalOptions = program.opts();
|
|
997
|
+
const runtime = await ensureRuntime();
|
|
998
|
+
const serverName = embeddedName;
|
|
999
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
1000
|
+
initialSchemas: embeddedSchemas,
|
|
1001
|
+
});
|
|
1002
|
+
try {
|
|
1003
|
+
const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
|
|
1004
|
+
if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
|
|
1005
|
+
const call = (proxy.runAllTests as any)(args);
|
|
1006
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
1007
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
1008
|
+
} finally {
|
|
1009
|
+
await runtime.close(serverName).catch(() => {});
|
|
1010
|
+
}
|
|
1011
|
+
})
|
|
1012
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.RunAllTests(tabIdentifier: \"example-id\")");
|
|
1013
|
+
|
|
1014
|
+
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>]")
|
|
1019
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
1020
|
+
|
|
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)")
|
|
1024
|
+
.action(async (cmdOpts) => {
|
|
1025
|
+
const globalOptions = program.opts();
|
|
1026
|
+
const runtime = await ensureRuntime();
|
|
1027
|
+
const serverName = embeddedName;
|
|
1028
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
1029
|
+
initialSchemas: embeddedSchemas,
|
|
1030
|
+
});
|
|
1031
|
+
try {
|
|
1032
|
+
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;
|
|
1035
|
+
if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
|
|
1036
|
+
const call = (proxy.xcodeWrite as any)(args);
|
|
1037
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
1038
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
1039
|
+
} finally {
|
|
1040
|
+
await runtime.close(serverName).catch(() => {});
|
|
1041
|
+
}
|
|
1042
|
+
})
|
|
1043
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeWrite(content: \"value\", filePath: \"/path/to/f, ...)");
|
|
1044
|
+
|
|
1045
|
+
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>]")
|
|
1050
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
1051
|
+
|
|
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')
|
|
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.)")
|
|
1065
|
+
.action(async (cmdOpts) => {
|
|
1066
|
+
const globalOptions = program.opts();
|
|
1067
|
+
const runtime = await ensureRuntime();
|
|
1068
|
+
const serverName = embeddedName;
|
|
1069
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
1070
|
+
initialSchemas: embeddedSchemas,
|
|
1071
|
+
});
|
|
1072
|
+
try {
|
|
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;
|
|
1085
|
+
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);
|
|
1088
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
1089
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
1090
|
+
} finally {
|
|
1091
|
+
await runtime.close(serverName).catch(() => {});
|
|
1092
|
+
}
|
|
1093
|
+
})
|
|
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');
|
|
1096
|
+
|
|
1097
|
+
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>]")
|
|
1102
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
1103
|
+
|
|
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')
|
|
1107
|
+
.requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
|
|
1108
|
+
.action(async (cmdOpts) => {
|
|
1109
|
+
const globalOptions = program.opts();
|
|
1110
|
+
const runtime = await ensureRuntime();
|
|
1111
|
+
const serverName = embeddedName;
|
|
1112
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
1113
|
+
initialSchemas: embeddedSchemas,
|
|
1114
|
+
});
|
|
1115
|
+
try {
|
|
1116
|
+
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;
|
|
1120
|
+
if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
|
|
1121
|
+
const call = (proxy.xcodeLS as any)(args);
|
|
1122
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
1123
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
1124
|
+
} finally {
|
|
1125
|
+
await runtime.close(serverName).catch(() => {});
|
|
1126
|
+
}
|
|
1127
|
+
})
|
|
1128
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeLS(ignore: [\"value1\", \"value2\"], path: \"/path, ...)");
|
|
1129
|
+
|
|
1130
|
+
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>]")
|
|
1135
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
1136
|
+
|
|
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")
|
|
1139
|
+
.action(async (cmdOpts) => {
|
|
1140
|
+
const globalOptions = program.opts();
|
|
1141
|
+
const runtime = await ensureRuntime();
|
|
1142
|
+
const serverName = embeddedName;
|
|
1143
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
1144
|
+
initialSchemas: embeddedSchemas,
|
|
1145
|
+
});
|
|
1146
|
+
try {
|
|
1147
|
+
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);
|
|
1151
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
1152
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
1153
|
+
} finally {
|
|
1154
|
+
await runtime.close(serverName).catch(() => {});
|
|
1155
|
+
}
|
|
1156
|
+
})
|
|
1157
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.DocumentationSearch(frameworks: [\"value1\", \"value2, ...)");
|
|
1158
|
+
|
|
1159
|
+
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>]")
|
|
1164
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
1165
|
+
|
|
1166
|
+
.requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
|
|
1167
|
+
.action(async (cmdOpts) => {
|
|
1168
|
+
const globalOptions = program.opts();
|
|
1169
|
+
const runtime = await ensureRuntime();
|
|
1170
|
+
const serverName = embeddedName;
|
|
1171
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
1172
|
+
initialSchemas: embeddedSchemas,
|
|
1173
|
+
});
|
|
1174
|
+
try {
|
|
1175
|
+
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);
|
|
1178
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
1179
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
1180
|
+
} finally {
|
|
1181
|
+
await runtime.close(serverName).catch(() => {});
|
|
1182
|
+
}
|
|
1183
|
+
})
|
|
1184
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.GetTestList(tabIdentifier: \"example-id\")");
|
|
1185
|
+
|
|
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>]")
|
|
1191
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
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
|
+
.requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
|
|
1196
|
+
.action(async (cmdOpts) => {
|
|
1197
|
+
const globalOptions = program.opts();
|
|
1198
|
+
const runtime = await ensureRuntime();
|
|
1199
|
+
const serverName = embeddedName;
|
|
1200
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
1201
|
+
initialSchemas: embeddedSchemas,
|
|
1202
|
+
});
|
|
1203
|
+
try {
|
|
1204
|
+
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);
|
|
1209
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
1210
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
1211
|
+
} finally {
|
|
1212
|
+
await runtime.close(serverName).catch(() => {});
|
|
1213
|
+
}
|
|
1214
|
+
})
|
|
1215
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeGlob(path: \"/path/to/file.md\", tabIdentifier:, ...)");
|
|
1216
|
+
|
|
1217
|
+
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>]")
|
|
1222
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
1223
|
+
|
|
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'.")
|
|
1227
|
+
.requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
|
|
1228
|
+
.action(async (cmdOpts) => {
|
|
1229
|
+
const globalOptions = program.opts();
|
|
1230
|
+
const runtime = await ensureRuntime();
|
|
1231
|
+
const serverName = embeddedName;
|
|
1232
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
1233
|
+
initialSchemas: embeddedSchemas,
|
|
1234
|
+
});
|
|
1235
|
+
try {
|
|
1236
|
+
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;
|
|
1240
|
+
if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
|
|
1241
|
+
const call = (proxy.xcodeListNavigatorIssues as any)(args);
|
|
1242
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
1243
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
1244
|
+
} finally {
|
|
1245
|
+
await runtime.close(serverName).catch(() => {});
|
|
1246
|
+
}
|
|
1247
|
+
})
|
|
1248
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeListNavigatorIssues(tabIdentifier: \"example-id\")");
|
|
1249
|
+
|
|
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>]")
|
|
1255
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
1256
|
+
|
|
1257
|
+
.requiredOption("--directory-path <directory-path>", "Project navigator relative path for the directory to create (example: /path/to/file.md)")
|
|
1258
|
+
.requiredOption("--tab-identifier <tab-identifier>", "The workspace tab identifier (example: example-id)")
|
|
1259
|
+
.action(async (cmdOpts) => {
|
|
1260
|
+
const globalOptions = program.opts();
|
|
1261
|
+
const runtime = await ensureRuntime();
|
|
1262
|
+
const serverName = embeddedName;
|
|
1263
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
1264
|
+
initialSchemas: embeddedSchemas,
|
|
1265
|
+
});
|
|
1266
|
+
try {
|
|
1267
|
+
const args = cmdOpts.raw ? JSON.parse(cmdOpts.raw) : ({} as Record<string, unknown>);
|
|
1268
|
+
if (cmdOpts.directoryPath !== undefined) args.directoryPath = cmdOpts.directoryPath;
|
|
1269
|
+
if (cmdOpts.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
|
|
1270
|
+
const call = (proxy.xcodeMakeDir as any)(args);
|
|
1271
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
1272
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
1273
|
+
} finally {
|
|
1274
|
+
await runtime.close(serverName).catch(() => {});
|
|
1275
|
+
}
|
|
1276
|
+
})
|
|
1277
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.XcodeMakeDir(directoryPath: \"/path/to/file.md\", ta, ...)");
|
|
1278
|
+
|
|
1279
|
+
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
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
1285
|
+
|
|
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
|
+
.action(async (cmdOpts) => {
|
|
1291
|
+
const globalOptions = program.opts();
|
|
1292
|
+
const runtime = await ensureRuntime();
|
|
1293
|
+
const serverName = embeddedName;
|
|
1294
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
1295
|
+
initialSchemas: embeddedSchemas,
|
|
1296
|
+
});
|
|
1297
|
+
try {
|
|
1298
|
+
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.tabIdentifier !== undefined) args.tabIdentifier = cmdOpts.tabIdentifier;
|
|
1302
|
+
if (cmdOpts.timeout !== undefined) args.timeout = cmdOpts.timeout;
|
|
1303
|
+
const call = (proxy.executeSnippet as any)(args);
|
|
1304
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
1305
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
1306
|
+
} finally {
|
|
1307
|
+
await runtime.close(serverName).catch(() => {});
|
|
1308
|
+
}
|
|
1309
|
+
})
|
|
1310
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.ExecuteSnippet(codeSnippet: \"value\", sourceFilePat, ...)");
|
|
1311
|
+
|
|
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>]")
|
|
1317
|
+
.option('--raw <json>', 'Provide raw JSON arguments to the tool, bypassing flag parsing.')
|
|
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)")
|
|
1321
|
+
.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
|
+
.action(async (cmdOpts) => {
|
|
1324
|
+
const globalOptions = program.opts();
|
|
1325
|
+
const runtime = await ensureRuntime();
|
|
1326
|
+
const serverName = embeddedName;
|
|
1327
|
+
const proxy = createServerProxy(runtime, serverName, {
|
|
1328
|
+
initialSchemas: embeddedSchemas,
|
|
1329
|
+
});
|
|
1330
|
+
try {
|
|
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;
|
|
1334
|
+
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);
|
|
1337
|
+
const result = await invokeWithTimeout(call, globalOptions.timeout || 30000);
|
|
1338
|
+
printResult(result, globalOptions.output ?? 'text');
|
|
1339
|
+
} finally {
|
|
1340
|
+
await runtime.close(serverName).catch(() => {});
|
|
1341
|
+
}
|
|
1342
|
+
})
|
|
1343
|
+
.addHelpText('after', () => '\nExample:\n ' + "mcporter call mcpbridge.RenderPreview(previewDefinitionIndexInFile: 1, sou, ...)");
|
|
1344
|
+
|
|
1345
|
+
program
|
|
1346
|
+
.command('__mcporter_inspect', { hidden: true })
|
|
1347
|
+
.description('Internal metadata printer for mcporter inspect-cli.')
|
|
1348
|
+
.action(() => {
|
|
1349
|
+
const payload = buildMetadataPayload();
|
|
1350
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
1351
|
+
});
|
|
1352
|
+
|
|
1353
|
+
configureToolCommandHelps();
|
|
1354
|
+
|
|
1355
|
+
const FORCE_COLOR = process.env.FORCE_COLOR?.toLowerCase();
|
|
1356
|
+
const forceDisableColor = FORCE_COLOR === '0' || FORCE_COLOR === 'false';
|
|
1357
|
+
const forceEnableColor = FORCE_COLOR === '1' || FORCE_COLOR === 'true' || FORCE_COLOR === '2' || FORCE_COLOR === '3';
|
|
1358
|
+
const hasNoColor = process.env.NO_COLOR !== undefined;
|
|
1359
|
+
const stdoutStream = process.stdout as NodeJS.WriteStream | undefined;
|
|
1360
|
+
const supportsAnsiColor = !hasNoColor && (forceEnableColor || (!forceDisableColor && Boolean(stdoutStream?.isTTY)));
|
|
1361
|
+
|
|
1362
|
+
const tint = {
|
|
1363
|
+
bold(text: string): string {
|
|
1364
|
+
return supportsAnsiColor ? '[1m' + text + '[0m' : text;
|
|
1365
|
+
},
|
|
1366
|
+
dim(text: string): string {
|
|
1367
|
+
return supportsAnsiColor ? '[90m' + text + '[0m' : text;
|
|
1368
|
+
},
|
|
1369
|
+
extraDim(text: string): string {
|
|
1370
|
+
return supportsAnsiColor ? '[38;5;244m' + text + '[0m' : text;
|
|
1371
|
+
},
|
|
1372
|
+
};
|
|
1373
|
+
|
|
1374
|
+
function configureGeneratedCommandHelp(command: Command): void {
|
|
1375
|
+
command.configureHelp({
|
|
1376
|
+
commandUsage(target) {
|
|
1377
|
+
const usage = (target.name() + ' ' + target.usage()).trim() || target.name();
|
|
1378
|
+
return supportsAnsiColor ? tint.bold(usage) : usage;
|
|
1379
|
+
},
|
|
1380
|
+
optionTerm(option) {
|
|
1381
|
+
const term = option.flags ?? '';
|
|
1382
|
+
return supportsAnsiColor ? tint.bold(term) : term;
|
|
1383
|
+
},
|
|
1384
|
+
optionDescription(option) {
|
|
1385
|
+
const description = option.description ?? '';
|
|
1386
|
+
return supportsAnsiColor ? tint.extraDim(description) : description;
|
|
1387
|
+
},
|
|
1388
|
+
});
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
function configureToolCommandHelps(): void {
|
|
1392
|
+
program.commands.forEach((cmd) => {
|
|
1393
|
+
if (cmd.name() === '__mcporter_inspect') {
|
|
1394
|
+
return;
|
|
1395
|
+
}
|
|
1396
|
+
configureGeneratedCommandHelp(cmd);
|
|
1397
|
+
});
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
function renderStandaloneHelp(): string {
|
|
1401
|
+
const colorfulTitle = tint.bold(embeddedName) + ' ' + tint.dim('— ' + embeddedDescription);
|
|
1402
|
+
const plainTitle = embeddedName + ' — ' + embeddedDescription;
|
|
1403
|
+
const title = supportsAnsiColor ? colorfulTitle : plainTitle;
|
|
1404
|
+
const lines = [title, '', 'Usage: ' + embeddedName + ' <command> [options]', ''];
|
|
1405
|
+
if (generatorTools) {
|
|
1406
|
+
lines.push(formatEmbeddedTools());
|
|
1407
|
+
}
|
|
1408
|
+
lines.push('', formatGlobalFlags(), '', formatQuickStart());
|
|
1409
|
+
if (generatorInfo) {
|
|
1410
|
+
lines.push('', tint.extraDim(generatorInfo));
|
|
1411
|
+
}
|
|
1412
|
+
return lines.join('\n');
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
program.helpInformation = () => renderStandaloneHelp();
|
|
1416
|
+
|
|
1417
|
+
function formatEmbeddedTools(): string {
|
|
1418
|
+
const header = supportsAnsiColor ? tint.bold('Embedded tools') : 'Embedded tools';
|
|
1419
|
+
if (!generatorTools.length) {
|
|
1420
|
+
return header;
|
|
1421
|
+
}
|
|
1422
|
+
const lines = [header];
|
|
1423
|
+
generatorTools.forEach((entry) => {
|
|
1424
|
+
const renderedDesc = entry.description
|
|
1425
|
+
? supportsAnsiColor
|
|
1426
|
+
? tint.extraDim(entry.description)
|
|
1427
|
+
: entry.description
|
|
1428
|
+
: undefined;
|
|
1429
|
+
const base = renderedDesc ? entry.name + ' - ' + renderedDesc : entry.name;
|
|
1430
|
+
lines.push(' ' + base);
|
|
1431
|
+
if (entry.flags) {
|
|
1432
|
+
const renderedFlags = supportsAnsiColor ? tint.extraDim(entry.flags) : entry.flags;
|
|
1433
|
+
lines.push(' ' + renderedFlags);
|
|
1434
|
+
}
|
|
1435
|
+
lines.push('');
|
|
1436
|
+
});
|
|
1437
|
+
if (lines[lines.length - 1] === '') {
|
|
1438
|
+
lines.pop();
|
|
1439
|
+
}
|
|
1440
|
+
return lines.join('\n');
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
function formatGlobalFlags(): string {
|
|
1444
|
+
const header = supportsAnsiColor ? tint.bold('Global flags') : 'Global flags';
|
|
1445
|
+
const entries = [
|
|
1446
|
+
['-t, --timeout <ms>', 'Call timeout in milliseconds'],
|
|
1447
|
+
['-o, --output <format>', 'text | markdown | json | raw (default text)'],
|
|
1448
|
+
];
|
|
1449
|
+
const formatted = entries.map(([flag, summary]) => ' ' + flag.padEnd(28) + summary);
|
|
1450
|
+
return [header, ...formatted].join('\n');
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
function formatQuickStart(): string {
|
|
1454
|
+
const header = supportsAnsiColor ? tint.bold('Quick start') : 'Quick start';
|
|
1455
|
+
const examples = quickStartExamples();
|
|
1456
|
+
if (!examples.length) {
|
|
1457
|
+
return header;
|
|
1458
|
+
}
|
|
1459
|
+
const formatted = examples.map(([cmd, note]) => ' ' + cmd + '\n ' + tint.dim('# ' + note));
|
|
1460
|
+
return [header, ...formatted].join('\n');
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
function quickStartExamples(): Array<[string, string]> {
|
|
1464
|
+
const examples: Array<[string, string]> = [];
|
|
1465
|
+
const commandMap = new Map<string, string>();
|
|
1466
|
+
program.commands.forEach((cmd) => {
|
|
1467
|
+
const name = cmd.name();
|
|
1468
|
+
if (name !== '__mcporter_inspect') {
|
|
1469
|
+
commandMap.set(name, name);
|
|
1470
|
+
}
|
|
1471
|
+
});
|
|
1472
|
+
const embedded = Array.isArray(generatorTools) ? generatorTools : [];
|
|
1473
|
+
for (const entry of embedded.slice(0, 3)) {
|
|
1474
|
+
const commandName = commandMap.get(entry.name) ?? entry.name;
|
|
1475
|
+
const flags = entry.flags ? ' ' + entry.flags.replace(/<[^>]+>/g, '<value>') : '';
|
|
1476
|
+
examples.push([embeddedName + ' ' + commandName + flags, 'invoke ' + commandName]);
|
|
1477
|
+
}
|
|
1478
|
+
if (!examples.length) {
|
|
1479
|
+
examples.push([embeddedName + ' <tool> --key value', 'invoke a tool with flags']);
|
|
1480
|
+
}
|
|
1481
|
+
return examples;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
function printResult(result: unknown, format: string) {
|
|
1485
|
+
const wrapped = createCallResult(result);
|
|
1486
|
+
switch (format) {
|
|
1487
|
+
case 'json': {
|
|
1488
|
+
const json = wrapped.json();
|
|
1489
|
+
if (json) {
|
|
1490
|
+
console.log(JSON.stringify(json, null, 2));
|
|
1491
|
+
return;
|
|
1492
|
+
}
|
|
1493
|
+
break;
|
|
1494
|
+
}
|
|
1495
|
+
case 'markdown': {
|
|
1496
|
+
const markdown = wrapped.markdown();
|
|
1497
|
+
if (markdown) {
|
|
1498
|
+
console.log(markdown);
|
|
1499
|
+
return;
|
|
1500
|
+
}
|
|
1501
|
+
break;
|
|
1502
|
+
}
|
|
1503
|
+
case 'raw': {
|
|
1504
|
+
console.log(JSON.stringify(wrapped.raw, null, 2));
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
const text = wrapped.text();
|
|
1509
|
+
if (text) {
|
|
1510
|
+
console.log(text);
|
|
1511
|
+
} else {
|
|
1512
|
+
console.log(JSON.stringify(wrapped.raw, null, 2));
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
function normalizeEmbeddedServer(server: typeof embeddedServer) {
|
|
1517
|
+
const base = { ...server } as Record<string, unknown>;
|
|
1518
|
+
if ((server.command as any).kind === 'http') {
|
|
1519
|
+
const urlRaw = (server.command as any).url;
|
|
1520
|
+
const urlValue = typeof urlRaw === 'string' ? urlRaw : String(urlRaw);
|
|
1521
|
+
return {
|
|
1522
|
+
...base,
|
|
1523
|
+
command: {
|
|
1524
|
+
...(server.command as Record<string, unknown>),
|
|
1525
|
+
url: new URL(urlValue),
|
|
1526
|
+
},
|
|
1527
|
+
};
|
|
1528
|
+
}
|
|
1529
|
+
if ((server.command as any).kind === 'stdio') {
|
|
1530
|
+
return {
|
|
1531
|
+
...base,
|
|
1532
|
+
command: {
|
|
1533
|
+
...(server.command as Record<string, unknown>),
|
|
1534
|
+
args: [ ...((server.command as any).args ?? []) ],
|
|
1535
|
+
},
|
|
1536
|
+
};
|
|
1537
|
+
}
|
|
1538
|
+
return base;
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
function determineArtifactKind(): 'template' | 'bundle' | 'binary' {
|
|
1542
|
+
const scriptPath = typeof process !== 'undefined' && Array.isArray(process.argv) ? process.argv[1] ?? '' : '';
|
|
1543
|
+
if (scriptPath.endsWith('.ts')) {
|
|
1544
|
+
return 'template';
|
|
1545
|
+
}
|
|
1546
|
+
if (scriptPath.endsWith('.js')) {
|
|
1547
|
+
return 'bundle';
|
|
1548
|
+
}
|
|
1549
|
+
return 'binary';
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
function resolveArtifactPath(): string {
|
|
1553
|
+
if (typeof process !== 'undefined' && Array.isArray(process.argv) && process.argv.length > 1) {
|
|
1554
|
+
const script = process.argv[1];
|
|
1555
|
+
if (script) {
|
|
1556
|
+
return script;
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
return embeddedMetadata.artifact.path;
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
function buildMetadataPayload() {
|
|
1563
|
+
const invocation = { ...embeddedMetadata.invocation };
|
|
1564
|
+
const path = resolveArtifactPath();
|
|
1565
|
+
if (artifactKind === 'template' && path) {
|
|
1566
|
+
invocation.outputPath = invocation.outputPath ?? path;
|
|
1567
|
+
} else if (artifactKind === 'bundle' && path) {
|
|
1568
|
+
invocation.bundle = invocation.bundle ?? path;
|
|
1569
|
+
} else if (artifactKind === 'binary' && path) {
|
|
1570
|
+
invocation.compile = invocation.compile ?? path;
|
|
1571
|
+
}
|
|
1572
|
+
return {
|
|
1573
|
+
...embeddedMetadata,
|
|
1574
|
+
artifact: {
|
|
1575
|
+
path,
|
|
1576
|
+
kind: artifactKind,
|
|
1577
|
+
},
|
|
1578
|
+
invocation,
|
|
1579
|
+
};
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
async function ensureRuntime(): Promise<Awaited<ReturnType<typeof createRuntime>>> {
|
|
1583
|
+
return await createRuntime({
|
|
1584
|
+
servers: [normalizeEmbeddedServer(embeddedServer)],
|
|
1585
|
+
});
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
async function invokeWithTimeout<T>(call: Promise<T>, timeout: number): Promise<T> {
|
|
1589
|
+
if (!Number.isFinite(timeout) || timeout <= 0) {
|
|
1590
|
+
return await call;
|
|
1591
|
+
}
|
|
1592
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
1593
|
+
try {
|
|
1594
|
+
return await Promise.race([
|
|
1595
|
+
call,
|
|
1596
|
+
new Promise<never>((_, reject) => {
|
|
1597
|
+
timer = setTimeout(() => {
|
|
1598
|
+
reject(new Error('Call timed out after ' + timeout + 'ms.'));
|
|
1599
|
+
}, timeout);
|
|
1600
|
+
}),
|
|
1601
|
+
]);
|
|
1602
|
+
} finally {
|
|
1603
|
+
if (timer) {
|
|
1604
|
+
clearTimeout(timer);
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
async function runCli(): Promise<void> {
|
|
1610
|
+
const args = process.argv.slice(2);
|
|
1611
|
+
if (args.length === 0) {
|
|
1612
|
+
program.outputHelp();
|
|
1613
|
+
return;
|
|
1614
|
+
}
|
|
1615
|
+
await program.parseAsync(process.argv);
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
if (process.env.MCPORTER_DISABLE_AUTORUN !== '1') {
|
|
1619
|
+
runCli().catch((error) => {
|
|
1620
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1621
|
+
console.error(message);
|
|
1622
|
+
process.exit(1);
|
|
1623
|
+
});
|
|
1624
|
+
}
|