@tmhs/mobile-mcp 0.10.0 → 0.12.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,303 @@
1
+ import { z } from "zod";
2
+ import { writeFileSync, mkdirSync, existsSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { textResponse, errorResponse } from "../types.js";
5
+ const inputSchema = {
6
+ project_path: z
7
+ .string()
8
+ .optional()
9
+ .describe("Absolute path to the project root. Defaults to cwd."),
10
+ framework: z
11
+ .enum(["expo", "flutter"])
12
+ .optional()
13
+ .default("expo")
14
+ .describe("Framework (default: expo)."),
15
+ output_directory: z
16
+ .string()
17
+ .optional()
18
+ .default("lib")
19
+ .describe("Output directory relative to project root (default: lib)."),
20
+ };
21
+ function generateExpoTokens() {
22
+ return `export const colors = {
23
+ light: {
24
+ primary: "#0A84FF",
25
+ primaryContainer: "#D6E4FF",
26
+ background: "#FFFFFF",
27
+ surface: "#F2F2F7",
28
+ surfaceVariant: "#E5E5EA",
29
+ text: "#000000",
30
+ textSecondary: "#3C3C43",
31
+ textTertiary: "#8E8E93",
32
+ border: "#C6C6C8",
33
+ error: "#FF3B30",
34
+ success: "#34C759",
35
+ warning: "#FF9500",
36
+ },
37
+ dark: {
38
+ primary: "#0A84FF",
39
+ primaryContainer: "#003A70",
40
+ background: "#000000",
41
+ surface: "#1C1C1E",
42
+ surfaceVariant: "#2C2C2E",
43
+ text: "#FFFFFF",
44
+ textSecondary: "#EBEBF5",
45
+ textTertiary: "#8E8E93",
46
+ border: "#38383A",
47
+ error: "#FF453A",
48
+ success: "#30D158",
49
+ warning: "#FF9F0A",
50
+ },
51
+ } as const;
52
+
53
+ export const spacing = {
54
+ xs: 4,
55
+ sm: 8,
56
+ md: 16,
57
+ lg: 24,
58
+ xl: 32,
59
+ xxl: 48,
60
+ } as const;
61
+
62
+ export const typography = {
63
+ largeTitle: { fontSize: 34, lineHeight: 41, fontWeight: "700" as const },
64
+ title1: { fontSize: 28, lineHeight: 34, fontWeight: "700" as const },
65
+ title2: { fontSize: 22, lineHeight: 28, fontWeight: "700" as const },
66
+ title3: { fontSize: 20, lineHeight: 25, fontWeight: "600" as const },
67
+ headline: { fontSize: 17, lineHeight: 22, fontWeight: "600" as const },
68
+ body: { fontSize: 17, lineHeight: 22, fontWeight: "400" as const },
69
+ callout: { fontSize: 16, lineHeight: 21, fontWeight: "400" as const },
70
+ subheadline: { fontSize: 15, lineHeight: 20, fontWeight: "400" as const },
71
+ footnote: { fontSize: 13, lineHeight: 18, fontWeight: "400" as const },
72
+ caption1: { fontSize: 12, lineHeight: 16, fontWeight: "400" as const },
73
+ caption2: { fontSize: 11, lineHeight: 13, fontWeight: "400" as const },
74
+ } as const;
75
+
76
+ export const radii = {
77
+ sm: 4,
78
+ md: 8,
79
+ lg: 12,
80
+ xl: 16,
81
+ full: 9999,
82
+ } as const;
83
+
84
+ export type ColorScheme = "light" | "dark";
85
+ export type Colors = typeof colors.light;
86
+ `;
87
+ }
88
+ function generateExpoThemeProvider() {
89
+ return `import React, { createContext, useContext, useEffect, useState } from "react";
90
+ import { useColorScheme as useSystemColorScheme } from "react-native";
91
+ import AsyncStorage from "@react-native-async-storage/async-storage";
92
+ import { colors, spacing, typography, radii, type ColorScheme, type Colors } from "./tokens";
93
+
94
+ const THEME_STORAGE_KEY = "@app_theme_preference";
95
+
96
+ interface ThemeContextValue {
97
+ colorScheme: ColorScheme;
98
+ colors: Colors;
99
+ spacing: typeof spacing;
100
+ typography: typeof typography;
101
+ radii: typeof radii;
102
+ setColorScheme: (scheme: ColorScheme | "system") => void;
103
+ isSystem: boolean;
104
+ }
105
+
106
+ const ThemeContext = createContext<ThemeContextValue | null>(null);
107
+
108
+ export function ThemeProvider({ children }: { children: React.ReactNode }) {
109
+ const systemScheme = useSystemColorScheme() ?? "light";
110
+ const [preference, setPreference] = useState<ColorScheme | "system">("system");
111
+ const [loaded, setLoaded] = useState(false);
112
+
113
+ useEffect(() => {
114
+ AsyncStorage.getItem(THEME_STORAGE_KEY).then((stored) => {
115
+ if (stored === "light" || stored === "dark" || stored === "system") {
116
+ setPreference(stored);
117
+ }
118
+ setLoaded(true);
119
+ });
120
+ }, []);
121
+
122
+ const colorScheme: ColorScheme = preference === "system" ? systemScheme : preference;
123
+
124
+ const setColorScheme = (scheme: ColorScheme | "system") => {
125
+ setPreference(scheme);
126
+ AsyncStorage.setItem(THEME_STORAGE_KEY, scheme);
127
+ };
128
+
129
+ if (!loaded) return null;
130
+
131
+ return (
132
+ <ThemeContext.Provider
133
+ value={{
134
+ colorScheme,
135
+ colors: colors[colorScheme],
136
+ spacing,
137
+ typography,
138
+ radii,
139
+ setColorScheme,
140
+ isSystem: preference === "system",
141
+ }}
142
+ >
143
+ {children}
144
+ </ThemeContext.Provider>
145
+ );
146
+ }
147
+
148
+ export function useTheme(): ThemeContextValue {
149
+ const ctx = useContext(ThemeContext);
150
+ if (!ctx) throw new Error("useTheme must be used within a ThemeProvider");
151
+ return ctx;
152
+ }
153
+ `;
154
+ }
155
+ function generateFlutterTokens() {
156
+ return `import 'package:flutter/material.dart';
157
+
158
+ abstract class AppColors {
159
+ static const light = _LightColors();
160
+ static const dark = _DarkColors();
161
+ }
162
+
163
+ class _LightColors {
164
+ const _LightColors();
165
+ Color get primary => const Color(0xFF0A84FF);
166
+ Color get primaryContainer => const Color(0xFFD6E4FF);
167
+ Color get background => const Color(0xFFFFFFFF);
168
+ Color get surface => const Color(0xFFF2F2F7);
169
+ Color get surfaceVariant => const Color(0xFFE5E5EA);
170
+ Color get onSurface => const Color(0xFF000000);
171
+ Color get onSurfaceVariant => const Color(0xFF3C3C43);
172
+ Color get outline => const Color(0xFFC6C6C8);
173
+ Color get error => const Color(0xFFFF3B30);
174
+ Color get success => const Color(0xFF34C759);
175
+ Color get warning => const Color(0xFFFF9500);
176
+ }
177
+
178
+ class _DarkColors {
179
+ const _DarkColors();
180
+ Color get primary => const Color(0xFF0A84FF);
181
+ Color get primaryContainer => const Color(0xFF003A70);
182
+ Color get background => const Color(0xFF000000);
183
+ Color get surface => const Color(0xFF1C1C1E);
184
+ Color get surfaceVariant => const Color(0xFF2C2C2E);
185
+ Color get onSurface => const Color(0xFFFFFFFF);
186
+ Color get onSurfaceVariant => const Color(0xFFEBEBF5);
187
+ Color get outline => const Color(0xFF38383A);
188
+ Color get error => const Color(0xFFFF453A);
189
+ Color get success => const Color(0xFF30D158);
190
+ Color get warning => const Color(0xFFFF9F0A);
191
+ }
192
+
193
+ abstract class AppSpacing {
194
+ static const double xs = 4;
195
+ static const double sm = 8;
196
+ static const double md = 16;
197
+ static const double lg = 24;
198
+ static const double xl = 32;
199
+ static const double xxl = 48;
200
+ }
201
+
202
+ abstract class AppRadii {
203
+ static const double sm = 4;
204
+ static const double md = 8;
205
+ static const double lg = 12;
206
+ static const double xl = 16;
207
+ static const double full = 9999;
208
+ }
209
+ `;
210
+ }
211
+ function generateFlutterTheme() {
212
+ return `import 'package:flutter/material.dart';
213
+ import 'tokens.dart';
214
+
215
+ class AppTheme {
216
+ static ThemeData light() {
217
+ final colors = AppColors.light;
218
+ return ThemeData(
219
+ useMaterial3: true,
220
+ brightness: Brightness.light,
221
+ colorScheme: ColorScheme.light(
222
+ primary: colors.primary,
223
+ primaryContainer: colors.primaryContainer,
224
+ surface: colors.surface,
225
+ surfaceContainerHighest: colors.surfaceVariant,
226
+ onSurface: colors.onSurface,
227
+ onSurfaceVariant: colors.onSurfaceVariant,
228
+ outline: colors.outline,
229
+ error: colors.error,
230
+ ),
231
+ scaffoldBackgroundColor: colors.background,
232
+ );
233
+ }
234
+
235
+ static ThemeData dark() {
236
+ final colors = AppColors.dark;
237
+ return ThemeData(
238
+ useMaterial3: true,
239
+ brightness: Brightness.dark,
240
+ colorScheme: ColorScheme.dark(
241
+ primary: colors.primary,
242
+ primaryContainer: colors.primaryContainer,
243
+ surface: colors.surface,
244
+ surfaceContainerHighest: colors.surfaceVariant,
245
+ onSurface: colors.onSurface,
246
+ onSurfaceVariant: colors.onSurfaceVariant,
247
+ outline: colors.outline,
248
+ error: colors.error,
249
+ ),
250
+ scaffoldBackgroundColor: colors.background,
251
+ );
252
+ }
253
+ }
254
+ `;
255
+ }
256
+ export function register(server) {
257
+ server.tool("mobile_setupTheming", "Initialize a design token system with light/dark themes, semantic colors, spacing, typography, and persistent theme preference.", inputSchema, async (args) => {
258
+ try {
259
+ const root = args.project_path || process.cwd();
260
+ const outDir = join(root, args.output_directory, "theme");
261
+ mkdirSync(outDir, { recursive: true });
262
+ const isFlutter = args.framework === "flutter";
263
+ const ext = isFlutter ? "dart" : "ts";
264
+ const files = [];
265
+ if (isFlutter) {
266
+ files.push({ name: `tokens.${ext}`, content: generateFlutterTokens() }, { name: `theme.${ext}`, content: generateFlutterTheme() });
267
+ }
268
+ else {
269
+ files.push({ name: `tokens.${ext}`, content: generateExpoTokens() }, { name: `theme-provider.${ext}x`, content: generateExpoThemeProvider() });
270
+ }
271
+ const created = [];
272
+ const skipped = [];
273
+ for (const file of files) {
274
+ const filePath = join(outDir, file.name);
275
+ if (existsSync(filePath)) {
276
+ skipped.push(filePath);
277
+ }
278
+ else {
279
+ writeFileSync(filePath, file.content, "utf-8");
280
+ created.push(filePath);
281
+ }
282
+ }
283
+ const nextSteps = [];
284
+ if (isFlutter) {
285
+ nextSteps.push("Use AppTheme.light() and AppTheme.dark() in MaterialApp's theme and darkTheme", "Access colors via Theme.of(context).colorScheme", "Use AppSpacing and AppRadii constants for consistent layout", "Add shared_preferences for persistent theme preference");
286
+ }
287
+ else {
288
+ nextSteps.push("Install @react-native-async-storage/async-storage for theme persistence", "Wrap your root layout with <ThemeProvider>", "Use const { colors, spacing } = useTheme() in components", "Use colorScheme for StatusBar and NavigationBar styling");
289
+ }
290
+ return textResponse(JSON.stringify({
291
+ success: true,
292
+ framework: args.framework,
293
+ files_created: created,
294
+ files_skipped: skipped,
295
+ next_steps: nextSteps,
296
+ }, null, 2));
297
+ }
298
+ catch (err) {
299
+ return errorResponse(err);
300
+ }
301
+ });
302
+ }
303
+ //# sourceMappingURL=setupTheming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setupTheming.js","sourceRoot":"","sources":["../../src/tools/setupTheming.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function register(server: McpServer): void;
3
+ //# sourceMappingURL=upgradeSDK.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgradeSDK.d.ts","sourceRoot":"","sources":["../../src/tools/upgradeSDK.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4JzE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2BhD"}
@@ -0,0 +1,170 @@
1
+ import { z } from "zod";
2
+ import { readFileSync, existsSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { execSync } from "node:child_process";
5
+ import { textResponse, errorResponse } from "../types.js";
6
+ const inputSchema = {
7
+ project_path: z
8
+ .string()
9
+ .optional()
10
+ .describe("Absolute path to the project root. Defaults to cwd."),
11
+ framework: z
12
+ .enum(["expo", "flutter"])
13
+ .optional()
14
+ .default("expo")
15
+ .describe("Framework (default: expo)."),
16
+ target_version: z
17
+ .string()
18
+ .optional()
19
+ .describe("Target SDK version to upgrade to. If omitted, detects latest."),
20
+ };
21
+ function detectExpoVersion(root) {
22
+ const pkgPath = join(root, "package.json");
23
+ if (!existsSync(pkgPath))
24
+ return null;
25
+ try {
26
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
27
+ const expoVersion = pkg.dependencies?.expo || pkg.devDependencies?.expo;
28
+ if (!expoVersion)
29
+ return null;
30
+ return expoVersion.replace(/[\^~>=<]/g, "").trim();
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
36
+ function detectFlutterVersion(root) {
37
+ try {
38
+ const output = execSync("flutter --version --machine", {
39
+ cwd: root,
40
+ timeout: 15000,
41
+ encoding: "utf-8",
42
+ stdio: ["pipe", "pipe", "pipe"],
43
+ });
44
+ const parsed = JSON.parse(output);
45
+ return parsed.frameworkVersion || null;
46
+ }
47
+ catch {
48
+ const pubspecPath = join(root, "pubspec.yaml");
49
+ if (!existsSync(pubspecPath))
50
+ return null;
51
+ try {
52
+ const content = readFileSync(pubspecPath, "utf-8");
53
+ const match = content.match(/sdk:\s*['"]?>=?\s*([\d.]+)/);
54
+ return match ? match[1] : null;
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ }
60
+ }
61
+ function getExpoUpgradeSteps(current, target) {
62
+ return {
63
+ framework: "expo",
64
+ current_version: current,
65
+ target_version: target || "latest",
66
+ pre_upgrade_checklist: [
67
+ "Commit all current changes to git (create a clean restore point)",
68
+ "Run existing tests and confirm they pass",
69
+ "Review CHANGELOG for target SDK version at expo.dev/changelog",
70
+ "Run npx expo-doctor to check current project health",
71
+ "Back up app.json / app.config.js",
72
+ ],
73
+ upgrade_steps: [
74
+ `Run: npx expo install expo@${target || "latest"} --fix`,
75
+ "Run: npx expo install --fix (updates all Expo packages to compatible versions)",
76
+ "Run: npx expo-doctor (check for remaining compatibility issues)",
77
+ "Update app.json sdkVersion if present",
78
+ "Run: npx expo prebuild --clean (regenerate native projects)",
79
+ "Run: npx expo start --clear (clear Metro cache)",
80
+ "Test on both iOS and Android simulators/devices",
81
+ ],
82
+ breaking_changes: [
83
+ "Check for deprecated APIs removed in the new SDK version",
84
+ "Review Expo Router version compatibility if using file-based routing",
85
+ "Check if any config plugins need updates for the new SDK",
86
+ "Verify native module compatibility with expo-doctor",
87
+ "Check React Native version bump (Expo SDK pins a specific RN version)",
88
+ ],
89
+ dependency_actions: [
90
+ "Run: npx expo install --check (list packages needing updates)",
91
+ "Update @react-navigation/* packages if using React Navigation directly",
92
+ "Update react-native-reanimated, react-native-gesture-handler to compatible versions",
93
+ "Check third-party native modules for SDK compatibility",
94
+ "Run: npm outdated (check for other stale dependencies)",
95
+ ],
96
+ rollback_strategy: [
97
+ "git stash or git checkout to restore pre-upgrade state",
98
+ "Restore package.json and package-lock.json from git",
99
+ "Run npm install to restore node_modules",
100
+ "Run npx expo prebuild --clean to regenerate native projects",
101
+ "If using EAS, the previous build is still available for download",
102
+ ],
103
+ };
104
+ }
105
+ function getFlutterUpgradeSteps(current, target) {
106
+ return {
107
+ framework: "flutter",
108
+ current_version: current,
109
+ target_version: target || "latest stable",
110
+ pre_upgrade_checklist: [
111
+ "Commit all current changes to git",
112
+ "Run flutter test and confirm tests pass",
113
+ "Run flutter analyze to check for existing issues",
114
+ "Review Flutter release notes at docs.flutter.dev/release/release-notes",
115
+ "Back up pubspec.yaml and pubspec.lock",
116
+ ],
117
+ upgrade_steps: [
118
+ `Run: flutter upgrade${target ? ` ${target}` : ""}`,
119
+ "Run: flutter pub upgrade --major-versions (update dependencies)",
120
+ "Run: flutter pub get",
121
+ "Run: flutter analyze (check for new lint warnings)",
122
+ "Run: dart fix --apply (auto-fix deprecations)",
123
+ "Run: flutter clean && flutter pub get",
124
+ "Test on both iOS and Android",
125
+ ],
126
+ breaking_changes: [
127
+ "Check for deprecated Widget APIs removed in the new version",
128
+ "Review Material 3 migration status if upgrading across major versions",
129
+ "Check Gradle and AGP version requirements for Android",
130
+ "Verify CocoaPods and Xcode version compatibility for iOS",
131
+ "Check for Dart language version changes affecting your code",
132
+ ],
133
+ dependency_actions: [
134
+ "Run: flutter pub outdated (list packages needing updates)",
135
+ "Update go_router, riverpod, bloc if using those packages",
136
+ "Check native plugin compatibility (firebase, maps, camera)",
137
+ "Update build.gradle minSdkVersion if required by new Flutter",
138
+ "Update Podfile deployment target if required",
139
+ ],
140
+ rollback_strategy: [
141
+ "git checkout to restore pre-upgrade state",
142
+ "Restore pubspec.yaml and pubspec.lock from git",
143
+ "Run flutter pub get to restore packages",
144
+ "Run flutter clean to clear build artifacts",
145
+ "Use flutter downgrade if needed (only works for latest->previous)",
146
+ ],
147
+ };
148
+ }
149
+ export function register(server) {
150
+ server.tool("mobile_upgradeSDK", "Detect current SDK version, compare to target, and generate a step-by-step upgrade plan with dependency fixes, breaking change warnings, and rollback strategy.", inputSchema, async (args) => {
151
+ try {
152
+ const root = args.project_path || process.cwd();
153
+ if (!existsSync(root)) {
154
+ return errorResponse(new Error(`Project path does not exist: ${root}`));
155
+ }
156
+ const isFlutter = args.framework === "flutter";
157
+ const currentVersion = isFlutter
158
+ ? detectFlutterVersion(root)
159
+ : detectExpoVersion(root);
160
+ const report = isFlutter
161
+ ? getFlutterUpgradeSteps(currentVersion, args.target_version ?? null)
162
+ : getExpoUpgradeSteps(currentVersion, args.target_version ?? null);
163
+ return textResponse(JSON.stringify(report, null, 2));
164
+ }
165
+ catch (err) {
166
+ return errorResponse(err);
167
+ }
168
+ });
169
+ }
170
+ //# sourceMappingURL=upgradeSDK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgradeSDK.js","sourceRoot":"","sources":["../../src/tools/upgradeSDK.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,WAAW,GAAG;IAClB,YAAY,EAAE,CAAC;SACZ,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,qDAAqD,CAAC;IAClE,SAAS,EAAE,CAAC;SACT,IAAI,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;SACzB,QAAQ,EAAE;SACV,OAAO,CAAC,MAAM,CAAC;SACf,QAAQ,CAAC,4BAA4B,CAAC;IACzC,cAAc,EAAE,CAAC;SACd,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,+DAA+D,CAAC;CAC7E,CAAC;AAaF,SAAS,iBAAiB,CAAC,IAAY;IACrC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAC3C,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACvD,MAAM,WAAW,GAAG,GAAG,CAAC,YAAY,EAAE,IAAI,IAAI,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC;QACxE,IAAI,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC;QAC9B,OAAO,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAY;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,6BAA6B,EAAE;YACrD,GAAG,EAAE,IAAI;YACT,OAAO,EAAE,KAAK;YACd,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAClC,OAAO,MAAM,CAAC,gBAAgB,IAAI,IAAI,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QAC/C,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1C,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YACnD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAC1D,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAsB,EAAE,MAAqB;IACxE,OAAO;QACL,SAAS,EAAE,MAAM;QACjB,eAAe,EAAE,OAAO;QACxB,cAAc,EAAE,MAAM,IAAI,QAAQ;QAClC,qBAAqB,EAAE;YACrB,kEAAkE;YAClE,0CAA0C;YAC1C,+DAA+D;YAC/D,qDAAqD;YACrD,kCAAkC;SACnC;QACD,aAAa,EAAE;YACb,8BAA8B,MAAM,IAAI,QAAQ,QAAQ;YACxD,gFAAgF;YAChF,iEAAiE;YACjE,uCAAuC;YACvC,6DAA6D;YAC7D,iDAAiD;YACjD,iDAAiD;SAClD;QACD,gBAAgB,EAAE;YAChB,0DAA0D;YAC1D,sEAAsE;YACtE,0DAA0D;YAC1D,qDAAqD;YACrD,uEAAuE;SACxE;QACD,kBAAkB,EAAE;YAClB,+DAA+D;YAC/D,wEAAwE;YACxE,qFAAqF;YACrF,wDAAwD;YACxD,wDAAwD;SACzD;QACD,iBAAiB,EAAE;YACjB,wDAAwD;YACxD,qDAAqD;YACrD,yCAAyC;YACzC,6DAA6D;YAC7D,kEAAkE;SACnE;KACF,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,OAAsB,EAAE,MAAqB;IAC3E,OAAO;QACL,SAAS,EAAE,SAAS;QACpB,eAAe,EAAE,OAAO;QACxB,cAAc,EAAE,MAAM,IAAI,eAAe;QACzC,qBAAqB,EAAE;YACrB,mCAAmC;YACnC,yCAAyC;YACzC,kDAAkD;YAClD,wEAAwE;YACxE,uCAAuC;SACxC;QACD,aAAa,EAAE;YACb,uBAAuB,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;YACnD,iEAAiE;YACjE,sBAAsB;YACtB,oDAAoD;YACpD,+CAA+C;YAC/C,uCAAuC;YACvC,8BAA8B;SAC/B;QACD,gBAAgB,EAAE;YAChB,6DAA6D;YAC7D,uEAAuE;YACvE,uDAAuD;YACvD,0DAA0D;YAC1D,6DAA6D;SAC9D;QACD,kBAAkB,EAAE;YAClB,2DAA2D;YAC3D,0DAA0D;YAC1D,4DAA4D;YAC5D,8DAA8D;YAC9D,8CAA8C;SAC/C;QACD,iBAAiB,EAAE;YACjB,2CAA2C;YAC3C,gDAAgD;YAChD,yCAAyC;YACzC,4CAA4C;YAC5C,mEAAmE;SACpE;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,MAAiB;IACxC,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,iKAAiK,EACjK,WAAW,EACX,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;YAChD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtB,OAAO,aAAa,CAAC,IAAI,KAAK,CAAC,gCAAgC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC1E,CAAC;YAED,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC;YAC/C,MAAM,cAAc,GAAG,SAAS;gBAC9B,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC;gBAC5B,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAE5B,MAAM,MAAM,GAAG,SAAS;gBACtB,CAAC,CAAC,sBAAsB,CAAC,cAAc,EAAE,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC;gBACrE,CAAC,CAAC,mBAAmB,CAAC,cAAc,EAAE,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,CAAC;YAErE,OAAO,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tmhs/mobile-mcp",
3
- "version": "0.10.0",
4
- "description": "MCP server for mobile app development - 30 tools for environment checks, project scaffolding, device deployment, screen/component generation, dependency installation, permissions, AI integration, build health, push notifications, deep links, dev environment reset, store builds, metadata validation, App Store submission, Play Store submission, screenshot capture, bundle analysis, OTA update configuration, test execution, CI/CD setup, test file generation, i18n setup, map integration, form generation, real-time client setup, security auditing, performance profiling, offline readiness checks, and APM monitoring setup.",
3
+ "version": "0.12.0",
4
+ "description": "MCP server for mobile app development - 36 tools for environment checks, project scaffolding, device deployment, screen/component generation, dependency installation, permissions, AI integration, build health, push notifications, deep links, dev environment reset, store builds, metadata validation, App Store submission, Play Store submission, screenshot capture, bundle analysis, OTA update configuration, test execution, CI/CD setup, test file generation, i18n setup, map integration, form generation, real-time client setup, security auditing, performance profiling, offline readiness checks, APM monitoring setup, theming setup, accessibility auditing, feature flag configuration, native module scaffolding, SDK upgrade planning, and native compatibility auditing.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "bin": {