@tmhs/mobile-mcp 0.9.0 → 0.11.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,222 @@
1
+ import { z } from "zod";
2
+ import { readFileSync, existsSync, readdirSync, statSync } from "node:fs";
3
+ import { join, extname } 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 to profile (default: expo)."),
15
+ };
16
+ function collectFiles(dir, extensions, maxDepth = 5, depth = 0) {
17
+ if (depth >= maxDepth || !existsSync(dir))
18
+ return [];
19
+ const results = [];
20
+ try {
21
+ for (const entry of readdirSync(dir)) {
22
+ if (entry.startsWith(".") || entry === "node_modules" || entry === "build" || entry === ".dart_tool")
23
+ continue;
24
+ const full = join(dir, entry);
25
+ try {
26
+ const stat = statSync(full);
27
+ if (stat.isDirectory()) {
28
+ results.push(...collectFiles(full, extensions, maxDepth, depth + 1));
29
+ }
30
+ else if (extensions.includes(extname(entry))) {
31
+ results.push(full);
32
+ }
33
+ }
34
+ catch { /* skip inaccessible */ }
35
+ }
36
+ }
37
+ catch { /* skip unreadable dirs */ }
38
+ return results;
39
+ }
40
+ function profileExpo(root) {
41
+ const issues = [];
42
+ const srcDir = existsSync(join(root, "src")) ? join(root, "src") : join(root, "app");
43
+ const files = collectFiles(srcDir, [".tsx", ".ts", ".jsx", ".js"]);
44
+ for (const file of files) {
45
+ let content;
46
+ try {
47
+ content = readFileSync(file, "utf-8");
48
+ }
49
+ catch {
50
+ continue;
51
+ }
52
+ const rel = file.replace(root, "").replace(/\\/g, "/");
53
+ if (content.includes("FlatList") && !content.includes("getItemLayout")) {
54
+ issues.push({
55
+ severity: "medium",
56
+ category: "List Performance",
57
+ message: "FlatList used without getItemLayout. Scroll-to-index and initial render will be slower.",
58
+ fix: "Add getItemLayout prop with fixed item heights for O(1) scroll offset calculation.",
59
+ file: rel,
60
+ });
61
+ }
62
+ if (content.includes("FlatList") && !content.includes("React.memo") && !content.includes("memo(")) {
63
+ issues.push({
64
+ severity: "medium",
65
+ category: "List Performance",
66
+ message: "FlatList renderItem component may not be memoized. Every parent re-render re-creates list items.",
67
+ fix: "Wrap the list item component in React.memo() and extract renderItem to a stable reference.",
68
+ file: rel,
69
+ });
70
+ }
71
+ const inlineStyleRegex = /style=\{\{[^}]+\}\}/g;
72
+ const inlineCount = (content.match(inlineStyleRegex) || []).length;
73
+ if (inlineCount > 5) {
74
+ issues.push({
75
+ severity: "low",
76
+ category: "Style Allocation",
77
+ message: `${inlineCount} inline style objects found. Each creates a new object on every render.`,
78
+ fix: "Move styles to StyleSheet.create() outside the component.",
79
+ file: rel,
80
+ });
81
+ }
82
+ if (/useEffect\(\s*\(\)\s*=>\s*\{[^}]*fetch\(/s.test(content) && !content.includes("useQuery") && !content.includes("useSWR")) {
83
+ issues.push({
84
+ severity: "low",
85
+ category: "Data Fetching",
86
+ message: "Data fetched in useEffect without a caching layer. Refetches on every mount.",
87
+ fix: "Use React Query (useQuery) or SWR for automatic caching, deduplication, and background refresh.",
88
+ file: rel,
89
+ });
90
+ }
91
+ const imageImports = (content.match(/<Image[^>]+source=\{\{[^}]*uri:/g) || []).length;
92
+ if (imageImports > 0 && !content.includes("cachePolicy") && !content.includes("expo-image") && !content.includes("FastImage")) {
93
+ issues.push({
94
+ severity: "medium",
95
+ category: "Image Performance",
96
+ message: "Remote images loaded without a caching library.",
97
+ fix: "Use expo-image (with cachePolicy) or react-native-fast-image for disk caching and progressive loading.",
98
+ file: rel,
99
+ });
100
+ }
101
+ }
102
+ const pkg = existsSync(join(root, "package.json"))
103
+ ? JSON.parse(readFileSync(join(root, "package.json"), "utf-8"))
104
+ : { dependencies: {} };
105
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
106
+ if (!deps["react-native-reanimated"] && files.some((f) => {
107
+ try {
108
+ return readFileSync(f, "utf-8").includes("Animated.");
109
+ }
110
+ catch {
111
+ return false;
112
+ }
113
+ })) {
114
+ issues.push({
115
+ severity: "medium",
116
+ category: "Animation Performance",
117
+ message: "Using the legacy Animated API. Animations run on the JS thread, causing jank.",
118
+ fix: "Migrate to react-native-reanimated for worklet-based animations on the UI thread.",
119
+ });
120
+ }
121
+ if (issues.length === 0) {
122
+ issues.push({
123
+ severity: "low",
124
+ category: "General",
125
+ message: "No common performance anti-patterns detected in source files.",
126
+ fix: "Profile with Flipper or React DevTools Profiler for render-time analysis.",
127
+ });
128
+ }
129
+ return issues;
130
+ }
131
+ function profileFlutter(root) {
132
+ const issues = [];
133
+ const libDir = join(root, "lib");
134
+ const files = collectFiles(libDir, [".dart"]);
135
+ for (const file of files) {
136
+ let content;
137
+ try {
138
+ content = readFileSync(file, "utf-8");
139
+ }
140
+ catch {
141
+ continue;
142
+ }
143
+ const rel = file.replace(root, "").replace(/\\/g, "/");
144
+ const buildMethodRegex = /Widget\s+build\(BuildContext/g;
145
+ const widgetCreations = (content.match(/new\s+\w+Widget\(|(?<!\bconst\s)\b[A-Z]\w+\(/g) || []).length;
146
+ if (buildMethodRegex.test(content) && widgetCreations > 15) {
147
+ issues.push({
148
+ severity: "medium",
149
+ category: "Widget Rebuilds",
150
+ message: "Large build method with many widget instantiations. Likely causes expensive rebuilds.",
151
+ fix: "Extract subtrees into separate widgets and use const constructors where possible.",
152
+ file: rel,
153
+ });
154
+ }
155
+ if (content.includes("setState") && content.includes("ListView")) {
156
+ issues.push({
157
+ severity: "medium",
158
+ category: "List Performance",
159
+ message: "setState used alongside ListView. The entire list may rebuild on every state change.",
160
+ fix: "Use ListView.builder with itemExtent for efficient rendering, or scope state with a focused widget.",
161
+ file: rel,
162
+ });
163
+ }
164
+ if (content.includes("Opacity(") && !content.includes("AnimatedOpacity")) {
165
+ issues.push({
166
+ severity: "low",
167
+ category: "Render Performance",
168
+ message: "Opacity widget causes an offscreen buffer. Expensive for complex subtrees.",
169
+ fix: "Use AnimatedOpacity for transitions, or FadeTransition. For static transparency, set color alpha.",
170
+ file: rel,
171
+ });
172
+ }
173
+ if (content.includes("RepaintBoundary") === false && (content.match(/CustomPaint/g) || []).length > 0) {
174
+ issues.push({
175
+ severity: "medium",
176
+ category: "Paint Performance",
177
+ message: "CustomPaint without RepaintBoundary. The canvas repaints with every ancestor rebuild.",
178
+ fix: "Wrap CustomPaint in a RepaintBoundary to isolate repaints.",
179
+ file: rel,
180
+ });
181
+ }
182
+ }
183
+ if (issues.length === 0) {
184
+ issues.push({
185
+ severity: "low",
186
+ category: "General",
187
+ message: "No common performance anti-patterns detected.",
188
+ fix: "Use Flutter DevTools Timeline to profile frame rendering and identify jank.",
189
+ });
190
+ }
191
+ return issues;
192
+ }
193
+ export function register(server) {
194
+ server.tool("mobile_profilePerformance", "Analyze a mobile project for common performance anti-patterns: slow lists, unnecessary re-renders, inline styles, uncached images, and animation issues.", inputSchema, async (args) => {
195
+ try {
196
+ const root = args.project_path || process.cwd();
197
+ if (!existsSync(root)) {
198
+ return errorResponse(new Error(`Project path does not exist: ${root}`));
199
+ }
200
+ const issues = args.framework === "flutter"
201
+ ? profileFlutter(root)
202
+ : profileExpo(root);
203
+ const highCount = issues.filter((i) => i.severity === "high").length;
204
+ const mediumCount = issues.filter((i) => i.severity === "medium").length;
205
+ return textResponse(JSON.stringify({
206
+ success: true,
207
+ framework: args.framework,
208
+ summary: {
209
+ total_issues: issues.length,
210
+ high: highCount,
211
+ medium: mediumCount,
212
+ low: issues.length - highCount - mediumCount,
213
+ },
214
+ issues,
215
+ }, null, 2));
216
+ }
217
+ catch (err) {
218
+ return errorResponse(err);
219
+ }
220
+ });
221
+ }
222
+ //# sourceMappingURL=profilePerformance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profilePerformance.js","sourceRoot":"","sources":["../../src/tools/profilePerformance.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=securityAudit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"securityAudit.d.ts","sourceRoot":"","sources":["../../src/tools/securityAudit.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA2NzE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyChD"}
@@ -0,0 +1,213 @@
1
+ import { z } from "zod";
2
+ import { readFileSync, 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 to audit (default: expo)."),
15
+ };
16
+ function readJsonSafe(filePath) {
17
+ try {
18
+ if (!existsSync(filePath))
19
+ return null;
20
+ return JSON.parse(readFileSync(filePath, "utf-8"));
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ function readFileSafe(filePath) {
27
+ try {
28
+ if (!existsSync(filePath))
29
+ return null;
30
+ return readFileSync(filePath, "utf-8");
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
36
+ function auditExpoProject(root) {
37
+ const findings = [];
38
+ const pkg = readJsonSafe(join(root, "package.json"));
39
+ if (pkg) {
40
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
41
+ if (!allDeps["react-native-ssl-pinning"] && !allDeps["react-native-cert-pinner"]) {
42
+ findings.push({
43
+ severity: "high",
44
+ category: "SSL Pinning",
45
+ message: "No SSL pinning library detected. API traffic is vulnerable to MITM attacks.",
46
+ fix: "Install react-native-ssl-pinning and configure certificate pins for your API endpoints.",
47
+ });
48
+ }
49
+ if (!allDeps["expo-secure-store"] && !allDeps["react-native-keychain"] && !allDeps["react-native-encrypted-storage"]) {
50
+ findings.push({
51
+ severity: "high",
52
+ category: "Secure Storage",
53
+ message: "No secure storage library found. Tokens stored in AsyncStorage are readable on rooted devices.",
54
+ fix: "Use expo-secure-store or react-native-keychain for auth tokens and secrets.",
55
+ });
56
+ }
57
+ if (!allDeps["jail-monkey"] && !allDeps["react-native-device-info"]) {
58
+ findings.push({
59
+ severity: "medium",
60
+ category: "Root/Jailbreak Detection",
61
+ message: "No jailbreak/root detection library found.",
62
+ fix: "Add jail-monkey to detect compromised devices and warn users or restrict functionality.",
63
+ });
64
+ }
65
+ const heavyDebugDeps = ["reactotron-react-native", "flipper-plugin", "react-native-flipper"];
66
+ for (const dep of heavyDebugDeps) {
67
+ if (pkg.dependencies?.[dep]) {
68
+ findings.push({
69
+ severity: "medium",
70
+ category: "Debug in Production",
71
+ message: `${dep} is in dependencies (not devDependencies). It will ship in production builds.`,
72
+ fix: `Move ${dep} to devDependencies.`,
73
+ });
74
+ }
75
+ }
76
+ }
77
+ const appJson = readJsonSafe(join(root, "app.json"));
78
+ if (appJson?.expo?.android?.usesCleartextTraffic === true) {
79
+ findings.push({
80
+ severity: "high",
81
+ category: "Cleartext Traffic",
82
+ message: "Cleartext (HTTP) traffic is enabled for Android. All network data can be intercepted.",
83
+ fix: "Set android.usesCleartextTraffic to false in app.json and use HTTPS endpoints.",
84
+ });
85
+ }
86
+ const appConfig = readFileSafe(join(root, "app.config.ts")) ?? readFileSafe(join(root, "app.config.js")) ?? "";
87
+ if (appConfig.includes("usesCleartextTraffic: true")) {
88
+ findings.push({
89
+ severity: "high",
90
+ category: "Cleartext Traffic",
91
+ message: "Cleartext traffic enabled in app.config. All HTTP traffic is unencrypted.",
92
+ fix: "Remove usesCleartextTraffic or set it to false.",
93
+ });
94
+ }
95
+ const easJson = readJsonSafe(join(root, "eas.json"));
96
+ if (easJson) {
97
+ const easStr = JSON.stringify(easJson);
98
+ if (easStr.includes("credentialsSource") && easStr.includes('"local"')) {
99
+ const keystoreInRepo = existsSync(join(root, "android", "app", "release.keystore")) ||
100
+ existsSync(join(root, "credentials"));
101
+ if (keystoreInRepo) {
102
+ findings.push({
103
+ severity: "high",
104
+ category: "Signing Credentials",
105
+ message: "Local signing credentials detected in the repository. Keystores should not be committed.",
106
+ fix: "Use EAS managed credentials or store keystores outside the repo and reference via environment variables.",
107
+ });
108
+ }
109
+ }
110
+ }
111
+ if (findings.length === 0) {
112
+ findings.push({
113
+ severity: "low",
114
+ category: "General",
115
+ message: "No obvious security issues detected. Consider a manual review for business logic vulnerabilities.",
116
+ fix: "Review OWASP Mobile Top 10 for comprehensive coverage.",
117
+ });
118
+ }
119
+ return findings;
120
+ }
121
+ function auditFlutterProject(root) {
122
+ const findings = [];
123
+ const pubspec = readFileSafe(join(root, "pubspec.yaml")) ?? "";
124
+ if (!pubspec.includes("flutter_jailbreak_detection") && !pubspec.includes("safe_device")) {
125
+ findings.push({
126
+ severity: "medium",
127
+ category: "Root/Jailbreak Detection",
128
+ message: "No jailbreak/root detection package found in pubspec.yaml.",
129
+ fix: "Add flutter_jailbreak_detection or safe_device to detect compromised devices.",
130
+ });
131
+ }
132
+ if (!pubspec.includes("flutter_secure_storage")) {
133
+ findings.push({
134
+ severity: "high",
135
+ category: "Secure Storage",
136
+ message: "flutter_secure_storage not found. SharedPreferences stores data in plaintext.",
137
+ fix: "Add flutter_secure_storage for auth tokens and sensitive data.",
138
+ });
139
+ }
140
+ if (!pubspec.includes("ssl_pinning_plugin") && !pubspec.includes("dio_http_certificate_pinning")) {
141
+ findings.push({
142
+ severity: "high",
143
+ category: "SSL Pinning",
144
+ message: "No SSL pinning package detected.",
145
+ fix: "Add ssl_pinning_plugin or configure certificate pinning in your HTTP client.",
146
+ });
147
+ }
148
+ const androidManifest = readFileSafe(join(root, "android", "app", "src", "main", "AndroidManifest.xml")) ?? "";
149
+ if (androidManifest.includes('android:usesCleartextTraffic="true"')) {
150
+ findings.push({
151
+ severity: "high",
152
+ category: "Cleartext Traffic",
153
+ message: "Cleartext traffic is allowed in AndroidManifest.xml.",
154
+ fix: 'Set android:usesCleartextTraffic="false" or remove the attribute.',
155
+ });
156
+ }
157
+ if (androidManifest.includes("android:debuggable")) {
158
+ findings.push({
159
+ severity: "high",
160
+ category: "Debug Flag",
161
+ message: "android:debuggable is set in AndroidManifest.xml. Ensure it is false for release builds.",
162
+ fix: "Remove android:debuggable from AndroidManifest.xml; Gradle sets it automatically per build type.",
163
+ });
164
+ }
165
+ const buildGradle = readFileSafe(join(root, "android", "app", "build.gradle")) ?? "";
166
+ if (buildGradle.includes("minifyEnabled false") || !buildGradle.includes("minifyEnabled")) {
167
+ findings.push({
168
+ severity: "medium",
169
+ category: "Code Obfuscation",
170
+ message: "ProGuard/R8 code shrinking may be disabled for release builds.",
171
+ fix: "Set minifyEnabled true and shrinkResources true in the release buildType.",
172
+ });
173
+ }
174
+ if (findings.length === 0) {
175
+ findings.push({
176
+ severity: "low",
177
+ category: "General",
178
+ message: "No obvious security issues detected. Review OWASP Mobile Top 10 for additional coverage.",
179
+ fix: "Consider manual penetration testing for business logic vulnerabilities.",
180
+ });
181
+ }
182
+ return findings;
183
+ }
184
+ export function register(server) {
185
+ server.tool("mobile_securityAudit", "Scan a mobile project for common security anti-patterns: insecure storage, missing SSL pinning, debug flags in release, cleartext traffic, exposed credentials.", inputSchema, async (args) => {
186
+ try {
187
+ const root = args.project_path || process.cwd();
188
+ if (!existsSync(root)) {
189
+ return errorResponse(new Error(`Project path does not exist: ${root}`));
190
+ }
191
+ const findings = args.framework === "flutter"
192
+ ? auditFlutterProject(root)
193
+ : auditExpoProject(root);
194
+ const highCount = findings.filter((f) => f.severity === "high").length;
195
+ const mediumCount = findings.filter((f) => f.severity === "medium").length;
196
+ return textResponse(JSON.stringify({
197
+ success: true,
198
+ framework: args.framework,
199
+ summary: {
200
+ total_findings: findings.length,
201
+ high: highCount,
202
+ medium: mediumCount,
203
+ low: findings.length - highCount - mediumCount,
204
+ },
205
+ findings,
206
+ }, null, 2));
207
+ }
208
+ catch (err) {
209
+ return errorResponse(err);
210
+ }
211
+ });
212
+ }
213
+ //# sourceMappingURL=securityAudit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"securityAudit.js","sourceRoot":"","sources":["../../src/tools/securityAudit.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=setupFeatureFlags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setupFeatureFlags.d.ts","sourceRoot":"","sources":["../../src/tools/setupFeatureFlags.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAqNzE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAwFhD"}