@nbakka/mcp-appium 2.0.27 → 2.0.28

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 (2) hide show
  1. package/lib/server.js +67 -67
  2. package/package.json +4 -4
package/lib/server.js CHANGED
@@ -139,73 +139,73 @@ const createMcpServer = () => {
139
139
  const fs = require('fs').promises;
140
140
  const path = require('path');
141
141
 
142
- tool(
143
- "mobile_learn_current_app_context",
144
- "Follow these instructions strictly to navigate through the app. This should be the first step after launching the app and before performing any tests. Provide the Google Sheet name to fetch locatorName and androidLocator from the specified sheet.",
145
- {
146
- sheetName: zod_1.z.string().describe("The name of the Google Sheet to fetch locator data from"),
147
- },
148
- async ({ sheetName }) => {
149
- try {
150
- // Read app context notes from file
151
- const notesFilePath = path.join(__dirname, 'app_context.txt');
152
- const fileContent = await fs.readFile(notesFilePath, 'utf-8');
153
-
154
- const notes = fileContent
155
- .split('\n')
156
- .map(line => line.trim())
157
- .filter(line => line.length > 0);
158
-
159
- // Initialize response object
160
- const context = { notes, locatorData: null };
161
-
162
- if (sheetName && sheetName.trim() !== '') {
163
- // Load Google Sheets credentials
164
- const keyFile = path.join(__dirname, 'secret.json');
165
- const credentials = JSON.parse(await fs.readFile(keyFile, 'utf-8'));
166
-
167
- const auth = new google.auth.GoogleAuth({
168
- credentials,
169
- scopes: ['https://www.googleapis.com/auth/spreadsheets.readonly'],
170
- });
171
-
172
- const authClient = await auth.getClient();
173
- const sheets = google.sheets({ version: 'v4', auth: authClient });
174
- const spreadsheetId = '1UapR81AxaztDUlPGDV-_EwHo2hWXkKCZXl8ALsvIyxA';
175
-
176
- const range = `${sheetName}!A1:Z1000`;
177
- const res = await sheets.spreadsheets.values.get({ spreadsheetId, range });
178
- const rows = res.data.values;
179
-
180
- if (!rows || rows.length === 0) {
181
- return `Sheet "${sheetName}" is empty or does not exist. Notes loaded: ${JSON.stringify(notes)}`;
182
- }
183
-
184
- // Normalize headers
185
- const header = rows[0].map(h => h.toString().toLowerCase().trim());
186
- const locatorNameIdx = header.indexOf('locatorName');
187
- const androidLocatorIdx = header.findIndex(h => h === 'androidXpath' || h === 'androidLocator');
188
-
189
- if (locatorNameIdx === -1 || androidLocatorIdx === -1) {
190
- return `Required columns "locator name" and/or "android xpath" not found in sheet "${sheetName}". Notes loaded: ${JSON.stringify(notes)}`;
191
- }
192
-
193
- const locatorData = rows.slice(1)
194
- .filter(row => row[locatorNameIdx] && row[androidLocatorIdx])
195
- .map(row => ({
196
- locatorName: row[locatorNameIdx],
197
- androidLocator: row[androidLocatorIdx],
198
- }));
199
-
200
- context.locatorData = locatorData;
201
- }
202
-
203
- return `App context learned: ${JSON.stringify(context)}`;
204
- } catch (error) {
205
- return `Error reading app context notes or fetching locator data: ${error.message}`;
206
- }
207
- }
208
- );
142
+ tool(
143
+ "mobile_learn_current_app_context",
144
+ "Follow these instructions strictly to navigate through the app. This should be the first step after launching the app and before performing any tests. Provide the Google Sheet name to fetch locatorName and androidLocator from the specified sheet.",
145
+ {
146
+ sheetName: z.string().describe("The name of the Google Sheet to fetch locator data from"),
147
+ },
148
+ async ({ sheetName }) => {
149
+ try {
150
+ // Read app context notes from file
151
+ const notesFilePath = path.join(__dirname, 'app_context.txt');
152
+ const fileContent = await fs.readFile(notesFilePath, 'utf-8');
153
+
154
+ const notes = fileContent
155
+ .split('\n')
156
+ .map(line => line.trim())
157
+ .filter(line => line.length > 0);
158
+
159
+ // Initialize response object
160
+ const context = { notes, locatorData: null };
161
+
162
+ if (sheetName && sheetName.trim() !== '') {
163
+ // Load Google Sheets credentials with keyFile option (no manual parse)
164
+ const keyFile = path.join(__dirname, 'secret.json');
165
+
166
+ const auth = new google.auth.GoogleAuth({
167
+ keyFile,
168
+ scopes: ['https://www.googleapis.com/auth/spreadsheets.readonly'],
169
+ });
170
+
171
+ const authClient = await auth.getClient();
172
+ const sheets = google.sheets({ version: 'v4', auth: authClient });
173
+ const spreadsheetId = '1UapR81AxaztDUlPGDV-_EwHo2hWXkKCZXl8ALsvIyxA';
174
+
175
+ const range = `${sheetName}!A1:Z1000`;
176
+ const res = await sheets.spreadsheets.values.get({ spreadsheetId, range });
177
+ const rows = res.data.values;
178
+
179
+ if (!rows || rows.length === 0) {
180
+ return `Sheet "${sheetName}" is empty or does not exist. Notes loaded: ${JSON.stringify(notes)}`;
181
+ }
182
+
183
+ // Map headers exactly (trimmed, case-sensitive)
184
+ const header = rows[0].map(h => h.toString().trim());
185
+
186
+ const locatorNameIdx = header.indexOf('locatorName');
187
+ const androidLocatorIdx = header.indexOf('androidLocator');
188
+
189
+ if (locatorNameIdx === -1 || androidLocatorIdx === -1) {
190
+ return `Required columns "locatorName" and/or "androidLocator" not found in sheet "${sheetName}". Notes loaded: ${JSON.stringify(notes)}`;
191
+ }
192
+
193
+ const locatorData = rows.slice(1)
194
+ .filter(row => row[locatorNameIdx] && row[androidLocatorIdx])
195
+ .map(row => ({
196
+ locatorName: row[locatorNameIdx],
197
+ androidLocator: row[androidLocatorIdx],
198
+ }));
199
+
200
+ context.locatorData = locatorData;
201
+ }
202
+
203
+ return `App context learned: ${JSON.stringify(context)}`;
204
+ } catch (error) {
205
+ return `Error reading app context notes or fetching locator data: ${error.message}`;
206
+ }
207
+ }
208
+ );
209
209
 
210
210
  tool("mobile_list_elements_on_screen", "List elements on screen and their coordinates, with display text or accessibility label. Do not cache this result.", {}, async ({}) => {
211
211
  requireRobot();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nbakka/mcp-appium",
3
- "version": "2.0.27",
3
+ "version": "2.0.28",
4
4
  "description": "Appium MCP",
5
5
  "engines": {
6
6
  "node": ">=18"
@@ -20,8 +20,8 @@
20
20
  "dependencies": {
21
21
  "@modelcontextprotocol/sdk": "^1.6.1",
22
22
  "fast-xml-parser": "^5.0.9",
23
- "zod-to-json-schema": "^3.24.4",
24
- "googleapis": "^39.2.0"
23
+ "googleapis": "^149.0.0",
24
+ "zod-to-json-schema": "^3.24.4"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@eslint/eslintrc": "^3.2.0",
@@ -37,8 +37,8 @@
37
37
  "eslint-plugin-import": "^2.31.0",
38
38
  "eslint-plugin-notice": "^1.0.0",
39
39
  "husky": "^9.1.7",
40
- "nyc": "^17.1.0",
41
40
  "mocha": "^11.1.0",
41
+ "nyc": "^17.1.0",
42
42
  "ts-node": "^10.9.2",
43
43
  "typescript": "^5.8.2"
44
44
  },