@kwonye/mcpx 0.1.94 → 0.1.96

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 (69) hide show
  1. package/dist/adapters/claude-desktop.d.ts.map +1 -1
  2. package/dist/adapters/claude.d.ts +2 -1
  3. package/dist/adapters/claude.d.ts.map +1 -1
  4. package/dist/adapters/cline.d.ts +3 -1
  5. package/dist/adapters/cline.d.ts.map +1 -1
  6. package/dist/adapters/codex.d.ts +2 -1
  7. package/dist/adapters/codex.d.ts.map +1 -1
  8. package/dist/adapters/cursor.d.ts +2 -1
  9. package/dist/adapters/cursor.d.ts.map +1 -1
  10. package/dist/adapters/hermes.d.ts +11 -0
  11. package/dist/adapters/hermes.d.ts.map +1 -0
  12. package/dist/adapters/index.d.ts.map +1 -1
  13. package/dist/adapters/kiro.d.ts.map +1 -1
  14. package/dist/adapters/openclaw.d.ts +11 -0
  15. package/dist/adapters/openclaw.d.ts.map +1 -0
  16. package/dist/adapters/opencode.d.ts +2 -1
  17. package/dist/adapters/opencode.d.ts.map +1 -1
  18. package/dist/adapters/qwen.d.ts.map +1 -1
  19. package/dist/adapters/utils/index.d.ts +7 -1
  20. package/dist/adapters/utils/index.d.ts.map +1 -1
  21. package/dist/adapters/vscode.d.ts +2 -1
  22. package/dist/adapters/vscode.d.ts.map +1 -1
  23. package/dist/{cli-n8vt375e.js → cli-2vg0te30.js} +715 -211
  24. package/dist/{cli-154shqmt.js → cli-ap2jhwnz.js} +311 -95
  25. package/dist/{cli-tk8bggg5.js → cli-remv48t3.js} +4 -2
  26. package/dist/{cli-csfsg1yf.js → cli-v27bt25d.js} +79 -7
  27. package/dist/{cli-9fmn9y72.js → cli-z1fv3ra8.js} +105 -29
  28. package/dist/cli.d.ts.map +1 -1
  29. package/dist/cli.js +362 -75
  30. package/dist/compat/hermes.d.ts +7 -0
  31. package/dist/compat/hermes.d.ts.map +1 -0
  32. package/dist/compat/index.d.ts.map +1 -1
  33. package/dist/compat/openclaw.d.ts +7 -0
  34. package/dist/compat/openclaw.d.ts.map +1 -0
  35. package/dist/{config-dtc3c79c.js → config-5p08cb0c.js} +1 -1
  36. package/dist/core/add-command.d.ts.map +1 -1
  37. package/dist/core/config-store.d.ts +30 -0
  38. package/dist/core/config-store.d.ts.map +1 -1
  39. package/dist/core/config.d.ts.map +1 -1
  40. package/dist/core/daemon.d.ts +5 -1
  41. package/dist/core/daemon.d.ts.map +1 -1
  42. package/dist/core/errors.d.ts.map +1 -1
  43. package/dist/core/index.d.ts +2 -2
  44. package/dist/core/index.d.ts.map +1 -1
  45. package/dist/core/index.js +16 -67
  46. package/dist/core/managed-index-lock.d.ts +2 -0
  47. package/dist/core/managed-index-lock.d.ts.map +1 -0
  48. package/dist/core/oauth.d.ts.map +1 -1
  49. package/dist/core/plugin-host.d.ts +2 -0
  50. package/dist/core/plugin-host.d.ts.map +1 -0
  51. package/dist/core/plugin-manager.d.ts +19 -6
  52. package/dist/core/plugin-manager.d.ts.map +1 -1
  53. package/dist/core/plugin-parse.d.ts.map +1 -1
  54. package/dist/core/plugin-projections.d.ts.map +1 -1
  55. package/dist/core/skill-projections.d.ts +3 -0
  56. package/dist/core/skill-projections.d.ts.map +1 -0
  57. package/dist/core/status.d.ts.map +1 -1
  58. package/dist/core/sync.d.ts.map +1 -1
  59. package/dist/core/update-manager.d.ts.map +1 -1
  60. package/dist/gateway/server.d.ts.map +1 -1
  61. package/dist/plugin-host-73dvcen6.js +129 -0
  62. package/dist/{plugin-manager-1sjwfnah.js → plugin-manager-y5txkse1.js} +12 -4
  63. package/dist/{registry-n12thgf2.js → registry-bnjb2345.js} +1 -1
  64. package/dist/types.d.ts +3 -1
  65. package/dist/types.d.ts.map +1 -1
  66. package/dist/version.d.ts +1 -1
  67. package/dist/version.d.ts.map +1 -1
  68. package/package.json +3 -2
  69. package/dist/cli-mxmgxdm2.js +0 -2257
package/dist/cli.js CHANGED
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- APP_VERSION,
4
3
  STATUS_CLIENTS,
5
4
  applyAuthReference,
6
5
  buildStatusReport,
@@ -14,6 +13,8 @@ import {
14
13
  listAuthBindings,
15
14
  mapRegistryToSpec,
16
15
  maybePrefixBearer,
16
+ mutateActiveConfig,
17
+ mutateConfig,
17
18
  performRollback,
18
19
  performUpdate,
19
20
  probeHttpAuthRequirement,
@@ -30,8 +31,9 @@ import {
30
31
  startDaemon,
31
32
  stopDaemon,
32
33
  toSecretRef
33
- } from "./cli-mxmgxdm2.js";
34
+ } from "./cli-ap2jhwnz.js";
34
35
  import {
36
+ APP_VERSION,
35
37
  deleteSkill,
36
38
  getAdapters,
37
39
  getGatewayUrl,
@@ -41,7 +43,7 @@ import {
41
43
  persistSyncState,
42
44
  saveSkill,
43
45
  syncAllClients
44
- } from "./cli-n8vt375e.js";
46
+ } from "./cli-2vg0te30.js";
45
47
  import {
46
48
  ConfigLoadError,
47
49
  loadConfig,
@@ -50,7 +52,7 @@ import {
50
52
  resolveActiveConfig,
51
53
  saveConfig,
52
54
  saveProjectConfig
53
- } from "./cli-csfsg1yf.js";
55
+ } from "./cli-v27bt25d.js";
54
56
  import {
55
57
  SecretsManager,
56
58
  addServer,
@@ -60,7 +62,7 @@ import {
60
62
  removeServer,
61
63
  rotateGatewayToken,
62
64
  setServerEnabled
63
- } from "./cli-tk8bggg5.js";
65
+ } from "./cli-remv48t3.js";
64
66
  import {
65
67
  getConfigPath,
66
68
  getManagedIndexPath,
@@ -731,6 +733,203 @@ function parseQwenArgs(argv) {
731
733
  }
732
734
  }
733
735
 
736
+ // src/compat/openclaw.ts
737
+ function parseOpenClawArgs(args) {
738
+ if (args.length === 0) {
739
+ return { error: "Usage: mcpx openclaw mcp add <name> --url <url> | --command <cmd>" };
740
+ }
741
+ let name;
742
+ let url;
743
+ let command;
744
+ let transport;
745
+ const headers = [];
746
+ const envVars = [];
747
+ const commandArgs = [];
748
+ let cwd;
749
+ let hasAuthOAuth = false;
750
+ let hasInclude = false;
751
+ let hasExclude = false;
752
+ let hasTimeout = false;
753
+ let hasConnectTimeout = false;
754
+ for (let i = 0;i < args.length; i++) {
755
+ const arg = args[i];
756
+ if (!name && !arg.startsWith("--")) {
757
+ name = arg;
758
+ continue;
759
+ }
760
+ if (arg === "--url") {
761
+ url = args[++i];
762
+ } else if (arg === "--command") {
763
+ command = args[++i];
764
+ } else if (arg === "--transport") {
765
+ transport = args[++i];
766
+ } else if (arg === "--header") {
767
+ const val = args[++i];
768
+ if (val && !val.startsWith("--")) {
769
+ headers.push(val);
770
+ }
771
+ } else if (arg === "--arg") {
772
+ const val = args[++i];
773
+ if (val && !val.startsWith("--")) {
774
+ commandArgs.push(val);
775
+ }
776
+ } else if (arg === "--env") {
777
+ const val = args[++i];
778
+ if (val && !val.startsWith("--")) {
779
+ envVars.push(val);
780
+ }
781
+ } else if (arg === "--cwd") {
782
+ cwd = args[++i];
783
+ } else if (arg === "--auth") {
784
+ const val = args[++i];
785
+ if (val === "oauth") {
786
+ hasAuthOAuth = true;
787
+ }
788
+ } else if (arg.startsWith("--include")) {
789
+ hasInclude = true;
790
+ } else if (arg.startsWith("--exclude")) {
791
+ hasExclude = true;
792
+ } else if (arg === "--timeout") {
793
+ hasTimeout = true;
794
+ i++;
795
+ } else if (arg === "--connect-timeout") {
796
+ hasConnectTimeout = true;
797
+ i++;
798
+ }
799
+ }
800
+ if (!name) {
801
+ return { error: "Server name is required." };
802
+ }
803
+ if (hasAuthOAuth) {
804
+ return { error: "--auth oauth is not supported. Use `mcpx auth` to configure auth after adding the server." };
805
+ }
806
+ if (hasInclude || hasExclude) {
807
+ return { error: "--include/--exclude are not supported. Use `mcpx add` directly for advanced configuration." };
808
+ }
809
+ if (url && command) {
810
+ return { error: "Cannot combine --url and --command. Specify one transport mode." };
811
+ }
812
+ if (hasTimeout) {
813
+ return { error: "--timeout is not supported. Configure timeouts in the server config after adding." };
814
+ }
815
+ if (hasConnectTimeout) {
816
+ return { error: "--connect-timeout is not supported. Configure timeouts in the server config after adding." };
817
+ }
818
+ if (url) {
819
+ const spec = {
820
+ transport: "http",
821
+ url
822
+ };
823
+ if (headers.length > 0) {
824
+ const headerObj = {};
825
+ for (const h of headers) {
826
+ const colonIndex = h.indexOf(":");
827
+ if (colonIndex > 0) {
828
+ const key = h.slice(0, colonIndex).trim();
829
+ const value = h.slice(colonIndex + 1).trim();
830
+ headerObj[key] = value;
831
+ }
832
+ }
833
+ spec.headers = headerObj;
834
+ }
835
+ return { name, spec };
836
+ }
837
+ if (command) {
838
+ const spec = {
839
+ transport: "stdio",
840
+ command
841
+ };
842
+ if (commandArgs.length > 0) {
843
+ spec.args = commandArgs;
844
+ }
845
+ if (envVars.length > 0) {
846
+ const envObj = {};
847
+ for (const e of envVars) {
848
+ const eqIndex = e.indexOf("=");
849
+ if (eqIndex > 0) {
850
+ envObj[e.slice(0, eqIndex)] = e.slice(eqIndex + 1);
851
+ }
852
+ }
853
+ spec.env = envObj;
854
+ }
855
+ if (cwd) {
856
+ spec.cwd = cwd;
857
+ }
858
+ return { name, spec };
859
+ }
860
+ return { error: "Server name is required." };
861
+ }
862
+
863
+ // src/compat/hermes.ts
864
+ function parseHermesArgs(args) {
865
+ if (args.length === 0) {
866
+ return { error: "Usage: mcpx hermes mcp add <name> --url <url> | --command <cmd>" };
867
+ }
868
+ let name;
869
+ let url;
870
+ let command;
871
+ const envVars = [];
872
+ const commandArgs = [];
873
+ let hasAuth = false;
874
+ let hasPreset = false;
875
+ for (let i = 0;i < args.length; i++) {
876
+ const arg = args[i];
877
+ if (!name && !arg.startsWith("--")) {
878
+ name = arg;
879
+ continue;
880
+ }
881
+ if (arg === "--url") {
882
+ url = args[++i];
883
+ } else if (arg === "--command") {
884
+ command = args[++i];
885
+ } else if (arg === "--args") {
886
+ while (i + 1 < args.length && !args[i + 1].startsWith("--")) {
887
+ commandArgs.push(args[++i]);
888
+ }
889
+ } else if (arg === "--env") {
890
+ const val = args[++i];
891
+ if (val && !val.startsWith("--")) {
892
+ envVars.push(val);
893
+ }
894
+ } else if (arg === "--auth") {
895
+ hasAuth = true;
896
+ } else if (arg === "--preset") {
897
+ hasPreset = true;
898
+ i++;
899
+ }
900
+ }
901
+ if (!name) {
902
+ return { error: "Server name is required." };
903
+ }
904
+ if (hasAuth) {
905
+ return { error: "--auth is not supported. Use `mcpx auth` to configure auth after adding the server." };
906
+ }
907
+ if (hasPreset) {
908
+ return { error: "--preset is not supported. Use `mcpx add` directly for advanced configuration." };
909
+ }
910
+ if (url) {
911
+ return { name, spec: { transport: "http", url } };
912
+ }
913
+ if (command) {
914
+ const spec = { transport: "stdio", command };
915
+ if (commandArgs.length > 0) {
916
+ spec.args = commandArgs;
917
+ }
918
+ if (envVars.length > 0) {
919
+ const envObj = {};
920
+ for (const e of envVars) {
921
+ const eqIndex = e.indexOf("=");
922
+ if (eqIndex > 0) {
923
+ envObj[e.slice(0, eqIndex)] = e.slice(eqIndex + 1);
924
+ }
925
+ }
926
+ spec.env = envObj;
927
+ }
928
+ return { name, spec };
929
+ }
930
+ return { error: "Server name is required." };
931
+ }
932
+
734
933
  // src/compat/unsupported.ts
735
934
  var UNSUPPORTED_CLIENTS = {
736
935
  "cursor-agent": "Cursor MCP management uses a different interface. Use `mcpx add <name> <url|command>` directly to add MCP servers to mcpx.",
@@ -827,11 +1026,68 @@ function parseCompatibilityArgs(argv) {
827
1026
  normalizedArgs: result.normalizedArgs
828
1027
  };
829
1028
  }
1029
+ if (argv[0] === "openclaw" && argv[1] === "mcp" && argv[2] === "add") {
1030
+ const openclawArgs = argv.slice(3);
1031
+ const result = parseOpenClawArgs(openclawArgs);
1032
+ if ("error" in result) {
1033
+ return {
1034
+ client: "openclaw",
1035
+ normalizedArgs: null,
1036
+ error: result.error
1037
+ };
1038
+ }
1039
+ return {
1040
+ client: "openclaw",
1041
+ normalizedArgs: ["--name", result.name, ...buildSpecArgs(result.spec)]
1042
+ };
1043
+ }
1044
+ if (argv[0] === "hermes" && argv[1] === "mcp" && argv[2] === "add") {
1045
+ const hermesArgs = argv.slice(3);
1046
+ const result = parseHermesArgs(hermesArgs);
1047
+ if ("error" in result) {
1048
+ return {
1049
+ client: "hermes",
1050
+ normalizedArgs: null,
1051
+ error: result.error
1052
+ };
1053
+ }
1054
+ return {
1055
+ client: "hermes",
1056
+ normalizedArgs: ["--name", result.name, ...buildSpecArgs(result.spec)]
1057
+ };
1058
+ }
830
1059
  return {
831
1060
  client: null,
832
1061
  normalizedArgs: null
833
1062
  };
834
1063
  }
1064
+ function buildSpecArgs(spec) {
1065
+ const args = [];
1066
+ if (spec.transport === "http") {
1067
+ args.push(spec.url);
1068
+ if (spec.headers) {
1069
+ for (const [k, v] of Object.entries(spec.headers)) {
1070
+ args.push("--header", `${k}=${v}`);
1071
+ }
1072
+ }
1073
+ } else {
1074
+ args.push("--command", spec.command);
1075
+ if (Array.isArray(spec.args) && spec.args.length > 0) {
1076
+ for (const a of spec.args) {
1077
+ args.push("--arg", a);
1078
+ }
1079
+ }
1080
+ if (spec.env) {
1081
+ for (const [k, v] of Object.entries(spec.env)) {
1082
+ args.push("--env", `${k}=${v}`);
1083
+ }
1084
+ }
1085
+ if (spec.cwd) {
1086
+ args.push("--cwd", spec.cwd);
1087
+ }
1088
+ }
1089
+ return args;
1090
+ }
835
1091
 
836
1092
  // src/core/proxy.ts
837
1093
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
@@ -1059,6 +1315,10 @@ function printSyncSummary(summary, asJson = false) {
1059
1315
  }
1060
1316
  process.stdout.write(`
1061
1317
  `);
1318
+ if (result.driftedEntries && result.driftedEntries.length > 0) {
1319
+ process.stdout.write(` (note: ${result.driftedEntries.length} manually-edited entr${result.driftedEntries.length === 1 ? "y was" : "ies were"} reset to mcpx-managed values: ${result.driftedEntries.join(", ")})
1320
+ `);
1321
+ }
1062
1322
  }
1063
1323
  }
1064
1324
  async function ensureDaemonIfEnabled(cliPath, secrets) {
@@ -1071,12 +1331,14 @@ async function ensureDaemonIfEnabled(cliPath, secrets) {
1071
1331
  }
1072
1332
  await startDaemon(config, cliPath, secrets);
1073
1333
  }
1074
- async function autoSyncManagedEntries(config, cliPath) {
1334
+ async function autoSyncManagedEntries(cliPath) {
1075
1335
  const secrets = new SecretsManager;
1076
1336
  await ensureDaemonIfEnabled(cliPath, secrets);
1337
+ const config = loadMergedConfig();
1077
1338
  const summary = syncAllClients(config, secrets);
1078
- persistSyncState(summary, config);
1079
- saveConfig(config);
1339
+ await mutateConfig((freshConfig) => {
1340
+ persistSyncState(summary, freshConfig);
1341
+ });
1080
1342
  printSyncSummary(summary, false);
1081
1343
  ensureExitCodeForSyncFailures(summary.hasErrors);
1082
1344
  }
@@ -1600,7 +1862,7 @@ async function setServerEnabledInteractively(rl, serverName, enabled, cliPath) {
1600
1862
  `);
1601
1863
  process.stdout.write(`Auto-syncing managed gateway entries across all supported clients...
1602
1864
  `);
1603
- await autoSyncManagedEntries(loadMergedConfig(), cliPath);
1865
+ await autoSyncManagedEntries(cliPath);
1604
1866
  return true;
1605
1867
  }
1606
1868
  }
@@ -1614,7 +1876,7 @@ async function setServerEnabledInteractively(rl, serverName, enabled, cliPath) {
1614
1876
  `);
1615
1877
  process.stdout.write(`Auto-syncing managed gateway entries across all supported clients...
1616
1878
  `);
1617
- await autoSyncManagedEntries(loadMergedConfig(), cliPath);
1879
+ await autoSyncManagedEntries(cliPath);
1618
1880
  return true;
1619
1881
  }
1620
1882
  function buildServerActionTitle(server) {
@@ -1736,25 +1998,23 @@ async function runInteractiveStatusMenu(cliPath) {
1736
1998
  }
1737
1999
  function registerEnabledCommand(parent, enabled, cliPath) {
1738
2000
  parent.command(enabled ? "enable <name>" : "disable <name>").option("-g, --global", "Force target the global configuration").option("-l, --local", "Force target (or initialize) a local `.mcpx.json` configuration").description(`${enabled ? "Enable" : "Disable"} an upstream MCP server`).action(async (name, options) => {
1739
- const context = resolveActiveConfig({ global: options.global, local: options.local });
1740
- setServerEnabled(context.config, name, enabled);
1741
- context.save();
1742
- if (context.type === "project" && context.projectPath) {
1743
- const globalConfig = loadConfig();
1744
- registerProject(globalConfig, context.projectPath);
1745
- saveConfig(globalConfig);
2001
+ const { type, projectPath } = await mutateActiveConfig({ global: options.global, local: options.local }, (config) => {
2002
+ setServerEnabled(config, name, enabled);
2003
+ });
2004
+ if (type === "project" && projectPath) {
2005
+ await mutateConfig((globalConfig) => {
2006
+ registerProject(globalConfig, projectPath, globalConfig.projects?.[path.resolve(projectPath)]?.name);
2007
+ });
1746
2008
  }
1747
- process.stdout.write(`${enabled ? "Enabled" : "Disabled"} server: ${name} (${context.type} config)
2009
+ process.stdout.write(`${enabled ? "Enabled" : "Disabled"} server: ${name} (${type} config)
1748
2010
  `);
1749
2011
  process.stdout.write(`Auto-syncing managed gateway entries across all supported clients...
1750
2012
  `);
1751
- const mergedConfig = loadMergedConfig();
1752
- await autoSyncManagedEntries(mergedConfig, cliPath);
2013
+ await autoSyncManagedEntries(cliPath);
1753
2014
  });
1754
2015
  }
1755
2016
  function registerAddCommand(parent, cliPath) {
1756
2017
  parent.command("add [values...]").allowUnknownOption(true).option("--transport <transport>", "MCP transport (auto|http|stdio)", "auto").option("--header <header>", "Header entry in KEY=VALUE form", (value, previous = []) => [...previous, value], []).option("--env <env>", "Env entry in KEY=VALUE form for stdio upstreams", (value, previous = []) => [...previous, value], []).option("--cwd <cwd>", "Working directory for stdio upstream").option("--force", "Overwrite existing server with same name").option("-g, --global", "Force saving to global configuration").option("-l, --local", "Force saving to local project configuration").description("Add an upstream MCP server").action(async (values, options) => {
1757
- const context = resolveActiveConfig({ global: options.global, local: options.local });
1758
2018
  const safeValues = values ?? [];
1759
2019
  const secrets = new SecretsManager;
1760
2020
  if (safeValues.length === 1 && safeValues[0]?.includes("/")) {
@@ -1809,46 +2069,46 @@ Value: ` : `${input.name} (${input.kind}): `;
1809
2069
  spec.env = Object.keys(env).length > 0 ? env : undefined;
1810
2070
  }
1811
2071
  }
1812
- if (context.type === "project") {
1813
- const globalConfig = loadConfig();
1814
- registerProject(globalConfig, context.projectPath);
1815
- saveConfig(globalConfig);
1816
- }
1817
- addServer(context.config, shortName, spec, options.force ?? false);
1818
2072
  await maybeAutoConfigureAuthForAddedServer(shortName, spec, secrets);
1819
- context.save();
1820
- process.stdout.write(`Added server: ${shortName} (${spec.transport}) from registry "${registryName}"${context.type === "project" ? ` (project: ${context.projectPath})` : ""}
2073
+ const { type, projectPath } = await mutateActiveConfig({ global: options.global, local: options.local }, (config) => {
2074
+ addServer(config, shortName, spec, options.force ?? false);
2075
+ });
2076
+ if (type === "project" && projectPath) {
2077
+ await mutateConfig((globalConfig) => {
2078
+ registerProject(globalConfig, projectPath, globalConfig.projects?.[path.resolve(projectPath)]?.name);
2079
+ });
2080
+ }
2081
+ process.stdout.write(`Added server: ${shortName} (${spec.transport}) from registry "${registryName}"${type === "project" ? ` (project: ${projectPath})` : ""}
1821
2082
  `);
1822
2083
  } else {
1823
2084
  const parsed = parseAddServerSpec(safeValues, options);
1824
- if (context.type === "project") {
1825
- const globalConfig = loadConfig();
1826
- registerProject(globalConfig, context.projectPath);
1827
- saveConfig(globalConfig);
1828
- }
1829
- addServer(context.config, parsed.name, parsed.spec, options.force ?? false);
1830
2085
  await maybeAutoConfigureAuthForAddedServer(parsed.name, parsed.spec, secrets);
1831
- context.save();
1832
- process.stdout.write(`Added server: ${parsed.name} (${parsed.spec.transport})${context.type === "project" ? ` (project: ${context.projectPath})` : ""}
2086
+ const { type, projectPath } = await mutateActiveConfig({ global: options.global, local: options.local }, (config) => {
2087
+ addServer(config, parsed.name, parsed.spec, options.force ?? false);
2088
+ });
2089
+ if (type === "project" && projectPath) {
2090
+ await mutateConfig((globalConfig) => {
2091
+ registerProject(globalConfig, projectPath, globalConfig.projects?.[path.resolve(projectPath)]?.name);
2092
+ });
2093
+ }
2094
+ process.stdout.write(`Added server: ${parsed.name} (${parsed.spec.transport})${type === "project" ? ` (project: ${projectPath})` : ""}
1833
2095
  `);
1834
2096
  }
1835
2097
  process.stdout.write(`Auto-syncing managed gateway entries across all supported clients...
1836
2098
  `);
1837
- const mergedConfig = loadMergedConfig();
1838
- await autoSyncManagedEntries(mergedConfig, cliPath);
2099
+ await autoSyncManagedEntries(cliPath);
1839
2100
  });
1840
2101
  }
1841
2102
  function registerRemoveCommand(parent, cliPath) {
1842
2103
  parent.command("remove <name>").option("--force", "Do not error if server does not exist").option("-g, --global", "Force target global configuration").option("-l, --local", "Force target local project configuration").description("Remove an upstream MCP server").action(async (name, options) => {
1843
- const context = resolveActiveConfig({ global: options.global, local: options.local });
1844
- removeServer(context.config, name, options.force ?? false);
1845
- context.save();
1846
- process.stdout.write(`Removed server: ${name} ${context.type === "project" ? `from project: ${context.projectPath}` : "globally"}
2104
+ const { type, projectPath } = await mutateActiveConfig({ global: options.global, local: options.local }, (config) => {
2105
+ removeServer(config, name, options.force ?? false);
2106
+ });
2107
+ process.stdout.write(`Removed server: ${name} ${type === "project" ? `from project: ${projectPath}` : "globally"}
1847
2108
  `);
1848
2109
  process.stdout.write(`Auto-syncing managed gateway entries across all supported clients...
1849
2110
  `);
1850
- const mergedConfig = loadMergedConfig();
1851
- await autoSyncManagedEntries(mergedConfig, cliPath);
2111
+ await autoSyncManagedEntries(cliPath);
1852
2112
  });
1853
2113
  }
1854
2114
  function registerListCommand(parent) {
@@ -1919,12 +2179,12 @@ function registerListCommand(parent) {
1919
2179
  });
1920
2180
  }
1921
2181
  function registerSyncCommand(program, cliPath) {
1922
- program.command("sync [clients...]").option("--client <id>", "Limit sync to specific client(s), comma-separated or repeated", (value, prev = []) => [...prev, value], []).option("--json", "Output JSON").description("Sync gateway configuration to supported clients (e.g. `mcpx sync claude`)").action(async (clients, options) => {
2182
+ program.command("sync [clients...]").option("--client <id>", "Limit sync to specific client(s), comma-separated or repeated", (value, prev = []) => [...prev, value], []).option("--import", "Also scan clients for unmanaged servers and adopt them into the mcpx catalog", false).option("--json", "Output JSON").description("Sync gateway configuration to supported clients (e.g. `mcpx sync claude`)").action(async (clients, options) => {
1923
2183
  const config = loadConfig();
1924
2184
  const targetClients = parseClientList([...clients ?? [], ...options.client ?? []]);
1925
2185
  const secrets = new SecretsManager;
1926
2186
  await ensureDaemonIfEnabled(cliPath, secrets);
1927
- const summary = syncAllClients(config, secrets, { targetClients });
2187
+ const summary = syncAllClients(config, secrets, { targetClients, importScan: options.import ?? false });
1928
2188
  persistSyncState(summary, config);
1929
2189
  saveConfig(config);
1930
2190
  printSyncSummary(summary, options.json ?? false);
@@ -2316,11 +2576,11 @@ function registerProjectCommands(program, cliPath) {
2316
2576
  name: projectName,
2317
2577
  servers: {}
2318
2578
  };
2319
- const { saveProjectConfig: saveProjectConfig2 } = await import("./config-dtc3c79c.js");
2579
+ const { saveProjectConfig: saveProjectConfig2 } = await import("./config-5p08cb0c.js");
2320
2580
  saveProjectConfig2(localConfig, targetPath);
2321
2581
  process.stdout.write(`Initialized project configuration at: ${targetPath}
2322
2582
  `);
2323
- const { registerProject: registerProject2 } = await import("./registry-n12thgf2.js");
2583
+ const { registerProject: registerProject2 } = await import("./registry-bnjb2345.js");
2324
2584
  const globalConfig = loadConfig();
2325
2585
  registerProject2(globalConfig, process.cwd(), projectName);
2326
2586
  saveConfig(globalConfig);
@@ -2351,21 +2611,20 @@ function registerProjectCommands(program, cliPath) {
2351
2611
  process.exit(1);
2352
2612
  }
2353
2613
  const entry = globalConfig.projects[resolvedPath];
2354
- const { unregisterProject: unregisterProject2 } = await import("./registry-n12thgf2.js");
2614
+ const { unregisterProject: unregisterProject2 } = await import("./registry-bnjb2345.js");
2355
2615
  unregisterProject2(globalConfig, resolvedPath);
2356
2616
  saveConfig(globalConfig);
2357
2617
  process.stdout.write(`Unregistered project "${entry.name}" (${resolvedPath}) from the global configuration.
2358
2618
  `);
2359
2619
  process.stdout.write(`Auto-syncing managed gateway entries across all supported clients...
2360
2620
  `);
2361
- const mergedConfig = loadMergedConfig();
2362
- await autoSyncManagedEntries(mergedConfig, cliPath);
2621
+ await autoSyncManagedEntries(cliPath);
2363
2622
  });
2364
2623
  }
2365
2624
  function registerPluginCommands(program, _cliPath) {
2366
2625
  const plugin = program.command("plugin").description("Manage plugins");
2367
2626
  plugin.command("inspect <source>").description("Inspect plugin manifest and components").action(async (source) => {
2368
- const { inspectPlugin } = await import("./plugin-manager-1sjwfnah.js");
2627
+ const { inspectPlugin } = await import("./plugin-manager-y5txkse1.js");
2369
2628
  try {
2370
2629
  const info = await inspectPlugin(source);
2371
2630
  process.stdout.write(JSON.stringify(info, null, 2) + `
@@ -2377,7 +2636,7 @@ function registerPluginCommands(program, _cliPath) {
2377
2636
  }
2378
2637
  });
2379
2638
  plugin.command("install <source>").option("--name <name>", "Plugin name").option("--no-enable", "Don't enable plugin after install").description("Install plugin").action(async (source, options) => {
2380
- const { installPlugin } = await import("./plugin-manager-1sjwfnah.js");
2639
+ const { installPlugin } = await import("./plugin-manager-y5txkse1.js");
2381
2640
  try {
2382
2641
  const p = await installPlugin(source, {
2383
2642
  name: options.name,
@@ -2392,7 +2651,7 @@ function registerPluginCommands(program, _cliPath) {
2392
2651
  }
2393
2652
  });
2394
2653
  plugin.command("approve <name> <component>").description("Approve a plugin component (hooks, mcpServers)").action(async (name, component) => {
2395
- const { approvePluginComponent } = await import("./plugin-manager-1sjwfnah.js");
2654
+ const { approvePluginComponent } = await import("./plugin-manager-y5txkse1.js");
2396
2655
  try {
2397
2656
  await approvePluginComponent(name, component);
2398
2657
  process.stdout.write(`Approved ${component} for plugin ${name}
@@ -2404,7 +2663,7 @@ function registerPluginCommands(program, _cliPath) {
2404
2663
  }
2405
2664
  });
2406
2665
  plugin.command("prepare <name>").description("Install plugin dependencies").action(async (name) => {
2407
- const { preparePlugin } = await import("./plugin-manager-1sjwfnah.js");
2666
+ const { preparePlugin } = await import("./plugin-manager-y5txkse1.js");
2408
2667
  try {
2409
2668
  await preparePlugin(name);
2410
2669
  process.stdout.write(`Plugin ${name} prepared
@@ -2416,7 +2675,7 @@ function registerPluginCommands(program, _cliPath) {
2416
2675
  }
2417
2676
  });
2418
2677
  plugin.command("update <name>").description("Update plugin to latest version").action(async (name) => {
2419
- const { updatePlugin } = await import("./plugin-manager-1sjwfnah.js");
2678
+ const { updatePlugin } = await import("./plugin-manager-y5txkse1.js");
2420
2679
  try {
2421
2680
  const p = await updatePlugin(name);
2422
2681
  process.stdout.write(`Plugin ${name} updated to ${p.version}
@@ -2428,7 +2687,7 @@ function registerPluginCommands(program, _cliPath) {
2428
2687
  }
2429
2688
  });
2430
2689
  plugin.command("uninstall <name>").option("--keep-data", "Keep plugin data after uninstall").description("Uninstall plugin").action(async (name, options) => {
2431
- const { uninstallPlugin } = await import("./plugin-manager-1sjwfnah.js");
2690
+ const { uninstallPlugin } = await import("./plugin-manager-y5txkse1.js");
2432
2691
  try {
2433
2692
  await uninstallPlugin(name, options.keepData || false);
2434
2693
  process.stdout.write(`Plugin ${name} uninstalled
@@ -2439,24 +2698,40 @@ function registerPluginCommands(program, _cliPath) {
2439
2698
  process.exit(1);
2440
2699
  }
2441
2700
  });
2442
- plugin.command("enable <name>").description("Enable plugin").action(async (name) => {
2443
- const { enablePlugin } = await import("./plugin-manager-1sjwfnah.js");
2701
+ plugin.command("enable <name>").option("--project <path>", "Scope this enable to a single registered project instead of globally").description("Enable plugin (globally, or for one project with --project)").action(async (name, options) => {
2444
2702
  try {
2445
- await enablePlugin(name);
2446
- process.stdout.write(`Plugin ${name} enabled
2703
+ if (options.project) {
2704
+ const { setPluginProjectOverride } = await import("./plugin-manager-y5txkse1.js");
2705
+ const resolvedPath = path.resolve(options.project);
2706
+ await setPluginProjectOverride(name, resolvedPath, { enabled: true });
2707
+ process.stdout.write(`Plugin ${name} enabled for project: ${resolvedPath}
2447
2708
  `);
2709
+ } else {
2710
+ const { enablePlugin } = await import("./plugin-manager-y5txkse1.js");
2711
+ await enablePlugin(name);
2712
+ process.stdout.write(`Plugin ${name} enabled
2713
+ `);
2714
+ }
2448
2715
  } catch (e) {
2449
2716
  process.stderr.write(`Error: ${e.message}
2450
2717
  `);
2451
2718
  process.exit(1);
2452
2719
  }
2453
2720
  });
2454
- plugin.command("disable <name>").description("Disable plugin").action(async (name) => {
2455
- const { disablePlugin } = await import("./plugin-manager-1sjwfnah.js");
2721
+ plugin.command("disable <name>").option("--project <path>", "Scope this disable to a single registered project instead of globally").description("Disable plugin (globally, or for one project with --project)").action(async (name, options) => {
2456
2722
  try {
2457
- await disablePlugin(name);
2458
- process.stdout.write(`Plugin ${name} disabled
2723
+ if (options.project) {
2724
+ const { setPluginProjectOverride } = await import("./plugin-manager-y5txkse1.js");
2725
+ const resolvedPath = path.resolve(options.project);
2726
+ await setPluginProjectOverride(name, resolvedPath, { enabled: false });
2727
+ process.stdout.write(`Plugin ${name} disabled for project: ${resolvedPath}
2459
2728
  `);
2729
+ } else {
2730
+ const { disablePlugin } = await import("./plugin-manager-y5txkse1.js");
2731
+ await disablePlugin(name);
2732
+ process.stdout.write(`Plugin ${name} disabled
2733
+ `);
2734
+ }
2460
2735
  } catch (e) {
2461
2736
  process.stderr.write(`Error: ${e.message}
2462
2737
  `);
@@ -2464,7 +2739,7 @@ function registerPluginCommands(program, _cliPath) {
2464
2739
  }
2465
2740
  });
2466
2741
  plugin.command("status [name]").description("Show plugin status").action(async (name) => {
2467
- const { getPluginStatus, listPlugins } = await import("./plugin-manager-1sjwfnah.js");
2742
+ const { getPluginStatus, listPlugins } = await import("./plugin-manager-y5txkse1.js");
2468
2743
  try {
2469
2744
  if (name) {
2470
2745
  const p = await getPluginStatus(name);
@@ -2487,6 +2762,12 @@ function registerPluginCommands(program, _cliPath) {
2487
2762
  }
2488
2763
  });
2489
2764
  }
2765
+ function registerPluginHostCommand(program) {
2766
+ program.command("plugin-host <plugin> <server>").description("Run a plugin MCP server under mcpx policy enforcement").action(async (plugin, server) => {
2767
+ const { runPluginHost } = await import("./plugin-host-73dvcen6.js");
2768
+ runPluginHost(plugin, server);
2769
+ });
2770
+ }
2490
2771
  function registerProxyCommand(program) {
2491
2772
  program.command("proxy <name>").description("Run a stdio MCP proxy bridging to the local mcpx HTTP gateway for the given upstream server").action(async (name) => {
2492
2773
  await runStdioProxy(name);
@@ -2511,14 +2792,19 @@ async function runCli(argv = process.argv) {
2511
2792
  const stagedCliPath = getStagedCliPath();
2512
2793
  const stagedInfo = getStagedUpdate();
2513
2794
  if (stagedCliPath && stagedInfo && stagedCliPath !== argv[1] && shouldUseStagedCli(stagedInfo.version, APP_VERSION)) {
2514
- execFileSync(process.execPath, [stagedCliPath, ...rawArgs], {
2515
- stdio: "inherit",
2516
- env: {
2517
- ...process.env,
2518
- MCPX_USING_STAGED: "1"
2519
- }
2520
- });
2521
- return;
2795
+ try {
2796
+ execFileSync(process.execPath, [stagedCliPath, ...rawArgs], {
2797
+ stdio: "inherit",
2798
+ env: {
2799
+ ...process.env,
2800
+ MCPX_USING_STAGED: "1"
2801
+ }
2802
+ });
2803
+ return;
2804
+ } catch (error) {
2805
+ process.stderr.write(`Warning: staged update v${stagedInfo.version} failed to run (${error.message}). ` + `Falling back to the currently installed version (v${APP_VERSION}). ` + `Run "mcpx update rollback" to clear the broken staged update.
2806
+ `);
2807
+ }
2522
2808
  }
2523
2809
  }
2524
2810
  if (rawArgs.length > 0) {
@@ -2548,6 +2834,7 @@ async function runCli(argv = process.argv) {
2548
2834
  registerAuthCommands(program);
2549
2835
  registerClientsCommands(program);
2550
2836
  registerSkillsCommands(program);
2837
+ registerPluginHostCommand(program);
2551
2838
  registerProxyCommand(program);
2552
2839
  registerMcpCompat(program, cliPath);
2553
2840
  registerUpdateCommand(program);