@nbakka/mcp-appium 3.0.25 → 4.0.1
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/lib/android.js +69 -8
- package/lib/ios.js +8 -0
- package/lib/iphone-simulator.js +4 -0
- package/lib/server.js +1359 -1673
- package/lib/webdriver-agent.js +63 -2
- package/package.json +6 -6
package/lib/webdriver-agent.js
CHANGED
|
@@ -153,16 +153,75 @@ class WebDriverAgent {
|
|
|
153
153
|
}
|
|
154
154
|
return output;
|
|
155
155
|
}
|
|
156
|
+
filterSimplifiedElements(source) {
|
|
157
|
+
const output = [];
|
|
158
|
+
|
|
159
|
+
// Recursively traverse children first
|
|
160
|
+
if (source.children) {
|
|
161
|
+
for (const child of source.children) {
|
|
162
|
+
output.push(...this.filterSimplifiedElements(child));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Only include visible elements with useful attributes
|
|
167
|
+
if (source.isVisible === "1" && this.isVisible(source.rect)) {
|
|
168
|
+
const hasLabel = source.label && source.label.trim().length > 0;
|
|
169
|
+
const hasName = source.name && source.name.trim().length > 0;
|
|
170
|
+
const hasValue = source.value && source.value.trim().length > 0;
|
|
171
|
+
|
|
172
|
+
if (hasLabel || hasName || hasValue) {
|
|
173
|
+
const element = {};
|
|
174
|
+
|
|
175
|
+
// Only include fields that have values
|
|
176
|
+
if (hasLabel) {
|
|
177
|
+
element.text = source.label;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (source.type) {
|
|
181
|
+
element.class = source.type;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (hasName) {
|
|
185
|
+
element.accessibilityId = source.name;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (hasValue) {
|
|
189
|
+
element.value = source.value;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Format bounds similar to Android format
|
|
193
|
+
if (source.rect) {
|
|
194
|
+
const x1 = Math.floor(source.rect.x);
|
|
195
|
+
const y1 = Math.floor(source.rect.y);
|
|
196
|
+
const x2 = Math.floor(source.rect.x + source.rect.width);
|
|
197
|
+
const y2 = Math.floor(source.rect.y + source.rect.height);
|
|
198
|
+
element.bounds = `[${x1},${y1}][${x2},${y2}]`;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
output.push(element);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return output;
|
|
206
|
+
}
|
|
156
207
|
async getPageSource() {
|
|
157
208
|
const url = `http://${this.host}:${this.port}/source/?format=json`;
|
|
158
209
|
const response = await fetch(url);
|
|
159
210
|
const json = await response.json();
|
|
160
211
|
return json;
|
|
161
212
|
}
|
|
213
|
+
async getXmlStructure() {
|
|
214
|
+
const source = await this.getPageSource();
|
|
215
|
+
return source;
|
|
216
|
+
}
|
|
162
217
|
async getElementsOnScreen() {
|
|
163
218
|
const source = await this.getPageSource();
|
|
164
219
|
return this.filterSourceElements(source.value);
|
|
165
220
|
}
|
|
221
|
+
async getSimplifiedElements() {
|
|
222
|
+
const source = await this.getPageSource();
|
|
223
|
+
return this.filterSimplifiedElements(source.value);
|
|
224
|
+
}
|
|
166
225
|
async openUrl(url) {
|
|
167
226
|
await this.withinSession(async (sessionUrl) => {
|
|
168
227
|
await fetch(`${sessionUrl}/url`, {
|
|
@@ -174,14 +233,16 @@ class WebDriverAgent {
|
|
|
174
233
|
async swipe(direction) {
|
|
175
234
|
await this.withinSession(async (sessionUrl) => {
|
|
176
235
|
const x0 = 200;
|
|
177
|
-
let y0 = 600;
|
|
236
|
+
let y0 = 600; // bottom
|
|
178
237
|
const x1 = 200;
|
|
179
|
-
let y1 = 200;
|
|
238
|
+
let y1 = 200; // top
|
|
180
239
|
if (direction === "up") {
|
|
240
|
+
// Scroll up to reveal content above (swipe down gesture: top to bottom)
|
|
181
241
|
const tmp = y0;
|
|
182
242
|
y0 = y1;
|
|
183
243
|
y1 = tmp;
|
|
184
244
|
}
|
|
245
|
+
// Default (down): Scroll down to reveal content below (swipe up gesture: bottom to top)
|
|
185
246
|
const url = `${sessionUrl}/actions`;
|
|
186
247
|
await fetch(url, {
|
|
187
248
|
method: "POST",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nbakka/mcp-appium",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "Appium MCP",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18"
|
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@modelcontextprotocol/sdk": "^1.6.1",
|
|
22
|
+
"axios": "^1.6.0",
|
|
23
|
+
"express": "5.1.0",
|
|
22
24
|
"fast-xml-parser": "^5.0.9",
|
|
23
25
|
"googleapis": "^149.0.0",
|
|
24
|
-
"
|
|
25
|
-
"axios": "^1.6.0",
|
|
26
|
+
"open": "10.2.0",
|
|
26
27
|
"openai": "^5.20.0",
|
|
27
|
-
"
|
|
28
|
-
"open": "10.2.0"
|
|
28
|
+
"zod-to-json-schema": "^3.24.4"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@eslint/eslintrc": "^3.2.0",
|
|
@@ -54,4 +54,4 @@
|
|
|
54
54
|
"lib": "lib"
|
|
55
55
|
},
|
|
56
56
|
"author": "nbakka"
|
|
57
|
-
}
|
|
57
|
+
}
|