@mobilenext/mobile-mcp 0.0.14 → 0.0.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/lib/android.js +2 -7
- package/lib/server.js +27 -4
- package/lib/webdriver-agent.js +1 -1
- package/package.json +1 -1
package/lib/android.js
CHANGED
|
@@ -139,7 +139,7 @@ class AndroidRobot {
|
|
|
139
139
|
this.adb("shell", "input", "swipe", `${x0}`, `${y0}`, `${x1}`, `${y1}`, "1000");
|
|
140
140
|
}
|
|
141
141
|
async getScreenshot() {
|
|
142
|
-
return this.adb("
|
|
142
|
+
return this.adb("exec-out", "screencap", "-p");
|
|
143
143
|
}
|
|
144
144
|
collectElements(node) {
|
|
145
145
|
const elements = [];
|
|
@@ -197,13 +197,8 @@ class AndroidRobot {
|
|
|
197
197
|
this.adb("shell", "input", "tap", `${x}`, `${y}`);
|
|
198
198
|
}
|
|
199
199
|
async setOrientation(orientation) {
|
|
200
|
-
// Android uses numbers for orientation:
|
|
201
|
-
// 0 - Portrait
|
|
202
|
-
// 1 - Landscape
|
|
203
200
|
const orientationValue = orientation === "portrait" ? 0 : 1;
|
|
204
|
-
// Set orientation using content provider
|
|
205
201
|
this.adb("shell", "content", "insert", "--uri", "content://settings/system", "--bind", "name:s:user_rotation", "--bind", `value:i:${orientationValue}`);
|
|
206
|
-
// Force the orientation change
|
|
207
202
|
this.adb("shell", "settings", "put", "system", "accelerometer_rotation", "0");
|
|
208
203
|
}
|
|
209
204
|
async getOrientation() {
|
|
@@ -228,7 +223,7 @@ class AndroidRobot {
|
|
|
228
223
|
const dump = await this.getUiAutomatorDump();
|
|
229
224
|
const parser = new xml.XMLParser({
|
|
230
225
|
ignoreAttributes: false,
|
|
231
|
-
attributeNamePrefix: ""
|
|
226
|
+
attributeNamePrefix: "",
|
|
232
227
|
});
|
|
233
228
|
return parser.parse(dump);
|
|
234
229
|
}
|
package/lib/server.js
CHANGED
|
@@ -14,6 +14,23 @@ const getAgentVersion = () => {
|
|
|
14
14
|
const json = require("../package.json");
|
|
15
15
|
return json.version;
|
|
16
16
|
};
|
|
17
|
+
const getLatestAgentVersion = async () => {
|
|
18
|
+
const response = await fetch("https://api.github.com/repos/mobile-next/mobile-mcp/tags?per_page=1");
|
|
19
|
+
const json = await response.json();
|
|
20
|
+
return json[0].name;
|
|
21
|
+
};
|
|
22
|
+
const checkForLatestAgentVersion = async () => {
|
|
23
|
+
try {
|
|
24
|
+
const latestVersion = await getLatestAgentVersion();
|
|
25
|
+
const currentVersion = getAgentVersion();
|
|
26
|
+
if (latestVersion !== currentVersion) {
|
|
27
|
+
(0, logger_1.trace)(`You are running an older version of the agent. Please update to the latest version: ${latestVersion}.`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
// ignore
|
|
32
|
+
}
|
|
33
|
+
};
|
|
17
34
|
const createMcpServer = () => {
|
|
18
35
|
const server = new mcp_js_1.McpServer({
|
|
19
36
|
name: "mobile-mcp",
|
|
@@ -136,15 +153,18 @@ const createMcpServer = () => {
|
|
|
136
153
|
requireRobot();
|
|
137
154
|
const elements = await robot.getElementsOnScreen();
|
|
138
155
|
const result = elements.map(element => {
|
|
139
|
-
const x = Number((element.rect.x + element.rect.width / 2)).toFixed(1);
|
|
140
|
-
const y = Number((element.rect.y + element.rect.height / 2)).toFixed(1);
|
|
141
156
|
const out = {
|
|
142
157
|
type: element.type,
|
|
143
158
|
text: element.text,
|
|
144
159
|
label: element.label,
|
|
145
160
|
name: element.name,
|
|
146
161
|
value: element.value,
|
|
147
|
-
coordinates: {
|
|
162
|
+
coordinates: {
|
|
163
|
+
x: element.rect.x,
|
|
164
|
+
y: element.rect.y,
|
|
165
|
+
width: element.rect.width,
|
|
166
|
+
height: element.rect.height,
|
|
167
|
+
},
|
|
148
168
|
};
|
|
149
169
|
if (element.focused) {
|
|
150
170
|
out.focused = true;
|
|
@@ -188,6 +208,7 @@ const createMcpServer = () => {
|
|
|
188
208
|
server.tool("mobile_take_screenshot", "Take a screenshot of the mobile device. Use this to understand what's on screen, if you need to press an element that is available through view hierarchy then you must list elements on screen instead. Do not cache this result.", {}, async ({}) => {
|
|
189
209
|
requireRobot();
|
|
190
210
|
try {
|
|
211
|
+
const screenSize = await robot.getScreenSize();
|
|
191
212
|
let screenshot = await robot.getScreenshot();
|
|
192
213
|
let mimeType = "image/png";
|
|
193
214
|
// validate we received a png, will throw exception otherwise
|
|
@@ -200,7 +221,7 @@ const createMcpServer = () => {
|
|
|
200
221
|
(0, logger_1.trace)("ImageMagick is installed, resizing screenshot");
|
|
201
222
|
const image = image_utils_1.Image.fromBuffer(screenshot);
|
|
202
223
|
const beforeSize = screenshot.length;
|
|
203
|
-
screenshot = image.resize(Math.floor(pngSize.width /
|
|
224
|
+
screenshot = image.resize(Math.floor(pngSize.width / screenSize.scale))
|
|
204
225
|
.jpeg({ quality: 75 })
|
|
205
226
|
.toBuffer();
|
|
206
227
|
const afterSize = screenshot.length;
|
|
@@ -233,6 +254,8 @@ const createMcpServer = () => {
|
|
|
233
254
|
const orientation = await robot.getOrientation();
|
|
234
255
|
return `Current device orientation is ${orientation}`;
|
|
235
256
|
});
|
|
257
|
+
// async check for latest agent version
|
|
258
|
+
checkForLatestAgentVersion().then();
|
|
236
259
|
return server;
|
|
237
260
|
};
|
|
238
261
|
exports.createMcpServer = createMcpServer;
|
package/lib/webdriver-agent.js
CHANGED
|
@@ -127,7 +127,7 @@ class WebDriverAgent {
|
|
|
127
127
|
}
|
|
128
128
|
filterSourceElements(source) {
|
|
129
129
|
const output = [];
|
|
130
|
-
const acceptedTypes = ["TextField", "Button", "Switch", "Icon", "SearchField"];
|
|
130
|
+
const acceptedTypes = ["TextField", "Button", "Switch", "Icon", "SearchField", "StaticText", "Image"];
|
|
131
131
|
if (acceptedTypes.includes(source.type)) {
|
|
132
132
|
if (source.isVisible === "1" && this.isVisible(source.rect)) {
|
|
133
133
|
if (source.label !== null || source.name !== null) {
|