@mobilenext/mobile-mcp 0.0.49 → 0.0.51

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/README.md CHANGED
@@ -7,24 +7,15 @@ This server allows Agents and LLMs to interact with native iOS/Android applicati
7
7
  <a href="https://github.com/mobile-next/mobile-mcp">
8
8
  <img src="https://img.shields.io/github/stars/mobile-next/mobile-mcp" alt="Mobile Next Stars" />
9
9
  </a>
10
- <a href="https://github.com/mobile-next/mobile-mcp">
11
- <img src="https://img.shields.io/github/contributors/mobile-next/mobile-mcp?color=green" alt="Mobile Next Downloads" />
12
- </a>
13
10
  <a href="https://www.npmjs.com/package/@mobilenext/mobile-mcp">
14
11
  <img src="https://img.shields.io/npm/dm/@mobilenext/mobile-mcp?logo=npm&style=flat&color=red" alt="npm" />
15
12
  </a>
16
13
  <a href="https://github.com/mobile-next/mobile-mcp/releases">
17
14
  <img src="https://img.shields.io/github/release/mobile-next/mobile-mcp" />
18
15
  </a>
19
- <a href="https://github.com/mobile-next/mobile-mcp/blob/main/LICENSE">
20
- <img src="https://img.shields.io/badge/license-Apache 2.0-blue.svg" alt="Mobile MCP is released under the Apache-2.0 License" />
21
- </a>
22
16
  <a href="https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%7B%22name%22%3A%22mobile-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40mobilenext%2Fmobile-mcp%40latest%22%5D%7D">
23
17
  <img src="https://img.shields.io/badge/VS_Code-VS_Code?style=flat-square&label=Install%20Server&color=0098FF" alt="Install in VS Code" />
24
18
  </a>
25
- </h4>
26
-
27
- <h4 align="center">
28
19
  <a href="https://github.com/mobile-next/mobile-mcp/wiki">
29
20
  <img src="https://img.shields.io/badge/documentation-wiki-blue" alt="wiki" />
30
21
  </a>
@@ -359,6 +350,31 @@ Or add the standard config under `mcpServers` in your settings as shown above.
359
350
 
360
351
  [Read more in our wiki](https://github.com/mobile-next/mobile-mcp/wiki)! 🚀
361
352
 
353
+ ### SSE Server Mode
354
+
355
+ By default, Mobile MCP runs over stdio. To start an SSE server instead, use the `--listen` flag:
356
+
357
+ ```bash
358
+ npx @mobilenext/mobile-mcp@latest --listen 3000
359
+ ```
360
+
361
+ This binds to `localhost:3000`. To bind to a specific interface:
362
+
363
+ ```bash
364
+ npx @mobilenext/mobile-mcp@latest --listen 0.0.0.0:3000
365
+ ```
366
+
367
+ Then configure your MCP client to connect to `http://<host>:3000/mcp`.
368
+
369
+ #### Authorization
370
+
371
+ To require Bearer token authorization on the SSE server, set the `MOBILEMCP_AUTH` environment variable:
372
+
373
+ ```bash
374
+ MOBILEMCP_AUTH=my-secret-token npx @mobilenext/mobile-mcp@latest --listen 3000
375
+ ```
376
+
377
+ When set, all requests must include the header `Authorization: Bearer my-secret-token`.
362
378
 
363
379
  ### 🛠️ How to Use 📝
364
380
 
@@ -444,6 +460,30 @@ When launched, Mobile MCP can connect to:
444
460
 
445
461
  Make sure you have your mobile platform SDKs (Xcode, Android SDK) installed and configured properly before running Mobile Next Mobile MCP.
446
462
 
463
+ ### Telemetry
464
+
465
+ Mobile MCP collects anonymous usage telemetry via PostHog. To disable it, set the `MOBILEMCP_DISABLE_TELEMETRY` environment variable:
466
+
467
+ ```bash
468
+ MOBILEMCP_DISABLE_TELEMETRY=1 npx @mobilenext/mobile-mcp@latest
469
+ ```
470
+
471
+ For json configurations:
472
+
473
+ ```json
474
+ {
475
+ "mcpServers": {
476
+ "mobile-mcp": {
477
+ "command": "npx",
478
+ "args": ["-y", "@mobilenext/mobile-mcp@latest"],
479
+ "env": {
480
+ "MOBILEMCP_DISABLE_TELEMETRY": "1"
481
+ }
482
+ }
483
+ }
484
+ }
485
+ ```
486
+
447
487
  ### Running in "headless" mode on Simulators/Emulators
448
488
 
449
489
  When you do not have a real device connected to your machine, you can run Mobile MCP with an emulator or simulator in the background.
package/lib/index.js CHANGED
@@ -10,9 +10,19 @@ const server_1 = require("./server");
10
10
  const logger_1 = require("./logger");
11
11
  const express_1 = __importDefault(require("express"));
12
12
  const commander_1 = require("commander");
13
- const startSseServer = async (port) => {
13
+ const startSseServer = async (host, port) => {
14
14
  const app = (0, express_1.default)();
15
15
  const server = (0, server_1.createMcpServer)();
16
+ const authToken = process.env.MOBILEMCP_AUTH;
17
+ if (authToken) {
18
+ app.use((req, res, next) => {
19
+ if (req.headers.authorization !== `Bearer ${authToken}`) {
20
+ res.status(401).json({ error: "Unauthorized" });
21
+ return;
22
+ }
23
+ next();
24
+ });
25
+ }
16
26
  let transport = null;
17
27
  app.post("/mcp", (req, res) => {
18
28
  if (transport) {
@@ -26,8 +36,8 @@ const startSseServer = async (port) => {
26
36
  transport = new sse_js_1.SSEServerTransport("/mcp", res);
27
37
  server.connect(transport);
28
38
  });
29
- app.listen(port, () => {
30
- (0, logger_1.error)(`mobile-mcp ${(0, server_1.getAgentVersion)()} sse server listening on http://localhost:${port}/mcp`);
39
+ app.listen(port, host, () => {
40
+ (0, logger_1.error)(`mobile-mcp ${(0, server_1.getAgentVersion)()} sse server listening on http://${host}:${port}/mcp`);
31
41
  });
32
42
  };
33
43
  const startStdioServer = async () => {
@@ -46,12 +56,28 @@ const startStdioServer = async () => {
46
56
  const main = async () => {
47
57
  commander_1.program
48
58
  .version((0, server_1.getAgentVersion)())
49
- .option("--port <port>", "Start SSE server on this port")
59
+ .option("--listen <listen>", "Start SSE server on [host:]port")
50
60
  .option("--stdio", "Start stdio server (default)")
51
61
  .parse(process.argv);
52
62
  const options = commander_1.program.opts();
53
- if (options.port) {
54
- await startSseServer(+options.port);
63
+ if (options.listen) {
64
+ const listen = options.listen.trim();
65
+ const lastColon = listen.lastIndexOf(":");
66
+ let host = "localhost";
67
+ let rawPort;
68
+ if (lastColon > 0) {
69
+ host = listen.substring(0, lastColon);
70
+ rawPort = listen.substring(lastColon + 1);
71
+ }
72
+ else {
73
+ rawPort = listen;
74
+ }
75
+ const port = Number.parseInt(rawPort, 10);
76
+ if (!host || !rawPort || !Number.isInteger(port) || port < 1 || port > 65535) {
77
+ (0, logger_1.error)(`Invalid --listen value "${listen}". Expected [host:]port with port 1-65535.`);
78
+ process.exit(1);
79
+ }
80
+ await startSseServer(host, port);
55
81
  }
56
82
  else {
57
83
  await startStdioServer();
package/lib/server.js CHANGED
@@ -78,6 +78,9 @@ const createMcpServer = () => {
78
78
  }));
79
79
  };
80
80
  const posthog = async (event, properties) => {
81
+ if (process.env.MOBILEMCP_DISABLE_TELEMETRY) {
82
+ return;
83
+ }
81
84
  try {
82
85
  const url = "https://us.i.posthog.com/i/v0/e/";
83
86
  const api_key = "phc_KHRTZmkDsU7A8EbydEK8s4lJpPoTDyyBhSlwer694cS";
@@ -351,6 +354,10 @@ const createMcpServer = () => {
351
354
  device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you."),
352
355
  url: zod_1.z.string().describe("The URL to open"),
353
356
  }, { destructiveHint: true }, async ({ device, url }) => {
357
+ const allowUnsafeUrls = process.env.MOBILEMCP_ALLOW_UNSAFE_URLS === "1";
358
+ if (!allowUnsafeUrls && !url.startsWith("http://") && !url.startsWith("https://")) {
359
+ throw new robot_1.ActionableError("Only http:// and https:// URLs are allowed. Set MOBILEMCP_ALLOW_UNSAFE_URLS=1 to allow other URL schemes.");
360
+ }
354
361
  const robot = getRobotFromDevice(device);
355
362
  await robot.openUrl(url);
356
363
  return `Opened URL: ${url}`;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mobilenext/mobile-mcp",
3
3
  "mcpName": "io.github.mobile-next/mobile-mcp",
4
- "version": "0.0.49",
4
+ "version": "0.0.51",
5
5
  "description": "Mobile MCP",
6
6
  "repository": {
7
7
  "type": "git",