appium-mcp 1.72.14 → 1.72.16
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/CHANGELOG.md +12 -0
- package/dist/tools/ai/handlers/find-element.d.ts.map +1 -1
- package/dist/tools/ai/handlers/find-element.js +5 -6
- package/dist/tools/ai/handlers/find-element.js.map +1 -1
- package/dist/tools/ai/schema.d.ts.map +1 -1
- package/dist/tools/ai/schema.js +14 -1
- package/dist/tools/ai/schema.js.map +1 -1
- package/dist/tools/app-management/app.d.ts.map +1 -1
- package/dist/tools/app-management/app.js +23 -4
- package/dist/tools/app-management/app.js.map +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/src/resources/submodules.zip +0 -0
- package/src/tools/ai/handlers/find-element.ts +6 -10
- package/src/tools/ai/schema.ts +35 -21
- package/src/tools/app-management/app.ts +23 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## [1.72.16](https://github.com/appium/appium-mcp/compare/v1.72.15...v1.72.16) (2026-05-14)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
* **ai:** enforce find_element instruction via Zod schema ([#329](https://github.com/appium/appium-mcp/issues/329)) ([a3bfe83](https://github.com/appium/appium-mcp/commit/a3bfe83576c6be9ec1ffa9371ab67b44cc86cc80))
|
|
6
|
+
|
|
7
|
+
## [1.72.15](https://github.com/appium/appium-mcp/compare/v1.72.14...v1.72.15) (2026-05-14)
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **app-management:** surface resolve by name failures in app lifecycle ([#332](https://github.com/appium/appium-mcp/issues/332)) ([85fe2b9](https://github.com/appium/appium-mcp/commit/85fe2b9de2e42165786813332146fc0c77bbe362))
|
|
12
|
+
|
|
1
13
|
## [1.72.14](https://github.com/appium/appium-mcp/compare/v1.72.13...v1.72.14) (2026-05-09)
|
|
2
14
|
|
|
3
15
|
### Miscellaneous Chores
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find-element.d.ts","sourceRoot":"","sources":["../../../../src/tools/ai/handlers/find-element.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAShE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"find-element.d.ts","sourceRoot":"","sources":["../../../../src/tools/ai/handlers/find-element.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAShE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAM3C,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,aAAa,CAAC,CA0CxB"}
|
|
@@ -7,12 +7,11 @@ import { errorResult, textResultWithPrimaryElementId, toolErrorMessage, } from '
|
|
|
7
7
|
// Creating a new AIVisionFinder() on every call would reset the cache each time.
|
|
8
8
|
let _finderInstance = null;
|
|
9
9
|
export async function handleFindElement(driver, args) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
10
|
+
// `instruction` presence/non-emptiness is enforced at schema level via
|
|
11
|
+
// `aiSchema.superRefine`. Narrow the optional type here for downstream calls.
|
|
12
|
+
const instruction = args.instruction;
|
|
14
13
|
try {
|
|
15
|
-
log.info(`Finding element using AI with instruction: "${
|
|
14
|
+
log.info(`Finding element using AI with instruction: "${instruction}"`);
|
|
16
15
|
const screenshotBase64 = await getScreenshot(driver);
|
|
17
16
|
const imageBuffer = Buffer.from(screenshotBase64, 'base64');
|
|
18
17
|
const sharp = imageUtil.requireSharp();
|
|
@@ -22,7 +21,7 @@ export async function handleFindElement(driver, args) {
|
|
|
22
21
|
}
|
|
23
22
|
const { width, height } = metadata;
|
|
24
23
|
const finder = getAIVisionFinder();
|
|
25
|
-
const result = await finder.findElement(screenshotBase64,
|
|
24
|
+
const result = await finder.findElement(screenshotBase64, instruction, width, height);
|
|
26
25
|
// Format: "ai-element:{x},{y}:{bbox}" — consumed by appium_gesture handlers.
|
|
27
26
|
const elementUUID = `ai-element:${result.center.x},${result.center.y}:${result.bbox.join(',')}`;
|
|
28
27
|
let detail = `Successfully found "${result.target}" at coordinates (${result.center.x}, ${result.center.y}) using AI vision.`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find-element.js","sourceRoot":"","sources":["../../../../src/tools/ai/handlers/find-element.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,GAAG,MAAM,oBAAoB,CAAC;AACrC,OAAO,EACL,WAAW,EACX,8BAA8B,EAC9B,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAGhC,4EAA4E;AAC5E,iFAAiF;AACjF,IAAI,eAAe,GAA0B,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"find-element.js","sourceRoot":"","sources":["../../../../src/tools/ai/handlers/find-element.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,GAAG,MAAM,oBAAoB,CAAC;AACrC,OAAO,EACL,WAAW,EACX,8BAA8B,EAC9B,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAGhC,4EAA4E;AAC5E,iFAAiF;AACjF,IAAI,eAAe,GAA0B,IAAI,CAAC;AAElD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAsB,EACtB,IAAY;IAEZ,uEAAuE;IACvE,8EAA8E;IAC9E,MAAM,WAAW,GAAG,IAAI,CAAC,WAAqB,CAAC;IAE/C,IAAI,CAAC;QACH,GAAG,CAAC,IAAI,CAAC,+CAA+C,WAAW,GAAG,CAAC,CAAC;QAExE,MAAM,gBAAgB,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC;QAErD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;QAC5D,MAAM,KAAK,GAAG,SAAS,CAAC,YAAY,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,CAAC;QAErD,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC;QAEnC,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CACrC,gBAAgB,EAChB,WAAW,EACX,KAAK,EACL,MAAM,CACP,CAAC;QAEF,6EAA6E;QAC7E,MAAM,WAAW,GAAG,cAAc,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAEhG,IAAI,MAAM,GAAG,uBAAuB,MAAM,CAAC,MAAM,qBAAqB,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,oBAAoB,CAAC;QAC9H,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;YAC9B,MAAM,IAAI,kBAAkB,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC1D,CAAC;QAED,OAAO,8BAA8B,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAC7D,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,YAAY,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;QAC3C,GAAG,CAAC,KAAK,CAAC,yBAAyB,EAAE,YAAY,CAAC,CAAC;QACnD,OAAO,WAAW,CAAC,kCAAkC,YAAY,EAAE,CAAC,CAAC;IACvE,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB;IACxB,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,eAAe,GAAG,IAAI,cAAc,EAAE,CAAC;IACzC,CAAC;IACD,OAAO,eAAe,CAAC;AACzB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/tools/ai/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,UAAU,2BAA4B,CAAC;AACpD,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,eAAO,MAAM,QAAQ;;;;;;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/tools/ai/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,UAAU,2BAA4B,CAAC;AACpD,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,eAAO,MAAM,QAAQ;;;;;;iBAoCjB,CAAC;AAEL,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAC"}
|
package/dist/tools/ai/schema.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export const AI_ACTIONS = ['find_element'];
|
|
3
|
-
export const aiSchema = z
|
|
3
|
+
export const aiSchema = z
|
|
4
|
+
.object({
|
|
4
5
|
action: z
|
|
5
6
|
.enum(AI_ACTIONS)
|
|
6
7
|
.describe(`AI capability to invoke. ` +
|
|
@@ -16,5 +17,17 @@ export const aiSchema = z.object({
|
|
|
16
17
|
.string()
|
|
17
18
|
.optional()
|
|
18
19
|
.describe('Session ID to target. If omitted, uses the active session.'),
|
|
20
|
+
})
|
|
21
|
+
.superRefine((data, ctx) => {
|
|
22
|
+
if (data.action === 'find_element') {
|
|
23
|
+
if (!data.instruction?.trim()) {
|
|
24
|
+
ctx.addIssue({
|
|
25
|
+
code: z.ZodIssueCode.custom,
|
|
26
|
+
message: 'instruction is required and must be non-empty when action is find_element. ' +
|
|
27
|
+
'Example: { "action": "find_element", "instruction": "yellow search button at bottom" }',
|
|
28
|
+
path: ['instruction'],
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
19
32
|
});
|
|
20
33
|
//# sourceMappingURL=schema.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/tools/ai/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,cAAc,CAAU,CAAC;AAGpD,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/tools/ai/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,cAAc,CAAU,CAAC;AAGpD,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC;KACtB,MAAM,CAAC;IACN,MAAM,EAAE,CAAC;SACN,IAAI,CAAC,UAAU,CAAC;SAChB,QAAQ,CACP,2BAA2B;QACzB,4FAA4F;QAC5F,iHAAiH,CACpH;IAEH,WAAW,EAAE,CAAC;SACX,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,sDAAsD;QACpD,8BAA8B;QAC9B,iHAAiH,CACpH;IAEH,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,4DAA4D,CAAC;CAC1E,CAAC;KACD,WAAW,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IACzB,IAAI,IAAI,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC;YAC9B,GAAG,CAAC,QAAQ,CAAC;gBACX,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;gBAC3B,OAAO,EACL,6EAA6E;oBAC7E,wFAAwF;gBAC1F,IAAI,EAAE,CAAC,aAAa,CAAC;aACtB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../../src/tools/app-management/app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AAetD,QAAA,MAAM,WAAW,uIAWP,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAwErD,MAAM,CAAC,OAAO,UAAU,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../../src/tools/app-management/app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,OAAO,EAAE,MAAM,SAAS,CAAC;AAetD,QAAA,MAAM,WAAW,uIAWP,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAwErD,MAAM,CAAC,OAAO,UAAU,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAmFjD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { errorResult } from '../tool-response.js';
|
|
1
|
+
import { errorResult, toolErrorMessage } from '../tool-response.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { resolveAppId, resolveId } from './resolve-app-id.js';
|
|
4
4
|
import { activate } from './activate-app.js';
|
|
@@ -103,12 +103,31 @@ export default function app(server) {
|
|
|
103
103
|
if (!args.url) {
|
|
104
104
|
return errorResult('url is required for deep_link');
|
|
105
105
|
}
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
let appId;
|
|
107
|
+
if (args.id !== undefined) {
|
|
108
|
+
appId = args.id;
|
|
109
|
+
}
|
|
110
|
+
else if (args.name) {
|
|
111
|
+
try {
|
|
112
|
+
appId = await resolveAppId(args.name, sessionId);
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
return errorResult(`deep_link: failed to resolve app by name: ${toolErrorMessage(err)}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
appId = undefined;
|
|
120
|
+
}
|
|
108
121
|
return deepLink(args.url, appId, args.waitForLaunch, sessionId);
|
|
109
122
|
}
|
|
110
123
|
// activate, terminate, uninstall, is_installed, query_state, clear — all require id or name
|
|
111
|
-
|
|
124
|
+
let id;
|
|
125
|
+
try {
|
|
126
|
+
id = await resolveId(args.id, args.name, sessionId);
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
return errorResult(`${action}: failed to resolve app id: ${toolErrorMessage(err)}`);
|
|
130
|
+
}
|
|
112
131
|
if (action === 'activate') {
|
|
113
132
|
return activate(id, sessionId);
|
|
114
133
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../../src/tools/app-management/app.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../../src/tools/app-management/app.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
"name": "io.github.appium/appium-mcp",
|
|
4
4
|
"title": "MCP Appium - Mobile Development and Automation Server",
|
|
5
5
|
"description": "MCP server for Appium mobile automation on iOS and Android devices with test creation tools.",
|
|
6
|
-
"version": "1.72.
|
|
6
|
+
"version": "1.72.16",
|
|
7
7
|
"packages": [
|
|
8
8
|
{
|
|
9
9
|
"registryType": "npm",
|
|
10
10
|
"identifier": "appium-mcp",
|
|
11
|
-
"version": "1.72.
|
|
11
|
+
"version": "1.72.16",
|
|
12
12
|
"transport": {
|
|
13
13
|
"type": "stdio"
|
|
14
14
|
}
|
|
Binary file
|
|
@@ -14,21 +14,17 @@ import type { AIArgs } from '../schema.js';
|
|
|
14
14
|
// Module-level singleton: ensures the LRU cache persists across tool calls.
|
|
15
15
|
// Creating a new AIVisionFinder() on every call would reset the cache each time.
|
|
16
16
|
let _finderInstance: AIVisionFinder | null = null;
|
|
17
|
+
|
|
17
18
|
export async function handleFindElement(
|
|
18
19
|
driver: DriverInstance,
|
|
19
20
|
args: AIArgs
|
|
20
21
|
): Promise<ContentResult> {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
'Example: { action: "find_element", instruction: "yellow search button at bottom" }'
|
|
25
|
-
);
|
|
26
|
-
}
|
|
22
|
+
// `instruction` presence/non-emptiness is enforced at schema level via
|
|
23
|
+
// `aiSchema.superRefine`. Narrow the optional type here for downstream calls.
|
|
24
|
+
const instruction = args.instruction as string;
|
|
27
25
|
|
|
28
26
|
try {
|
|
29
|
-
log.info(
|
|
30
|
-
`Finding element using AI with instruction: "${args.instruction}"`
|
|
31
|
-
);
|
|
27
|
+
log.info(`Finding element using AI with instruction: "${instruction}"`);
|
|
32
28
|
|
|
33
29
|
const screenshotBase64 = await getScreenshot(driver);
|
|
34
30
|
|
|
@@ -45,7 +41,7 @@ export async function handleFindElement(
|
|
|
45
41
|
const finder = getAIVisionFinder();
|
|
46
42
|
const result = await finder.findElement(
|
|
47
43
|
screenshotBase64,
|
|
48
|
-
|
|
44
|
+
instruction,
|
|
49
45
|
width,
|
|
50
46
|
height
|
|
51
47
|
);
|
package/src/tools/ai/schema.ts
CHANGED
|
@@ -3,28 +3,42 @@ import { z } from 'zod';
|
|
|
3
3
|
export const AI_ACTIONS = ['find_element'] as const;
|
|
4
4
|
export type AIAction = (typeof AI_ACTIONS)[number];
|
|
5
5
|
|
|
6
|
-
export const aiSchema = z
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
`
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
export const aiSchema = z
|
|
7
|
+
.object({
|
|
8
|
+
action: z
|
|
9
|
+
.enum(AI_ACTIONS)
|
|
10
|
+
.describe(
|
|
11
|
+
`AI capability to invoke. ` +
|
|
12
|
+
`find_element: locate an element from a natural-language description using a vision model. ` +
|
|
13
|
+
`Returns a coordinate UUID (format: ai-element:x,y:bbox) usable with appium_gesture (tap/double_tap/long_press).`
|
|
14
|
+
),
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
instruction: z
|
|
17
|
+
.string()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe(
|
|
20
|
+
`Natural-language description of the target element. ` +
|
|
21
|
+
`Required for: find_element. ` +
|
|
22
|
+
`Examples: "yellow search button at bottom", "username input field at top", "settings icon in top-right corner".`
|
|
23
|
+
),
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
})
|
|
25
|
+
sessionId: z
|
|
26
|
+
.string()
|
|
27
|
+
.optional()
|
|
28
|
+
.describe('Session ID to target. If omitted, uses the active session.'),
|
|
29
|
+
})
|
|
30
|
+
.superRefine((data, ctx) => {
|
|
31
|
+
if (data.action === 'find_element') {
|
|
32
|
+
if (!data.instruction?.trim()) {
|
|
33
|
+
ctx.addIssue({
|
|
34
|
+
code: z.ZodIssueCode.custom,
|
|
35
|
+
message:
|
|
36
|
+
'instruction is required and must be non-empty when action is find_element. ' +
|
|
37
|
+
'Example: { "action": "find_element", "instruction": "yellow search button at bottom" }',
|
|
38
|
+
path: ['instruction'],
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
});
|
|
29
43
|
|
|
30
44
|
export type AIArgs = z.infer<typeof aiSchema>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ContentResult, FastMCP } from 'fastmcp';
|
|
2
|
-
import { errorResult } from '../tool-response.js';
|
|
2
|
+
import { errorResult, toolErrorMessage } from '../tool-response.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { resolveAppId, resolveId } from './resolve-app-id.js';
|
|
5
5
|
import { activate } from './activate-app.js';
|
|
@@ -133,14 +133,32 @@ export default function app(server: FastMCP): void {
|
|
|
133
133
|
if (!args.url) {
|
|
134
134
|
return errorResult('url is required for deep_link');
|
|
135
135
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
let appId: string | undefined;
|
|
137
|
+
if (args.id !== undefined) {
|
|
138
|
+
appId = args.id;
|
|
139
|
+
} else if (args.name) {
|
|
140
|
+
try {
|
|
141
|
+
appId = await resolveAppId(args.name, sessionId);
|
|
142
|
+
} catch (err: unknown) {
|
|
143
|
+
return errorResult(
|
|
144
|
+
`deep_link: failed to resolve app by name: ${toolErrorMessage(err)}`
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
appId = undefined;
|
|
149
|
+
}
|
|
139
150
|
return deepLink(args.url, appId, args.waitForLaunch, sessionId);
|
|
140
151
|
}
|
|
141
152
|
|
|
142
153
|
// activate, terminate, uninstall, is_installed, query_state, clear — all require id or name
|
|
143
|
-
|
|
154
|
+
let id: string;
|
|
155
|
+
try {
|
|
156
|
+
id = await resolveId(args.id, args.name, sessionId);
|
|
157
|
+
} catch (err: unknown) {
|
|
158
|
+
return errorResult(
|
|
159
|
+
`${action}: failed to resolve app id: ${toolErrorMessage(err)}`
|
|
160
|
+
);
|
|
161
|
+
}
|
|
144
162
|
|
|
145
163
|
if (action === 'activate') {
|
|
146
164
|
return activate(id, sessionId);
|