@algosuite/vo-mcp 0.2.0-beta.59 → 0.2.0-beta.61

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.
@@ -546,6 +546,43 @@ function installCodexMcpConfigAt(configPath, cliPath, controlPlaneUrl, log, mana
546
546
  log(`\u2713 Wrote AlgoHQ MCP to Codex: ${configPath}`);
547
547
  }
548
548
 
549
+ // src/remote-mcp-entry.ts
550
+ var REMOTE_MCP_SERVER_KEY = "vo-mcp-remote";
551
+ var REMOTE_MCP_TOKEN_ENV = "VO_MCP_REMOTE_TOKEN";
552
+ var REMOTE_MCP_ENDPOINT_PATH = "/api/v1/mcp";
553
+ var REMOTE_MCP_AUTH_HEADER = `Bearer \${${REMOTE_MCP_TOKEN_ENV}}`;
554
+ function remoteMcpOptIn(env) {
555
+ return (env["VO_REMOTE_MCP"] ?? "").trim() === "1";
556
+ }
557
+ function remoteMcpUrl(controlPlaneUrl) {
558
+ return `${controlPlaneUrl.trim().replace(/\/+$/, "")}${REMOTE_MCP_ENDPOINT_PATH}`;
559
+ }
560
+ function buildRemoteMcpEntry(controlPlaneUrl) {
561
+ return {
562
+ type: "http",
563
+ url: remoteMcpUrl(controlPlaneUrl),
564
+ headers: { Authorization: REMOTE_MCP_AUTH_HEADER }
565
+ };
566
+ }
567
+ function asRecord(value) {
568
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
569
+ }
570
+ function isManagedRemoteMcpEntry(value) {
571
+ const entry = asRecord(value);
572
+ if (!entry) return false;
573
+ if (entry["type"] !== "http") return false;
574
+ const url = entry["url"];
575
+ if (typeof url !== "string" || !url.endsWith(REMOTE_MCP_ENDPOINT_PATH)) return false;
576
+ const headers = asRecord(entry["headers"]);
577
+ return headers?.["Authorization"] === REMOTE_MCP_AUTH_HEADER;
578
+ }
579
+ function remoteMcpEntryIsCurrent(value, desired) {
580
+ const entry = asRecord(value);
581
+ if (!entry) return false;
582
+ const headers = asRecord(entry["headers"]);
583
+ return entry["type"] === desired.type && entry["url"] === desired.url && headers?.["Authorization"] === desired.headers["Authorization"];
584
+ }
585
+
549
586
  // src/autostart.ts
550
587
  import { homedir as homedir3, platform as platform2 } from "node:os";
551
588
  import { isAbsolute as isAbsolute2, join as join5 } from "node:path";
@@ -810,7 +847,20 @@ function resolveVoMcpCliPath() {
810
847
  }
811
848
  var INSTALL_LAUNCHER = { sticky: false, onlyExisting: false };
812
849
  var HEAL_LAUNCHER = { sticky: true, onlyExisting: true };
813
- function installMcpConfigAt(configPath, cliPath, controlPlaneUrl, log, label, launcher = { launcherPath: null, ...INSTALL_LAUNCHER }) {
850
+ function reconcileRemoteEntry(mcpServers, remote) {
851
+ const existing = mcpServers[REMOTE_MCP_SERVER_KEY];
852
+ if (remote) {
853
+ return {
854
+ fragment: { [REMOTE_MCP_SERVER_KEY]: remote },
855
+ current: remoteMcpEntryIsCurrent(existing, remote)
856
+ };
857
+ }
858
+ if (existing !== void 0 && isManagedRemoteMcpEntry(existing)) {
859
+ return { fragment: { [REMOTE_MCP_SERVER_KEY]: void 0 }, current: false };
860
+ }
861
+ return { fragment: {}, current: true };
862
+ }
863
+ function installMcpConfigAt(configPath, cliPath, controlPlaneUrl, log, label, launcher = { launcherPath: null, ...INSTALL_LAUNCHER }, remote = null) {
814
864
  if (launcher.onlyExisting && !existsSync6(configPath)) return;
815
865
  const read = readClaudeConfig(configPath);
816
866
  if (read.kind === "invalid" || read.kind === "empty" && launcher.onlyExisting) {
@@ -824,8 +874,9 @@ function installMcpConfigAt(configPath, cliPath, controlPlaneUrl, log, label, la
824
874
  const voEntry = managedEntry ?? mcpServers["vo"];
825
875
  const { launcherPath } = launcher;
826
876
  const fallbackCli = chooseFallbackCli(voEntry?.env?.[MCP_FALLBACK_CLI_ENV], cliPath, launcher.sticky, launcherPath ? dirname4(launcherPath) : null);
827
- const current = launcherPath ? !isStaleVoMcpEntry(voEntry, launcherPath, fallbackCli) : Boolean(voEntry?.args?.some((a) => a.includes(cliPath)));
828
- if (current) {
877
+ const localCurrent = launcherPath ? !isStaleVoMcpEntry(voEntry, launcherPath, fallbackCli) : Boolean(voEntry?.args?.some((a) => a.includes(cliPath)));
878
+ const remoteState = reconcileRemoteEntry(mcpServers, remote);
879
+ if (localCurrent && remoteState.current) {
829
880
  log(` ${label} already current: ${configPath}`);
830
881
  return;
831
882
  }
@@ -845,7 +896,11 @@ function installMcpConfigAt(configPath, cliPath, controlPlaneUrl, log, label, la
845
896
  ...preservedEnv,
846
897
  ...launcherPath && fallbackCli ? { [MCP_FALLBACK_CLI_ENV]: fallbackCli } : {}
847
898
  }
848
- }
899
+ },
900
+ // Additive remote entry (11.3 slice A) — or the removal of one we wrote,
901
+ // when the operator has opted back out. Spread LAST so it can delete its
902
+ // own key; it never names 'vo-mcp', so the stdio entry above is safe.
903
+ ...remoteState.fragment
849
904
  }
850
905
  };
851
906
  if (readMtime !== null && (!existsSync6(configPath) || statSync3(configPath).mtimeMs !== readMtime)) {
@@ -854,6 +909,12 @@ function installMcpConfigAt(configPath, cliPath, controlPlaneUrl, log, label, la
854
909
  }
855
910
  writeClaudeConfig(configPath, merged);
856
911
  log(`\u2713 Wrote vo-mcp to ${label}: ${configPath}`);
912
+ if (remote) {
913
+ log(` + remote MCP entry '${REMOTE_MCP_SERVER_KEY}' \u2192 ${remote.url} (serves vo_skill_list; every other tool stays on the local vo-mcp entry)`);
914
+ log(` Set ${REMOTE_MCP_TOKEN_ENV} in your environment to authenticate it \u2014 no token is written to this file.`);
915
+ } else if (!remoteState.current) {
916
+ log(` - removed the remote MCP entry '${REMOTE_MCP_SERVER_KEY}' (VO_REMOTE_MCP is not set to 1)`);
917
+ }
857
918
  }
858
919
  function installMcpConfig(log, env, mode = "install") {
859
920
  const home = env["HOME"]?.trim() || env["USERPROFILE"]?.trim() || homedir4();
@@ -861,6 +922,7 @@ function installMcpConfig(log, env, mode = "install") {
861
922
  const plat = platform3();
862
923
  const cliPath = resolveVoMcpCliPath();
863
924
  const controlPlaneUrl = env["VO_CONTROL_PLANE_URL"]?.trim() || DEFAULT_CONTROL_PLANE_URL2;
925
+ const remote = remoteMcpOptIn(env) ? buildRemoteMcpEntry(controlPlaneUrl) : null;
864
926
  const launcherPath = writeMcpLauncherForEnv(env, log, { platform: plat, home });
865
927
  const launcher = { launcherPath, ...mode === "heal" ? HEAL_LAUNCHER : INSTALL_LAUNCHER };
866
928
  const leg = (label, run) => {
@@ -871,8 +933,8 @@ function installMcpConfig(log, env, mode = "install") {
871
933
  log(` \u26A0 ${label}: could not update the MCP registration \u2014 ${err instanceof Error ? err.message : String(err)}`);
872
934
  }
873
935
  };
874
- leg("Claude Code CLI", () => installMcpConfigAt(resolveCodeConfigPath(home), cliPath, controlPlaneUrl, log, "Claude Code CLI", launcher));
875
- leg("Claude Desktop", () => installMcpConfigAt(resolveDesktopConfigPath(home, plat, appData), cliPath, controlPlaneUrl, log, "Claude Desktop", launcher));
936
+ leg("Claude Code CLI", () => installMcpConfigAt(resolveCodeConfigPath(home), cliPath, controlPlaneUrl, log, "Claude Code CLI", launcher, remote));
937
+ leg("Claude Desktop", () => installMcpConfigAt(resolveDesktopConfigPath(home, plat, appData), cliPath, controlPlaneUrl, log, "Claude Desktop", launcher, remote));
876
938
  const codexPath = resolveCodexConfigPath(home);
877
939
  if (launcher.onlyExisting && !existsSync6(codexPath)) return;
878
940
  leg("Codex", () => {