mobile-device-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.
Files changed (74) hide show
  1. package/README.md +181 -0
  2. package/dist/ai/analyzer.d.ts +98 -0
  3. package/dist/ai/analyzer.d.ts.map +1 -0
  4. package/dist/ai/analyzer.js +451 -0
  5. package/dist/ai/analyzer.js.map +1 -0
  6. package/dist/ai/client.d.ts +92 -0
  7. package/dist/ai/client.d.ts.map +1 -0
  8. package/dist/ai/client.js +281 -0
  9. package/dist/ai/client.js.map +1 -0
  10. package/dist/ai/element-search.d.ts +12 -0
  11. package/dist/ai/element-search.d.ts.map +1 -0
  12. package/dist/ai/element-search.js +387 -0
  13. package/dist/ai/element-search.js.map +1 -0
  14. package/dist/ai/prompts.d.ts +27 -0
  15. package/dist/ai/prompts.d.ts.map +1 -0
  16. package/dist/ai/prompts.js +153 -0
  17. package/dist/ai/prompts.js.map +1 -0
  18. package/dist/drivers/android/adb.d.ts +21 -0
  19. package/dist/drivers/android/adb.d.ts.map +1 -0
  20. package/dist/drivers/android/adb.js +122 -0
  21. package/dist/drivers/android/adb.js.map +1 -0
  22. package/dist/drivers/android/index.d.ts +70 -0
  23. package/dist/drivers/android/index.d.ts.map +1 -0
  24. package/dist/drivers/android/index.js +529 -0
  25. package/dist/drivers/android/index.js.map +1 -0
  26. package/dist/index.d.ts +3 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +131 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/server.d.ts +13 -0
  31. package/dist/server.d.ts.map +1 -0
  32. package/dist/server.js +41 -0
  33. package/dist/server.js.map +1 -0
  34. package/dist/tools/ai-tools.d.ts +11 -0
  35. package/dist/tools/ai-tools.d.ts.map +1 -0
  36. package/dist/tools/ai-tools.js +238 -0
  37. package/dist/tools/ai-tools.js.map +1 -0
  38. package/dist/tools/app-tools.d.ts +4 -0
  39. package/dist/tools/app-tools.d.ts.map +1 -0
  40. package/dist/tools/app-tools.js +222 -0
  41. package/dist/tools/app-tools.js.map +1 -0
  42. package/dist/tools/device-tools.d.ts +4 -0
  43. package/dist/tools/device-tools.d.ts.map +1 -0
  44. package/dist/tools/device-tools.js +104 -0
  45. package/dist/tools/device-tools.js.map +1 -0
  46. package/dist/tools/index.d.ts +21 -0
  47. package/dist/tools/index.d.ts.map +1 -0
  48. package/dist/tools/index.js +30 -0
  49. package/dist/tools/index.js.map +1 -0
  50. package/dist/tools/interaction-tools.d.ts +4 -0
  51. package/dist/tools/interaction-tools.d.ts.map +1 -0
  52. package/dist/tools/interaction-tools.js +304 -0
  53. package/dist/tools/interaction-tools.js.map +1 -0
  54. package/dist/tools/log-tools.d.ts +4 -0
  55. package/dist/tools/log-tools.d.ts.map +1 -0
  56. package/dist/tools/log-tools.js +60 -0
  57. package/dist/tools/log-tools.js.map +1 -0
  58. package/dist/tools/screen-tools.d.ts +4 -0
  59. package/dist/tools/screen-tools.d.ts.map +1 -0
  60. package/dist/tools/screen-tools.js +105 -0
  61. package/dist/tools/screen-tools.js.map +1 -0
  62. package/dist/types.d.ts +219 -0
  63. package/dist/types.d.ts.map +1 -0
  64. package/dist/types.js +19 -0
  65. package/dist/types.js.map +1 -0
  66. package/dist/utils/discovery.d.ts +20 -0
  67. package/dist/utils/discovery.d.ts.map +1 -0
  68. package/dist/utils/discovery.js +156 -0
  69. package/dist/utils/discovery.js.map +1 -0
  70. package/dist/utils/image.d.ts +46 -0
  71. package/dist/utils/image.d.ts.map +1 -0
  72. package/dist/utils/image.js +170 -0
  73. package/dist/utils/image.js.map +1 -0
  74. package/package.json +69 -0
package/dist/index.js ADDED
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env node
2
+ // ============================================================
3
+ // CLI entry point for mobile-device-mcp
4
+ //
5
+ // All user-facing output goes to stderr.
6
+ // stdout is reserved for the MCP JSON-RPC protocol.
7
+ // ============================================================
8
+ import { createServer } from "./server.js";
9
+ import { findAdbPath, getDefaultDevice } from "./utils/discovery.js";
10
+ import { DEFAULT_CONFIG, DEFAULT_AI_CONFIG } from "./types.js";
11
+ const PREFIX = "[mobile-device-mcp]";
12
+ /** Write a message to stderr (never stdout). */
13
+ function log(message) {
14
+ process.stderr.write(`${PREFIX} ${message}\n`);
15
+ }
16
+ /** Parse an env var as a positive integer, or return undefined. */
17
+ function envInt(name) {
18
+ const raw = process.env[name];
19
+ if (raw === undefined || raw === "")
20
+ return undefined;
21
+ const n = parseInt(raw, 10);
22
+ return Number.isFinite(n) && n > 0 ? n : undefined;
23
+ }
24
+ async function main() {
25
+ log("Starting...");
26
+ // 1. Discover ADB
27
+ let adbPath;
28
+ const envAdbPath = process.env["MCP_ADB_PATH"];
29
+ if (envAdbPath) {
30
+ adbPath = envAdbPath;
31
+ log(`Using ADB from MCP_ADB_PATH: ${adbPath}`);
32
+ }
33
+ else {
34
+ adbPath = await findAdbPath();
35
+ log(`Found ADB: ${adbPath}`);
36
+ }
37
+ // 2. Discover default device
38
+ let defaultDevice = process.env["MCP_DEFAULT_DEVICE"];
39
+ if (!defaultDevice) {
40
+ defaultDevice = await getDefaultDevice(adbPath);
41
+ }
42
+ if (defaultDevice) {
43
+ log(`Default device: ${defaultDevice}`);
44
+ }
45
+ // 3. Build config from defaults + env overrides
46
+ const screenshotFormat = process.env["MCP_SCREENSHOT_FORMAT"];
47
+ const config = {
48
+ adbPath,
49
+ defaultDevice,
50
+ screenshotFormat: screenshotFormat === "jpeg" || screenshotFormat === "png"
51
+ ? screenshotFormat
52
+ : DEFAULT_CONFIG.screenshotFormat,
53
+ screenshotQuality: envInt("MCP_SCREENSHOT_QUALITY") ?? DEFAULT_CONFIG.screenshotQuality,
54
+ screenshotMaxWidth: envInt("MCP_SCREENSHOT_MAX_WIDTH") ?? DEFAULT_CONFIG.screenshotMaxWidth,
55
+ };
56
+ // 3b. AI configuration — supports Anthropic and Google Gemini
57
+ const anthropicKey = process.env.ANTHROPIC_API_KEY || "";
58
+ const googleKey = process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY || "";
59
+ const apiKey = anthropicKey || googleKey || process.env.MCP_AI_API_KEY || "";
60
+ if (apiKey) {
61
+ // Auto-detect provider from which key is set; env var can override.
62
+ const envProvider = process.env.MCP_AI_PROVIDER;
63
+ let provider;
64
+ if (envProvider === "anthropic" || envProvider === "google") {
65
+ provider = envProvider;
66
+ }
67
+ else if (googleKey && !anthropicKey) {
68
+ provider = "google";
69
+ }
70
+ else {
71
+ provider = "anthropic";
72
+ }
73
+ // Default model depends on provider.
74
+ const defaultModel = provider === "google" ? "gemini-2.5-flash" : "claude-sonnet-4-20250514";
75
+ config.ai = {
76
+ provider,
77
+ apiKey,
78
+ model: process.env.MCP_AI_MODEL || defaultModel,
79
+ maxTokens: parseInt(process.env.MCP_AI_MAX_TOKENS || String(DEFAULT_AI_CONFIG.maxTokens)),
80
+ analyzeWithScreenshot: process.env.MCP_AI_SCREENSHOT !== "false",
81
+ analyzeWithUITree: process.env.MCP_AI_UITREE !== "false",
82
+ };
83
+ log(`AI features enabled (provider: ${provider}, model: ${config.ai.model})`);
84
+ }
85
+ else {
86
+ log("AI features disabled (set ANTHROPIC_API_KEY or GOOGLE_API_KEY to enable)");
87
+ }
88
+ // 4. Create and start the server
89
+ const { start } = createServer(config);
90
+ await start();
91
+ log("Server running on stdio");
92
+ }
93
+ // ------------------------------------------------------------------
94
+ // Graceful shutdown
95
+ // ------------------------------------------------------------------
96
+ function shutdown(signal) {
97
+ log(`Received ${signal}, shutting down...`);
98
+ process.exit(0);
99
+ }
100
+ process.on("SIGINT", () => shutdown("SIGINT"));
101
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
102
+ // ------------------------------------------------------------------
103
+ // Error handling
104
+ // ------------------------------------------------------------------
105
+ process.on("uncaughtException", (error) => {
106
+ log(`Fatal error: ${error.message}`);
107
+ if (error.stack) {
108
+ process.stderr.write(`${error.stack}\n`);
109
+ }
110
+ process.exit(1);
111
+ });
112
+ process.on("unhandledRejection", (reason) => {
113
+ const message = reason instanceof Error ? reason.message : String(reason);
114
+ log(`Unhandled rejection: ${message}`);
115
+ if (reason instanceof Error && reason.stack) {
116
+ process.stderr.write(`${reason.stack}\n`);
117
+ }
118
+ process.exit(1);
119
+ });
120
+ // ------------------------------------------------------------------
121
+ // Run
122
+ // ------------------------------------------------------------------
123
+ main().catch((error) => {
124
+ const message = error instanceof Error ? error.message : String(error);
125
+ log(`Failed to start: ${message}`);
126
+ if (error instanceof Error && error.stack) {
127
+ process.stderr.write(`${error.stack}\n`);
128
+ }
129
+ process.exit(1);
130
+ });
131
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ServerConfig } from "./types.js";
3
+ /**
4
+ * Create a configured MCP server ready to start.
5
+ *
6
+ * Returns the server instance and a `start()` function that connects
7
+ * a stdio transport (the MCP JSON-RPC channel).
8
+ */
9
+ export declare function createServer(config: ServerConfig): {
10
+ server: McpServer;
11
+ start: () => Promise<void>;
12
+ };
13
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAS/C;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG;IAClD,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CA2BA"}
package/dist/server.js ADDED
@@ -0,0 +1,41 @@
1
+ // ============================================================
2
+ // MCP Server factory — creates and wires up the server
3
+ // ============================================================
4
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import { AndroidDriver } from "./drivers/android/index.js";
7
+ import { registerAllTools } from "./tools/index.js";
8
+ import { AIClient } from "./ai/client.js";
9
+ import { ScreenAnalyzer } from "./ai/analyzer.js";
10
+ /** Server version — matches package.json */
11
+ const SERVER_VERSION = "0.1.0";
12
+ /**
13
+ * Create a configured MCP server ready to start.
14
+ *
15
+ * Returns the server instance and a `start()` function that connects
16
+ * a stdio transport (the MCP JSON-RPC channel).
17
+ */
18
+ export function createServer(config) {
19
+ const server = new McpServer({
20
+ name: "mobile-device-mcp",
21
+ version: SERVER_VERSION,
22
+ });
23
+ const driver = new AndroidDriver(config.adbPath);
24
+ // Set up AI features if configured
25
+ let analyzer = null;
26
+ if (config.ai && config.ai.apiKey) {
27
+ const aiClient = new AIClient(config.ai);
28
+ analyzer = new ScreenAnalyzer(aiClient, driver, config.ai, {
29
+ format: config.screenshotFormat,
30
+ quality: config.screenshotQuality,
31
+ maxWidth: config.screenshotMaxWidth,
32
+ });
33
+ }
34
+ registerAllTools(server, () => driver, () => analyzer);
35
+ async function start() {
36
+ const transport = new StdioServerTransport();
37
+ await server.connect(transport);
38
+ }
39
+ return { server, start };
40
+ }
41
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,uDAAuD;AACvD,+DAA+D;AAE/D,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,4CAA4C;AAC5C,MAAM,cAAc,GAAG,OAAO,CAAC;AAE/B;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,MAAoB;IAI/C,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,mBAAmB;QACzB,OAAO,EAAE,cAAc;KACxB,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEjD,mCAAmC;IACnC,IAAI,QAAQ,GAA0B,IAAI,CAAC;IAC3C,IAAI,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACzC,QAAQ,GAAG,IAAI,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE;YACzD,MAAM,EAAE,MAAM,CAAC,gBAAgB;YAC/B,OAAO,EAAE,MAAM,CAAC,iBAAiB;YACjC,QAAQ,EAAE,MAAM,CAAC,kBAAkB;SACpC,CAAC,CAAC;IACL,CAAC;IAED,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;IAEvD,KAAK,UAAU,KAAK;QAClB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ScreenAnalyzer } from "../ai/analyzer.js";
3
+ /**
4
+ * Register AI-powered MCP tools on the given server.
5
+ *
6
+ * @param server — The McpServer instance to register tools on.
7
+ * @param getAnalyzer — Returns the active ScreenAnalyzer, or null if AI
8
+ * features are not configured (missing API key).
9
+ */
10
+ export declare function registerAITools(server: McpServer, getAnalyzer: () => ScreenAnalyzer | null): void;
11
+ //# sourceMappingURL=ai-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-tools.d.ts","sourceRoot":"","sources":["../../src/tools/ai-tools.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAyCxD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,cAAc,GAAG,IAAI,GACvC,IAAI,CAsPN"}
@@ -0,0 +1,238 @@
1
+ // ============================================================
2
+ // AI-powered tools — visual analysis, smart interactions,
3
+ // element finding, and screen verification via Claude vision.
4
+ // ============================================================
5
+ import { z } from "zod";
6
+ /** Standard error payload when AI features are unavailable. */
7
+ const AI_UNAVAILABLE = {
8
+ content: [
9
+ {
10
+ type: "text",
11
+ text: "AI features are not available. Set ANTHROPIC_API_KEY environment variable to enable AI-powered tools.",
12
+ },
13
+ ],
14
+ isError: true,
15
+ };
16
+ /**
17
+ * Format a value as a JSON text MCP response with 2-space indentation.
18
+ */
19
+ function jsonResponse(value) {
20
+ return {
21
+ content: [
22
+ {
23
+ type: "text",
24
+ text: JSON.stringify(value, null, 2),
25
+ },
26
+ ],
27
+ };
28
+ }
29
+ /**
30
+ * Format an error as a text MCP response.
31
+ */
32
+ function errorResponse(label, error) {
33
+ return {
34
+ content: [
35
+ {
36
+ type: "text",
37
+ text: `Error in ${label}: ${error instanceof Error ? error.message : String(error)}`,
38
+ },
39
+ ],
40
+ };
41
+ }
42
+ /**
43
+ * Register AI-powered MCP tools on the given server.
44
+ *
45
+ * @param server — The McpServer instance to register tools on.
46
+ * @param getAnalyzer — Returns the active ScreenAnalyzer, or null if AI
47
+ * features are not configured (missing API key).
48
+ */
49
+ export function registerAITools(server, getAnalyzer) {
50
+ // ----------------------------------------------------------
51
+ // analyze_screen
52
+ // ----------------------------------------------------------
53
+ server.registerTool("analyze_screen", {
54
+ title: "Analyze Screen (AI)",
55
+ description: "Uses AI vision to analyze the current screen of a mobile device. Returns a structured analysis including app name, screen type, interactive elements with coordinates, visible text, and suggested next actions. This is the primary tool for understanding what is currently displayed on the device.",
56
+ inputSchema: z.object({
57
+ device_id: z.string().describe("Device serial ID"),
58
+ }),
59
+ }, async ({ device_id }) => {
60
+ try {
61
+ const analyzer = getAnalyzer();
62
+ if (!analyzer)
63
+ return AI_UNAVAILABLE;
64
+ const analysis = await analyzer.analyzeScreen(device_id);
65
+ return jsonResponse(analysis);
66
+ }
67
+ catch (error) {
68
+ return errorResponse("analyze_screen", error);
69
+ }
70
+ });
71
+ // ----------------------------------------------------------
72
+ // find_element
73
+ // ----------------------------------------------------------
74
+ server.registerTool("find_element", {
75
+ title: "Find Element by Description (AI)",
76
+ description: "Uses AI vision to find a specific UI element by natural language description. Returns the element's coordinates, type, and confidence score. Use this when you need to locate a specific button, field, or other UI element. Example queries: 'the login button', 'email input field', 'the red error message'.",
77
+ inputSchema: z.object({
78
+ device_id: z.string().describe("Device serial ID"),
79
+ query: z
80
+ .string()
81
+ .describe("Natural language description of the element to find, e.g. 'the blue Submit button' or 'email input field'"),
82
+ }),
83
+ }, async ({ device_id, query }) => {
84
+ try {
85
+ const analyzer = getAnalyzer();
86
+ if (!analyzer)
87
+ return AI_UNAVAILABLE;
88
+ const match = await analyzer.findElement(device_id, query);
89
+ return jsonResponse(match);
90
+ }
91
+ catch (error) {
92
+ return errorResponse("find_element", error);
93
+ }
94
+ });
95
+ // ----------------------------------------------------------
96
+ // suggest_actions
97
+ // ----------------------------------------------------------
98
+ server.registerTool("suggest_actions", {
99
+ title: "Suggest Actions for Goal (AI)",
100
+ description: "Uses AI to analyze the current screen and suggest a sequence of actions to achieve a specified goal. Returns step-by-step instructions with exact coordinates for each action. Example goals: 'log into the app', 'navigate to settings', 'add an item to cart'.",
101
+ inputSchema: z.object({
102
+ device_id: z.string().describe("Device serial ID"),
103
+ goal: z
104
+ .string()
105
+ .describe("What you want to accomplish, e.g. 'log into the app' or 'navigate to settings'"),
106
+ }),
107
+ }, async ({ device_id, goal }) => {
108
+ try {
109
+ const analyzer = getAnalyzer();
110
+ if (!analyzer)
111
+ return AI_UNAVAILABLE;
112
+ const plan = await analyzer.suggestActions(device_id, goal);
113
+ return jsonResponse(plan);
114
+ }
115
+ catch (error) {
116
+ return errorResponse("suggest_actions", error);
117
+ }
118
+ });
119
+ // ----------------------------------------------------------
120
+ // visual_diff
121
+ // ----------------------------------------------------------
122
+ server.registerTool("visual_diff", {
123
+ title: "Visual Diff (AI)",
124
+ description: "Compares the current screen with a previous screenshot to identify what changed. Provide a base64 PNG screenshot as the 'before' image — the tool captures the current screen as the 'after' image. Returns a list of changes with descriptions and regions. Useful for verifying that an action had the expected effect.",
125
+ inputSchema: z.object({
126
+ device_id: z.string().describe("Device serial ID"),
127
+ before_screenshot: z
128
+ .string()
129
+ .describe("Base64-encoded PNG of the previous screen state to compare against"),
130
+ }),
131
+ }, async ({ device_id, before_screenshot }) => {
132
+ try {
133
+ const analyzer = getAnalyzer();
134
+ if (!analyzer)
135
+ return AI_UNAVAILABLE;
136
+ const diff = await analyzer.compareScreenshots(device_id, before_screenshot);
137
+ return jsonResponse(diff);
138
+ }
139
+ catch (error) {
140
+ return errorResponse("visual_diff", error);
141
+ }
142
+ });
143
+ // ----------------------------------------------------------
144
+ // smart_tap
145
+ // ----------------------------------------------------------
146
+ server.registerTool("smart_tap", {
147
+ title: "Smart Tap (AI)",
148
+ description: "Finds a UI element by natural language description and taps it. Combines element finding and tapping into a single action. Example: smart_tap('the Sign In button') will locate the button and tap its center coordinates. Returns whether the tap succeeded and which element was tapped.",
149
+ inputSchema: z.object({
150
+ device_id: z.string().describe("Device serial ID"),
151
+ element_description: z
152
+ .string()
153
+ .describe("Description of the element to tap, e.g. 'the Submit button' or 'the settings icon'"),
154
+ }),
155
+ }, async ({ device_id, element_description }) => {
156
+ try {
157
+ const analyzer = getAnalyzer();
158
+ if (!analyzer)
159
+ return AI_UNAVAILABLE;
160
+ const result = await analyzer.smartTap(device_id, element_description);
161
+ return jsonResponse(result);
162
+ }
163
+ catch (error) {
164
+ return errorResponse("smart_tap", error);
165
+ }
166
+ });
167
+ // ----------------------------------------------------------
168
+ // smart_type
169
+ // ----------------------------------------------------------
170
+ server.registerTool("smart_type", {
171
+ title: "Smart Type (AI)",
172
+ description: "Finds an input field by natural language description, taps it to focus, and types the specified text. Example: smart_type('email field', 'user@example.com') will find the email input, tap it, and type the email address.",
173
+ inputSchema: z.object({
174
+ device_id: z.string().describe("Device serial ID"),
175
+ field_description: z
176
+ .string()
177
+ .describe("Description of the input field, e.g. 'email field' or 'search bar'"),
178
+ text: z.string().describe("Text to type into the field"),
179
+ }),
180
+ }, async ({ device_id, field_description, text }) => {
181
+ try {
182
+ const analyzer = getAnalyzer();
183
+ if (!analyzer)
184
+ return AI_UNAVAILABLE;
185
+ const result = await analyzer.smartType(device_id, field_description, text);
186
+ return jsonResponse(result);
187
+ }
188
+ catch (error) {
189
+ return errorResponse("smart_type", error);
190
+ }
191
+ });
192
+ // ----------------------------------------------------------
193
+ // extract_text
194
+ // ----------------------------------------------------------
195
+ server.registerTool("extract_text", {
196
+ title: "Extract Text from Screen (AI)",
197
+ description: "Uses AI vision to extract all visible text from the current screen. Returns text in reading order (top to bottom, left to right). Useful for reading content, checking labels, or getting text that isn't in the accessibility tree.",
198
+ inputSchema: z.object({
199
+ device_id: z.string().describe("Device serial ID"),
200
+ }),
201
+ }, async ({ device_id }) => {
202
+ try {
203
+ const analyzer = getAnalyzer();
204
+ if (!analyzer)
205
+ return AI_UNAVAILABLE;
206
+ const texts = await analyzer.extractText(device_id);
207
+ return jsonResponse({ texts });
208
+ }
209
+ catch (error) {
210
+ return errorResponse("extract_text", error);
211
+ }
212
+ });
213
+ // ----------------------------------------------------------
214
+ // verify_screen
215
+ // ----------------------------------------------------------
216
+ server.registerTool("verify_screen", {
217
+ title: "Verify Screen State (AI)",
218
+ description: "Uses AI to verify whether a specific assertion about the current screen is true. Returns a boolean result with confidence score and evidence. Example assertions: 'the login was successful', 'an error message is displayed', 'the cart has 3 items'.",
219
+ inputSchema: z.object({
220
+ device_id: z.string().describe("Device serial ID"),
221
+ assertion: z
222
+ .string()
223
+ .describe("What to verify about the current screen state, e.g. 'the login was successful' or 'an error message is showing'"),
224
+ }),
225
+ }, async ({ device_id, assertion }) => {
226
+ try {
227
+ const analyzer = getAnalyzer();
228
+ if (!analyzer)
229
+ return AI_UNAVAILABLE;
230
+ const verification = await analyzer.verifyScreen(device_id, assertion);
231
+ return jsonResponse(verification);
232
+ }
233
+ catch (error) {
234
+ return errorResponse("verify_screen", error);
235
+ }
236
+ });
237
+ }
238
+ //# sourceMappingURL=ai-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-tools.js","sourceRoot":"","sources":["../../src/tools/ai-tools.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,0DAA0D;AAC1D,8DAA8D;AAC9D,+DAA+D;AAG/D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,+DAA+D;AAC/D,MAAM,cAAc,GAAG;IACrB,OAAO,EAAE;QACP;YACE,IAAI,EAAE,MAAe;YACrB,IAAI,EAAE,uGAAuG;SAC9G;KACF;IACD,OAAO,EAAE,IAAI;CACd,CAAC;AAEF;;GAEG;AACH,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;aACrC;SACF;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,KAAa,EAAE,KAAc;IAClD,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,YAAY,KAAK,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;aACrF;SACF;KACF,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAiB,EACjB,WAAwC;IAExC,6DAA6D;IAC7D,iBAAiB;IACjB,6DAA6D;IAC7D,MAAM,CAAC,YAAY,CACjB,gBAAgB,EAChB;QACE,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EACT,wSAAwS;QAC1S,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;SACnD,CAAC;KACH,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE;QACtB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ;gBAAE,OAAO,cAAc,CAAC;YAErC,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;YACzD,OAAO,YAAY,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;QAChD,CAAC;IACH,CAAC,CACF,CAAC;IAEF,6DAA6D;IAC7D,eAAe;IACf,6DAA6D;IAC7D,MAAM,CAAC,YAAY,CACjB,cAAc,EACd;QACE,KAAK,EAAE,kCAAkC;QACzC,WAAW,EACT,iTAAiT;QACnT,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;YAClD,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,CACP,2GAA2G,CAC5G;SACJ,CAAC;KACH,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ;gBAAE,OAAO,cAAc,CAAC;YAErC,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAC3D,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC,CACF,CAAC;IAEF,6DAA6D;IAC7D,kBAAkB;IAClB,6DAA6D;IAC7D,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,KAAK,EAAE,+BAA+B;QACtC,WAAW,EACT,kQAAkQ;QACpQ,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;YAClD,IAAI,EAAE,CAAC;iBACJ,MAAM,EAAE;iBACR,QAAQ,CACP,gFAAgF,CACjF;SACJ,CAAC;KACH,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE;QAC5B,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ;gBAAE,OAAO,cAAc,CAAC;YAErC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YAC5D,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;QACjD,CAAC;IACH,CAAC,CACF,CAAC;IAEF,6DAA6D;IAC7D,cAAc;IACd,6DAA6D;IAC7D,MAAM,CAAC,YAAY,CACjB,aAAa,EACb;QACE,KAAK,EAAE,kBAAkB;QACzB,WAAW,EACT,2TAA2T;QAC7T,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;YAClD,iBAAiB,EAAE,CAAC;iBACjB,MAAM,EAAE;iBACR,QAAQ,CACP,oEAAoE,CACrE;SACJ,CAAC;KACH,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,EAAE,EAAE;QACzC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ;gBAAE,OAAO,cAAc,CAAC;YAErC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,kBAAkB,CAC5C,SAAS,EACT,iBAAiB,CAClB,CAAC;YACF,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC,CACF,CAAC;IAEF,6DAA6D;IAC7D,YAAY;IACZ,6DAA6D;IAC7D,MAAM,CAAC,YAAY,CACjB,WAAW,EACX;QACE,KAAK,EAAE,gBAAgB;QACvB,WAAW,EACT,4RAA4R;QAC9R,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;YAClD,mBAAmB,EAAE,CAAC;iBACnB,MAAM,EAAE;iBACR,QAAQ,CACP,oFAAoF,CACrF;SACJ,CAAC;KACH,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,mBAAmB,EAAE,EAAE,EAAE;QAC3C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ;gBAAE,OAAO,cAAc,CAAC;YAErC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;YACvE,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC,CACF,CAAC;IAEF,6DAA6D;IAC7D,aAAa;IACb,6DAA6D;IAC7D,MAAM,CAAC,YAAY,CACjB,YAAY,EACZ;QACE,KAAK,EAAE,iBAAiB;QACxB,WAAW,EACT,6NAA6N;QAC/N,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;YAClD,iBAAiB,EAAE,CAAC;iBACjB,MAAM,EAAE;iBACR,QAAQ,CACP,oEAAoE,CACrE;YACH,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;SACzD,CAAC;KACH,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,IAAI,EAAE,EAAE,EAAE;QAC/C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ;gBAAE,OAAO,cAAc,CAAC;YAErC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,SAAS,CACrC,SAAS,EACT,iBAAiB,EACjB,IAAI,CACL,CAAC;YACF,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC,CACF,CAAC;IAEF,6DAA6D;IAC7D,eAAe;IACf,6DAA6D;IAC7D,MAAM,CAAC,YAAY,CACjB,cAAc,EACd;QACE,KAAK,EAAE,+BAA+B;QACtC,WAAW,EACT,sOAAsO;QACxO,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;SACnD,CAAC;KACH,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE;QACtB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ;gBAAE,OAAO,cAAc,CAAC;YAErC,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;YACpD,OAAO,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC,CACF,CAAC;IAEF,6DAA6D;IAC7D,gBAAgB;IAChB,6DAA6D;IAC7D,MAAM,CAAC,YAAY,CACjB,eAAe,EACf;QACE,KAAK,EAAE,0BAA0B;QACjC,WAAW,EACT,wPAAwP;QAC1P,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;YAClD,SAAS,EAAE,CAAC;iBACT,MAAM,EAAE;iBACR,QAAQ,CACP,iHAAiH,CAClH;SACJ,CAAC;KACH,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE;QACjC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ;gBAAE,OAAO,cAAc,CAAC;YAErC,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YACvE,OAAO,YAAY,CAAC,YAAY,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { DeviceDriver } from "../types.js";
3
+ export declare function registerAppTools(server: McpServer, getDriver: () => DeviceDriver): void;
4
+ //# sourceMappingURL=app-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-tools.d.ts","sourceRoot":"","sources":["../../src/tools/app-tools.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,YAAY,GAC5B,IAAI,CAqQN"}