patchxnote-agent 0.2.7 → 0.2.9

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
@@ -9,7 +9,32 @@ PatchXNote Agent is the local AI assistant connector for PatchXNote. It lets an
9
9
  Give this one-line prompt to a local-command-capable AI assistant:
10
10
 
11
11
  ```text
12
- Connect PatchXNote Agent by following the public guide at https://patchx2025.feishu.cn/wiki/PnVRwYT7IirFPckairGcWPnHnCd: run npx -y patchxnote-agent@latest mcp config, add the printed MCP JSON config to this AI assistant, then guide me through npx -y patchxnote-agent@latest login in the editor terminal. Do not ask me to paste OTP codes, access tokens, or refresh tokens into chat. GitHub repository: https://github.com/ZsTs119/patchxnote-agent
12
+ Connect PatchXNote Agent by following the public guide at https://patchx2025.feishu.cn/wiki/PnVRwYT7IirFPckairGcWPnHnCd: run npx -y patchxnote-agent@latest setup --client <my-client>, keep MCP config secret-free, and guide me through login in the same runtime that will launch the MCP server. Do not ask me to paste OTP codes, access tokens, or refresh tokens into chat. GitHub repository: https://github.com/ZsTs119/patchxnote-agent
13
+ ```
14
+
15
+ Run setup for a supported local client:
16
+
17
+ ```sh
18
+ npx -y patchxnote-agent@latest setup --client cursor
19
+ npx -y patchxnote-agent@latest setup --client vscode
20
+ npx -y patchxnote-agent@latest setup --client codex
21
+ ```
22
+
23
+ PatchXNote Agent currently exposes two login surfaces and two MCP service shapes:
24
+
25
+ | Mode | Entry | Use when |
26
+ | --- | --- | --- |
27
+ | Browser MCP login | `npx -y patchxnote-agent@latest mcp login` | Recommended for desktop editors and local MCP hosts. |
28
+ | Terminal CLI login | `npx -y patchxnote-agent@latest login` | Terminal-only users, headless runtimes, or the legacy local Agent path. |
29
+ | Local MCP service | `npx -y patchxnote-agent@latest mcp serve` | VS Code, Cursor, Codex, Claude Desktop, Windsurf, Trae, Qoder, WorkBuddy, and other stdio MCP clients. |
30
+ | Hosted remote MCP gateway | `https://ws-lab.patch-x.cn/patchnote-test-api/mcp` | Feishu Aily, Doubao Work Partner, Tencent Agent Development Platform, enterprise WorkBuddy, and other platform clients that cannot run local commands. |
31
+
32
+ Log in with browser OAuth, then check or clear the MCP login state:
33
+
34
+ ```sh
35
+ npx -y patchxnote-agent@latest mcp login
36
+ npx -y patchxnote-agent@latest mcp status
37
+ npx -y patchxnote-agent@latest mcp logout --local-only
13
38
  ```
14
39
 
15
40
  Print the generic MCP config manually:
@@ -24,12 +49,18 @@ The generated config uses this universal local stdio MCP command:
24
49
  npx -y patchxnote-agent@latest mcp serve
25
50
  ```
26
51
 
27
- Log in from the editor terminal:
52
+ The older terminal Agent login remains available for legacy local CLI/MCP fallback:
28
53
 
29
54
  ```sh
30
55
  npx -y patchxnote-agent@latest login
31
56
  ```
32
57
 
58
+ `setup` reuses the same `mcp login` browser OAuth flow. The GoServer website owns phone OTP input; the local Agent owns the loopback callback, token exchange, secure storage, and stdio bridge. `mcp serve` never opens a browser during editor startup. It stores credentials in the OS-native keychain and keeps MCP config free of phone numbers, OTP codes, access tokens, refresh tokens, webhook secrets, and base URL by default.
59
+
60
+ P0 local client IDs: `vscode`, `cursor`, `codex`, `claude-code`, `claude-desktop`, `windsurf`, `trae`, `qoder`, `workbuddy`.
61
+
62
+ Platform clients such as Feishu Aily, Doubao Work Partner, Tencent Agent Development Platform, and enterprise WorkBuddy need the hosted remote MCP gateway plus platform-console acceptance; local `npx` setup is for desktop and terminal clients.
63
+
33
64
  If a client rejects `npx` or times out during first binary download, run the stable absolute-path fallback:
34
65
 
35
66
  ```sh
@@ -29,10 +29,18 @@ async function main(argv) {
29
29
  await runLogin(parsed);
30
30
  return;
31
31
  }
32
+ if (parsed.command === "setup") {
33
+ await runSetup(parsed);
34
+ return;
35
+ }
32
36
  if (parsed.command === "mcp" && parsed.subcommand === "config") {
33
37
  printUniversalMCPConfig();
34
38
  return;
35
39
  }
40
+ if (parsed.command === "mcp" && ["login", "status", "logout"].includes(parsed.subcommand)) {
41
+ await runMCPSubcommand(parsed);
42
+ return;
43
+ }
36
44
  if (parsed.command === "mcp" && parsed.subcommand === "serve") {
37
45
  await runMCPServe(parsed);
38
46
  return;
@@ -74,6 +82,14 @@ async function runLogin(parsed) {
74
82
  process.exitCode = code;
75
83
  }
76
84
 
85
+ async function runSetup(parsed) {
86
+ const plan = await ensureBinary(parsed.options, { stderr: process.stderr });
87
+ const code = await spawnAndWait(plan.install_path, ["setup", ...parsed.passthroughArgs], {
88
+ stdio: "inherit"
89
+ });
90
+ process.exitCode = code;
91
+ }
92
+
77
93
  async function runMCPServe(parsed) {
78
94
  const plan = await ensureBinary(parsed.options, { stderr: process.stderr });
79
95
  const code = await spawnAndWait(plan.install_path, ["mcp", "serve", ...parsed.passthroughArgs], {
@@ -83,6 +99,14 @@ async function runMCPServe(parsed) {
83
99
  process.exitCode = code;
84
100
  }
85
101
 
102
+ async function runMCPSubcommand(parsed) {
103
+ const plan = await ensureBinary(parsed.options, { stderr: process.stderr });
104
+ const code = await spawnAndWait(plan.install_path, ["mcp", parsed.subcommand, ...parsed.passthroughArgs], {
105
+ stdio: "inherit"
106
+ });
107
+ process.exitCode = code;
108
+ }
109
+
86
110
  function createInstallPlan(command, options = {}) {
87
111
  const target = resolveTarget(options.platform || process.platform, options.arch || process.arch);
88
112
  const installDir = options.installDir || defaultInstallDir(process.platform);
@@ -371,13 +395,21 @@ function parseArgs(argv) {
371
395
  const launcher = parseLauncherOptions(rest, { allowPassthrough: true, rejectPrintConfig: true });
372
396
  return { command, options: launcher.options, passthroughArgs: launcher.passthroughArgs };
373
397
  }
398
+ if (command === "setup") {
399
+ const launcher = parseLauncherOptions(rest, {
400
+ allowPassthrough: true,
401
+ passThroughDryRun: true,
402
+ passThroughPrintConfig: true
403
+ });
404
+ return { command, options: launcher.options, passthroughArgs: launcher.passthroughArgs };
405
+ }
374
406
  if (command === "mcp") {
375
407
  const [subcommand, ...subcommandArgs] = rest;
376
- if (!["serve", "config"].includes(subcommand)) {
408
+ if (!["serve", "config", "login", "status", "logout"].includes(subcommand)) {
377
409
  throw new Error(mcpUsage());
378
410
  }
379
411
  const launcher = parseLauncherOptions(subcommandArgs, {
380
- allowPassthrough: subcommand === "serve",
412
+ allowPassthrough: subcommand !== "config",
381
413
  rejectPrintConfig: true
382
414
  });
383
415
  return { command, subcommand, options: launcher.options, passthroughArgs: launcher.passthroughArgs };
@@ -432,8 +464,16 @@ function parseLauncherOptions(rest, settings = {}) {
432
464
  }
433
465
  throw new Error(`unknown option ${arg}`);
434
466
  case "--dry-run":
467
+ if (settings.passThroughDryRun) {
468
+ passthroughArgs.push(arg);
469
+ break;
470
+ }
435
471
  throw new Error("--dry-run is only valid for install/update/uninstall");
436
472
  case "--print-config":
473
+ if (settings.passThroughPrintConfig) {
474
+ passthroughArgs.push(arg);
475
+ break;
476
+ }
437
477
  if (settings.rejectPrintConfig) {
438
478
  throw new Error("--print-config is not valid for this command");
439
479
  }
@@ -629,11 +669,11 @@ function verifyChecksum(binary, assetName, checksumsText) {
629
669
  }
630
670
 
631
671
  function usage() {
632
- return "usage: patchxnote-agent <install|update|uninstall|login|mcp> [options]";
672
+ return "usage: patchxnote-agent <install|update|uninstall|login|setup|mcp> [options]";
633
673
  }
634
674
 
635
675
  function mcpUsage() {
636
- return "usage: patchxnote-agent mcp <serve|config> [options]";
676
+ return "usage: patchxnote-agent mcp <serve|config|login|status|logout> [options]";
637
677
  }
638
678
 
639
679
  if (require.main === module) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchxnote-agent",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "description": "Installer wrapper for the PatchXNote Agent CLI and local MCP server.",
5
5
  "repository": {
6
6
  "type": "git",