@snapback/cli 1.1.12 → 1.1.15

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 (59) hide show
  1. package/README.md +79 -18
  2. package/dist/SkippedTestDetector-AXTMWWHC.js +5 -0
  3. package/dist/SkippedTestDetector-QLSQV7K7.js +5 -0
  4. package/dist/analysis-6WTBZJH3.js +6 -0
  5. package/dist/analysis-C472LUGW.js +2475 -0
  6. package/dist/auth-HFJRXXG2.js +1446 -0
  7. package/dist/auto-provision-organization-SF6XM7X4.js +161 -0
  8. package/dist/chunk-23G5VYA3.js +4259 -0
  9. package/dist/{chunk-QAKFE3NE.js → chunk-4YTE4JEW.js} +3 -4
  10. package/dist/chunk-5EOPYJ4Y.js +12 -0
  11. package/dist/{chunk-G7QXHNGB.js → chunk-5SQA44V7.js} +1125 -32
  12. package/dist/{chunk-BW7RALUZ.js → chunk-7ADPL4Q3.js} +11 -4
  13. package/dist/chunk-CBGOC6RV.js +293 -0
  14. package/dist/chunk-DNEADD2G.js +3499 -0
  15. package/dist/{chunk-NKBZIXCN.js → chunk-DPWFZNMY.js} +122 -15
  16. package/dist/chunk-GQ73B37K.js +314 -0
  17. package/dist/chunk-HR34NJP7.js +6133 -0
  18. package/dist/chunk-ICKSHS3A.js +2264 -0
  19. package/dist/{chunk-KPETDXQO.js → chunk-OI2HNNT6.js} +565 -50
  20. package/dist/chunk-PL4HF4M2.js +593 -0
  21. package/dist/chunk-WS36HDEU.js +3735 -0
  22. package/dist/chunk-XYU5FFE3.js +111 -0
  23. package/dist/chunk-ZBQDE6WJ.js +108 -0
  24. package/dist/client-WIO6W447.js +8 -0
  25. package/dist/dist-E7E2T3DQ.js +9 -0
  26. package/dist/dist-TEWNOZYS.js +5 -0
  27. package/dist/dist-YZBJAYEJ.js +12 -0
  28. package/dist/index.js +65215 -26627
  29. package/dist/local-service-adapter-3JHN6G4O.js +6 -0
  30. package/dist/pioneer-oauth-hook-V2JKEXM7.js +12 -0
  31. package/dist/{secure-credentials-6UMEU22H.js → secure-credentials-UEPG7GWW.js} +15 -8
  32. package/dist/snapback-dir-MG7DTRMF.js +6 -0
  33. package/package.json +8 -42
  34. package/scripts/postinstall.mjs +2 -3
  35. package/dist/SkippedTestDetector-B3JZUE5G.js +0 -5
  36. package/dist/SkippedTestDetector-B3JZUE5G.js.map +0 -1
  37. package/dist/analysis-Z53F5FT2.js +0 -6
  38. package/dist/analysis-Z53F5FT2.js.map +0 -1
  39. package/dist/chunk-6MR2TINI.js +0 -27
  40. package/dist/chunk-6MR2TINI.js.map +0 -1
  41. package/dist/chunk-BW7RALUZ.js.map +0 -1
  42. package/dist/chunk-G7QXHNGB.js.map +0 -1
  43. package/dist/chunk-ISVRGBWT.js +0 -16223
  44. package/dist/chunk-ISVRGBWT.js.map +0 -1
  45. package/dist/chunk-KPETDXQO.js.map +0 -1
  46. package/dist/chunk-NKBZIXCN.js.map +0 -1
  47. package/dist/chunk-QAKFE3NE.js.map +0 -1
  48. package/dist/chunk-YOVA65PS.js +0 -12745
  49. package/dist/chunk-YOVA65PS.js.map +0 -1
  50. package/dist/dist-7UKXVKH3.js +0 -5
  51. package/dist/dist-7UKXVKH3.js.map +0 -1
  52. package/dist/dist-VDK7WEF4.js +0 -5
  53. package/dist/dist-VDK7WEF4.js.map +0 -1
  54. package/dist/dist-WKLJSPJT.js +0 -8
  55. package/dist/dist-WKLJSPJT.js.map +0 -1
  56. package/dist/index.js.map +0 -1
  57. package/dist/secure-credentials-6UMEU22H.js.map +0 -1
  58. package/dist/snapback-dir-T3CRQRY6.js +0 -6
  59. package/dist/snapback-dir-T3CRQRY6.js.map +0 -1
@@ -1,16 +1,92 @@
1
- #!/usr/bin/env node
2
- import { __name } from './chunk-BW7RALUZ.js';
3
- import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
1
+ #!/usr/bin/env node --no-warnings=ExperimentalWarning
2
+ import { __name } from './chunk-7ADPL4Q3.js';
3
+ import { readFileSync, mkdirSync, writeFileSync, existsSync } from 'fs';
4
4
  import { homedir, platform } from 'os';
5
5
  import { join, resolve, dirname } from 'path';
6
6
  import { randomUUID } from 'crypto';
7
- import { execSync } from 'child_process';
7
+ import { exec, execSync } from 'child_process';
8
+ import { promisify } from 'util';
8
9
 
10
+ process.env.SNAPBACK_CLI='true';
9
11
  var __defProp = Object.defineProperty;
10
12
  var __name2 = /* @__PURE__ */ __name((target, value) => __defProp(target, "name", {
11
13
  value,
12
14
  configurable: true
13
15
  }), "__name");
16
+ var CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
17
+ function getCacheFilePath() {
18
+ return join(homedir(), ".snapback", "mcp-configs", "paths.json");
19
+ }
20
+ __name(getCacheFilePath, "getCacheFilePath");
21
+ __name2(getCacheFilePath, "getCacheFilePath");
22
+ function readCache() {
23
+ try {
24
+ const raw = readFileSync(getCacheFilePath(), "utf-8");
25
+ const parsed = JSON.parse(raw);
26
+ if (parsed.version === 1 && typeof parsed.discovered === "object") {
27
+ return parsed;
28
+ }
29
+ } catch {
30
+ }
31
+ return {
32
+ version: 1,
33
+ discovered: {}
34
+ };
35
+ }
36
+ __name(readCache, "readCache");
37
+ __name2(readCache, "readCache");
38
+ function writeCache(cache) {
39
+ try {
40
+ const dir = join(homedir(), ".snapback", "mcp-configs");
41
+ mkdirSync(dir, {
42
+ recursive: true
43
+ });
44
+ writeFileSync(getCacheFilePath(), JSON.stringify(cache, null, 2));
45
+ } catch {
46
+ }
47
+ }
48
+ __name(writeCache, "writeCache");
49
+ __name2(writeCache, "writeCache");
50
+ function getCachedPath(clientName) {
51
+ const cache = readCache();
52
+ const entry = cache.discovered[clientName];
53
+ if (!entry) return null;
54
+ const age = Date.now() - new Date(entry.discoveredAt).getTime();
55
+ if (age > CACHE_TTL_MS) return null;
56
+ if (!existsSync(entry.path)) {
57
+ delete cache.discovered[clientName];
58
+ writeCache(cache);
59
+ return null;
60
+ }
61
+ return entry.path;
62
+ }
63
+ __name(getCachedPath, "getCachedPath");
64
+ __name2(getCachedPath, "getCachedPath");
65
+ function setCachedPath(clientName, configPath) {
66
+ const cache = readCache();
67
+ cache.discovered[clientName] = {
68
+ path: configPath,
69
+ discoveredAt: /* @__PURE__ */ (/* @__PURE__ */ new Date()).toISOString(),
70
+ platform: process.platform
71
+ };
72
+ writeCache(cache);
73
+ }
74
+ __name(setCachedPath, "setCachedPath");
75
+ __name2(setCachedPath, "setCachedPath");
76
+ function evictCachedPath(clientName) {
77
+ const cache = readCache();
78
+ if (cache.discovered[clientName]) {
79
+ delete cache.discovered[clientName];
80
+ writeCache(cache);
81
+ }
82
+ }
83
+ __name(evictCachedPath, "evictCachedPath");
84
+ __name2(evictCachedPath, "evictCachedPath");
85
+ function getAllCachedPaths() {
86
+ return readCache().discovered;
87
+ }
88
+ __name(getAllCachedPaths, "getAllCachedPaths");
89
+ __name2(getAllCachedPaths, "getAllCachedPaths");
14
90
  var CLIENT_CONFIGS = {
15
91
  claude: /* @__PURE__ */ __name2((home) => {
16
92
  switch (platform()) {
@@ -35,11 +111,17 @@ var CLIENT_CONFIGS = {
35
111
  ] : [],
36
112
  join(_home, ".cursor/mcp.json")
37
113
  ], "cursor"),
114
+ // Windsurf only has a global config — no project-level support (confirmed by Windsurf docs, June 2025)
38
115
  windsurf: /* @__PURE__ */ __name2((home) => [
39
116
  join(home, ".codeium/windsurf/mcp_config.json")
40
117
  ], "windsurf"),
41
- continue: /* @__PURE__ */ __name2((home) => [
42
- join(home, ".continue/config.json")
118
+ // Continue: global config.json or config.yaml; project-level .continue/mcpServers/mcp.json
119
+ continue: /* @__PURE__ */ __name2((home, cwd) => [
120
+ ...cwd ? [
121
+ join(cwd, ".continue/mcpServers/mcp.json")
122
+ ] : [],
123
+ join(home, ".continue/config.json"),
124
+ join(home, ".continue/config.yaml")
43
125
  ], "continue"),
44
126
  // New clients
45
127
  vscode: /* @__PURE__ */ __name2((_home, cwd) => [
@@ -47,9 +129,16 @@ var CLIENT_CONFIGS = {
47
129
  join(cwd, ".vscode/mcp.json")
48
130
  ] : []
49
131
  ], "vscode"),
50
- zed: /* @__PURE__ */ __name2((home) => [
132
+ // Zed: global ~/.config/zed/settings.json, plus project-level .zed/settings.json
133
+ zed: /* @__PURE__ */ __name2((home, cwd) => [
134
+ ...cwd ? [
135
+ join(cwd, ".zed/settings.json")
136
+ ] : [],
51
137
  join(home, ".config/zed/settings.json")
52
138
  ], "zed"),
139
+ // Cline / Roo Code store their actual settings in VS Code extension globalStorage,
140
+ // but `snap tools configure --cline/--roo-code` writes to these paths as a side-channel.
141
+ // Detection via these paths is best-effort; users may need `snap mcp link --client cline` instead.
53
142
  cline: /* @__PURE__ */ __name2((home) => [
54
143
  join(home, ".cline/mcp.json")
55
144
  ], "cline"),
@@ -63,21 +152,31 @@ var CLIENT_CONFIGS = {
63
152
  join(home, ".roo-code/mcp.json")
64
153
  ], "roo-code"),
65
154
  // Qoder (VS Code fork) - supports both project-level and global configs
66
- qoder: /* @__PURE__ */ __name2((home) => {
67
- switch (platform()) {
68
- case "darwin":
69
- return [
70
- join(home, "Library/Application Support/Qoder/SharedClientCache/extension/local/mcp.json")
71
- ];
72
- case "win32":
73
- return [
74
- join(process.env.APPDATA || "", "Qoder/mcp.json")
75
- ];
76
- default:
77
- return [
78
- join(home, ".config/Qoder/mcp.json")
79
- ];
80
- }
155
+ qoder: /* @__PURE__ */ __name2((home, cwd) => {
156
+ const workspaceConfig = cwd ? [
157
+ join(cwd, ".qoder-mcp-config.json")
158
+ ] : [];
159
+ const globalConfigs = (() => {
160
+ switch (platform()) {
161
+ case "darwin":
162
+ return [
163
+ join(home, "Library/Application Support/Qoder/SharedClientCache/mcp.json"),
164
+ join(home, "Library/Application Support/Qoder/SharedClientCache/extension/local/mcp.json")
165
+ ];
166
+ case "win32":
167
+ return [
168
+ join(process.env.APPDATA || "", "Qoder/mcp.json")
169
+ ];
170
+ default:
171
+ return [
172
+ join(home, ".config/Qoder/mcp.json")
173
+ ];
174
+ }
175
+ })();
176
+ return [
177
+ ...workspaceConfig,
178
+ ...globalConfigs
179
+ ];
81
180
  }, "qoder")
82
181
  };
83
182
  var CLIENT_DISPLAY_NAMES = {
@@ -99,7 +198,12 @@ function detectAIClients(options = {}) {
99
198
  const clients = [];
100
199
  const seenPaths = /* @__PURE__ */ new Set();
101
200
  for (const [name, getPaths] of Object.entries(CLIENT_CONFIGS)) {
102
- const paths = getPaths(home, cwd);
201
+ const candidates = getPaths(home, cwd);
202
+ const cachedPath = getCachedPath(name);
203
+ const paths = cachedPath && candidates.includes(cachedPath) ? [
204
+ cachedPath,
205
+ ...candidates.filter((p) => p !== cachedPath)
206
+ ] : candidates;
103
207
  for (const configPath of paths) {
104
208
  if (seenPaths.has(configPath)) {
105
209
  continue;
@@ -108,6 +212,7 @@ function detectAIClients(options = {}) {
108
212
  const exists = existsSync(configPath);
109
213
  let hasSnapback = false;
110
214
  if (exists) {
215
+ setCachedPath(name, configPath);
111
216
  try {
112
217
  const content = readFileSync(configPath, "utf-8");
113
218
  if (configPath.endsWith(".yaml") || configPath.endsWith(".yml")) {
@@ -160,20 +265,34 @@ function checkForSnapback(config, format) {
160
265
  case "claude":
161
266
  case "cursor":
162
267
  case "windsurf":
163
- case "vscode":
164
268
  case "cline":
165
269
  case "roo-code":
270
+ if ("mcpServers" in configObj && typeof configObj.mcpServers === "object" && configObj.mcpServers !== null) {
271
+ const servers = configObj.mcpServers;
272
+ return "snapback" in servers || `snapback-${format}` in servers;
273
+ }
274
+ return false;
166
275
  case "qoder":
167
276
  if ("mcpServers" in configObj && typeof configObj.mcpServers === "object" && configObj.mcpServers !== null) {
168
277
  const servers = configObj.mcpServers;
169
- return "snapback" in servers;
278
+ return Object.keys(servers).some((k) => k === "snapback" || k.startsWith("snapback-"));
279
+ }
280
+ return false;
281
+ case "vscode":
282
+ if ("servers" in configObj && typeof configObj.servers === "object" && configObj.servers !== null) {
283
+ const servers = configObj.servers;
284
+ return "snapback" in servers || "snapback-vscode" in servers;
170
285
  }
171
286
  return false;
172
287
  case "gemini":
173
288
  case "zed":
289
+ if ("context_servers" in configObj && typeof configObj.context_servers === "object" && configObj.context_servers !== null) {
290
+ const servers = configObj.context_servers;
291
+ return "snapback" in servers || "snapback-zed" in servers;
292
+ }
174
293
  if ("mcpServers" in configObj && typeof configObj.mcpServers === "object" && configObj.mcpServers !== null) {
175
294
  const servers = configObj.mcpServers;
176
- return "snapback" in servers;
295
+ return "snapback" in servers || `snapback-${format}` in servers;
177
296
  }
178
297
  return false;
179
298
  case "continue":
@@ -212,6 +331,64 @@ function readClientConfig(client) {
212
331
  }
213
332
  __name(readClientConfig, "readClientConfig");
214
333
  __name2(readClientConfig, "readClientConfig");
334
+ function detectWorkspaceConfig(workspaceRoot) {
335
+ const root = workspaceRoot || process.cwd();
336
+ const qoderConfig = join(root, ".qoder-mcp-config.json");
337
+ if (existsSync(qoderConfig)) {
338
+ try {
339
+ const content = readFileSync(qoderConfig, "utf-8");
340
+ if (content.includes("snapback")) {
341
+ return {
342
+ path: qoderConfig,
343
+ type: "qoder"
344
+ };
345
+ }
346
+ } catch {
347
+ }
348
+ }
349
+ const cursorConfig = join(root, ".cursor", "mcp.json");
350
+ if (existsSync(cursorConfig)) {
351
+ try {
352
+ const content = readFileSync(cursorConfig, "utf-8");
353
+ if (content.includes("snapback")) {
354
+ return {
355
+ path: cursorConfig,
356
+ type: "cursor"
357
+ };
358
+ }
359
+ } catch {
360
+ }
361
+ }
362
+ const vscodeConfig = join(root, ".vscode", "mcp.json");
363
+ if (existsSync(vscodeConfig)) {
364
+ try {
365
+ const content = readFileSync(vscodeConfig, "utf-8");
366
+ if (content.includes("snapback")) {
367
+ return {
368
+ path: vscodeConfig,
369
+ type: "vscode"
370
+ };
371
+ }
372
+ } catch {
373
+ }
374
+ }
375
+ const windsurfConfig = join(root, ".windsurf", "mcp.json");
376
+ if (existsSync(windsurfConfig)) {
377
+ try {
378
+ const content = readFileSync(windsurfConfig, "utf-8");
379
+ if (content.includes("snapback")) {
380
+ return {
381
+ path: windsurfConfig,
382
+ type: "windsurf"
383
+ };
384
+ }
385
+ } catch {
386
+ }
387
+ }
388
+ return null;
389
+ }
390
+ __name(detectWorkspaceConfig, "detectWorkspaceConfig");
391
+ __name2(detectWorkspaceConfig, "detectWorkspaceConfig");
215
392
  function getSnapbackConfigDir() {
216
393
  const isWindows = process.platform === "win32";
217
394
  if (isWindows) {
@@ -308,6 +485,90 @@ function resetIdentityCache() {
308
485
  }
309
486
  __name(resetIdentityCache, "resetIdentityCache");
310
487
  __name2(resetIdentityCache, "resetIdentityCache");
488
+ var execAsync = promisify(exec);
489
+ async function detectMCPProcesses() {
490
+ try {
491
+ const { stdout } = await execAsync('ps aux | grep -E "(mcp.*--stdio|--stdio.*mcp|uvx.*mcp-server|npx.*mcp|node.*mcp)" | grep -v grep', {
492
+ timeout: 5e3
493
+ });
494
+ const processes = parseProcessOutput(stdout);
495
+ const snapbackProcesses = processes.filter((p) => p.isSnapback);
496
+ return {
497
+ allProcesses: processes,
498
+ snapbackProcesses,
499
+ snapbackRunning: snapbackProcesses.length > 0,
500
+ totalCount: processes.length,
501
+ checkedAt: /* @__PURE__ */ new Date()
502
+ };
503
+ } catch {
504
+ return {
505
+ allProcesses: [],
506
+ snapbackProcesses: [],
507
+ snapbackRunning: false,
508
+ totalCount: 0,
509
+ checkedAt: /* @__PURE__ */ new Date()
510
+ };
511
+ }
512
+ }
513
+ __name(detectMCPProcesses, "detectMCPProcesses");
514
+ __name2(detectMCPProcesses, "detectMCPProcesses");
515
+ function parseProcessOutput(output) {
516
+ const lines = output.trim().split("\n").filter((line) => line.trim());
517
+ const processes = [];
518
+ for (const line of lines) {
519
+ const match = line.match(/^(\S+)\s+(\d+)\s+.*?\s+(.+)$/);
520
+ if (!match) {
521
+ continue;
522
+ }
523
+ const [, , pidStr, command] = match;
524
+ const pid = Number.parseInt(pidStr, 10);
525
+ if (Number.isNaN(pid)) {
526
+ continue;
527
+ }
528
+ const serverName = extractServerName(command);
529
+ const isSnapback = command.toLowerCase().includes("snapback");
530
+ processes.push({
531
+ pid,
532
+ command: command.trim(),
533
+ serverName,
534
+ isSnapback
535
+ });
536
+ }
537
+ return processes;
538
+ }
539
+ __name(parseProcessOutput, "parseProcessOutput");
540
+ __name2(parseProcessOutput, "parseProcessOutput");
541
+ function extractServerName(command) {
542
+ const patterns = [
543
+ // snapback mcp --stdio
544
+ /snapback[/\s]/i,
545
+ // mcp-server-fetch
546
+ /mcp-server-(\w+)/,
547
+ // @modelcontextprotocol/server-sequential-thinking
548
+ /server-(\w+)/,
549
+ // context7-mcp
550
+ /(\w+)-mcp/,
551
+ // fly mcp server
552
+ /fly.*mcp/i,
553
+ // supabase-mcp
554
+ /supabase-mcp/i
555
+ ];
556
+ for (const pattern of patterns) {
557
+ const match = command.match(pattern);
558
+ if (match) {
559
+ return match[1] || match[0];
560
+ }
561
+ }
562
+ return "mcp";
563
+ }
564
+ __name(extractServerName, "extractServerName");
565
+ __name2(extractServerName, "extractServerName");
566
+ async function isSnapbackMCPRunning() {
567
+ const health = await detectMCPProcesses();
568
+ return health.snapbackRunning;
569
+ }
570
+ __name(isSnapbackMCPRunning, "isSnapbackMCPRunning");
571
+ __name2(isSnapbackMCPRunning, "isSnapbackMCPRunning");
311
572
  function validateClientConfig(client) {
312
573
  const issues = [];
313
574
  if (!existsSync(client.configPath)) {
@@ -504,7 +765,15 @@ function validateSnapbackConfig(config, issues) {
504
765
  severity: "error",
505
766
  code: "MISSING_STDIO_ARG",
506
767
  message: "Args must include '--stdio' flag",
507
- fix: "Run: snap tools configure --force"
768
+ fix: "Run: snap mcp repair --client <name>"
769
+ });
770
+ }
771
+ if (config.args.includes("shim")) {
772
+ issues.push({
773
+ severity: "error",
774
+ code: "DEPRECATED_SHIM_COMMAND",
775
+ message: "Args contain deprecated 'shim' command - use '--stdio' instead",
776
+ fix: "Run: snap mcp repair --client <name>"
508
777
  });
509
778
  }
510
779
  if (!config.args.includes("--workspace")) {
@@ -623,14 +892,15 @@ function isCommandExecutable2(command) {
623
892
  }
624
893
  __name(isCommandExecutable2, "isCommandExecutable2");
625
894
  __name2(isCommandExecutable2, "isCommandExecutable");
895
+ var STDIO_ONLY_CLIENTS = /* @__PURE__ */ new Set([
896
+ "claude"
897
+ ]);
626
898
  function getSnapbackMCPConfig(options = {}) {
627
- const { apiKey, workspaceId, serverUrl, useNpx = false, useBinary = false, customCommand, additionalEnv, workspaceRoot, useLocalDev = false, localCliPath } = options;
899
+ const { apiKey, workspaceId, serverUrl, useBinary = false, customCommand, additionalEnv, workspaceRoot, useLocalDev = false, localCliPath, client, useDoppler = false, dopplerProject = "snapback-shared", dopplerConfig = "dev", useSse = false, useStreamableHttp = false } = options;
900
+ const useNpx = options.useNpx ?? (client ? STDIO_ONLY_CLIENTS.has(client) : false);
628
901
  const env = {
629
902
  ...additionalEnv
630
903
  };
631
- if (workspaceId) {
632
- env.SNAPBACK_WORKSPACE_ID = workspaceId;
633
- }
634
904
  if (apiKey) {
635
905
  env.SNAPBACK_API_KEY = apiKey;
636
906
  }
@@ -643,9 +913,65 @@ function getSnapbackMCPConfig(options = {}) {
643
913
  }
644
914
  };
645
915
  }
916
+ if (useSse || useStreamableHttp) {
917
+ const url = serverUrl || "https://mcp.snapback.dev/mcp";
918
+ const headers2 = {};
919
+ if (workspaceId) {
920
+ headers2["x-workspace-id"] = workspaceId;
921
+ }
922
+ if (apiKey) {
923
+ headers2["x-api-key"] = apiKey;
924
+ }
925
+ return {
926
+ url,
927
+ ...Object.keys(headers2).length > 0 && {
928
+ headers: headers2
929
+ }
930
+ };
931
+ }
932
+ if (useDoppler && localCliPath) {
933
+ const tier = apiKey ? "pro" : "free";
934
+ const nodePath = resolveNodePath();
935
+ const dopplerArgs = [
936
+ "run",
937
+ "--project",
938
+ dopplerProject,
939
+ "--config",
940
+ dopplerConfig,
941
+ "--",
942
+ nodePath,
943
+ localCliPath,
944
+ "mcp",
945
+ "--stdio",
946
+ "--tier",
947
+ tier
948
+ ];
949
+ if (workspaceRoot) {
950
+ dopplerArgs.push("--workspace", workspaceRoot);
951
+ }
952
+ return {
953
+ command: "doppler",
954
+ args: dopplerArgs
955
+ };
956
+ }
646
957
  if (useNpx) {
958
+ const isClaudeDesktop = client === "claude";
959
+ if (isClaudeDesktop) {
960
+ const args2 = [
961
+ "--yes",
962
+ "@snapback/mcpb"
963
+ ];
964
+ if (workspaceRoot) {
965
+ args2.push(workspaceRoot);
966
+ }
967
+ return {
968
+ command: "npx",
969
+ args: args2
970
+ };
971
+ }
647
972
  const tier = apiKey ? "pro" : "free";
648
973
  const args = [
974
+ "--yes",
649
975
  "@snapback/cli",
650
976
  "mcp",
651
977
  "--stdio",
@@ -663,12 +989,19 @@ function getSnapbackMCPConfig(options = {}) {
663
989
  }
664
990
  };
665
991
  }
666
- if (serverUrl || !useLocalDev && !useBinary) {
667
- const url = serverUrl || "https://snapback-mcp.fly.dev";
992
+ if (serverUrl || !useLocalDev && !useBinary && !useDoppler) {
993
+ const url = serverUrl || "https://mcp.snapback.dev/mcp";
994
+ const headers2 = {};
995
+ if (workspaceId) {
996
+ headers2["x-workspace-id"] = workspaceId;
997
+ }
998
+ if (apiKey) {
999
+ headers2["x-api-key"] = apiKey;
1000
+ }
668
1001
  return {
669
1002
  url,
670
- ...Object.keys(env).length > 0 && {
671
- env
1003
+ ...Object.keys(headers2).length > 0 && {
1004
+ headers: headers2
672
1005
  }
673
1006
  };
674
1007
  }
@@ -712,10 +1045,17 @@ function getSnapbackMCPConfig(options = {}) {
712
1045
  }
713
1046
  };
714
1047
  }
1048
+ const headers = {};
1049
+ if (workspaceId) {
1050
+ headers["x-workspace-id"] = workspaceId;
1051
+ }
1052
+ if (apiKey) {
1053
+ headers["x-api-key"] = apiKey;
1054
+ }
715
1055
  return {
716
- url: "https://snapback-mcp.fly.dev",
717
- ...Object.keys(env).length > 0 && {
718
- env
1056
+ url: "https://mcp.snapback.dev/mcp",
1057
+ ...Object.keys(headers).length > 0 && {
1058
+ headers
719
1059
  }
720
1060
  };
721
1061
  }
@@ -773,6 +1113,10 @@ function removeSnapbackConfig(client) {
773
1113
  case "claude":
774
1114
  case "cursor":
775
1115
  case "windsurf":
1116
+ case "cline":
1117
+ case "roo-code":
1118
+ case "gemini":
1119
+ case "qoder":
776
1120
  if (config.mcpServers?.[serverKey]) {
777
1121
  delete config.mcpServers[serverKey];
778
1122
  }
@@ -780,6 +1124,28 @@ function removeSnapbackConfig(client) {
780
1124
  delete config.mcpServers.snapback;
781
1125
  }
782
1126
  break;
1127
+ case "vscode": {
1128
+ const vscodeConfig = config;
1129
+ const servers = vscodeConfig.servers;
1130
+ if (servers?.[serverKey]) {
1131
+ delete servers[serverKey];
1132
+ }
1133
+ if (servers?.snapback) {
1134
+ delete servers.snapback;
1135
+ }
1136
+ break;
1137
+ }
1138
+ case "zed": {
1139
+ const zedConfig = config;
1140
+ const contextServers = zedConfig.context_servers;
1141
+ if (contextServers?.[serverKey]) {
1142
+ delete contextServers[serverKey];
1143
+ }
1144
+ if (contextServers?.snapback) {
1145
+ delete contextServers.snapback;
1146
+ }
1147
+ break;
1148
+ }
783
1149
  case "continue": {
784
1150
  const experimental = config.experimental;
785
1151
  if (experimental?.modelContextProtocolServers) {
@@ -790,6 +1156,7 @@ function removeSnapbackConfig(client) {
790
1156
  }
791
1157
  }
792
1158
  writeFileSync(client.configPath, JSON.stringify(config, null, 2));
1159
+ evictCachedPath(client.name);
793
1160
  return {
794
1161
  success: true
795
1162
  };
@@ -815,13 +1182,9 @@ function mergeConfig(existing, snapbackConfig, format) {
815
1182
  switch (format) {
816
1183
  case "claude":
817
1184
  case "cursor":
818
- case "windsurf":
819
- case "vscode":
820
1185
  case "cline":
821
1186
  case "roo-code":
822
1187
  case "gemini":
823
- case "zed":
824
- case "qoder":
825
1188
  return {
826
1189
  ...existing,
827
1190
  mcpServers: {
@@ -829,6 +1192,58 @@ function mergeConfig(existing, snapbackConfig, format) {
829
1192
  [serverKey]: snapbackConfig
830
1193
  }
831
1194
  };
1195
+ case "windsurf":
1196
+ return {
1197
+ ...existing,
1198
+ mcpServers: {
1199
+ ...existing.mcpServers || {},
1200
+ [serverKey]: {
1201
+ ...snapbackConfig,
1202
+ disabled: false,
1203
+ alwaysAllow: []
1204
+ }
1205
+ }
1206
+ };
1207
+ case "qoder": {
1208
+ const qoderType = snapbackConfig.url ? "sse" : "stdio";
1209
+ return {
1210
+ ...existing,
1211
+ mcpServers: {
1212
+ ...existing.mcpServers || {},
1213
+ [serverKey]: {
1214
+ type: qoderType,
1215
+ ...snapbackConfig
1216
+ }
1217
+ }
1218
+ };
1219
+ }
1220
+ case "vscode": {
1221
+ const vscodeConfig = existing;
1222
+ const servers = vscodeConfig.servers || {};
1223
+ const { mcpServers: _, ...rest } = vscodeConfig;
1224
+ return {
1225
+ ...rest,
1226
+ servers: {
1227
+ ...servers,
1228
+ [serverKey]: {
1229
+ type: "stdio",
1230
+ ...snapbackConfig
1231
+ }
1232
+ }
1233
+ };
1234
+ }
1235
+ case "zed": {
1236
+ const zedConfig = existing;
1237
+ const contextServers = zedConfig.context_servers || {};
1238
+ const { mcpServers: _, ...rest } = zedConfig;
1239
+ return {
1240
+ ...rest,
1241
+ context_servers: {
1242
+ ...contextServers,
1243
+ [serverKey]: snapbackConfig
1244
+ }
1245
+ };
1246
+ }
832
1247
  case "continue": {
833
1248
  const continueConfig = existing;
834
1249
  const experimental = continueConfig.experimental || {};
@@ -863,6 +1278,87 @@ function mergeConfig(existing, snapbackConfig, format) {
863
1278
  }
864
1279
  __name(mergeConfig, "mergeConfig");
865
1280
  __name2(mergeConfig, "mergeConfig");
1281
+ function patchApiKeyInClientConfig(client, apiKey) {
1282
+ try {
1283
+ if (!existsSync(client.configPath)) return false;
1284
+ const raw = readFileSync(client.configPath, "utf-8");
1285
+ const config = JSON.parse(raw);
1286
+ const serverKey = getServerKey(client.format);
1287
+ let patched = false;
1288
+ const patchEntry = /* @__PURE__ */ __name2((entry) => {
1289
+ if (typeof entry !== "object" || entry === null) return false;
1290
+ const e = entry;
1291
+ if (e.url && typeof e.url === "string") {
1292
+ if (!e.headers || typeof e.headers !== "object") {
1293
+ e.headers = {};
1294
+ }
1295
+ e.headers["x-api-key"] = apiKey;
1296
+ const headers = e.headers;
1297
+ if (headers.Authorization?.includes("<your-token>")) {
1298
+ delete headers.Authorization;
1299
+ }
1300
+ return true;
1301
+ }
1302
+ if (!e.env || typeof e.env !== "object") {
1303
+ e.env = {};
1304
+ }
1305
+ e.env.SNAPBACK_API_KEY = apiKey;
1306
+ return true;
1307
+ }, "patchEntry");
1308
+ switch (client.format) {
1309
+ case "claude":
1310
+ case "cursor":
1311
+ case "windsurf":
1312
+ case "cline":
1313
+ case "roo-code":
1314
+ case "gemini": {
1315
+ const servers = config.mcpServers || {};
1316
+ const entry = servers[serverKey] ?? servers.snapback;
1317
+ if (entry) patched = patchEntry(entry);
1318
+ break;
1319
+ }
1320
+ case "qoder": {
1321
+ const servers = config.mcpServers || {};
1322
+ for (const key of Object.keys(servers)) {
1323
+ if (key === "snapback" || key.startsWith("snapback-")) {
1324
+ patched = patchEntry(servers[key]) || patched;
1325
+ }
1326
+ }
1327
+ break;
1328
+ }
1329
+ case "vscode": {
1330
+ const servers = config.servers || {};
1331
+ const entry = servers[serverKey] ?? servers.snapback;
1332
+ if (entry) patched = patchEntry(entry);
1333
+ break;
1334
+ }
1335
+ case "zed": {
1336
+ const servers = config.context_servers || {};
1337
+ const entry = servers[serverKey] ?? servers.snapback;
1338
+ if (entry) patched = patchEntry(entry);
1339
+ break;
1340
+ }
1341
+ case "continue": {
1342
+ const exp = config.experimental || {};
1343
+ const list = exp.modelContextProtocolServers || [];
1344
+ for (const item of list) {
1345
+ if (typeof item.name === "string" && item.name.startsWith("snapback")) {
1346
+ patched = patchEntry(item) || patched;
1347
+ }
1348
+ }
1349
+ break;
1350
+ }
1351
+ }
1352
+ if (patched) {
1353
+ writeFileSync(client.configPath, JSON.stringify(config, null, 2));
1354
+ }
1355
+ return patched;
1356
+ } catch {
1357
+ return false;
1358
+ }
1359
+ }
1360
+ __name(patchApiKeyInClientConfig, "patchApiKeyInClientConfig");
1361
+ __name2(patchApiKeyInClientConfig, "patchApiKeyInClientConfig");
866
1362
  function validateConfig(client) {
867
1363
  try {
868
1364
  const content = readFileSync(client.configPath, "utf-8");
@@ -872,15 +1368,33 @@ function validateConfig(client) {
872
1368
  case "claude":
873
1369
  case "cursor":
874
1370
  case "windsurf":
875
- case "vscode":
876
1371
  case "cline":
877
1372
  case "roo-code":
878
1373
  case "gemini":
879
- case "zed":
880
1374
  case "qoder": {
881
1375
  const serverConfig = config.mcpServers?.[serverKey] || config.mcpServers?.snapback;
882
1376
  return Boolean(serverConfig?.command || serverConfig?.url);
883
1377
  }
1378
+ case "vscode": {
1379
+ const vscodeConfig = config;
1380
+ const servers = vscodeConfig.servers;
1381
+ const serverConfig = servers?.[serverKey] || servers?.snapback;
1382
+ if (typeof serverConfig === "object" && serverConfig !== null) {
1383
+ const cfg = serverConfig;
1384
+ return Boolean(cfg.command || cfg.url);
1385
+ }
1386
+ return false;
1387
+ }
1388
+ case "zed": {
1389
+ const zedConfig = config;
1390
+ const contextServers = zedConfig.context_servers;
1391
+ const serverConfig = contextServers?.[serverKey] || contextServers?.snapback;
1392
+ if (typeof serverConfig === "object" && serverConfig !== null) {
1393
+ const cfg = serverConfig;
1394
+ return Boolean(cfg.command || cfg.url);
1395
+ }
1396
+ return false;
1397
+ }
884
1398
  case "continue": {
885
1399
  const expCfg = config.experimental;
886
1400
  const srvs = expCfg?.modelContextProtocolServers;
@@ -1007,6 +1521,7 @@ function attemptFix(client, issue, _validation, options) {
1007
1521
  case "MISSING_ARGS":
1008
1522
  case "MISSING_MCP_ARG":
1009
1523
  case "MISSING_STDIO_ARG":
1524
+ case "DEPRECATED_SHIM_COMMAND":
1010
1525
  case "INVALID_URL":
1011
1526
  return performFullReconfiguration(client, options);
1012
1527
  case "COMMAND_NOT_EXECUTABLE": {
@@ -1072,7 +1587,8 @@ function performFullReconfiguration(client, options) {
1072
1587
  workspaceId: options.workspaceId,
1073
1588
  workspaceRoot,
1074
1589
  useLocalDev: true,
1075
- localCliPath: cliPath
1590
+ localCliPath: cliPath,
1591
+ client: client.format
1076
1592
  });
1077
1593
  const nodePath = resolveNodePath();
1078
1594
  console.error(`[MCP Repair] Using node path: ${nodePath}`);
@@ -1080,9 +1596,10 @@ function performFullReconfiguration(client, options) {
1080
1596
  mcpConfig = getSnapbackMCPConfig({
1081
1597
  apiKey: options.apiKey,
1082
1598
  workspaceId: options.workspaceId,
1083
- useLocalDev: false
1599
+ useLocalDev: false,
1600
+ client: client.format
1084
1601
  });
1085
- console.error("[MCP Repair] Using remote HTTP mode (CLI not found locally)");
1602
+ console.error("[MCP Repair] Using default mode (CLI not found locally)");
1086
1603
  }
1087
1604
  const writeResult = writeClientConfig(client, mcpConfig);
1088
1605
  if (writeResult.success) {
@@ -1155,6 +1672,4 @@ function findCliPath() {
1155
1672
  __name(findCliPath, "findCliPath");
1156
1673
  __name2(findCliPath, "findCliPath");
1157
1674
 
1158
- export { createManagedMetadata, detectAIClients, getClient, getClientConfigPath, getConfiguredClients, getOrCreateIdentity, getServerKey, getSnapbackConfigDir, getSnapbackMCPConfig, injectWorkspacePath, isCommandExecutable2, isOwnedByThisInstall, readClientConfig, removeSnapbackConfig, repairClientConfig, resetIdentityCache, resolveNodePath, validateClientConfig, validateConfig, validateWorkspacePath, writeClientConfig };
1159
- //# sourceMappingURL=chunk-KPETDXQO.js.map
1160
- //# sourceMappingURL=chunk-KPETDXQO.js.map
1675
+ export { createManagedMetadata, detectAIClients, detectMCPProcesses, detectWorkspaceConfig, evictCachedPath, getAllCachedPaths, getCachedPath, getClient, getClientConfigPath, getConfiguredClients, getOrCreateIdentity, getServerKey, getSnapbackConfigDir, getSnapbackMCPConfig, injectWorkspacePath, isCommandExecutable2, isOwnedByThisInstall, isSnapbackMCPRunning, patchApiKeyInClientConfig, readClientConfig, removeSnapbackConfig, repairClientConfig, resetIdentityCache, resolveNodePath, setCachedPath, validateClientConfig, validateConfig, validateWorkspacePath, writeClientConfig };