preflight-ios-mcp 1.0.0

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.
@@ -0,0 +1,85 @@
1
+ import { z } from 'zod';
2
+ export declare const listAppsParams: {
3
+ deviceId: z.ZodOptional<z.ZodString>;
4
+ includeSystem: z.ZodOptional<z.ZodBoolean>;
5
+ };
6
+ export declare function handleListApps(args: {
7
+ deviceId?: string;
8
+ includeSystem?: boolean;
9
+ }): Promise<{
10
+ content: {
11
+ type: "text";
12
+ text: string;
13
+ }[];
14
+ }>;
15
+ export declare const appInfoParams: {
16
+ bundleId: z.ZodString;
17
+ deviceId: z.ZodOptional<z.ZodString>;
18
+ };
19
+ export declare function handleAppInfo(args: {
20
+ bundleId: string;
21
+ deviceId?: string;
22
+ }): Promise<{
23
+ content: {
24
+ type: "text";
25
+ text: string;
26
+ }[];
27
+ }>;
28
+ export declare const launchAppParams: {
29
+ bundleId: z.ZodString;
30
+ terminateRunning: z.ZodOptional<z.ZodBoolean>;
31
+ args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
32
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
33
+ deviceId: z.ZodOptional<z.ZodString>;
34
+ };
35
+ export declare function handleLaunchApp(args: {
36
+ bundleId: string;
37
+ terminateRunning?: boolean;
38
+ args?: string[];
39
+ env?: Record<string, string>;
40
+ deviceId?: string;
41
+ }): Promise<{
42
+ content: {
43
+ type: "text";
44
+ text: string;
45
+ }[];
46
+ }>;
47
+ export declare const terminateAppParams: {
48
+ bundleId: z.ZodString;
49
+ deviceId: z.ZodOptional<z.ZodString>;
50
+ };
51
+ export declare function handleTerminateApp(args: {
52
+ bundleId: string;
53
+ deviceId?: string;
54
+ }): Promise<{
55
+ content: {
56
+ type: "text";
57
+ text: string;
58
+ }[];
59
+ }>;
60
+ export declare const installAppParams: {
61
+ path: z.ZodString;
62
+ deviceId: z.ZodOptional<z.ZodString>;
63
+ };
64
+ export declare function handleInstallApp(args: {
65
+ path: string;
66
+ deviceId?: string;
67
+ }): Promise<{
68
+ content: {
69
+ type: "text";
70
+ text: string;
71
+ }[];
72
+ }>;
73
+ export declare const uninstallAppParams: {
74
+ bundleId: z.ZodString;
75
+ deviceId: z.ZodOptional<z.ZodString>;
76
+ };
77
+ export declare function handleUninstallApp(args: {
78
+ bundleId: string;
79
+ deviceId?: string;
80
+ }): Promise<{
81
+ content: {
82
+ type: "text";
83
+ text: string;
84
+ }[];
85
+ }>;
@@ -0,0 +1,177 @@
1
+ import { z } from 'zod';
2
+ import { execSimctl, resolveDevice } from '../helpers/simctl.js';
3
+ import { execFile } from 'node:child_process';
4
+ import { promisify } from 'node:util';
5
+ import { writeFile, unlink } from 'node:fs/promises';
6
+ import { join } from 'node:path';
7
+ import { tmpdir } from 'node:os';
8
+ const execFileAsync = promisify(execFile);
9
+ // --- list_apps ---
10
+ export const listAppsParams = {
11
+ deviceId: z.string().optional().describe('Device UDID, name, or "booted" (default: booted)'),
12
+ includeSystem: z.boolean().optional().describe('Include system apps (default: false)'),
13
+ };
14
+ export async function handleListApps(args) {
15
+ const device = await resolveDevice(args.deviceId);
16
+ // Use JSON output via plutil for reliable parsing
17
+ const { stdout } = await execSimctl(['listapps', device], 'tool:listApps');
18
+ let apps = [];
19
+ try {
20
+ // Write plist to temp file then convert to JSON
21
+ const tmpFile = join(tmpdir(), `simctl-apps-${Date.now()}.plist`);
22
+ await writeFile(tmpFile, stdout, 'utf-8');
23
+ let data;
24
+ try {
25
+ const result = await execFileAsync('plutil', ['-convert', 'json', '-o', '-', tmpFile], {
26
+ maxBuffer: 50 * 1024 * 1024,
27
+ encoding: 'utf-8',
28
+ timeout: 15000,
29
+ });
30
+ data = JSON.parse(result.stdout);
31
+ }
32
+ finally {
33
+ await unlink(tmpFile).catch(() => { });
34
+ }
35
+ for (const [bundleId, info] of Object.entries(data)) {
36
+ const name = info.CFBundleDisplayName || info.CFBundleName || bundleId;
37
+ const version = info.CFBundleShortVersionString || info.CFBundleVersion;
38
+ const isSystem = info.ApplicationType === 'System';
39
+ if (!args.includeSystem && isSystem)
40
+ continue;
41
+ apps.push({ name, bundleId, version, isSystem });
42
+ }
43
+ }
44
+ catch {
45
+ // Fallback: regex parsing
46
+ const bundleIdMatches = [...stdout.matchAll(/CFBundleIdentifier\s*=\s*"?([^";\n]+)"?/g)];
47
+ const nameMatches = [...stdout.matchAll(/(?:CFBundleDisplayName|CFBundleName)\s*=\s*"?([^";\n]+)"?/g)];
48
+ apps = bundleIdMatches.map((m, i) => ({
49
+ bundleId: m[1].trim(),
50
+ name: nameMatches[i]?.[1]?.trim() || m[1].trim(),
51
+ }));
52
+ }
53
+ apps.sort((a, b) => a.name.localeCompare(b.name));
54
+ const lines = apps.map(a => `${a.name} — ${a.bundleId}${a.version ? ` (v${a.version})` : ''}`);
55
+ return {
56
+ content: [{
57
+ type: 'text',
58
+ text: apps.length === 0
59
+ ? 'No apps found.'
60
+ : `Installed apps (${apps.length}):\n\n${lines.join('\n')}`,
61
+ }],
62
+ };
63
+ }
64
+ // --- app_info ---
65
+ export const appInfoParams = {
66
+ bundleId: z.string().describe('App bundle identifier (e.g., "com.apple.mobilesafari")'),
67
+ deviceId: z.string().optional().describe('Device UDID, name, or "booted" (default: booted)'),
68
+ };
69
+ export async function handleAppInfo(args) {
70
+ const device = await resolveDevice(args.deviceId);
71
+ const { stdout } = await execSimctl(['appinfo', device, args.bundleId], 'tool:appInfo');
72
+ // Convert plist to JSON for readability
73
+ try {
74
+ const tmpFile2 = join(tmpdir(), `simctl-appinfo-${Date.now()}.plist`);
75
+ await writeFile(tmpFile2, stdout, 'utf-8');
76
+ let data;
77
+ try {
78
+ const result = await execFileAsync('plutil', ['-convert', 'json', '-o', '-', tmpFile2], {
79
+ maxBuffer: 10 * 1024 * 1024,
80
+ encoding: 'utf-8',
81
+ timeout: 5000,
82
+ });
83
+ data = JSON.parse(result.stdout);
84
+ }
85
+ finally {
86
+ await unlink(tmpFile2).catch(() => { });
87
+ }
88
+ const fields = [
89
+ `Bundle ID: ${data.CFBundleIdentifier || args.bundleId}`,
90
+ `Name: ${data.CFBundleDisplayName || data.CFBundleName || '—'}`,
91
+ `Version: ${data.CFBundleShortVersionString || '—'} (${data.CFBundleVersion || '—'})`,
92
+ `Type: ${data.ApplicationType || '—'}`,
93
+ `Bundle Path: ${data.Path || data.CFBundleExecutable || '—'}`,
94
+ `Data Path: ${data.DataContainer || '—'}`,
95
+ `SDK: ${data.DTSDKName || '—'}`,
96
+ `Min iOS: ${data.MinimumOSVersion || '—'}`,
97
+ ];
98
+ return { content: [{ type: 'text', text: fields.join('\n') }] };
99
+ }
100
+ catch {
101
+ return { content: [{ type: 'text', text: stdout }] };
102
+ }
103
+ }
104
+ // --- launch_app ---
105
+ export const launchAppParams = {
106
+ bundleId: z.string().describe('App bundle identifier to launch'),
107
+ terminateRunning: z.boolean().optional().describe('Terminate the app first if already running (default: false)'),
108
+ args: z.array(z.string()).optional().describe('Launch arguments to pass to the app'),
109
+ env: z.record(z.string()).optional().describe('Environment variables to set (will be prefixed with SIMCTL_CHILD_)'),
110
+ deviceId: z.string().optional().describe('Device UDID, name, or "booted" (default: booted)'),
111
+ };
112
+ export async function handleLaunchApp(args) {
113
+ const device = await resolveDevice(args.deviceId);
114
+ // Terminate first if requested
115
+ if (args.terminateRunning) {
116
+ try {
117
+ await execSimctl(['terminate', device, args.bundleId], 'tool:launchApp');
118
+ }
119
+ catch { /* app may not be running, ignore */ }
120
+ }
121
+ if (args.env) {
122
+ for (const [key, value] of Object.entries(args.env)) {
123
+ process.env[`SIMCTL_CHILD_${key}`] = value;
124
+ }
125
+ }
126
+ const cmdArgs = ['launch', device, args.bundleId, ...(args.args || [])];
127
+ const { stdout } = await execSimctl(cmdArgs, 'tool:launchApp');
128
+ if (args.env) {
129
+ for (const key of Object.keys(args.env)) {
130
+ delete process.env[`SIMCTL_CHILD_${key}`];
131
+ }
132
+ }
133
+ return {
134
+ content: [{
135
+ type: 'text',
136
+ text: `Launched ${args.bundleId}. ${stdout.trim()}`,
137
+ }],
138
+ };
139
+ }
140
+ // --- terminate_app ---
141
+ export const terminateAppParams = {
142
+ bundleId: z.string().describe('App bundle identifier to terminate'),
143
+ deviceId: z.string().optional().describe('Device UDID, name, or "booted" (default: booted)'),
144
+ };
145
+ export async function handleTerminateApp(args) {
146
+ const device = await resolveDevice(args.deviceId);
147
+ try {
148
+ await execSimctl(['terminate', device, args.bundleId], 'tool:terminateApp');
149
+ }
150
+ catch (err) {
151
+ // Not running is not an error
152
+ const msg = err.message;
153
+ if (!msg.includes('not running') && !msg.includes('No such process'))
154
+ throw err;
155
+ }
156
+ return { content: [{ type: 'text', text: `Terminated ${args.bundleId}.` }] };
157
+ }
158
+ // --- install_app ---
159
+ export const installAppParams = {
160
+ path: z.string().describe('Path to .app bundle or .ipa file to install'),
161
+ deviceId: z.string().optional().describe('Device UDID, name, or "booted" (default: booted)'),
162
+ };
163
+ export async function handleInstallApp(args) {
164
+ const device = await resolveDevice(args.deviceId);
165
+ await execSimctl(['install', device, args.path], 'tool:installApp');
166
+ return { content: [{ type: 'text', text: `Installed app from ${args.path}.` }] };
167
+ }
168
+ // --- uninstall_app ---
169
+ export const uninstallAppParams = {
170
+ bundleId: z.string().describe('App bundle identifier to uninstall'),
171
+ deviceId: z.string().optional().describe('Device UDID, name, or "booted" (default: booted)'),
172
+ };
173
+ export async function handleUninstallApp(args) {
174
+ const device = await resolveDevice(args.deviceId);
175
+ await execSimctl(['uninstall', device, args.bundleId], 'tool:uninstallApp');
176
+ return { content: [{ type: 'text', text: `Uninstalled ${args.bundleId}.` }] };
177
+ }
@@ -0,0 +1,140 @@
1
+ import { z } from 'zod';
2
+ export declare const getLogsParams: {
3
+ process: z.ZodOptional<z.ZodString>;
4
+ subsystem: z.ZodOptional<z.ZodString>;
5
+ category: z.ZodOptional<z.ZodString>;
6
+ level: z.ZodOptional<z.ZodEnum<["debug", "info", "default", "error", "fault"]>>;
7
+ since: z.ZodOptional<z.ZodString>;
8
+ messageContains: z.ZodOptional<z.ZodString>;
9
+ limit: z.ZodOptional<z.ZodNumber>;
10
+ deviceId: z.ZodOptional<z.ZodString>;
11
+ };
12
+ export declare function handleGetLogs(args: {
13
+ process?: string;
14
+ subsystem?: string;
15
+ category?: string;
16
+ level?: string;
17
+ since?: string;
18
+ messageContains?: string;
19
+ limit?: number;
20
+ deviceId?: string;
21
+ }): Promise<{
22
+ content: {
23
+ type: "text";
24
+ text: string;
25
+ }[];
26
+ }>;
27
+ export declare const streamLogsParams: {
28
+ action: z.ZodEnum<["start", "read", "stop"]>;
29
+ process: z.ZodOptional<z.ZodString>;
30
+ level: z.ZodOptional<z.ZodEnum<["debug", "info", "default", "error", "fault"]>>;
31
+ bufferSize: z.ZodOptional<z.ZodNumber>;
32
+ deviceId: z.ZodOptional<z.ZodString>;
33
+ };
34
+ export declare function handleStreamLogs(args: {
35
+ action: 'start' | 'read' | 'stop';
36
+ process?: string;
37
+ level?: string;
38
+ bufferSize?: number;
39
+ deviceId?: string;
40
+ }): Promise<{
41
+ content: {
42
+ type: "text";
43
+ text: string;
44
+ }[];
45
+ }>;
46
+ export declare const getAppContainerParams: {
47
+ bundleId: z.ZodString;
48
+ containerType: z.ZodOptional<z.ZodEnum<["app", "data", "groups"]>>;
49
+ deviceId: z.ZodOptional<z.ZodString>;
50
+ };
51
+ export declare function handleGetAppContainer(args: {
52
+ bundleId: string;
53
+ containerType?: string;
54
+ deviceId?: string;
55
+ }): Promise<{
56
+ content: {
57
+ type: "text";
58
+ text: string;
59
+ }[];
60
+ }>;
61
+ export declare const listAppFilesParams: {
62
+ bundleId: z.ZodString;
63
+ subPath: z.ZodOptional<z.ZodString>;
64
+ deviceId: z.ZodOptional<z.ZodString>;
65
+ };
66
+ export declare function handleListAppFiles(args: {
67
+ bundleId: string;
68
+ subPath?: string;
69
+ deviceId?: string;
70
+ }): Promise<{
71
+ content: {
72
+ type: "text";
73
+ text: string;
74
+ }[];
75
+ }>;
76
+ export declare const readAppFileParams: {
77
+ bundleId: z.ZodString;
78
+ filePath: z.ZodString;
79
+ deviceId: z.ZodOptional<z.ZodString>;
80
+ };
81
+ export declare function handleReadAppFile(args: {
82
+ bundleId: string;
83
+ filePath: string;
84
+ deviceId?: string;
85
+ }): Promise<{
86
+ content: {
87
+ type: "text";
88
+ text: string;
89
+ }[];
90
+ }>;
91
+ export declare const getCrashLogsParams: {
92
+ processName: z.ZodOptional<z.ZodString>;
93
+ since: z.ZodOptional<z.ZodString>;
94
+ limit: z.ZodOptional<z.ZodNumber>;
95
+ deviceId: z.ZodOptional<z.ZodString>;
96
+ };
97
+ export declare function handleGetCrashLogs(args: {
98
+ processName?: string;
99
+ since?: string;
100
+ limit?: number;
101
+ deviceId?: string;
102
+ }): Promise<{
103
+ content: {
104
+ type: "text";
105
+ text: string;
106
+ }[];
107
+ }>;
108
+ export declare const diagnoseParams: {
109
+ deviceId: z.ZodOptional<z.ZodString>;
110
+ };
111
+ export declare function handleDiagnose(args: {
112
+ deviceId?: string;
113
+ }): Promise<{
114
+ content: {
115
+ type: "text";
116
+ text: string;
117
+ }[];
118
+ }>;
119
+ export declare const accessibilityAuditParams: {
120
+ deviceId: z.ZodOptional<z.ZodString>;
121
+ };
122
+ export declare function handleAccessibilityAudit(args: {
123
+ deviceId?: string;
124
+ }): Promise<{
125
+ content: {
126
+ type: "text";
127
+ text: string;
128
+ }[];
129
+ }>;
130
+ export declare const getScreenInfoParams: {
131
+ deviceId: z.ZodOptional<z.ZodString>;
132
+ };
133
+ export declare function handleGetScreenInfo(args: {
134
+ deviceId?: string;
135
+ }): Promise<{
136
+ content: {
137
+ type: "text";
138
+ text: string;
139
+ }[];
140
+ }>;