@ada-mcp/mcp-server 0.1.4 → 0.1.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/README.md CHANGED
@@ -8,6 +8,14 @@ ADA MCP server package that supports:
8
8
 
9
9
  ## Run with pnpm(推荐,尤其 Windows)
10
10
 
11
+ **全程自动选最快镜像(推荐):**
12
+
13
+ ```bash
14
+ pnpm dlx @ada-mcp/launcher
15
+ ```
16
+
17
+ 或直接(`0.1.5+` 在同次 dlx 安装依赖时 `preinstall` 测速):
18
+
11
19
  ```bash
12
20
  pnpm dlx @ada-mcp/mcp-server
13
21
  ```
@@ -45,8 +53,9 @@ npx -y @ada-mcp/mcp-server
45
53
 
46
54
  | 阶段 | 自动探测最快镜像 |
47
55
  |------|------------------|
48
- | `pnpm dlx` / `npx` 拉 MCP 包 | `npm_config_registry` 或 `pnpm dlx --registry …` |
49
- | 启动后 `install-deps` | 内置五家国内镜像 + 官方源测速选最快(**无需配置**) |
56
+ | `pnpm dlx @ada-mcp/launcher` | **是**拉包前测速(推荐) |
57
+ | `pnpm dlx @ada-mcp/mcp-server` | tarball 仍走本机源;**同次安装的依赖**由 `preinstall` 测速(0.1.5+) |
58
+ | 启动后 `install-deps` | 是 — 内置五家国内镜像测速(**无需配置**) |
50
59
 
51
60
  默认 npm 探测候选(按优先级,延迟相同取靠前):阿里云 npmmirror → 腾讯云 → 清华 → 华为云 → 网易 → npm 官方。
52
61
 
@@ -104,10 +113,10 @@ npx -y @ada-mcp/mcp-server
104
113
  "mcpServers": {
105
114
  "ada-mcp": {
106
115
  "command": "pnpm",
107
- "args": ["dlx", "@ada-mcp/mcp-server@0.1.3"],
108
- "env": {
109
- "npm_config_registry": "https://registry.npmmirror.com"
110
- }
116
+ "args": ["dlx", "@ada-mcp/launcher"]
117
+ ```
118
+
119
+ 或 `["dlx", "@ada-mcp/mcp-server@0.1.5"]`(依赖安装走 preinstall 探测,无需 `npm_config_registry`)
111
120
  }
112
121
  }
113
122
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ada-mcp/mcp-server",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "ADA MCP server for web/mobile automation (stdio + remote HTTP)",
5
5
  "private": false,
6
6
  "type": "commonjs",
@@ -12,9 +12,12 @@
12
12
  "files": [
13
13
  "dist/cli.cjs",
14
14
  "plugins",
15
+ "scripts/preinstall-registry.mjs",
16
+ "scripts/registry-probe.mjs",
15
17
  "README.md"
16
18
  ],
17
19
  "scripts": {
20
+ "preinstall": "node scripts/preinstall-registry.mjs",
18
21
  "dev": "tsx src/cli.ts",
19
22
  "prebuild": "node ../../scripts/generate-bundled-config.mjs",
20
23
  "build": "tsc -p tsconfig.json",
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * pnpm dlx / npm install 本包时:在安装 dependencies 之前测速并写入 .npmrc,
4
+ * 使同一次安装中的 playwright 等依赖走最快 registry。
5
+ */
6
+ import fs from "node:fs";
7
+ import path from "node:path";
8
+ import { detectBestRegistry, registryCandidateList } from "./registry-probe.mjs";
9
+
10
+ function installRoot() {
11
+ const init = process.env.INIT_CWD?.trim();
12
+ if (init && fs.existsSync(init)) {
13
+ return init;
14
+ }
15
+ return process.cwd();
16
+ }
17
+
18
+ function shouldRunProbe() {
19
+ if (process.env.ADA_MCP_SKIP_REGISTRY_PROBE === "1") {
20
+ return false;
21
+ }
22
+ if (process.env.ADA_MCP_FORCE_PREINSTALL_PROBE === "1") {
23
+ return true;
24
+ }
25
+ const init = (process.env.INIT_CWD || "").replace(/\\/g, "/");
26
+ if (/[\\/]dlx[\\/]/.test(init) || init.includes("__npx")) {
27
+ return true;
28
+ }
29
+ if (init) {
30
+ try {
31
+ if (fs.existsSync(path.join(init, "pnpm-workspace.yaml"))) {
32
+ return false;
33
+ }
34
+ } catch {
35
+ // ignore
36
+ }
37
+ }
38
+ return init.length > 0;
39
+ }
40
+
41
+ async function main() {
42
+ if (!shouldRunProbe()) {
43
+ return;
44
+ }
45
+ const root = installRoot();
46
+ const candidates = registryCandidateList();
47
+ const { best, probeResults } = await detectBestRegistry(candidates);
48
+ const npmrcPath = path.join(root, ".npmrc");
49
+ const line = `registry=${best}\n`;
50
+ let existing = "";
51
+ try {
52
+ existing = fs.readFileSync(npmrcPath, "utf8");
53
+ } catch {
54
+ // new file
55
+ }
56
+ if (!existing.includes(`registry=${best}`)) {
57
+ fs.writeFileSync(npmrcPath, `${existing}${line}`, "utf8");
58
+ }
59
+ console.error(
60
+ `[ada-mcp preinstall] registry probe: selected ${best} (candidates: ${candidates.join(", ")})`
61
+ );
62
+ for (const { candidate, latency } of probeResults) {
63
+ console.error(`[ada-mcp preinstall] ${candidate} -> ${latency === null ? "fail" : `${latency}ms`}`);
64
+ }
65
+ }
66
+
67
+ main().catch((error) => {
68
+ console.error("[ada-mcp preinstall] registry probe failed:", error);
69
+ process.exit(0);
70
+ });
@@ -0,0 +1,76 @@
1
+ /**
2
+ * 零依赖 npm registry 测速(供 preinstall / launcher 共用)
3
+ */
4
+ export const DEFAULT_NPM_REGISTRY_CANDIDATES = [
5
+ "https://registry.npmmirror.com",
6
+ "https://mirrors.cloud.tencent.com/npm",
7
+ "https://mirrors.tuna.tsinghua.edu.cn/npm",
8
+ "https://repo.huaweicloud.com/repository/npm",
9
+ "https://mirrors.163.com/npm",
10
+ "https://registry.npmjs.org"
11
+ ];
12
+
13
+ function normalizeRegistryUrl(url) {
14
+ return String(url).replace(/\/$/, "");
15
+ }
16
+
17
+ export function registryCandidateList(extraEnv) {
18
+ const primary = normalizeRegistryUrl(
19
+ process.env.ADA_NPM_PROXY_REGISTRY?.trim() || DEFAULT_NPM_REGISTRY_CANDIDATES[0]
20
+ );
21
+ const extra = extraEnv?.trim()
22
+ ? extraEnv.split(",").map((x) => normalizeRegistryUrl(x.trim())).filter(Boolean)
23
+ : process.env.ADA_REGISTRY_CANDIDATES?.trim()
24
+ ? process.env.ADA_REGISTRY_CANDIDATES.split(",").map((x) => normalizeRegistryUrl(x.trim())).filter(Boolean)
25
+ : [];
26
+ const ordered = [primary, ...DEFAULT_NPM_REGISTRY_CANDIDATES, ...extra];
27
+ const seen = new Set();
28
+ const out = [];
29
+ for (const url of ordered) {
30
+ const n = normalizeRegistryUrl(url);
31
+ if (!seen.has(n)) {
32
+ seen.add(n);
33
+ out.push(n);
34
+ }
35
+ }
36
+ return out;
37
+ }
38
+
39
+ async function probeRegistryLatency(registry) {
40
+ const target = `${normalizeRegistryUrl(registry)}/appium`;
41
+ const started = Date.now();
42
+ const controller = new AbortController();
43
+ const timer = setTimeout(() => controller.abort(), 5000);
44
+ try {
45
+ const response = await fetch(target, { method: "GET", signal: controller.signal });
46
+ if (!response.ok) return null;
47
+ return Date.now() - started;
48
+ } catch {
49
+ return null;
50
+ } finally {
51
+ clearTimeout(timer);
52
+ }
53
+ }
54
+
55
+ export async function detectBestRegistry(candidates = registryCandidateList()) {
56
+ const probeResults = await Promise.all(
57
+ candidates.map(async (candidate) => ({
58
+ candidate,
59
+ latency: await probeRegistryLatency(candidate)
60
+ }))
61
+ );
62
+ let best = candidates[0] ?? DEFAULT_NPM_REGISTRY_CANDIDATES[0];
63
+ let bestLatency = Number.POSITIVE_INFINITY;
64
+ let bestPriority = Number.POSITIVE_INFINITY;
65
+ for (const { candidate, latency } of probeResults) {
66
+ if (latency === null) continue;
67
+ const priority = candidates.indexOf(candidate);
68
+ const prio = priority >= 0 ? priority : Number.POSITIVE_INFINITY;
69
+ if (latency < bestLatency || (latency === bestLatency && prio < bestPriority)) {
70
+ best = candidate;
71
+ bestLatency = latency;
72
+ bestPriority = prio;
73
+ }
74
+ }
75
+ return { best: normalizeRegistryUrl(best), candidates, probeResults };
76
+ }