@tmhs/mobile-mcp 0.1.0 → 0.3.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.
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/tools/addPermission.d.ts +3 -0
- package/dist/tools/addPermission.d.ts.map +1 -0
- package/dist/tools/addPermission.js +124 -0
- package/dist/tools/addPermission.js.map +1 -0
- package/dist/tools/checkBuildHealth.d.ts +3 -0
- package/dist/tools/checkBuildHealth.d.ts.map +1 -0
- package/dist/tools/checkBuildHealth.js +215 -0
- package/dist/tools/checkBuildHealth.js.map +1 -0
- package/dist/tools/generateComponent.d.ts +3 -0
- package/dist/tools/generateComponent.d.ts.map +1 -0
- package/dist/tools/generateComponent.js +98 -0
- package/dist/tools/generateComponent.js.map +1 -0
- package/dist/tools/generateScreen.d.ts +3 -0
- package/dist/tools/generateScreen.d.ts.map +1 -0
- package/dist/tools/generateScreen.js +120 -0
- package/dist/tools/generateScreen.js.map +1 -0
- package/dist/tools/installDependency.d.ts +3 -0
- package/dist/tools/installDependency.d.ts.map +1 -0
- package/dist/tools/installDependency.js +79 -0
- package/dist/tools/installDependency.js.map +1 -0
- package/dist/tools/integrateAI.d.ts +3 -0
- package/dist/tools/integrateAI.d.ts.map +1 -0
- package/dist/tools/integrateAI.js +156 -0
- package/dist/tools/integrateAI.js.map +1 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -4,13 +4,25 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
4
4
|
import { register as registerCheckDevEnvironment } from "./tools/checkDevEnvironment.js";
|
|
5
5
|
import { register as registerScaffoldProject } from "./tools/scaffoldProject.js";
|
|
6
6
|
import { register as registerRunOnDevice } from "./tools/runOnDevice.js";
|
|
7
|
+
import { register as registerGenerateScreen } from "./tools/generateScreen.js";
|
|
8
|
+
import { register as registerGenerateComponent } from "./tools/generateComponent.js";
|
|
9
|
+
import { register as registerInstallDependency } from "./tools/installDependency.js";
|
|
10
|
+
import { register as registerAddPermission } from "./tools/addPermission.js";
|
|
11
|
+
import { register as registerIntegrateAI } from "./tools/integrateAI.js";
|
|
12
|
+
import { register as registerCheckBuildHealth } from "./tools/checkBuildHealth.js";
|
|
7
13
|
const server = new McpServer({
|
|
8
14
|
name: "mobile-mcp",
|
|
9
|
-
version: "0.
|
|
15
|
+
version: "0.3.0",
|
|
10
16
|
});
|
|
11
17
|
registerCheckDevEnvironment(server);
|
|
12
18
|
registerScaffoldProject(server);
|
|
13
19
|
registerRunOnDevice(server);
|
|
20
|
+
registerGenerateScreen(server);
|
|
21
|
+
registerGenerateComponent(server);
|
|
22
|
+
registerInstallDependency(server);
|
|
23
|
+
registerAddPermission(server);
|
|
24
|
+
registerIntegrateAI(server);
|
|
25
|
+
registerCheckBuildHealth(server);
|
|
14
26
|
async function main() {
|
|
15
27
|
const transport = new StdioServerTransport();
|
|
16
28
|
await server.connect(transport);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,QAAQ,IAAI,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,QAAQ,IAAI,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,QAAQ,IAAI,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,QAAQ,IAAI,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,QAAQ,IAAI,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,QAAQ,IAAI,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,QAAQ,IAAI,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,QAAQ,IAAI,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACrF,OAAO,EAAE,QAAQ,IAAI,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACrF,OAAO,EAAE,QAAQ,IAAI,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,QAAQ,IAAI,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,QAAQ,IAAI,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAEnF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,YAAY;IAClB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,2BAA2B,CAAC,MAAM,CAAC,CAAC;AACpC,uBAAuB,CAAC,MAAM,CAAC,CAAC;AAChC,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAC5B,sBAAsB,CAAC,MAAM,CAAC,CAAC;AAC/B,yBAAyB,CAAC,MAAM,CAAC,CAAC;AAClC,yBAAyB,CAAC,MAAM,CAAC,CAAC;AAClC,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAC9B,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAC5B,wBAAwB,CAAC,MAAM,CAAC,CAAC;AAEjC,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addPermission.d.ts","sourceRoot":"","sources":["../../src/tools/addPermission.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4EzE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8EhD"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { textResponse, errorResponse } from "../types.js";
|
|
5
|
+
const PERMISSION_CONFIGS = {
|
|
6
|
+
camera: {
|
|
7
|
+
package: "expo-camera",
|
|
8
|
+
plugin: "expo-camera",
|
|
9
|
+
keys: {
|
|
10
|
+
cameraPermission: "This app uses the camera to take photos and videos.",
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
location: {
|
|
14
|
+
package: "expo-location",
|
|
15
|
+
plugin: "expo-location",
|
|
16
|
+
keys: {
|
|
17
|
+
locationWhenInUsePermission: "This app uses your location to provide location-based features.",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
contacts: {
|
|
21
|
+
package: "expo-contacts",
|
|
22
|
+
plugin: "expo-contacts",
|
|
23
|
+
keys: {
|
|
24
|
+
contactsPermission: "This app accesses your contacts to help you connect with friends.",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
"media-library": {
|
|
28
|
+
package: "expo-media-library",
|
|
29
|
+
plugin: "expo-media-library",
|
|
30
|
+
keys: {
|
|
31
|
+
photosPermission: "This app accesses your photo library to select photos.",
|
|
32
|
+
savePhotosPermission: "This app saves photos to your library.",
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
notifications: {
|
|
36
|
+
package: "expo-notifications",
|
|
37
|
+
plugin: "expo-notifications",
|
|
38
|
+
keys: {},
|
|
39
|
+
},
|
|
40
|
+
microphone: {
|
|
41
|
+
package: "expo-av",
|
|
42
|
+
plugin: "expo-av",
|
|
43
|
+
keys: {
|
|
44
|
+
microphonePermission: "This app uses the microphone for audio recording.",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
const inputSchema = {
|
|
49
|
+
permission_type: z
|
|
50
|
+
.enum([
|
|
51
|
+
"camera",
|
|
52
|
+
"location",
|
|
53
|
+
"contacts",
|
|
54
|
+
"media-library",
|
|
55
|
+
"notifications",
|
|
56
|
+
"microphone",
|
|
57
|
+
])
|
|
58
|
+
.describe("Type of permission to add"),
|
|
59
|
+
rationale: z
|
|
60
|
+
.string()
|
|
61
|
+
.optional()
|
|
62
|
+
.describe("Custom iOS usage description string. If not provided, a sensible default is used."),
|
|
63
|
+
project_path: z
|
|
64
|
+
.string()
|
|
65
|
+
.optional()
|
|
66
|
+
.describe("Absolute path to the Expo project root. Defaults to cwd."),
|
|
67
|
+
};
|
|
68
|
+
export function register(server) {
|
|
69
|
+
server.tool("mobile_addPermission", "Add a platform permission to an Expo project with iOS rationale string in app.json.", inputSchema, async (args) => {
|
|
70
|
+
try {
|
|
71
|
+
const root = args.project_path || process.cwd();
|
|
72
|
+
const appJsonPath = join(root, "app.json");
|
|
73
|
+
if (!existsSync(appJsonPath)) {
|
|
74
|
+
return errorResponse(new Error(`No app.json found at ${root}. Is this an Expo project root?`));
|
|
75
|
+
}
|
|
76
|
+
const config = PERMISSION_CONFIGS[args.permission_type];
|
|
77
|
+
if (!config) {
|
|
78
|
+
return errorResponse(new Error(`Unknown permission type: ${args.permission_type}`));
|
|
79
|
+
}
|
|
80
|
+
const appJson = JSON.parse(readFileSync(appJsonPath, "utf-8"));
|
|
81
|
+
if (!appJson.expo) {
|
|
82
|
+
appJson.expo = {};
|
|
83
|
+
}
|
|
84
|
+
if (!appJson.expo.plugins) {
|
|
85
|
+
appJson.expo.plugins = [];
|
|
86
|
+
}
|
|
87
|
+
const existingIndex = appJson.expo.plugins.findIndex((p) => (Array.isArray(p) && p[0] === config.plugin) || p === config.plugin);
|
|
88
|
+
const pluginKeys = { ...config.keys };
|
|
89
|
+
if (args.rationale) {
|
|
90
|
+
const firstKey = Object.keys(pluginKeys)[0];
|
|
91
|
+
if (firstKey) {
|
|
92
|
+
pluginKeys[firstKey] = args.rationale;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const pluginEntry = Object.keys(pluginKeys).length > 0
|
|
96
|
+
? [config.plugin, pluginKeys]
|
|
97
|
+
: config.plugin;
|
|
98
|
+
if (existingIndex >= 0) {
|
|
99
|
+
appJson.expo.plugins[existingIndex] = pluginEntry;
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
appJson.expo.plugins.push(pluginEntry);
|
|
103
|
+
}
|
|
104
|
+
writeFileSync(appJsonPath, JSON.stringify(appJson, null, 2) + "\n");
|
|
105
|
+
const result = {
|
|
106
|
+
success: true,
|
|
107
|
+
permission_type: args.permission_type,
|
|
108
|
+
package: config.package,
|
|
109
|
+
plugin_added: pluginEntry,
|
|
110
|
+
app_json_updated: appJsonPath,
|
|
111
|
+
next_steps: [
|
|
112
|
+
`Install the package: npx expo install ${config.package}`,
|
|
113
|
+
"Run npx expo prebuild to regenerate native projects",
|
|
114
|
+
"Test on a physical device (permissions behave differently on simulators)",
|
|
115
|
+
],
|
|
116
|
+
};
|
|
117
|
+
return textResponse(JSON.stringify(result, null, 2));
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
return errorResponse(err);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=addPermission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addPermission.js","sourceRoot":"","sources":["../../src/tools/addPermission.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkBuildHealth.d.ts","sourceRoot":"","sources":["../../src/tools/checkBuildHealth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA6MzE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyChD"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
3
|
+
import { execSync } from "node:child_process";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { textResponse, errorResponse } from "../types.js";
|
|
6
|
+
const inputSchema = {
|
|
7
|
+
project_path: z
|
|
8
|
+
.string()
|
|
9
|
+
.optional()
|
|
10
|
+
.describe("Absolute path to the Expo project root. Defaults to cwd."),
|
|
11
|
+
platform: z
|
|
12
|
+
.enum(["ios", "android", "both"])
|
|
13
|
+
.optional()
|
|
14
|
+
.default("both")
|
|
15
|
+
.describe("Platform to check build health for"),
|
|
16
|
+
};
|
|
17
|
+
function checkAppJson(root) {
|
|
18
|
+
const appJsonPath = join(root, "app.json");
|
|
19
|
+
if (!existsSync(appJsonPath)) {
|
|
20
|
+
return { name: "app.json", status: "fail", message: "app.json not found" };
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
const content = readFileSync(appJsonPath, "utf-8");
|
|
24
|
+
const config = JSON.parse(content);
|
|
25
|
+
if (!config.expo) {
|
|
26
|
+
return {
|
|
27
|
+
name: "app.json",
|
|
28
|
+
status: "fail",
|
|
29
|
+
message: 'app.json missing "expo" key',
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
const warnings = [];
|
|
33
|
+
if (!config.expo.name)
|
|
34
|
+
warnings.push("missing expo.name");
|
|
35
|
+
if (!config.expo.slug)
|
|
36
|
+
warnings.push("missing expo.slug");
|
|
37
|
+
if (!config.expo.version)
|
|
38
|
+
warnings.push("missing expo.version");
|
|
39
|
+
if (!config.expo.scheme)
|
|
40
|
+
warnings.push("missing expo.scheme (needed for deep linking)");
|
|
41
|
+
if (warnings.length > 0) {
|
|
42
|
+
return {
|
|
43
|
+
name: "app.json",
|
|
44
|
+
status: "warn",
|
|
45
|
+
message: `Valid JSON but: ${warnings.join(", ")}`,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return { name: "app.json", status: "pass", message: "Valid configuration" };
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
return {
|
|
52
|
+
name: "app.json",
|
|
53
|
+
status: "fail",
|
|
54
|
+
message: `Invalid JSON: ${e instanceof Error ? e.message : String(e)}`,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function checkPackageJson(root) {
|
|
59
|
+
const pkgPath = join(root, "package.json");
|
|
60
|
+
if (!existsSync(pkgPath)) {
|
|
61
|
+
return {
|
|
62
|
+
name: "package.json",
|
|
63
|
+
status: "fail",
|
|
64
|
+
message: "package.json not found",
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
69
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
70
|
+
if (!deps.expo) {
|
|
71
|
+
return {
|
|
72
|
+
name: "package.json",
|
|
73
|
+
status: "fail",
|
|
74
|
+
message: "expo is not listed as a dependency",
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
name: "package.json",
|
|
79
|
+
status: "pass",
|
|
80
|
+
message: `Expo ${deps.expo} detected`,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
return {
|
|
85
|
+
name: "package.json",
|
|
86
|
+
status: "fail",
|
|
87
|
+
message: `Invalid JSON: ${e instanceof Error ? e.message : String(e)}`,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function checkNodeModules(root) {
|
|
92
|
+
if (!existsSync(join(root, "node_modules"))) {
|
|
93
|
+
return {
|
|
94
|
+
name: "node_modules",
|
|
95
|
+
status: "fail",
|
|
96
|
+
message: 'node_modules not found. Run "npm install".',
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return { name: "node_modules", status: "pass", message: "Installed" };
|
|
100
|
+
}
|
|
101
|
+
function checkTypeScript(root) {
|
|
102
|
+
const tsconfigPath = join(root, "tsconfig.json");
|
|
103
|
+
if (!existsSync(tsconfigPath)) {
|
|
104
|
+
return {
|
|
105
|
+
name: "TypeScript",
|
|
106
|
+
status: "warn",
|
|
107
|
+
message: "No tsconfig.json found. TypeScript is recommended.",
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
execSync("npx tsc --noEmit", {
|
|
112
|
+
cwd: root,
|
|
113
|
+
encoding: "utf-8",
|
|
114
|
+
timeout: 60000,
|
|
115
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
116
|
+
});
|
|
117
|
+
return {
|
|
118
|
+
name: "TypeScript",
|
|
119
|
+
status: "pass",
|
|
120
|
+
message: "Compiles without errors",
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
const stderr = e instanceof Error && "stderr" in e ? e.stderr : String(e);
|
|
125
|
+
const errorCount = (stderr.match(/error TS/g) || []).length;
|
|
126
|
+
return {
|
|
127
|
+
name: "TypeScript",
|
|
128
|
+
status: "fail",
|
|
129
|
+
message: `${errorCount} TypeScript error(s) found`,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function checkNativeModules(root, platform) {
|
|
134
|
+
const pkgPath = join(root, "package.json");
|
|
135
|
+
if (!existsSync(pkgPath)) {
|
|
136
|
+
return {
|
|
137
|
+
name: "Native modules",
|
|
138
|
+
status: "warn",
|
|
139
|
+
message: "Cannot check without package.json",
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
143
|
+
const deps = Object.keys(pkg.dependencies || {});
|
|
144
|
+
const nativePackages = deps.filter((d) => d.startsWith("expo-camera") ||
|
|
145
|
+
d.startsWith("expo-location") ||
|
|
146
|
+
d.startsWith("expo-contacts") ||
|
|
147
|
+
d.startsWith("expo-media-library") ||
|
|
148
|
+
d.startsWith("expo-notifications") ||
|
|
149
|
+
d.startsWith("expo-sensors") ||
|
|
150
|
+
d.startsWith("expo-local-authentication") ||
|
|
151
|
+
d.startsWith("react-native-reanimated") ||
|
|
152
|
+
d.startsWith("react-native-gesture-handler") ||
|
|
153
|
+
d.startsWith("react-native-maps") ||
|
|
154
|
+
d.startsWith("react-native-webview"));
|
|
155
|
+
if (nativePackages.length === 0) {
|
|
156
|
+
return {
|
|
157
|
+
name: "Native modules",
|
|
158
|
+
status: "pass",
|
|
159
|
+
message: "No native modules detected (Expo Go compatible)",
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
const hasIosBuild = existsSync(join(root, "ios"));
|
|
163
|
+
const hasAndroidBuild = existsSync(join(root, "android"));
|
|
164
|
+
const needsIos = platform === "ios" || platform === "both";
|
|
165
|
+
const needsAndroid = platform === "android" || platform === "both";
|
|
166
|
+
const warnings = [];
|
|
167
|
+
if (needsIos && !hasIosBuild)
|
|
168
|
+
warnings.push("ios/ directory missing");
|
|
169
|
+
if (needsAndroid && !hasAndroidBuild)
|
|
170
|
+
warnings.push("android/ directory missing");
|
|
171
|
+
if (warnings.length > 0) {
|
|
172
|
+
return {
|
|
173
|
+
name: "Native modules",
|
|
174
|
+
status: "warn",
|
|
175
|
+
message: `${nativePackages.length} native module(s) found but ${warnings.join(", ")}. Run "npx expo prebuild".`,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
name: "Native modules",
|
|
180
|
+
status: "pass",
|
|
181
|
+
message: `${nativePackages.length} native module(s), native directories present`,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
export function register(server) {
|
|
185
|
+
server.tool("mobile_checkBuildHealth", "Run build health checks on an Expo project: validate app.json, check dependencies, verify TypeScript, detect native module issues.", inputSchema, async (args) => {
|
|
186
|
+
try {
|
|
187
|
+
const root = args.project_path || process.cwd();
|
|
188
|
+
if (!existsSync(join(root, "app.json")) && !existsSync(join(root, "package.json"))) {
|
|
189
|
+
return errorResponse(new Error(`Not an Expo project: no app.json or package.json at ${root}`));
|
|
190
|
+
}
|
|
191
|
+
const checks = [
|
|
192
|
+
checkAppJson(root),
|
|
193
|
+
checkPackageJson(root),
|
|
194
|
+
checkNodeModules(root),
|
|
195
|
+
checkTypeScript(root),
|
|
196
|
+
checkNativeModules(root, args.platform),
|
|
197
|
+
];
|
|
198
|
+
const passed = checks.filter((c) => c.status === "pass").length;
|
|
199
|
+
const failed = checks.filter((c) => c.status === "fail").length;
|
|
200
|
+
const warned = checks.filter((c) => c.status === "warn").length;
|
|
201
|
+
const result = {
|
|
202
|
+
project_path: root,
|
|
203
|
+
platform: args.platform,
|
|
204
|
+
summary: `${passed} passed, ${failed} failed, ${warned} warnings`,
|
|
205
|
+
healthy: failed === 0,
|
|
206
|
+
checks,
|
|
207
|
+
};
|
|
208
|
+
return textResponse(JSON.stringify(result, null, 2));
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
return errorResponse(err);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=checkBuildHealth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkBuildHealth.js","sourceRoot":"","sources":["../../src/tools/checkBuildHealth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateComponent.d.ts","sourceRoot":"","sources":["../../src/tools/generateComponent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA2DzE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAoDhD"}
|
|
@@ -0,0 +1,98 @@
|
|
|
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
|
+
name: z
|
|
7
|
+
.string()
|
|
8
|
+
.describe("Component name in PascalCase (e.g. 'Avatar', 'ProductCard')"),
|
|
9
|
+
directory: z
|
|
10
|
+
.string()
|
|
11
|
+
.optional()
|
|
12
|
+
.default("components")
|
|
13
|
+
.describe("Directory relative to project root (e.g. 'components/ui')"),
|
|
14
|
+
with_tests: z
|
|
15
|
+
.boolean()
|
|
16
|
+
.optional()
|
|
17
|
+
.default(false)
|
|
18
|
+
.describe("Generate a companion test file alongside the component"),
|
|
19
|
+
project_path: z
|
|
20
|
+
.string()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe("Absolute path to the Expo project root. Defaults to cwd."),
|
|
23
|
+
};
|
|
24
|
+
function generateComponentContent(name) {
|
|
25
|
+
return `import { View, Text, StyleSheet } from "react-native";
|
|
26
|
+
|
|
27
|
+
interface ${name}Props {
|
|
28
|
+
// TODO: define props
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function ${name}({}: ${name}Props) {
|
|
32
|
+
return (
|
|
33
|
+
<View style={styles.container}>
|
|
34
|
+
<Text>${name}</Text>
|
|
35
|
+
</View>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const styles = StyleSheet.create({
|
|
40
|
+
container: {
|
|
41
|
+
// TODO: add styles
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
`;
|
|
45
|
+
}
|
|
46
|
+
function generateTestContent(name) {
|
|
47
|
+
return `import { render, screen } from "@testing-library/react-native";
|
|
48
|
+
import { ${name} } from "../${name}";
|
|
49
|
+
|
|
50
|
+
describe("${name}", () => {
|
|
51
|
+
it("renders without crashing", () => {
|
|
52
|
+
render(<${name} />);
|
|
53
|
+
expect(screen.getByText("${name}")).toBeTruthy();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
`;
|
|
57
|
+
}
|
|
58
|
+
export function register(server) {
|
|
59
|
+
server.tool("mobile_generateComponent", "Create a React Native component file with typed props, StyleSheet, and optional test file.", inputSchema, async (args) => {
|
|
60
|
+
try {
|
|
61
|
+
const root = args.project_path || process.cwd();
|
|
62
|
+
const componentDir = join(root, args.directory);
|
|
63
|
+
mkdirSync(componentDir, { recursive: true });
|
|
64
|
+
const componentFile = join(componentDir, `${args.name}.tsx`);
|
|
65
|
+
if (existsSync(componentFile)) {
|
|
66
|
+
return errorResponse(new Error(`Component already exists: ${componentFile}`));
|
|
67
|
+
}
|
|
68
|
+
writeFileSync(componentFile, generateComponentContent(args.name));
|
|
69
|
+
const filesCreated = [componentFile];
|
|
70
|
+
if (args.with_tests) {
|
|
71
|
+
const testDir = join(componentDir, "__tests__");
|
|
72
|
+
mkdirSync(testDir, { recursive: true });
|
|
73
|
+
const testFile = join(testDir, `${args.name}.test.tsx`);
|
|
74
|
+
writeFileSync(testFile, generateTestContent(args.name));
|
|
75
|
+
filesCreated.push(testFile);
|
|
76
|
+
}
|
|
77
|
+
const result = {
|
|
78
|
+
success: true,
|
|
79
|
+
files_created: filesCreated,
|
|
80
|
+
component_name: args.name,
|
|
81
|
+
directory: args.directory,
|
|
82
|
+
has_tests: args.with_tests,
|
|
83
|
+
next_steps: [
|
|
84
|
+
`Define props in the ${args.name}Props interface`,
|
|
85
|
+
"Add styles to the StyleSheet",
|
|
86
|
+
args.with_tests
|
|
87
|
+
? "Update the test to match your final props"
|
|
88
|
+
: "Consider adding tests later with with_tests: true",
|
|
89
|
+
],
|
|
90
|
+
};
|
|
91
|
+
return textResponse(JSON.stringify(result, null, 2));
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
return errorResponse(err);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=generateComponent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateComponent.js","sourceRoot":"","sources":["../../src/tools/generateComponent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateScreen.d.ts","sourceRoot":"","sources":["../../src/tools/generateScreen.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA2EzE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8DhD"}
|
|
@@ -0,0 +1,120 @@
|
|
|
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
|
+
name: z
|
|
7
|
+
.string()
|
|
8
|
+
.describe("Screen name (lowercase, used as filename e.g. 'profile')"),
|
|
9
|
+
type: z
|
|
10
|
+
.enum(["tab", "stack", "modal"])
|
|
11
|
+
.describe("Navigation type for this screen"),
|
|
12
|
+
layout_group: z
|
|
13
|
+
.string()
|
|
14
|
+
.optional()
|
|
15
|
+
.default("")
|
|
16
|
+
.describe("Route group directory (e.g. '(tabs)' or 'settings'). Empty for root-level screen."),
|
|
17
|
+
project_path: z
|
|
18
|
+
.string()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe("Absolute path to the Expo project root. Defaults to cwd."),
|
|
21
|
+
};
|
|
22
|
+
function generateScreenContent(name, type) {
|
|
23
|
+
const componentName = name.charAt(0).toUpperCase() + name.slice(1) + "Screen";
|
|
24
|
+
return `import { View, Text, StyleSheet } from "react-native";
|
|
25
|
+
import { Stack } from "expo-router";
|
|
26
|
+
|
|
27
|
+
export default function ${componentName}() {
|
|
28
|
+
return (
|
|
29
|
+
<View style={styles.container}>
|
|
30
|
+
<Stack.Screen options={{ title: "${name.charAt(0).toUpperCase() + name.slice(1)}" }} />
|
|
31
|
+
<Text style={styles.title}>${name.charAt(0).toUpperCase() + name.slice(1)}</Text>
|
|
32
|
+
</View>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const styles = StyleSheet.create({
|
|
37
|
+
container: {
|
|
38
|
+
flex: 1,
|
|
39
|
+
alignItems: "center",
|
|
40
|
+
justifyContent: "center",
|
|
41
|
+
padding: 16,
|
|
42
|
+
},
|
|
43
|
+
title: {
|
|
44
|
+
fontSize: 24,
|
|
45
|
+
fontWeight: "600",
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
`;
|
|
49
|
+
}
|
|
50
|
+
function generateLayoutContent(group, type) {
|
|
51
|
+
if (type === "tab") {
|
|
52
|
+
return `import { Tabs } from "expo-router";
|
|
53
|
+
|
|
54
|
+
export default function ${group.replace(/[()]/g, "")}Layout() {
|
|
55
|
+
return (
|
|
56
|
+
<Tabs
|
|
57
|
+
screenOptions={{
|
|
58
|
+
tabBarActiveTintColor: "#007AFF",
|
|
59
|
+
}}
|
|
60
|
+
/>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
`;
|
|
64
|
+
}
|
|
65
|
+
return `import { Stack } from "expo-router";
|
|
66
|
+
|
|
67
|
+
export default function ${group.replace(/[()]/g, "")}Layout() {
|
|
68
|
+
return <Stack />;
|
|
69
|
+
}
|
|
70
|
+
`;
|
|
71
|
+
}
|
|
72
|
+
export function register(server) {
|
|
73
|
+
server.tool("mobile_generateScreen", "Create a new Expo Router screen file with navigation wiring and boilerplate.", inputSchema, async (args) => {
|
|
74
|
+
try {
|
|
75
|
+
const root = args.project_path || process.cwd();
|
|
76
|
+
const appDir = join(root, "app");
|
|
77
|
+
const screenDir = args.layout_group
|
|
78
|
+
? join(appDir, args.layout_group)
|
|
79
|
+
: appDir;
|
|
80
|
+
mkdirSync(screenDir, { recursive: true });
|
|
81
|
+
const screenFile = join(screenDir, `${args.name}.tsx`);
|
|
82
|
+
if (existsSync(screenFile)) {
|
|
83
|
+
return errorResponse(new Error(`Screen already exists: ${screenFile}`));
|
|
84
|
+
}
|
|
85
|
+
writeFileSync(screenFile, generateScreenContent(args.name, args.type));
|
|
86
|
+
const layoutFile = join(screenDir, "_layout.tsx");
|
|
87
|
+
let layoutCreated = false;
|
|
88
|
+
if (!existsSync(layoutFile) && args.layout_group) {
|
|
89
|
+
writeFileSync(layoutFile, generateLayoutContent(args.layout_group, args.type));
|
|
90
|
+
layoutCreated = true;
|
|
91
|
+
}
|
|
92
|
+
const result = {
|
|
93
|
+
success: true,
|
|
94
|
+
screen_file: screenFile,
|
|
95
|
+
layout_file: layoutCreated ? layoutFile : null,
|
|
96
|
+
layout_created: layoutCreated,
|
|
97
|
+
name: args.name,
|
|
98
|
+
type: args.type,
|
|
99
|
+
layout_group: args.layout_group || "(root)",
|
|
100
|
+
next_steps: [
|
|
101
|
+
layoutCreated
|
|
102
|
+
? `Review the generated _layout.tsx in ${args.layout_group}`
|
|
103
|
+
: null,
|
|
104
|
+
`Edit ${screenFile} to add your screen content`,
|
|
105
|
+
args.type === "tab"
|
|
106
|
+
? "Add a tabBarIcon to the Tabs.Screen options in the layout"
|
|
107
|
+
: null,
|
|
108
|
+
args.type === "modal"
|
|
109
|
+
? 'Add presentation: "modal" to the Stack.Screen options in the parent layout'
|
|
110
|
+
: null,
|
|
111
|
+
].filter(Boolean),
|
|
112
|
+
};
|
|
113
|
+
return textResponse(JSON.stringify(result, null, 2));
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
return errorResponse(err);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=generateScreen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateScreen.js","sourceRoot":"","sources":["../../src/tools/generateScreen.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installDependency.d.ts","sourceRoot":"","sources":["../../src/tools/installDependency.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAyCzE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8DhD"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { textResponse, errorResponse } from "../types.js";
|
|
6
|
+
const NATIVE_MODULE_INDICATORS = [
|
|
7
|
+
"react-native-reanimated",
|
|
8
|
+
"react-native-gesture-handler",
|
|
9
|
+
"react-native-screens",
|
|
10
|
+
"react-native-svg",
|
|
11
|
+
"react-native-maps",
|
|
12
|
+
"react-native-webview",
|
|
13
|
+
"expo-camera",
|
|
14
|
+
"expo-location",
|
|
15
|
+
"expo-notifications",
|
|
16
|
+
"expo-sensors",
|
|
17
|
+
"expo-media-library",
|
|
18
|
+
"expo-contacts",
|
|
19
|
+
"expo-calendar",
|
|
20
|
+
"expo-barcode-scanner",
|
|
21
|
+
"expo-print",
|
|
22
|
+
"expo-local-authentication",
|
|
23
|
+
"expo-audio",
|
|
24
|
+
"expo-video",
|
|
25
|
+
];
|
|
26
|
+
const inputSchema = {
|
|
27
|
+
package_name: z
|
|
28
|
+
.string()
|
|
29
|
+
.describe("Package to install (e.g. 'zustand' or '@tanstack/react-query'). Multiple packages separated by spaces."),
|
|
30
|
+
project_path: z
|
|
31
|
+
.string()
|
|
32
|
+
.optional()
|
|
33
|
+
.describe("Absolute path to the Expo project root. Defaults to cwd."),
|
|
34
|
+
dev: z
|
|
35
|
+
.boolean()
|
|
36
|
+
.optional()
|
|
37
|
+
.default(false)
|
|
38
|
+
.describe("Install as a dev dependency"),
|
|
39
|
+
};
|
|
40
|
+
export function register(server) {
|
|
41
|
+
server.tool("mobile_installDependency", "Install a package using npx expo install for Expo compatibility. Detects native modules and warns about Expo Go limitations.", inputSchema, async (args) => {
|
|
42
|
+
try {
|
|
43
|
+
const cwd = args.project_path || process.cwd();
|
|
44
|
+
const packages = args.package_name.split(/\s+/).filter(Boolean);
|
|
45
|
+
const appJsonPath = join(cwd, "app.json");
|
|
46
|
+
if (!existsSync(appJsonPath)) {
|
|
47
|
+
return errorResponse(new Error(`No app.json found at ${cwd}. Is this an Expo project root?`));
|
|
48
|
+
}
|
|
49
|
+
const nativePackages = packages.filter((p) => NATIVE_MODULE_INDICATORS.some((n) => p === n || p.startsWith(n + "@")));
|
|
50
|
+
const devFlag = args.dev ? "-- --save-dev" : "";
|
|
51
|
+
const command = `npx expo install ${packages.join(" ")} ${devFlag}`.trim();
|
|
52
|
+
const output = execSync(command, {
|
|
53
|
+
cwd,
|
|
54
|
+
encoding: "utf-8",
|
|
55
|
+
timeout: 120000,
|
|
56
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
57
|
+
});
|
|
58
|
+
const warnings = [];
|
|
59
|
+
if (nativePackages.length > 0) {
|
|
60
|
+
warnings.push(`Native modules detected: ${nativePackages.join(", ")}. These require a development build (npx expo run:ios / npx expo run:android) and will not work in Expo Go.`);
|
|
61
|
+
warnings.push("Run `npx expo prebuild` or use EAS Build to create a dev client.");
|
|
62
|
+
}
|
|
63
|
+
const result = {
|
|
64
|
+
success: true,
|
|
65
|
+
packages_installed: packages,
|
|
66
|
+
command_used: command,
|
|
67
|
+
output: output.trim(),
|
|
68
|
+
native_modules_detected: nativePackages,
|
|
69
|
+
warnings,
|
|
70
|
+
needs_dev_build: nativePackages.length > 0,
|
|
71
|
+
};
|
|
72
|
+
return textResponse(JSON.stringify(result, null, 2));
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
return errorResponse(err);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=installDependency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installDependency.js","sourceRoot":"","sources":["../../src/tools/installDependency.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrateAI.d.ts","sourceRoot":"","sources":["../../src/tools/integrateAI.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAgIzE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+ChD"}
|
|
@@ -0,0 +1,156 @@
|
|
|
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
|
+
provider: z
|
|
7
|
+
.enum(["openai", "anthropic", "google"])
|
|
8
|
+
.describe("AI provider to integrate"),
|
|
9
|
+
features: z
|
|
10
|
+
.array(z.enum(["vision", "text", "audio"]))
|
|
11
|
+
.describe("AI features to scaffold (vision, text, audio)"),
|
|
12
|
+
project_path: z
|
|
13
|
+
.string()
|
|
14
|
+
.optional()
|
|
15
|
+
.describe("Absolute path to the Expo project root. Defaults to cwd."),
|
|
16
|
+
};
|
|
17
|
+
function generateClientCode(provider, features) {
|
|
18
|
+
const lines = [];
|
|
19
|
+
lines.push(`// AI client for ${provider}`);
|
|
20
|
+
lines.push(`// API keys must NOT be bundled in the app. Use a backend proxy.`);
|
|
21
|
+
lines.push(``);
|
|
22
|
+
lines.push(`const API_BASE = process.env.EXPO_PUBLIC_AI_PROXY_URL || "http://localhost:3000";`);
|
|
23
|
+
lines.push(``);
|
|
24
|
+
lines.push(`interface AIResponse {`);
|
|
25
|
+
lines.push(` text: string;`);
|
|
26
|
+
lines.push(` usage?: { prompt_tokens: number; completion_tokens: number };`);
|
|
27
|
+
lines.push(`}`);
|
|
28
|
+
lines.push(``);
|
|
29
|
+
lines.push(`interface AIError {`);
|
|
30
|
+
lines.push(` message: string;`);
|
|
31
|
+
lines.push(` status: number;`);
|
|
32
|
+
lines.push(`}`);
|
|
33
|
+
lines.push(``);
|
|
34
|
+
lines.push(`async function aiRequest(`);
|
|
35
|
+
lines.push(` endpoint: string,`);
|
|
36
|
+
lines.push(` body: Record<string, unknown>,`);
|
|
37
|
+
lines.push(` authToken: string,`);
|
|
38
|
+
lines.push(`): Promise<AIResponse> {`);
|
|
39
|
+
lines.push(` const controller = new AbortController();`);
|
|
40
|
+
lines.push(` const timeout = setTimeout(() => controller.abort(), 30000);`);
|
|
41
|
+
lines.push(``);
|
|
42
|
+
lines.push(` try {`);
|
|
43
|
+
lines.push(` const res = await fetch(\`\${API_BASE}\${endpoint}\`, {`);
|
|
44
|
+
lines.push(` method: "POST",`);
|
|
45
|
+
lines.push(` headers: {`);
|
|
46
|
+
lines.push(` "Content-Type": "application/json",`);
|
|
47
|
+
lines.push(` Authorization: \`Bearer \${authToken}\`,`);
|
|
48
|
+
lines.push(` },`);
|
|
49
|
+
lines.push(` body: JSON.stringify({ ...body, provider: "${provider}" }),`);
|
|
50
|
+
lines.push(` signal: controller.signal,`);
|
|
51
|
+
lines.push(` });`);
|
|
52
|
+
lines.push(``);
|
|
53
|
+
lines.push(` if (!res.ok) {`);
|
|
54
|
+
lines.push(` const error = await res.text();`);
|
|
55
|
+
lines.push(` throw new Error(\`AI request failed (\${res.status}): \${error}\`);`);
|
|
56
|
+
lines.push(` }`);
|
|
57
|
+
lines.push(``);
|
|
58
|
+
lines.push(` return res.json();`);
|
|
59
|
+
lines.push(` } finally {`);
|
|
60
|
+
lines.push(` clearTimeout(timeout);`);
|
|
61
|
+
lines.push(` }`);
|
|
62
|
+
lines.push(`}`);
|
|
63
|
+
if (features.includes("text")) {
|
|
64
|
+
lines.push(``);
|
|
65
|
+
lines.push(`export async function generateText(`);
|
|
66
|
+
lines.push(` prompt: string,`);
|
|
67
|
+
lines.push(` authToken: string,`);
|
|
68
|
+
lines.push(`): Promise<AIResponse> {`);
|
|
69
|
+
lines.push(` return aiRequest("/api/ai/text", { prompt }, authToken);`);
|
|
70
|
+
lines.push(`}`);
|
|
71
|
+
}
|
|
72
|
+
if (features.includes("vision")) {
|
|
73
|
+
lines.push(``);
|
|
74
|
+
lines.push(`export async function analyzeImage(`);
|
|
75
|
+
lines.push(` imageBase64: string,`);
|
|
76
|
+
lines.push(` prompt: string,`);
|
|
77
|
+
lines.push(` authToken: string,`);
|
|
78
|
+
lines.push(`): Promise<AIResponse> {`);
|
|
79
|
+
lines.push(` return aiRequest(`);
|
|
80
|
+
lines.push(` "/api/ai/vision",`);
|
|
81
|
+
lines.push(` { prompt, image: \`data:image/jpeg;base64,\${imageBase64}\` },`);
|
|
82
|
+
lines.push(` authToken,`);
|
|
83
|
+
lines.push(` );`);
|
|
84
|
+
lines.push(`}`);
|
|
85
|
+
}
|
|
86
|
+
if (features.includes("audio")) {
|
|
87
|
+
lines.push(``);
|
|
88
|
+
lines.push(`export async function transcribeAudio(`);
|
|
89
|
+
lines.push(` audioUri: string,`);
|
|
90
|
+
lines.push(` authToken: string,`);
|
|
91
|
+
lines.push(`): Promise<AIResponse> {`);
|
|
92
|
+
lines.push(` const formData = new FormData();`);
|
|
93
|
+
lines.push(` formData.append("file", {`);
|
|
94
|
+
lines.push(` uri: audioUri,`);
|
|
95
|
+
lines.push(` type: "audio/m4a",`);
|
|
96
|
+
lines.push(` name: "recording.m4a",`);
|
|
97
|
+
lines.push(` } as any);`);
|
|
98
|
+
lines.push(``);
|
|
99
|
+
lines.push(` const controller = new AbortController();`);
|
|
100
|
+
lines.push(` const timeout = setTimeout(() => controller.abort(), 60000);`);
|
|
101
|
+
lines.push(``);
|
|
102
|
+
lines.push(` try {`);
|
|
103
|
+
lines.push(` const res = await fetch(\`\${API_BASE}/api/ai/transcribe\`, {`);
|
|
104
|
+
lines.push(` method: "POST",`);
|
|
105
|
+
lines.push(` headers: { Authorization: \`Bearer \${authToken}\` },`);
|
|
106
|
+
lines.push(` body: formData,`);
|
|
107
|
+
lines.push(` signal: controller.signal,`);
|
|
108
|
+
lines.push(` });`);
|
|
109
|
+
lines.push(``);
|
|
110
|
+
lines.push(` if (!res.ok) throw new Error(\`Transcription failed: \${res.status}\`);`);
|
|
111
|
+
lines.push(` return res.json();`);
|
|
112
|
+
lines.push(` } finally {`);
|
|
113
|
+
lines.push(` clearTimeout(timeout);`);
|
|
114
|
+
lines.push(` }`);
|
|
115
|
+
lines.push(`}`);
|
|
116
|
+
}
|
|
117
|
+
lines.push(``);
|
|
118
|
+
return lines.join("\n");
|
|
119
|
+
}
|
|
120
|
+
export function register(server) {
|
|
121
|
+
server.tool("mobile_integrateAI", "Scaffold AI API integration with provider config, error handling, and TypeScript types.", inputSchema, async (args) => {
|
|
122
|
+
try {
|
|
123
|
+
const root = args.project_path || process.cwd();
|
|
124
|
+
const libDir = join(root, "lib");
|
|
125
|
+
mkdirSync(libDir, { recursive: true });
|
|
126
|
+
const clientFile = join(libDir, "ai.ts");
|
|
127
|
+
if (existsSync(clientFile)) {
|
|
128
|
+
return errorResponse(new Error(`AI client already exists at ${clientFile}. Delete it first or edit manually.`));
|
|
129
|
+
}
|
|
130
|
+
const code = generateClientCode(args.provider, args.features);
|
|
131
|
+
writeFileSync(clientFile, code);
|
|
132
|
+
const result = {
|
|
133
|
+
success: true,
|
|
134
|
+
provider: args.provider,
|
|
135
|
+
features: args.features,
|
|
136
|
+
file_created: clientFile,
|
|
137
|
+
next_steps: [
|
|
138
|
+
"Set EXPO_PUBLIC_AI_PROXY_URL in your .env to point to your backend proxy",
|
|
139
|
+
"Deploy a backend that proxies requests to the AI provider and holds the API key",
|
|
140
|
+
"Never bundle AI provider API keys directly in the mobile app",
|
|
141
|
+
args.features.includes("vision")
|
|
142
|
+
? "Install expo-camera for vision features: npx expo install expo-camera"
|
|
143
|
+
: null,
|
|
144
|
+
args.features.includes("audio")
|
|
145
|
+
? "Install expo-av for audio recording: npx expo install expo-av"
|
|
146
|
+
: null,
|
|
147
|
+
].filter(Boolean),
|
|
148
|
+
};
|
|
149
|
+
return textResponse(JSON.stringify(result, null, 2));
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
return errorResponse(err);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=integrateAI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrateAI.js","sourceRoot":"","sources":["../../src/tools/integrateAI.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tmhs/mobile-mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "MCP server for mobile app development -
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "MCP server for mobile app development - 9 tools for environment checks, project scaffolding, device deployment, screen/component generation, dependency installation, permissions, AI integration, and build health checks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|