@midscene/ios 1.7.5-beta-20260421030751.0 → 1.7.5

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/dist/es/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createReportCliCommands, getMidsceneLocationSchema, z } from "@midscene/core";
2
- import { CLIError, runToolsCLI } from "@midscene/shared/cli";
2
+ import { reportCLIError, runToolsCLI } from "@midscene/shared/cli";
3
3
  import { getDebug } from "@midscene/shared/logger";
4
- import { BaseMidsceneTools } from "@midscene/shared/mcp";
4
+ import { BaseMidsceneTools } from "@midscene/shared/mcp/base-tools";
5
5
  import { Agent } from "@midscene/core/agent";
6
6
  import { mergeAndNormalizeAppNameMapping, normalizeForComparison } from "@midscene/shared/utils";
7
7
  import node_assert from "node:assert";
@@ -1320,17 +1320,46 @@ async function agentFromWebDriverAgent(opts) {
1320
1320
  await device.connect();
1321
1321
  return new IOSAgent(device, opts);
1322
1322
  }
1323
+ function mcp_tools_define_property(obj, key, value) {
1324
+ if (key in obj) Object.defineProperty(obj, key, {
1325
+ value: value,
1326
+ enumerable: true,
1327
+ configurable: true,
1328
+ writable: true
1329
+ });
1330
+ else obj[key] = value;
1331
+ return obj;
1332
+ }
1323
1333
  const debug = getDebug('mcp:ios-tools');
1334
+ const iosInitArgShape = {
1335
+ deviceId: z.string().optional().describe('iOS device UDID (optional when WDA auto-detect is sufficient)'),
1336
+ wdaHost: z.string().optional().describe('WebDriverAgent host, defaults to localhost'),
1337
+ wdaPort: z.number().optional().describe('WebDriverAgent port'),
1338
+ useWDA: z.boolean().optional().describe('Whether to reuse an existing WebDriverAgent session'),
1339
+ wdaMjpegPort: z.number().optional().describe('WebDriverAgent MJPEG streaming port')
1340
+ };
1324
1341
  class IOSMidsceneTools extends BaseMidsceneTools {
1325
1342
  createTemporaryDevice() {
1326
1343
  return new IOSDevice({});
1327
1344
  }
1328
- async ensureAgent() {
1345
+ async ensureAgent(opts) {
1346
+ const hasOpts = !!opts && Object.keys(opts).length > 0;
1347
+ const nextSignature = hasOpts ? JSON.stringify(opts) : void 0;
1348
+ if (this.agent && hasOpts && nextSignature !== this.lastOptsSignature) {
1349
+ try {
1350
+ await this.agent.destroy?.();
1351
+ } catch (error) {
1352
+ debug('Failed to destroy agent during cleanup:', error);
1353
+ }
1354
+ this.agent = void 0;
1355
+ }
1329
1356
  if (this.agent) return this.agent;
1330
- debug('Creating iOS agent with WebDriverAgent');
1357
+ debug('Creating iOS agent with WebDriverAgent options:', opts || {});
1331
1358
  this.agent = await agentFromWebDriverAgent({
1332
- autoDismissKeyboard: false
1359
+ autoDismissKeyboard: false,
1360
+ ...opts ?? {}
1333
1361
  });
1362
+ this.lastOptsSignature = nextSignature;
1334
1363
  return this.agent;
1335
1364
  }
1336
1365
  preparePlatformTools() {
@@ -1338,15 +1367,17 @@ class IOSMidsceneTools extends BaseMidsceneTools {
1338
1367
  {
1339
1368
  name: 'ios_connect',
1340
1369
  description: 'Connect to iOS device or simulator via WebDriverAgent',
1341
- schema: {},
1342
- handler: async ()=>{
1343
- const agent = await this.ensureAgent();
1370
+ schema: this.getAgentInitArgSchema(),
1371
+ cli: this.getAgentInitArgCliMetadata(),
1372
+ handler: async (args)=>{
1373
+ const initArgs = this.extractAgentInitParam(args);
1374
+ const agent = await this.ensureAgent(initArgs);
1344
1375
  const screenshot = await agent.page.screenshotBase64();
1345
1376
  return {
1346
1377
  content: [
1347
1378
  {
1348
1379
  type: 'text',
1349
- text: 'Connected to iOS device'
1380
+ text: `Connected to iOS device${initArgs?.deviceId ? `: ${initArgs.deviceId}` : ''}`
1350
1381
  },
1351
1382
  ...this.buildScreenshotContent(screenshot)
1352
1383
  ],
@@ -1362,13 +1393,22 @@ class IOSMidsceneTools extends BaseMidsceneTools {
1362
1393
  }
1363
1394
  ];
1364
1395
  }
1396
+ constructor(...args){
1397
+ super(...args), mcp_tools_define_property(this, "initArgSpec", {
1398
+ namespace: 'ios',
1399
+ shape: iosInitArgShape,
1400
+ cli: {
1401
+ preferBareKeys: true
1402
+ },
1403
+ adapt: (extracted)=>extracted
1404
+ }), mcp_tools_define_property(this, "lastOptsSignature", void 0);
1405
+ }
1365
1406
  }
1366
1407
  const tools = new IOSMidsceneTools();
1367
1408
  runToolsCLI(tools, 'midscene-ios', {
1368
1409
  stripPrefix: 'ios_',
1369
- version: "1.7.5-beta-20260421030751.0",
1410
+ version: "1.7.5",
1370
1411
  extraCommands: createReportCliCommands()
1371
1412
  }).catch((e)=>{
1372
- if (!(e instanceof CLIError)) console.error(e);
1373
- process.exit(e instanceof CLIError ? e.exitCode : 1);
1413
+ process.exit(reportCLIError(e));
1374
1414
  });
package/dist/es/index.mjs CHANGED
@@ -8,7 +8,7 @@ import { getDebug } from "@midscene/shared/logger";
8
8
  import { mergeAndNormalizeAppNameMapping, normalizeForComparison } from "@midscene/shared/utils";
9
9
  import { WDAManager, WebDriverClient } from "@midscene/webdriver";
10
10
  import { Agent } from "@midscene/core/agent";
11
- import { BaseMidsceneTools } from "@midscene/shared/mcp";
11
+ import { BaseMidsceneTools } from "@midscene/shared/mcp/base-tools";
12
12
  import { overrideAIConfig } from "@midscene/shared/env";
13
13
  import { exec } from "node:child_process";
14
14
  import { platform } from "node:os";
@@ -1326,17 +1326,46 @@ async function agentFromWebDriverAgent(opts) {
1326
1326
  await device.connect();
1327
1327
  return new IOSAgent(device, opts);
1328
1328
  }
1329
+ function mcp_tools_define_property(obj, key, value) {
1330
+ if (key in obj) Object.defineProperty(obj, key, {
1331
+ value: value,
1332
+ enumerable: true,
1333
+ configurable: true,
1334
+ writable: true
1335
+ });
1336
+ else obj[key] = value;
1337
+ return obj;
1338
+ }
1329
1339
  const debug = getDebug('mcp:ios-tools');
1340
+ const iosInitArgShape = {
1341
+ deviceId: z.string().optional().describe('iOS device UDID (optional when WDA auto-detect is sufficient)'),
1342
+ wdaHost: z.string().optional().describe('WebDriverAgent host, defaults to localhost'),
1343
+ wdaPort: z.number().optional().describe('WebDriverAgent port'),
1344
+ useWDA: z.boolean().optional().describe('Whether to reuse an existing WebDriverAgent session'),
1345
+ wdaMjpegPort: z.number().optional().describe('WebDriverAgent MJPEG streaming port')
1346
+ };
1330
1347
  class IOSMidsceneTools extends BaseMidsceneTools {
1331
1348
  createTemporaryDevice() {
1332
1349
  return new IOSDevice({});
1333
1350
  }
1334
- async ensureAgent() {
1351
+ async ensureAgent(opts) {
1352
+ const hasOpts = !!opts && Object.keys(opts).length > 0;
1353
+ const nextSignature = hasOpts ? JSON.stringify(opts) : void 0;
1354
+ if (this.agent && hasOpts && nextSignature !== this.lastOptsSignature) {
1355
+ try {
1356
+ await this.agent.destroy?.();
1357
+ } catch (error) {
1358
+ debug('Failed to destroy agent during cleanup:', error);
1359
+ }
1360
+ this.agent = void 0;
1361
+ }
1335
1362
  if (this.agent) return this.agent;
1336
- debug('Creating iOS agent with WebDriverAgent');
1363
+ debug('Creating iOS agent with WebDriverAgent options:', opts || {});
1337
1364
  this.agent = await agentFromWebDriverAgent({
1338
- autoDismissKeyboard: false
1365
+ autoDismissKeyboard: false,
1366
+ ...opts ?? {}
1339
1367
  });
1368
+ this.lastOptsSignature = nextSignature;
1340
1369
  return this.agent;
1341
1370
  }
1342
1371
  preparePlatformTools() {
@@ -1344,15 +1373,17 @@ class IOSMidsceneTools extends BaseMidsceneTools {
1344
1373
  {
1345
1374
  name: 'ios_connect',
1346
1375
  description: 'Connect to iOS device or simulator via WebDriverAgent',
1347
- schema: {},
1348
- handler: async ()=>{
1349
- const agent = await this.ensureAgent();
1376
+ schema: this.getAgentInitArgSchema(),
1377
+ cli: this.getAgentInitArgCliMetadata(),
1378
+ handler: async (args)=>{
1379
+ const initArgs = this.extractAgentInitParam(args);
1380
+ const agent = await this.ensureAgent(initArgs);
1350
1381
  const screenshot = await agent.page.screenshotBase64();
1351
1382
  return {
1352
1383
  content: [
1353
1384
  {
1354
1385
  type: 'text',
1355
- text: 'Connected to iOS device'
1386
+ text: `Connected to iOS device${initArgs?.deviceId ? `: ${initArgs.deviceId}` : ''}`
1356
1387
  },
1357
1388
  ...this.buildScreenshotContent(screenshot)
1358
1389
  ],
@@ -1368,6 +1399,16 @@ class IOSMidsceneTools extends BaseMidsceneTools {
1368
1399
  }
1369
1400
  ];
1370
1401
  }
1402
+ constructor(...args){
1403
+ super(...args), mcp_tools_define_property(this, "initArgSpec", {
1404
+ namespace: 'ios',
1405
+ shape: iosInitArgShape,
1406
+ cli: {
1407
+ preferBareKeys: true
1408
+ },
1409
+ adapt: (extracted)=>extracted
1410
+ }), mcp_tools_define_property(this, "lastOptsSignature", void 0);
1411
+ }
1371
1412
  }
1372
1413
  const execAsync = promisify(exec);
1373
1414
  const debugUtils = getDebug('ios:utils');
@@ -1,4 +1,4 @@
1
- import { BaseMCPServer, BaseMidsceneTools, createMCPServerLauncher } from "@midscene/shared/mcp";
1
+ import { BaseMCPServer, createMCPServerLauncher } from "@midscene/shared/mcp";
2
2
  import { Agent } from "@midscene/core/agent";
3
3
  import { getDebug } from "@midscene/shared/logger";
4
4
  import { mergeAndNormalizeAppNameMapping, normalizeForComparison } from "@midscene/shared/utils";
@@ -9,6 +9,7 @@ import { sleep } from "@midscene/core/utils";
9
9
  import { DEFAULT_WDA_PORT } from "@midscene/shared/constants";
10
10
  import { createImgBase64ByFormat } from "@midscene/shared/img";
11
11
  import { WDAManager, WebDriverClient } from "@midscene/webdriver";
12
+ import { BaseMidsceneTools } from "@midscene/shared/mcp/base-tools";
12
13
  const defaultAppNameMapping = {
13
14
  微信: 'com.tencent.xin',
14
15
  企业微信: 'com.tencent.ww',
@@ -1319,17 +1320,46 @@ async function agentFromWebDriverAgent(opts) {
1319
1320
  await device.connect();
1320
1321
  return new IOSAgent(device, opts);
1321
1322
  }
1323
+ function mcp_tools_define_property(obj, key, value) {
1324
+ if (key in obj) Object.defineProperty(obj, key, {
1325
+ value: value,
1326
+ enumerable: true,
1327
+ configurable: true,
1328
+ writable: true
1329
+ });
1330
+ else obj[key] = value;
1331
+ return obj;
1332
+ }
1322
1333
  const debug = getDebug('mcp:ios-tools');
1334
+ const iosInitArgShape = {
1335
+ deviceId: z.string().optional().describe('iOS device UDID (optional when WDA auto-detect is sufficient)'),
1336
+ wdaHost: z.string().optional().describe('WebDriverAgent host, defaults to localhost'),
1337
+ wdaPort: z.number().optional().describe('WebDriverAgent port'),
1338
+ useWDA: z.boolean().optional().describe('Whether to reuse an existing WebDriverAgent session'),
1339
+ wdaMjpegPort: z.number().optional().describe('WebDriverAgent MJPEG streaming port')
1340
+ };
1323
1341
  class IOSMidsceneTools extends BaseMidsceneTools {
1324
1342
  createTemporaryDevice() {
1325
1343
  return new IOSDevice({});
1326
1344
  }
1327
- async ensureAgent() {
1345
+ async ensureAgent(opts) {
1346
+ const hasOpts = !!opts && Object.keys(opts).length > 0;
1347
+ const nextSignature = hasOpts ? JSON.stringify(opts) : void 0;
1348
+ if (this.agent && hasOpts && nextSignature !== this.lastOptsSignature) {
1349
+ try {
1350
+ await this.agent.destroy?.();
1351
+ } catch (error) {
1352
+ debug('Failed to destroy agent during cleanup:', error);
1353
+ }
1354
+ this.agent = void 0;
1355
+ }
1328
1356
  if (this.agent) return this.agent;
1329
- debug('Creating iOS agent with WebDriverAgent');
1357
+ debug('Creating iOS agent with WebDriverAgent options:', opts || {});
1330
1358
  this.agent = await agentFromWebDriverAgent({
1331
- autoDismissKeyboard: false
1359
+ autoDismissKeyboard: false,
1360
+ ...opts ?? {}
1332
1361
  });
1362
+ this.lastOptsSignature = nextSignature;
1333
1363
  return this.agent;
1334
1364
  }
1335
1365
  preparePlatformTools() {
@@ -1337,15 +1367,17 @@ class IOSMidsceneTools extends BaseMidsceneTools {
1337
1367
  {
1338
1368
  name: 'ios_connect',
1339
1369
  description: 'Connect to iOS device or simulator via WebDriverAgent',
1340
- schema: {},
1341
- handler: async ()=>{
1342
- const agent = await this.ensureAgent();
1370
+ schema: this.getAgentInitArgSchema(),
1371
+ cli: this.getAgentInitArgCliMetadata(),
1372
+ handler: async (args)=>{
1373
+ const initArgs = this.extractAgentInitParam(args);
1374
+ const agent = await this.ensureAgent(initArgs);
1343
1375
  const screenshot = await agent.page.screenshotBase64();
1344
1376
  return {
1345
1377
  content: [
1346
1378
  {
1347
1379
  type: 'text',
1348
- text: 'Connected to iOS device'
1380
+ text: `Connected to iOS device${initArgs?.deviceId ? `: ${initArgs.deviceId}` : ''}`
1349
1381
  },
1350
1382
  ...this.buildScreenshotContent(screenshot)
1351
1383
  ],
@@ -1361,6 +1393,16 @@ class IOSMidsceneTools extends BaseMidsceneTools {
1361
1393
  }
1362
1394
  ];
1363
1395
  }
1396
+ constructor(...args){
1397
+ super(...args), mcp_tools_define_property(this, "initArgSpec", {
1398
+ namespace: 'ios',
1399
+ shape: iosInitArgShape,
1400
+ cli: {
1401
+ preferBareKeys: true
1402
+ },
1403
+ adapt: (extracted)=>extracted
1404
+ }), mcp_tools_define_property(this, "lastOptsSignature", void 0);
1405
+ }
1364
1406
  }
1365
1407
  class IOSMCPServer extends BaseMCPServer {
1366
1408
  createToolsManager() {
@@ -1369,7 +1411,7 @@ class IOSMCPServer extends BaseMCPServer {
1369
1411
  constructor(toolsManager){
1370
1412
  super({
1371
1413
  name: '@midscene/ios-mcp',
1372
- version: "1.7.5-beta-20260421030751.0",
1414
+ version: "1.7.5",
1373
1415
  description: 'Control the iOS device using natural language commands'
1374
1416
  }, toolsManager);
1375
1417
  }
package/dist/lib/cli.js CHANGED
@@ -24,7 +24,7 @@ var __webpack_exports__ = {};
24
24
  const core_namespaceObject = require("@midscene/core");
25
25
  const cli_namespaceObject = require("@midscene/shared/cli");
26
26
  const logger_namespaceObject = require("@midscene/shared/logger");
27
- const mcp_namespaceObject = require("@midscene/shared/mcp");
27
+ const base_tools_namespaceObject = require("@midscene/shared/mcp/base-tools");
28
28
  const agent_namespaceObject = require("@midscene/core/agent");
29
29
  const utils_namespaceObject = require("@midscene/shared/utils");
30
30
  const defaultAppNameMapping = {
@@ -1344,17 +1344,46 @@ async function agentFromWebDriverAgent(opts) {
1344
1344
  await device.connect();
1345
1345
  return new IOSAgent(device, opts);
1346
1346
  }
1347
+ function mcp_tools_define_property(obj, key, value) {
1348
+ if (key in obj) Object.defineProperty(obj, key, {
1349
+ value: value,
1350
+ enumerable: true,
1351
+ configurable: true,
1352
+ writable: true
1353
+ });
1354
+ else obj[key] = value;
1355
+ return obj;
1356
+ }
1347
1357
  const debug = (0, logger_namespaceObject.getDebug)('mcp:ios-tools');
1348
- class IOSMidsceneTools extends mcp_namespaceObject.BaseMidsceneTools {
1358
+ const iosInitArgShape = {
1359
+ deviceId: core_namespaceObject.z.string().optional().describe('iOS device UDID (optional when WDA auto-detect is sufficient)'),
1360
+ wdaHost: core_namespaceObject.z.string().optional().describe('WebDriverAgent host, defaults to localhost'),
1361
+ wdaPort: core_namespaceObject.z.number().optional().describe('WebDriverAgent port'),
1362
+ useWDA: core_namespaceObject.z.boolean().optional().describe('Whether to reuse an existing WebDriverAgent session'),
1363
+ wdaMjpegPort: core_namespaceObject.z.number().optional().describe('WebDriverAgent MJPEG streaming port')
1364
+ };
1365
+ class IOSMidsceneTools extends base_tools_namespaceObject.BaseMidsceneTools {
1349
1366
  createTemporaryDevice() {
1350
1367
  return new IOSDevice({});
1351
1368
  }
1352
- async ensureAgent() {
1369
+ async ensureAgent(opts) {
1370
+ const hasOpts = !!opts && Object.keys(opts).length > 0;
1371
+ const nextSignature = hasOpts ? JSON.stringify(opts) : void 0;
1372
+ if (this.agent && hasOpts && nextSignature !== this.lastOptsSignature) {
1373
+ try {
1374
+ await this.agent.destroy?.();
1375
+ } catch (error) {
1376
+ debug('Failed to destroy agent during cleanup:', error);
1377
+ }
1378
+ this.agent = void 0;
1379
+ }
1353
1380
  if (this.agent) return this.agent;
1354
- debug('Creating iOS agent with WebDriverAgent');
1381
+ debug('Creating iOS agent with WebDriverAgent options:', opts || {});
1355
1382
  this.agent = await agentFromWebDriverAgent({
1356
- autoDismissKeyboard: false
1383
+ autoDismissKeyboard: false,
1384
+ ...opts ?? {}
1357
1385
  });
1386
+ this.lastOptsSignature = nextSignature;
1358
1387
  return this.agent;
1359
1388
  }
1360
1389
  preparePlatformTools() {
@@ -1362,15 +1391,17 @@ class IOSMidsceneTools extends mcp_namespaceObject.BaseMidsceneTools {
1362
1391
  {
1363
1392
  name: 'ios_connect',
1364
1393
  description: 'Connect to iOS device or simulator via WebDriverAgent',
1365
- schema: {},
1366
- handler: async ()=>{
1367
- const agent = await this.ensureAgent();
1394
+ schema: this.getAgentInitArgSchema(),
1395
+ cli: this.getAgentInitArgCliMetadata(),
1396
+ handler: async (args)=>{
1397
+ const initArgs = this.extractAgentInitParam(args);
1398
+ const agent = await this.ensureAgent(initArgs);
1368
1399
  const screenshot = await agent.page.screenshotBase64();
1369
1400
  return {
1370
1401
  content: [
1371
1402
  {
1372
1403
  type: 'text',
1373
- text: 'Connected to iOS device'
1404
+ text: `Connected to iOS device${initArgs?.deviceId ? `: ${initArgs.deviceId}` : ''}`
1374
1405
  },
1375
1406
  ...this.buildScreenshotContent(screenshot)
1376
1407
  ],
@@ -1386,15 +1417,24 @@ class IOSMidsceneTools extends mcp_namespaceObject.BaseMidsceneTools {
1386
1417
  }
1387
1418
  ];
1388
1419
  }
1420
+ constructor(...args){
1421
+ super(...args), mcp_tools_define_property(this, "initArgSpec", {
1422
+ namespace: 'ios',
1423
+ shape: iosInitArgShape,
1424
+ cli: {
1425
+ preferBareKeys: true
1426
+ },
1427
+ adapt: (extracted)=>extracted
1428
+ }), mcp_tools_define_property(this, "lastOptsSignature", void 0);
1429
+ }
1389
1430
  }
1390
1431
  const tools = new IOSMidsceneTools();
1391
1432
  (0, cli_namespaceObject.runToolsCLI)(tools, 'midscene-ios', {
1392
1433
  stripPrefix: 'ios_',
1393
- version: "1.7.5-beta-20260421030751.0",
1434
+ version: "1.7.5",
1394
1435
  extraCommands: (0, core_namespaceObject.createReportCliCommands)()
1395
1436
  }).catch((e)=>{
1396
- if (!(e instanceof cli_namespaceObject.CLIError)) console.error(e);
1397
- process.exit(e instanceof cli_namespaceObject.CLIError ? e.exitCode : 1);
1437
+ process.exit((0, cli_namespaceObject.reportCLIError)(e));
1398
1438
  });
1399
1439
  for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
1400
1440
  Object.defineProperty(exports, '__esModule', {
package/dist/lib/index.js CHANGED
@@ -1363,18 +1363,47 @@ async function agentFromWebDriverAgent(opts) {
1363
1363
  await device.connect();
1364
1364
  return new IOSAgent(device, opts);
1365
1365
  }
1366
- const mcp_namespaceObject = require("@midscene/shared/mcp");
1366
+ const base_tools_namespaceObject = require("@midscene/shared/mcp/base-tools");
1367
+ function mcp_tools_define_property(obj, key, value) {
1368
+ if (key in obj) Object.defineProperty(obj, key, {
1369
+ value: value,
1370
+ enumerable: true,
1371
+ configurable: true,
1372
+ writable: true
1373
+ });
1374
+ else obj[key] = value;
1375
+ return obj;
1376
+ }
1367
1377
  const debug = (0, logger_namespaceObject.getDebug)('mcp:ios-tools');
1368
- class IOSMidsceneTools extends mcp_namespaceObject.BaseMidsceneTools {
1378
+ const iosInitArgShape = {
1379
+ deviceId: core_namespaceObject.z.string().optional().describe('iOS device UDID (optional when WDA auto-detect is sufficient)'),
1380
+ wdaHost: core_namespaceObject.z.string().optional().describe('WebDriverAgent host, defaults to localhost'),
1381
+ wdaPort: core_namespaceObject.z.number().optional().describe('WebDriverAgent port'),
1382
+ useWDA: core_namespaceObject.z.boolean().optional().describe('Whether to reuse an existing WebDriverAgent session'),
1383
+ wdaMjpegPort: core_namespaceObject.z.number().optional().describe('WebDriverAgent MJPEG streaming port')
1384
+ };
1385
+ class IOSMidsceneTools extends base_tools_namespaceObject.BaseMidsceneTools {
1369
1386
  createTemporaryDevice() {
1370
1387
  return new IOSDevice({});
1371
1388
  }
1372
- async ensureAgent() {
1389
+ async ensureAgent(opts) {
1390
+ const hasOpts = !!opts && Object.keys(opts).length > 0;
1391
+ const nextSignature = hasOpts ? JSON.stringify(opts) : void 0;
1392
+ if (this.agent && hasOpts && nextSignature !== this.lastOptsSignature) {
1393
+ try {
1394
+ await this.agent.destroy?.();
1395
+ } catch (error) {
1396
+ debug('Failed to destroy agent during cleanup:', error);
1397
+ }
1398
+ this.agent = void 0;
1399
+ }
1373
1400
  if (this.agent) return this.agent;
1374
- debug('Creating iOS agent with WebDriverAgent');
1401
+ debug('Creating iOS agent with WebDriverAgent options:', opts || {});
1375
1402
  this.agent = await agentFromWebDriverAgent({
1376
- autoDismissKeyboard: false
1403
+ autoDismissKeyboard: false,
1404
+ ...opts ?? {}
1377
1405
  });
1406
+ this.lastOptsSignature = nextSignature;
1378
1407
  return this.agent;
1379
1408
  }
1380
1409
  preparePlatformTools() {
@@ -1382,15 +1411,17 @@ class IOSMidsceneTools extends mcp_namespaceObject.BaseMidsceneTools {
1382
1411
  {
1383
1412
  name: 'ios_connect',
1384
1413
  description: 'Connect to iOS device or simulator via WebDriverAgent',
1385
- schema: {},
1386
- handler: async ()=>{
1387
- const agent = await this.ensureAgent();
1414
+ schema: this.getAgentInitArgSchema(),
1415
+ cli: this.getAgentInitArgCliMetadata(),
1416
+ handler: async (args)=>{
1417
+ const initArgs = this.extractAgentInitParam(args);
1418
+ const agent = await this.ensureAgent(initArgs);
1388
1419
  const screenshot = await agent.page.screenshotBase64();
1389
1420
  return {
1390
1421
  content: [
1391
1422
  {
1392
1423
  type: 'text',
1393
- text: 'Connected to iOS device'
1424
+ text: `Connected to iOS device${initArgs?.deviceId ? `: ${initArgs.deviceId}` : ''}`
1394
1425
  },
1395
1426
  ...this.buildScreenshotContent(screenshot)
1396
1427
  ],
@@ -1406,6 +1437,16 @@ class IOSMidsceneTools extends mcp_namespaceObject.BaseMidsceneTools {
1406
1437
  }
1407
1438
  ];
1408
1439
  }
1440
+ constructor(...args){
1441
+ super(...args), mcp_tools_define_property(this, "initArgSpec", {
1442
+ namespace: 'ios',
1443
+ shape: iosInitArgShape,
1444
+ cli: {
1445
+ preferBareKeys: true
1446
+ },
1447
+ adapt: (extracted)=>extracted
1448
+ }), mcp_tools_define_property(this, "lastOptsSignature", void 0);
1449
+ }
1409
1450
  }
1410
1451
  const env_namespaceObject = require("@midscene/shared/env");
1411
1452
  const external_node_child_process_namespaceObject = require("node:child_process");
@@ -1359,17 +1359,47 @@ async function agentFromWebDriverAgent(opts) {
1359
1359
  await device.connect();
1360
1360
  return new IOSAgent(device, opts);
1361
1361
  }
1362
+ const base_tools_namespaceObject = require("@midscene/shared/mcp/base-tools");
1363
+ function mcp_tools_define_property(obj, key, value) {
1364
+ if (key in obj) Object.defineProperty(obj, key, {
1365
+ value: value,
1366
+ enumerable: true,
1367
+ configurable: true,
1368
+ writable: true
1369
+ });
1370
+ else obj[key] = value;
1371
+ return obj;
1372
+ }
1362
1373
  const debug = (0, logger_namespaceObject.getDebug)('mcp:ios-tools');
1363
- class IOSMidsceneTools extends mcp_namespaceObject.BaseMidsceneTools {
1374
+ const iosInitArgShape = {
1375
+ deviceId: core_namespaceObject.z.string().optional().describe('iOS device UDID (optional when WDA auto-detect is sufficient)'),
1376
+ wdaHost: core_namespaceObject.z.string().optional().describe('WebDriverAgent host, defaults to localhost'),
1377
+ wdaPort: core_namespaceObject.z.number().optional().describe('WebDriverAgent port'),
1378
+ useWDA: core_namespaceObject.z.boolean().optional().describe('Whether to reuse an existing WebDriverAgent session'),
1379
+ wdaMjpegPort: core_namespaceObject.z.number().optional().describe('WebDriverAgent MJPEG streaming port')
1380
+ };
1381
+ class IOSMidsceneTools extends base_tools_namespaceObject.BaseMidsceneTools {
1364
1382
  createTemporaryDevice() {
1365
1383
  return new IOSDevice({});
1366
1384
  }
1367
- async ensureAgent() {
1385
+ async ensureAgent(opts) {
1386
+ const hasOpts = !!opts && Object.keys(opts).length > 0;
1387
+ const nextSignature = hasOpts ? JSON.stringify(opts) : void 0;
1388
+ if (this.agent && hasOpts && nextSignature !== this.lastOptsSignature) {
1389
+ try {
1390
+ await this.agent.destroy?.();
1391
+ } catch (error) {
1392
+ debug('Failed to destroy agent during cleanup:', error);
1393
+ }
1394
+ this.agent = void 0;
1395
+ }
1368
1396
  if (this.agent) return this.agent;
1369
- debug('Creating iOS agent with WebDriverAgent');
1397
+ debug('Creating iOS agent with WebDriverAgent options:', opts || {});
1370
1398
  this.agent = await agentFromWebDriverAgent({
1371
- autoDismissKeyboard: false
1399
+ autoDismissKeyboard: false,
1400
+ ...opts ?? {}
1372
1401
  });
1402
+ this.lastOptsSignature = nextSignature;
1373
1403
  return this.agent;
1374
1404
  }
1375
1405
  preparePlatformTools() {
@@ -1377,15 +1407,17 @@ class IOSMidsceneTools extends mcp_namespaceObject.BaseMidsceneTools {
1377
1407
  {
1378
1408
  name: 'ios_connect',
1379
1409
  description: 'Connect to iOS device or simulator via WebDriverAgent',
1380
- schema: {},
1381
- handler: async ()=>{
1382
- const agent = await this.ensureAgent();
1410
+ schema: this.getAgentInitArgSchema(),
1411
+ cli: this.getAgentInitArgCliMetadata(),
1412
+ handler: async (args)=>{
1413
+ const initArgs = this.extractAgentInitParam(args);
1414
+ const agent = await this.ensureAgent(initArgs);
1383
1415
  const screenshot = await agent.page.screenshotBase64();
1384
1416
  return {
1385
1417
  content: [
1386
1418
  {
1387
1419
  type: 'text',
1388
- text: 'Connected to iOS device'
1420
+ text: `Connected to iOS device${initArgs?.deviceId ? `: ${initArgs.deviceId}` : ''}`
1389
1421
  },
1390
1422
  ...this.buildScreenshotContent(screenshot)
1391
1423
  ],
@@ -1401,6 +1433,16 @@ class IOSMidsceneTools extends mcp_namespaceObject.BaseMidsceneTools {
1401
1433
  }
1402
1434
  ];
1403
1435
  }
1436
+ constructor(...args){
1437
+ super(...args), mcp_tools_define_property(this, "initArgSpec", {
1438
+ namespace: 'ios',
1439
+ shape: iosInitArgShape,
1440
+ cli: {
1441
+ preferBareKeys: true
1442
+ },
1443
+ adapt: (extracted)=>extracted
1444
+ }), mcp_tools_define_property(this, "lastOptsSignature", void 0);
1445
+ }
1404
1446
  }
1405
1447
  class IOSMCPServer extends mcp_namespaceObject.BaseMCPServer {
1406
1448
  createToolsManager() {
@@ -1409,7 +1451,7 @@ class IOSMCPServer extends mcp_namespaceObject.BaseMCPServer {
1409
1451
  constructor(toolsManager){
1410
1452
  super({
1411
1453
  name: '@midscene/ios-mcp',
1412
- version: "1.7.5-beta-20260421030751.0",
1454
+ version: "1.7.5",
1413
1455
  description: 'Control the iOS device using natural language commands'
1414
1456
  }, toolsManager);
1415
1457
  }
@@ -3,9 +3,10 @@ import type { ActionParam } from '@midscene/core';
3
3
  import type { ActionReturn } from '@midscene/core';
4
4
  import { Agent } from '@midscene/core/agent';
5
5
  import { AgentOpt } from '@midscene/core/agent';
6
- import { BaseMidsceneTools } from '@midscene/shared/mcp';
6
+ import { BaseMidsceneTools } from '@midscene/shared/mcp/base-tools';
7
7
  import { DeviceAction } from '@midscene/core';
8
8
  import type { ElementInfo } from '@midscene/shared/extractor';
9
+ import { InitArgSpec } from '@midscene/shared/mcp/base-tools';
9
10
  import { InterfaceType } from '@midscene/core';
10
11
  import { IOSDeviceInputOpt } from '@midscene/core/device';
11
12
  import { IOSDeviceOpt } from '@midscene/core/device';
@@ -13,7 +14,7 @@ import { overrideAIConfig } from '@midscene/shared/env';
13
14
  import { PlaygroundPlatformDescriptor } from '@midscene/playground';
14
15
  import { Point } from '@midscene/core';
15
16
  import { Size } from '@midscene/core';
16
- import { ToolDefinition } from '@midscene/shared/mcp';
17
+ import type { ToolDefinition } from '@midscene/shared/mcp/types';
17
18
  import { WebDriverClient } from '@midscene/webdriver';
18
19
  import { z } from '@midscene/core';
19
20
 
@@ -177,13 +178,17 @@ export declare class IOSDevice implements AbstractInterface {
177
178
  destroy(): Promise<void>;
178
179
  }
179
180
 
181
+ declare type IOSInitArgs = Pick<IOSDeviceOpt, 'deviceId' | 'wdaHost' | 'wdaPort' | 'useWDA' | 'wdaMjpegPort'>;
182
+
180
183
  /**
181
184
  * iOS-specific tools manager
182
185
  * Extends BaseMidsceneTools to provide iOS WebDriverAgent connection tools
183
186
  */
184
- export declare class IOSMidsceneTools extends BaseMidsceneTools<IOSAgent> {
187
+ export declare class IOSMidsceneTools extends BaseMidsceneTools<IOSAgent, IOSInitArgs> {
188
+ protected readonly initArgSpec: InitArgSpec<IOSInitArgs>;
189
+ private lastOptsSignature?;
185
190
  protected createTemporaryDevice(): IOSDevice;
186
- protected ensureAgent(): Promise<IOSAgent>;
191
+ protected ensureAgent(opts?: IOSInitArgs): Promise<IOSAgent>;
187
192
  /**
188
193
  * Provide iOS-specific platform tools
189
194
  */