@tmhs/mobile-mcp 0.1.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.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/checkDevEnvironment.d.ts +3 -0
- package/dist/tools/checkDevEnvironment.d.ts.map +1 -0
- package/dist/tools/checkDevEnvironment.js +102 -0
- package/dist/tools/checkDevEnvironment.js.map +1 -0
- package/dist/tools/runOnDevice.d.ts +3 -0
- package/dist/tools/runOnDevice.d.ts.map +1 -0
- package/dist/tools/runOnDevice.js +64 -0
- package/dist/tools/runOnDevice.js.map +1 -0
- package/dist/tools/scaffoldProject.d.ts +3 -0
- package/dist/tools/scaffoldProject.d.ts.map +1 -0
- package/dist/tools/scaffoldProject.js +54 -0
- package/dist/tools/scaffoldProject.js.map +1 -0
- package/dist/types.d.ts +12 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -0
- package/package.json +47 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { register as registerCheckDevEnvironment } from "./tools/checkDevEnvironment.js";
|
|
5
|
+
import { register as registerScaffoldProject } from "./tools/scaffoldProject.js";
|
|
6
|
+
import { register as registerRunOnDevice } from "./tools/runOnDevice.js";
|
|
7
|
+
const server = new McpServer({
|
|
8
|
+
name: "mobile-mcp",
|
|
9
|
+
version: "0.1.0",
|
|
10
|
+
});
|
|
11
|
+
registerCheckDevEnvironment(server);
|
|
12
|
+
registerScaffoldProject(server);
|
|
13
|
+
registerRunOnDevice(server);
|
|
14
|
+
async function main() {
|
|
15
|
+
const transport = new StdioServerTransport();
|
|
16
|
+
await server.connect(transport);
|
|
17
|
+
}
|
|
18
|
+
main().catch((error) => {
|
|
19
|
+
console.error("Fatal error:", error);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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;AAEzE,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;AAE5B,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":"checkDevEnvironment.d.ts","sourceRoot":"","sources":["../../src/tools/checkDevEnvironment.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAqDzE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2EhD"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
import { platform } from "node:os";
|
|
4
|
+
import { textResponse, errorResponse } from "../types.js";
|
|
5
|
+
const TOOLS = [
|
|
6
|
+
{ name: "Node.js", command: "node --version", required: true },
|
|
7
|
+
{ name: "npm", command: "npm --version", required: true },
|
|
8
|
+
{ name: "Git", command: "git --version", required: true },
|
|
9
|
+
{ name: "Expo CLI", command: "npx expo --version", required: false },
|
|
10
|
+
{ name: "Watchman", command: "watchman --version", required: false },
|
|
11
|
+
{ name: "Xcode CLI Tools", command: "xcode-select -p", required: false, platforms: ["darwin"] },
|
|
12
|
+
{ name: "CocoaPods", command: "pod --version", required: false, platforms: ["darwin"] },
|
|
13
|
+
{ name: "JDK", command: "java -version", required: false },
|
|
14
|
+
];
|
|
15
|
+
function tryCommand(command) {
|
|
16
|
+
try {
|
|
17
|
+
return execSync(command, {
|
|
18
|
+
encoding: "utf-8",
|
|
19
|
+
timeout: 15000,
|
|
20
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
21
|
+
}).trim();
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function checkAndroidSdk() {
|
|
28
|
+
const androidHome = process.env.ANDROID_HOME ||
|
|
29
|
+
process.env.ANDROID_SDK_ROOT ||
|
|
30
|
+
null;
|
|
31
|
+
if (androidHome) {
|
|
32
|
+
return androidHome;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const inputSchema = {
|
|
37
|
+
target_platform: z
|
|
38
|
+
.enum(["ios", "android", "both"])
|
|
39
|
+
.optional()
|
|
40
|
+
.default("both")
|
|
41
|
+
.describe("Target platform to check requirements for"),
|
|
42
|
+
};
|
|
43
|
+
export function register(server) {
|
|
44
|
+
server.tool("mobile_checkDevEnvironment", "Detect installed mobile development tools, SDKs, and simulators. Report what is installed and what is missing with install instructions.", inputSchema, async (args) => {
|
|
45
|
+
try {
|
|
46
|
+
const os = platform();
|
|
47
|
+
const targetPlatform = args.target_platform;
|
|
48
|
+
const results = [];
|
|
49
|
+
for (const tool of TOOLS) {
|
|
50
|
+
if (tool.platforms && !tool.platforms.includes(os)) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const output = tryCommand(tool.command);
|
|
54
|
+
results.push({
|
|
55
|
+
name: tool.name,
|
|
56
|
+
status: output ? "installed" : "missing",
|
|
57
|
+
version: output || "-",
|
|
58
|
+
required: tool.required,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
const androidSdk = checkAndroidSdk();
|
|
62
|
+
if (targetPlatform === "android" || targetPlatform === "both") {
|
|
63
|
+
results.push({
|
|
64
|
+
name: "Android SDK",
|
|
65
|
+
status: androidSdk ? "installed" : "missing",
|
|
66
|
+
version: androidSdk || "-",
|
|
67
|
+
required: targetPlatform === "android",
|
|
68
|
+
note: androidSdk
|
|
69
|
+
? `ANDROID_HOME=${androidSdk}`
|
|
70
|
+
: "Set ANDROID_HOME environment variable",
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if (os !== "darwin" && (targetPlatform === "ios" || targetPlatform === "both")) {
|
|
74
|
+
results.push({
|
|
75
|
+
name: "iOS Build Support",
|
|
76
|
+
status: "missing",
|
|
77
|
+
version: "-",
|
|
78
|
+
required: false,
|
|
79
|
+
note: "iOS builds require macOS. Use Expo Go or EAS Build (cloud) on this platform.",
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const installed = results.filter((r) => r.status === "installed");
|
|
83
|
+
const missing = results.filter((r) => r.status === "missing");
|
|
84
|
+
const missingRequired = missing.filter((r) => r.required);
|
|
85
|
+
const summary = {
|
|
86
|
+
os,
|
|
87
|
+
target_platform: targetPlatform,
|
|
88
|
+
total_checked: results.length,
|
|
89
|
+
installed: installed.length,
|
|
90
|
+
missing: missing.length,
|
|
91
|
+
missing_required: missingRequired.length,
|
|
92
|
+
ready: missingRequired.length === 0,
|
|
93
|
+
tools: results,
|
|
94
|
+
};
|
|
95
|
+
return textResponse(JSON.stringify(summary, null, 2));
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
return errorResponse(err);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=checkDevEnvironment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkDevEnvironment.js","sourceRoot":"","sources":["../../src/tools/checkDevEnvironment.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runOnDevice.d.ts","sourceRoot":"","sources":["../../src/tools/runOnDevice.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAmBzE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAiGhD"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { platform } from "node:os";
|
|
3
|
+
import { textResponse } from "../types.js";
|
|
4
|
+
const inputSchema = {
|
|
5
|
+
project_path: z
|
|
6
|
+
.string()
|
|
7
|
+
.optional()
|
|
8
|
+
.describe("Path to the Expo project (defaults to current directory)"),
|
|
9
|
+
target_platform: z
|
|
10
|
+
.enum(["ios", "android"])
|
|
11
|
+
.optional()
|
|
12
|
+
.describe("Target device platform"),
|
|
13
|
+
connection: z
|
|
14
|
+
.enum(["lan", "tunnel", "usb"])
|
|
15
|
+
.optional()
|
|
16
|
+
.default("lan")
|
|
17
|
+
.describe("Connection method between dev server and device"),
|
|
18
|
+
};
|
|
19
|
+
export function register(server) {
|
|
20
|
+
server.tool("mobile_runOnDevice", "Start the Expo dev server and provide step-by-step instructions for connecting a physical device.", inputSchema, async (args) => {
|
|
21
|
+
const os = platform();
|
|
22
|
+
const connection = args.connection;
|
|
23
|
+
const targetPlatform = args.target_platform;
|
|
24
|
+
const startCommand = connection === "tunnel"
|
|
25
|
+
? "npx expo start --tunnel"
|
|
26
|
+
: "npx expo start";
|
|
27
|
+
const instructions = [
|
|
28
|
+
`## Run on Device`,
|
|
29
|
+
``,
|
|
30
|
+
`**Start the dev server:**`,
|
|
31
|
+
`\`\`\`bash`,
|
|
32
|
+
`cd ${args.project_path || "."}`,
|
|
33
|
+
startCommand,
|
|
34
|
+
`\`\`\``,
|
|
35
|
+
``,
|
|
36
|
+
];
|
|
37
|
+
if (connection === "tunnel") {
|
|
38
|
+
instructions.push(`**Tunnel mode** routes through Expo's servers. Slower but works across different networks and through firewalls.`, ``);
|
|
39
|
+
}
|
|
40
|
+
if (!targetPlatform || targetPlatform === "ios") {
|
|
41
|
+
instructions.push(`### iOS Device`, `1. Install **Expo Go** from the App Store`, `2. Open the **Camera** app on your iPhone/iPad`, `3. Point it at the QR code shown in the terminal`, `4. Tap the notification to open in Expo Go`, ``);
|
|
42
|
+
if (os !== "darwin") {
|
|
43
|
+
instructions.push(`> Note: You are not on macOS. You can test via Expo Go but cannot create native iOS builds locally. Use EAS Build for cloud-based iOS builds.`, ``);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (!targetPlatform || targetPlatform === "android") {
|
|
47
|
+
instructions.push(`### Android Device`, `1. Install **Expo Go** from the Play Store`, `2. Open Expo Go and tap **Scan QR Code**`, `3. Scan the QR code from the terminal`, ``);
|
|
48
|
+
if (connection === "usb") {
|
|
49
|
+
instructions.push(`### USB Debugging (Android)`, `1. Enable Developer Options: Settings > About phone > tap "Build number" 7 times`, `2. Enable USB Debugging: Settings > Developer options > USB debugging`, `3. Connect USB cable`, `4. Accept "Allow USB debugging" prompt on the phone`, `5. Run: \`npx expo run:android\``, ``);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
instructions.push(`### Troubleshooting`, ``, `| Problem | Fix |`, `|---------|-----|`, `| QR code won't scan | Type the URL manually in Expo Go |`, `| "Network response timed out" | Use \`npx expo start --tunnel\` |`, `| Red error screen | Read the error. Usually a missing dependency or syntax error |`, `| Hot reload not working | Shake device > enable Fast Refresh |`, `| "Untrusted Developer" (iOS) | Settings > General > VPN & Device Management > trust certificate |`);
|
|
53
|
+
const result = {
|
|
54
|
+
start_command: startCommand,
|
|
55
|
+
project_path: args.project_path || ".",
|
|
56
|
+
connection_method: connection,
|
|
57
|
+
target_platform: targetPlatform || "both",
|
|
58
|
+
host_os: os,
|
|
59
|
+
instructions: instructions.join("\n"),
|
|
60
|
+
};
|
|
61
|
+
return textResponse(JSON.stringify(result, null, 2));
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=runOnDevice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runOnDevice.js","sourceRoot":"","sources":["../../src/tools/runOnDevice.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffoldProject.d.ts","sourceRoot":"","sources":["../../src/tools/scaffoldProject.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAkBzE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4ChD"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
import { textResponse, errorResponse } from "../types.js";
|
|
4
|
+
const inputSchema = {
|
|
5
|
+
name: z
|
|
6
|
+
.string()
|
|
7
|
+
.describe("Project name (lowercase, no spaces, used as directory name)"),
|
|
8
|
+
template: z
|
|
9
|
+
.enum(["default", "blank", "tabs"])
|
|
10
|
+
.optional()
|
|
11
|
+
.default("default")
|
|
12
|
+
.describe("Expo template to use"),
|
|
13
|
+
directory: z
|
|
14
|
+
.string()
|
|
15
|
+
.optional()
|
|
16
|
+
.describe("Parent directory to create the project in (defaults to current directory)"),
|
|
17
|
+
};
|
|
18
|
+
export function register(server) {
|
|
19
|
+
server.tool("mobile_scaffoldProject", "Generate a new Expo project with TypeScript and recommended configuration.", inputSchema, async (args) => {
|
|
20
|
+
try {
|
|
21
|
+
const cwd = args.directory || process.cwd();
|
|
22
|
+
const templateArg = args.template === "blank"
|
|
23
|
+
? "--template blank"
|
|
24
|
+
: args.template === "tabs"
|
|
25
|
+
? "--template tabs"
|
|
26
|
+
: "";
|
|
27
|
+
const command = `npx create-expo-app@latest ${args.name} ${templateArg}`.trim();
|
|
28
|
+
const output = execSync(command, {
|
|
29
|
+
cwd,
|
|
30
|
+
encoding: "utf-8",
|
|
31
|
+
timeout: 120000,
|
|
32
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
33
|
+
});
|
|
34
|
+
const result = {
|
|
35
|
+
success: true,
|
|
36
|
+
project_name: args.name,
|
|
37
|
+
template: args.template,
|
|
38
|
+
path: `${cwd}/${args.name}`,
|
|
39
|
+
command_used: command,
|
|
40
|
+
output: output.trim(),
|
|
41
|
+
next_steps: [
|
|
42
|
+
`cd ${args.name}`,
|
|
43
|
+
"npx expo start",
|
|
44
|
+
"Scan the QR code with Expo Go (iOS: Camera app, Android: Expo Go app)",
|
|
45
|
+
],
|
|
46
|
+
};
|
|
47
|
+
return textResponse(JSON.stringify(result, null, 2));
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
return errorResponse(err);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=scaffoldProject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffoldProject.js","sourceRoot":"","sources":["../../src/tools/scaffoldProject.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,WAAW,GAAG;IAClB,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,QAAQ,CAAC,6DAA6D,CAAC;IAC1E,QAAQ,EAAE,CAAC;SACR,IAAI,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;SAClC,QAAQ,EAAE;SACV,OAAO,CAAC,SAAS,CAAC;SAClB,QAAQ,CAAC,sBAAsB,CAAC;IACnC,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,2EAA2E,CAAC;CACzF,CAAC;AAEF,MAAM,UAAU,QAAQ,CAAC,MAAiB;IACxC,MAAM,CAAC,IAAI,CACT,wBAAwB,EACxB,4EAA4E,EAC5E,WAAW,EACX,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;YAC5C,MAAM,WAAW,GACf,IAAI,CAAC,QAAQ,KAAK,OAAO;gBACvB,CAAC,CAAC,kBAAkB;gBACpB,CAAC,CAAC,IAAI,CAAC,QAAQ,KAAK,MAAM;oBACxB,CAAC,CAAC,iBAAiB;oBACnB,CAAC,CAAC,EAAE,CAAC;YAEX,MAAM,OAAO,GAAG,8BAA8B,IAAI,CAAC,IAAI,IAAI,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;YAEhF,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,EAAE;gBAC/B,GAAG;gBACH,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,MAAM;gBACf,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;aAChC,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG;gBACb,OAAO,EAAE,IAAI;gBACb,YAAY,EAAE,IAAI,CAAC,IAAI;gBACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,IAAI,EAAE,GAAG,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE;gBAC3B,YAAY,EAAE,OAAO;gBACrB,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;gBACrB,UAAU,EAAE;oBACV,MAAM,IAAI,CAAC,IAAI,EAAE;oBACjB,gBAAgB;oBAChB,uEAAuE;iBACxE;aACF,CAAC;YAEF,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/dist/types.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ToolResponse {
|
|
2
|
+
[key: string]: unknown;
|
|
3
|
+
content: Array<{
|
|
4
|
+
type: "text";
|
|
5
|
+
text: string;
|
|
6
|
+
}>;
|
|
7
|
+
isError?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function textResponse(text: string): ToolResponse;
|
|
10
|
+
export declare function errorResponse(error: unknown): ToolResponse;
|
|
11
|
+
export declare function stubResponse(toolName: string, version: string): ToolResponse;
|
|
12
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAEvD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,CAQ1D;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,CAI5E"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function textResponse(text) {
|
|
2
|
+
return { content: [{ type: "text", text }] };
|
|
3
|
+
}
|
|
4
|
+
export function errorResponse(error) {
|
|
5
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
6
|
+
return {
|
|
7
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
8
|
+
isError: true,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export function stubResponse(toolName, version) {
|
|
12
|
+
return textResponse(`${toolName} is not yet implemented. Coming in ${version}.`);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,MAAM,OAAO,GACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEzD,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC;QAC/D,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,OAAe;IAC5D,OAAO,YAAY,CACjB,GAAG,QAAQ,sCAAsC,OAAO,GAAG,CAC5D,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tmhs/mobile-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for mobile app development - 3 tools for environment checks, project scaffolding, and device deployment.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mobile-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">= 20.0.0"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"dev": "tsx watch src/index.ts",
|
|
21
|
+
"start": "node dist/index.js",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest",
|
|
24
|
+
"prepublishOnly": "npm run build"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
28
|
+
"zod": "^3.23.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^22.0.0",
|
|
32
|
+
"tsx": "^4.19.0",
|
|
33
|
+
"typescript": "^5.7.0",
|
|
34
|
+
"vitest": "^3.0.0"
|
|
35
|
+
},
|
|
36
|
+
"license": "CC-BY-NC-ND-4.0",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/TMHSDigital/Mobile-App-Developer-Tools.git",
|
|
40
|
+
"directory": "mcp-server"
|
|
41
|
+
},
|
|
42
|
+
"homepage": "https://github.com/TMHSDigital/Mobile-App-Developer-Tools",
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/TMHSDigital/Mobile-App-Developer-Tools/issues"
|
|
45
|
+
},
|
|
46
|
+
"author": "TMHSDigital"
|
|
47
|
+
}
|