@mastra/code-sdk 1.0.3-alpha.0 → 1.1.0-alpha.2

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 (258) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/acp/agent.js +155 -167
  3. package/dist/acp/agent.js.map +1 -1
  4. package/dist/acp/event-mapper.js +193 -168
  5. package/dist/acp/event-mapper.js.map +1 -1
  6. package/dist/acp/index.js +60 -49
  7. package/dist/acp/index.js.map +1 -1
  8. package/dist/acp/server.js +31 -30
  9. package/dist/acp/server.js.map +1 -1
  10. package/dist/acp.js +1 -4
  11. package/dist/agents/credential-resolver.js +40 -29
  12. package/dist/agents/credential-resolver.js.map +1 -1
  13. package/dist/agents/custom-provider-source.js +16 -9
  14. package/dist/agents/custom-provider-source.js.map +1 -1
  15. package/dist/agents/instructions.js +27 -36
  16. package/dist/agents/instructions.js.map +1 -1
  17. package/dist/agents/mastracode-gateway.js +355 -428
  18. package/dist/agents/mastracode-gateway.js.map +1 -1
  19. package/dist/agents/memory.js +87 -78
  20. package/dist/agents/memory.js.map +1 -1
  21. package/dist/agents/model.js +114 -119
  22. package/dist/agents/model.js.map +1 -1
  23. package/dist/agents/modes/build.js +12 -13
  24. package/dist/agents/modes/build.js.map +1 -1
  25. package/dist/agents/modes/explore.js +14 -13
  26. package/dist/agents/modes/explore.js.map +1 -1
  27. package/dist/agents/modes/plan.js +14 -15
  28. package/dist/agents/modes/plan.js.map +1 -1
  29. package/dist/agents/prompts/agent-instructions.js +78 -69
  30. package/dist/agents/prompts/agent-instructions.js.map +1 -1
  31. package/dist/agents/prompts/build.js +19 -16
  32. package/dist/agents/prompts/build.js.map +1 -1
  33. package/dist/agents/prompts/fast.js +8 -4
  34. package/dist/agents/prompts/fast.js.map +1 -1
  35. package/dist/agents/prompts/index.js +48 -47
  36. package/dist/agents/prompts/index.js.map +1 -1
  37. package/dist/agents/prompts/model.js +6 -5
  38. package/dist/agents/prompts/model.js.map +1 -1
  39. package/dist/agents/prompts/plan.js +20 -16
  40. package/dist/agents/prompts/plan.js.map +1 -1
  41. package/dist/agents/prompts/tool-guidance.js +77 -109
  42. package/dist/agents/prompts/tool-guidance.js.map +1 -1
  43. package/dist/agents/sandbox-filesystem.js +245 -259
  44. package/dist/agents/sandbox-filesystem.js.map +1 -1
  45. package/dist/agents/sandbox-reattach.js +9 -11
  46. package/dist/agents/sandbox-reattach.js.map +1 -1
  47. package/dist/agents/thread-caveman-state.js +92 -81
  48. package/dist/agents/thread-caveman-state.js.map +1 -1
  49. package/dist/agents/tool-availability.js +62 -80
  50. package/dist/agents/tool-availability.js.map +1 -1
  51. package/dist/agents/tools.js +99 -139
  52. package/dist/agents/tools.js.map +1 -1
  53. package/dist/agents/workspace.js +232 -225
  54. package/dist/agents/workspace.js.map +1 -1
  55. package/dist/analytics.js +139 -128
  56. package/dist/analytics.js.map +1 -1
  57. package/dist/auth/authorization-input.js +39 -25
  58. package/dist/auth/authorization-input.js.map +1 -1
  59. package/dist/auth/device-code.js +112 -80
  60. package/dist/auth/device-code.js.map +1 -1
  61. package/dist/auth/index.js +2 -9
  62. package/dist/auth/pkce.js +27 -16
  63. package/dist/auth/pkce.js.map +1 -1
  64. package/dist/auth/providers/anthropic.js +107 -93
  65. package/dist/auth/providers/anthropic.js.map +1 -1
  66. package/dist/auth/providers/github-copilot.js +304 -293
  67. package/dist/auth/providers/github-copilot.js.map +1 -1
  68. package/dist/auth/providers/openai-codex.js +442 -460
  69. package/dist/auth/providers/openai-codex.js.map +1 -1
  70. package/dist/auth/providers/xai.js +179 -145
  71. package/dist/auth/providers/xai.js.map +1 -1
  72. package/dist/auth/storage.js +182 -175
  73. package/dist/auth/storage.js.map +1 -1
  74. package/dist/auth/types.js +1 -1
  75. package/dist/clipboard/index.js +206 -172
  76. package/dist/clipboard/index.js.map +1 -1
  77. package/dist/constants.js +11 -16
  78. package/dist/constants.js.map +1 -1
  79. package/dist/error-classification.js +19 -11
  80. package/dist/error-classification.js.map +1 -1
  81. package/dist/evals/context-builder.js +145 -104
  82. package/dist/evals/context-builder.js.map +1 -1
  83. package/dist/evals/index.js +4 -7
  84. package/dist/evals/scorers/classify-command.js +62 -41
  85. package/dist/evals/scorers/classify-command.js.map +1 -1
  86. package/dist/evals/scorers/efficiency.js +239 -181
  87. package/dist/evals/scorers/efficiency.js.map +1 -1
  88. package/dist/evals/scorers/extract-tools.js +51 -47
  89. package/dist/evals/scorers/extract-tools.js.map +1 -1
  90. package/dist/evals/scorers/index.js +1 -5
  91. package/dist/evals/scorers/outcome.js +321 -212
  92. package/dist/evals/scorers/outcome.js.map +1 -1
  93. package/dist/goal-manager.js +266 -261
  94. package/dist/goal-manager.js.map +1 -1
  95. package/dist/goal-signal.js +14 -13
  96. package/dist/goal-signal.js.map +1 -1
  97. package/dist/headless/cli.js +153 -154
  98. package/dist/headless/cli.js.map +1 -1
  99. package/dist/headless/flags.js +180 -178
  100. package/dist/headless/flags.js.map +1 -1
  101. package/dist/headless/format.js +72 -71
  102. package/dist/headless/format.js.map +1 -1
  103. package/dist/headless/index.js +5 -31
  104. package/dist/headless/policy.js +35 -31
  105. package/dist/headless/policy.js.map +1 -1
  106. package/dist/headless/run-mc.js +332 -334
  107. package/dist/headless/run-mc.js.map +1 -1
  108. package/dist/headless/types.js +16 -7
  109. package/dist/headless/types.js.map +1 -1
  110. package/dist/hooks/config.js +56 -61
  111. package/dist/hooks/config.js.map +1 -1
  112. package/dist/hooks/executor.js +118 -116
  113. package/dist/hooks/executor.js.map +1 -1
  114. package/dist/hooks/index.js +4 -15
  115. package/dist/hooks/manager.js +221 -280
  116. package/dist/hooks/manager.js.map +1 -1
  117. package/dist/hooks/types.js +5 -4
  118. package/dist/hooks/types.js.map +1 -1
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +632 -712
  121. package/dist/index.js.map +1 -1
  122. package/dist/ipc/ipc-reporter.js +19 -22
  123. package/dist/ipc/ipc-reporter.js.map +1 -1
  124. package/dist/lsp/client.js +248 -306
  125. package/dist/lsp/client.js.map +1 -1
  126. package/dist/lsp/index.js +1 -6
  127. package/dist/lsp/language.js +39 -43
  128. package/dist/lsp/language.js.map +1 -1
  129. package/dist/lsp/manager.js +78 -93
  130. package/dist/lsp/manager.js.map +1 -1
  131. package/dist/lsp/server.js +151 -120
  132. package/dist/lsp/server.js.map +1 -1
  133. package/dist/lsp/workspace.js +50 -47
  134. package/dist/lsp/workspace.js.map +1 -1
  135. package/dist/mcp/config.js +210 -199
  136. package/dist/mcp/config.js.map +1 -1
  137. package/dist/mcp/index.js +2 -9
  138. package/dist/mcp/manager.js +482 -475
  139. package/dist/mcp/manager.js.map +1 -1
  140. package/dist/mcp/types.js +1 -1
  141. package/dist/onboarding/custom-packs.js +14 -17
  142. package/dist/onboarding/custom-packs.js.map +1 -1
  143. package/dist/onboarding/custom-providers.js +22 -20
  144. package/dist/onboarding/custom-providers.js.map +1 -1
  145. package/dist/onboarding/index.d.ts +1 -1
  146. package/dist/onboarding/index.d.ts.map +1 -1
  147. package/dist/onboarding/index.js +3 -21
  148. package/dist/onboarding/om-settings.d.ts +5 -0
  149. package/dist/onboarding/om-settings.d.ts.map +1 -1
  150. package/dist/onboarding/om-settings.js +41 -20
  151. package/dist/onboarding/om-settings.js.map +1 -1
  152. package/dist/onboarding/packs.d.ts +4 -6
  153. package/dist/onboarding/packs.d.ts.map +1 -1
  154. package/dist/onboarding/packs.js +154 -105
  155. package/dist/onboarding/packs.js.map +1 -1
  156. package/dist/onboarding/settings.js +575 -517
  157. package/dist/onboarding/settings.js.map +1 -1
  158. package/dist/permissions.js +112 -99
  159. package/dist/permissions.js.map +1 -1
  160. package/dist/plugin.js +21 -23
  161. package/dist/plugin.js.map +1 -1
  162. package/dist/plugins/dependencies.js +64 -87
  163. package/dist/plugins/dependencies.js.map +1 -1
  164. package/dist/plugins/install.js +159 -169
  165. package/dist/plugins/install.js.map +1 -1
  166. package/dist/plugins/loader.js +170 -185
  167. package/dist/plugins/loader.js.map +1 -1
  168. package/dist/plugins/manager.js +374 -380
  169. package/dist/plugins/manager.js.map +1 -1
  170. package/dist/plugins/manifest.js +38 -63
  171. package/dist/plugins/manifest.js.map +1 -1
  172. package/dist/plugins/package-link.js +48 -64
  173. package/dist/plugins/package-link.js.map +1 -1
  174. package/dist/plugins/paths.js +18 -19
  175. package/dist/plugins/paths.js.map +1 -1
  176. package/dist/plugins/registry.js +97 -81
  177. package/dist/plugins/registry.js.map +1 -1
  178. package/dist/plugins/scaffold.js +62 -98
  179. package/dist/plugins/scaffold.js.map +1 -1
  180. package/dist/plugins/types.js +1 -1
  181. package/dist/processors/plan-rejection-abort.js +45 -44
  182. package/dist/processors/plan-rejection-abort.js.map +1 -1
  183. package/dist/providers/amazon-bedrock-gateway.js +134 -125
  184. package/dist/providers/amazon-bedrock-gateway.js.map +1 -1
  185. package/dist/providers/amazon-bedrock.js +68 -47
  186. package/dist/providers/amazon-bedrock.js.map +1 -1
  187. package/dist/providers/claude-max.js +153 -133
  188. package/dist/providers/claude-max.js.map +1 -1
  189. package/dist/providers/github-copilot.js +232 -230
  190. package/dist/providers/github-copilot.js.map +1 -1
  191. package/dist/providers/openai-codex.js +271 -260
  192. package/dist/providers/openai-codex.js.map +1 -1
  193. package/dist/providers/xai.js +57 -50
  194. package/dist/providers/xai.js.map +1 -1
  195. package/dist/schema.js +91 -89
  196. package/dist/schema.js.map +1 -1
  197. package/dist/theme-palette.js +18 -14
  198. package/dist/theme-palette.js.map +1 -1
  199. package/dist/tool-names.js +46 -37
  200. package/dist/tool-names.js.map +1 -1
  201. package/dist/tools/index.js +2 -8
  202. package/dist/tools/request-sandbox-access.js +71 -80
  203. package/dist/tools/request-sandbox-access.js.map +1 -1
  204. package/dist/tools/utils.js +26 -16
  205. package/dist/tools/utils.js.map +1 -1
  206. package/dist/tools/web-search.js +51 -55
  207. package/dist/tools/web-search.js.map +1 -1
  208. package/dist/utils/binaries.js +65 -61
  209. package/dist/utils/binaries.js.map +1 -1
  210. package/dist/utils/debug-log.js +51 -47
  211. package/dist/utils/debug-log.js.map +1 -1
  212. package/dist/utils/errors.js +157 -192
  213. package/dist/utils/errors.js.map +1 -1
  214. package/dist/utils/gateway-sync.js +49 -37
  215. package/dist/utils/gateway-sync.js.map +1 -1
  216. package/dist/utils/path-security.js +7 -6
  217. package/dist/utils/path-security.js.map +1 -1
  218. package/dist/utils/plan-diff.js +58 -39
  219. package/dist/utils/plan-diff.js.map +1 -1
  220. package/dist/utils/plans.js +92 -74
  221. package/dist/utils/plans.js.map +1 -1
  222. package/dist/utils/project.js +318 -256
  223. package/dist/utils/project.js.map +1 -1
  224. package/dist/utils/signals-pubsub.js +117 -99
  225. package/dist/utils/signals-pubsub.js.map +1 -1
  226. package/dist/utils/slash-command-loader.js +118 -154
  227. package/dist/utils/slash-command-loader.js.map +1 -1
  228. package/dist/utils/slash-command-processor.js +92 -83
  229. package/dist/utils/slash-command-processor.js.map +1 -1
  230. package/dist/utils/stdin-pipe.js +87 -63
  231. package/dist/utils/stdin-pipe.js.map +1 -1
  232. package/dist/utils/storage-factory.js +104 -84
  233. package/dist/utils/storage-factory.js.map +1 -1
  234. package/dist/utils/storage-maintenance.js +249 -211
  235. package/dist/utils/storage-maintenance.js.map +1 -1
  236. package/dist/utils/thread-lock.js +96 -92
  237. package/dist/utils/thread-lock.js.map +1 -1
  238. package/dist/utils/token-estimator.js +12 -12
  239. package/dist/utils/token-estimator.js.map +1 -1
  240. package/dist/utils/update-check.d.ts +1 -1
  241. package/dist/utils/update-check.js +341 -259
  242. package/dist/utils/update-check.js.map +1 -1
  243. package/dist/voice/stt-registry.js +131 -113
  244. package/dist/voice/stt-registry.js.map +1 -1
  245. package/package.json +11 -11
  246. package/dist/acp.js.map +0 -1
  247. package/dist/auth/index.js.map +0 -1
  248. package/dist/auth/types.js.map +0 -1
  249. package/dist/evals/index.js.map +0 -1
  250. package/dist/evals/scorers/index.js.map +0 -1
  251. package/dist/headless/index.js.map +0 -1
  252. package/dist/hooks/index.js.map +0 -1
  253. package/dist/lsp/index.js.map +0 -1
  254. package/dist/mcp/index.js.map +0 -1
  255. package/dist/mcp/types.js.map +0 -1
  256. package/dist/onboarding/index.js.map +0 -1
  257. package/dist/plugins/types.js.map +0 -1
  258. package/dist/tools/index.js.map +0 -1
@@ -1,487 +1,494 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync } from "node:fs";
2
- import { dirname, join } from "node:path";
3
- import { MCPClient, MCPOAuthClientProvider } from "@mastra/mcp";
4
1
  import { DEFAULT_CONFIG_DIR } from "../constants.js";
5
2
  import { getAppDataDir } from "../utils/project.js";
6
- import {
7
- DEFAULT_OAUTH_REDIRECT_URL,
8
- loadMcpConfig,
9
- getProjectMcpPath,
10
- getGlobalMcpPath,
11
- getClaudeSettingsPath,
12
- resolveOAuthRedirectUrl
13
- } from "./config.js";
14
- const MASTRACODE_MCP_TIMEOUT_MS = 7 * 24 * 60 * 60 * 1e3;
3
+ import { DEFAULT_OAUTH_REDIRECT_URL, getClaudeSettingsPath, getGlobalMcpPath, getProjectMcpPath, loadMcpConfig, resolveOAuthRedirectUrl } from "./config.js";
4
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
5
+ import { dirname, join } from "path";
6
+ import { MCPClient, MCPOAuthClientProvider } from "@mastra/mcp";
7
+ //#region src/mcp/manager.ts
8
+ /**
9
+ * MCP manager — orchestrates MCP server connections using MCPClient directly.
10
+ * Created once at startup, provides tools from connected MCP servers.
11
+ */
12
+ const MASTRACODE_MCP_TIMEOUT_MS = 10080 * 60 * 1e3;
15
13
  function getTransport(cfg) {
16
- return "url" in cfg ? "http" : "stdio";
17
- }
18
- class FileOAuthStorage {
19
- constructor(filePath) {
20
- this.filePath = filePath;
21
- }
22
- filePath;
23
- get(key) {
24
- return this.read()[key];
25
- }
26
- set(key, value) {
27
- const data = this.read();
28
- data[key] = value;
29
- this.write(data);
30
- }
31
- delete(key) {
32
- const data = this.read();
33
- delete data[key];
34
- this.write(data);
35
- }
36
- read() {
37
- if (!existsSync(this.filePath)) return {};
38
- try {
39
- return JSON.parse(readFileSync(this.filePath, "utf-8"));
40
- } catch {
41
- return {};
42
- }
43
- }
44
- write(data) {
45
- const dir = dirname(this.filePath);
46
- if (!existsSync(dir)) {
47
- mkdirSync(dir, { recursive: true, mode: 448 });
48
- }
49
- const tmpPath = `${this.filePath}.tmp`;
50
- writeFileSync(tmpPath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
51
- renameSync(tmpPath, this.filePath);
52
- }
14
+ return "url" in cfg ? "http" : "stdio";
53
15
  }
16
+ var FileOAuthStorage = class {
17
+ filePath;
18
+ constructor(filePath) {
19
+ this.filePath = filePath;
20
+ }
21
+ get(key) {
22
+ return this.read()[key];
23
+ }
24
+ set(key, value) {
25
+ const data = this.read();
26
+ data[key] = value;
27
+ this.write(data);
28
+ }
29
+ delete(key) {
30
+ const data = this.read();
31
+ delete data[key];
32
+ this.write(data);
33
+ }
34
+ read() {
35
+ if (!existsSync(this.filePath)) return {};
36
+ try {
37
+ return JSON.parse(readFileSync(this.filePath, "utf-8"));
38
+ } catch {
39
+ return {};
40
+ }
41
+ }
42
+ write(data) {
43
+ const dir = dirname(this.filePath);
44
+ if (!existsSync(dir)) mkdirSync(dir, {
45
+ recursive: true,
46
+ mode: 448
47
+ });
48
+ const tmpPath = `${this.filePath}.tmp`;
49
+ writeFileSync(tmpPath, JSON.stringify(data, null, 2), {
50
+ encoding: "utf-8",
51
+ mode: 384
52
+ });
53
+ renameSync(tmpPath, this.filePath);
54
+ }
55
+ };
56
+ /**
57
+ * Zero-config OAuth defaults for servers with a bare `url` entry. Dynamic
58
+ * client registration provisions the client, so no `clientId` is needed.
59
+ */
54
60
  const DEFAULT_OAUTH_CONFIG = { redirectUrl: DEFAULT_OAUTH_REDIRECT_URL };
55
61
  function getOAuthStoragePath(projectDir, name, cfg) {
56
- const key = JSON.stringify({
57
- projectDir,
58
- name,
59
- url: cfg.url,
60
- redirectUrl: resolveOAuthRedirectUrl(cfg.oauth),
61
- clientId: cfg.oauth?.clientId,
62
- scopes: cfg.oauth?.scopes ?? []
63
- });
64
- return join(getAppDataDir(), "mcp-oauth", `${getStorageKeyFingerprint(key)}.json`);
62
+ const key = JSON.stringify({
63
+ projectDir,
64
+ name,
65
+ url: cfg.url,
66
+ redirectUrl: resolveOAuthRedirectUrl(cfg.oauth),
67
+ clientId: cfg.oauth?.clientId,
68
+ scopes: cfg.oauth?.scopes ?? []
69
+ });
70
+ return join(getAppDataDir(), "mcp-oauth", `${getStorageKeyFingerprint(key)}.json`);
65
71
  }
66
72
  function getStorageKeyFingerprint(value) {
67
- let fingerprint = 0xcbf29ce484222325n;
68
- for (let i = 0; i < value.length; i += 1) {
69
- fingerprint ^= BigInt(value.charCodeAt(i));
70
- fingerprint = BigInt.asUintN(64, fingerprint * 0x100000001b3n);
71
- }
72
- return fingerprint.toString(16).padStart(16, "0");
73
+ let fingerprint = 14695981039346656037n;
74
+ for (let i = 0; i < value.length; i += 1) {
75
+ fingerprint ^= BigInt(value.charCodeAt(i));
76
+ fingerprint = BigInt.asUintN(64, fingerprint * 1099511628211n);
77
+ }
78
+ return fingerprint.toString(16).padStart(16, "0");
73
79
  }
80
+ /**
81
+ * Create an MCP manager that wraps MCPClient with config-file discovery
82
+ * and per-server status tracking.
83
+ */
74
84
  function createMcpManager(projectDir, configDirName = DEFAULT_CONFIG_DIR, extraServers) {
75
- const applyExtraServers = (base) => {
76
- if (!extraServers || Object.keys(extraServers).length === 0) return base;
77
- return { ...base, mcpServers: { ...base.mcpServers, ...extraServers } };
78
- };
79
- let config = applyExtraServers(loadMcpConfig(projectDir, configDirName));
80
- let client = null;
81
- let serverDefs = {};
82
- let tools = {};
83
- let serverStatuses = /* @__PURE__ */ new Map();
84
- let stderrLogs = /* @__PURE__ */ new Map();
85
- let initialized = false;
86
- const authUrlHandlers = /* @__PURE__ */ new Map();
87
- const authenticatingServers = /* @__PURE__ */ new Set();
88
- const cancelledAuthServers = /* @__PURE__ */ new Set();
89
- const withAuthenticating = (status) => authenticatingServers.has(status.name) ? { ...status, authenticating: true } : status;
90
- const MAX_STDERR_LINES = 200;
91
- function captureStderr(serverName) {
92
- if (!client || typeof client.getServerStderr !== "function") return;
93
- const stream = client.getServerStderr(serverName);
94
- if (!stream) return;
95
- let buffer = "";
96
- const lines = stderrLogs.get(serverName) ?? [];
97
- stderrLogs.set(serverName, lines);
98
- stream.on("data", (chunk) => {
99
- buffer += chunk.toString();
100
- const parts = buffer.split("\n");
101
- buffer = parts.pop();
102
- for (const line of parts) {
103
- if (line.trim()) {
104
- lines.push(line);
105
- if (lines.length > MAX_STDERR_LINES) {
106
- lines.shift();
107
- }
108
- }
109
- }
110
- });
111
- stream.on("end", () => {
112
- if (buffer.trim()) {
113
- lines.push(buffer);
114
- if (lines.length > MAX_STDERR_LINES) {
115
- lines.shift();
116
- }
117
- }
118
- });
119
- }
120
- function createOAuthProvider(name, cfg) {
121
- const oauth = cfg.oauth ?? (existsSync(getOAuthStoragePath(projectDir, name, cfg)) ? DEFAULT_OAUTH_CONFIG : void 0);
122
- if (!oauth) return void 0;
123
- const redirectUrl = resolveOAuthRedirectUrl(oauth);
124
- return new MCPOAuthClientProvider({
125
- redirectUrl,
126
- clientMetadata: {
127
- redirect_uris: [redirectUrl],
128
- client_name: oauth.clientName ?? `Mastra Code MCP ${name}`,
129
- grant_types: ["authorization_code", "refresh_token"],
130
- response_types: ["code"],
131
- ...oauth.scopes?.length ? { scope: oauth.scopes.join(" ") } : {}
132
- },
133
- clientInformation: oauth.clientId ? {
134
- client_id: oauth.clientId,
135
- ...oauth.clientSecret ? { client_secret: oauth.clientSecret } : {}
136
- } : void 0,
137
- storage: new FileOAuthStorage(getOAuthStoragePath(projectDir, name, cfg)),
138
- onRedirectToAuthorization: (url) => {
139
- authUrlHandlers.get(name)?.(url.toString());
140
- }
141
- });
142
- }
143
- function buildServerDefs(servers) {
144
- const defs = {};
145
- for (const [name, cfg] of Object.entries(servers)) {
146
- if ("url" in cfg) {
147
- const httpCfg = cfg;
148
- defs[name] = {
149
- url: new URL(httpCfg.url),
150
- requestInit: httpCfg.headers ? { headers: httpCfg.headers } : void 0,
151
- authProvider: createOAuthProvider(name, httpCfg)
152
- };
153
- } else {
154
- defs[name] = { command: cfg.command, args: cfg.args, env: cfg.env, stderr: "pipe" };
155
- }
156
- }
157
- return defs;
158
- }
159
- async function connectAndCollectTools() {
160
- const servers = config.mcpServers;
161
- if (!servers || Object.keys(servers).length === 0) {
162
- return;
163
- }
164
- const serverNames = Object.keys(servers);
165
- for (const name of serverNames) {
166
- serverStatuses.set(name, {
167
- name,
168
- connected: false,
169
- connecting: true,
170
- toolCount: 0,
171
- toolNames: [],
172
- transport: getTransport(servers[name])
173
- });
174
- }
175
- serverDefs = buildServerDefs(servers);
176
- client = new MCPClient({
177
- id: "mastra-code-mcp",
178
- servers: serverDefs,
179
- timeout: MASTRACODE_MCP_TIMEOUT_MS
180
- });
181
- try {
182
- const { toolsets, errors } = await client.listToolsetsWithErrors();
183
- const typedToolsets = toolsets;
184
- for (const [serverName, serverTools] of Object.entries(typedToolsets)) {
185
- for (const [toolName, toolConfig] of Object.entries(serverTools)) {
186
- tools[`${serverName}_${toolName}`] = toolConfig;
187
- }
188
- }
189
- for (const name of serverNames) {
190
- const serverTools = typedToolsets[name];
191
- if (serverTools && Object.keys(serverTools).length > 0) {
192
- const toolNames = Object.keys(serverTools).map((t) => `${name}_${t}`);
193
- serverStatuses.set(name, {
194
- name,
195
- connected: true,
196
- toolCount: toolNames.length,
197
- toolNames,
198
- transport: getTransport(servers[name])
199
- });
200
- } else {
201
- const error = errors[name] ?? "Failed to connect";
202
- serverStatuses.set(name, {
203
- name,
204
- connected: false,
205
- toolCount: 0,
206
- toolNames: [],
207
- transport: getTransport(servers[name]),
208
- error,
209
- ...serverNeedsAuth(name, servers[name], error) ? { needsAuth: true } : {}
210
- });
211
- }
212
- }
213
- for (const name of serverNames) {
214
- captureStderr(name);
215
- }
216
- } catch (error) {
217
- const errMsg = error instanceof Error ? error.message : String(error);
218
- for (const name of serverNames) {
219
- serverStatuses.set(name, {
220
- name,
221
- connected: false,
222
- toolCount: 0,
223
- toolNames: [],
224
- transport: getTransport(servers[name]),
225
- error: errMsg,
226
- ...serverNeedsAuth(name, servers[name], errMsg) ? { needsAuth: true } : {}
227
- });
228
- }
229
- }
230
- }
231
- function serverNeedsAuth(name, cfg, error) {
232
- if (getTransport(cfg) !== "http") return false;
233
- if (client?.getServerAuthState?.(name) === "needs-auth") return true;
234
- if (serverDefs[name]?.authProvider) return false;
235
- return error !== void 0 && /\b401\b|unauthorized|invalid_token/i.test(error);
236
- }
237
- async function connectSingleServer(name, cfg, connect) {
238
- const transport = getTransport(cfg);
239
- const prefix = `${name}_`;
240
- for (const key of Object.keys(tools)) {
241
- if (key.startsWith(prefix)) {
242
- delete tools[key];
243
- }
244
- }
245
- stderrLogs.delete(name);
246
- serverStatuses.set(name, {
247
- name,
248
- connected: false,
249
- connecting: true,
250
- toolCount: 0,
251
- toolNames: [],
252
- transport
253
- });
254
- try {
255
- await connect();
256
- captureStderr(name);
257
- const { toolsets, errors } = await client.listToolsetsWithErrors();
258
- const serverTools = toolsets[name];
259
- const serverError = errors[name];
260
- if (serverError) {
261
- const status = {
262
- name,
263
- connected: false,
264
- toolCount: 0,
265
- toolNames: [],
266
- transport,
267
- error: serverError,
268
- ...serverNeedsAuth(name, cfg, serverError) ? { needsAuth: true } : {}
269
- };
270
- serverStatuses.set(name, status);
271
- return status;
272
- } else if (serverTools && Object.keys(serverTools).length > 0) {
273
- const toolNames = Object.keys(serverTools).map((t) => `${name}_${t}`);
274
- for (const [toolName, toolConfig] of Object.entries(serverTools)) {
275
- tools[`${name}_${toolName}`] = toolConfig;
276
- }
277
- const status = {
278
- name,
279
- connected: true,
280
- toolCount: toolNames.length,
281
- toolNames,
282
- transport
283
- };
284
- serverStatuses.set(name, status);
285
- return status;
286
- } else {
287
- const status = {
288
- name,
289
- connected: false,
290
- toolCount: 0,
291
- toolNames: [],
292
- transport,
293
- error: "Failed to connect"
294
- };
295
- serverStatuses.set(name, status);
296
- return status;
297
- }
298
- } catch (error) {
299
- const errMsg = error instanceof Error ? error.message : String(error);
300
- const status = {
301
- name,
302
- connected: false,
303
- toolCount: 0,
304
- toolNames: [],
305
- transport,
306
- error: errMsg,
307
- ...serverNeedsAuth(name, cfg, errMsg) ? { needsAuth: true } : {}
308
- };
309
- serverStatuses.set(name, status);
310
- return status;
311
- }
312
- }
313
- async function disconnect() {
314
- if (client) {
315
- try {
316
- await client.disconnect();
317
- } catch {
318
- }
319
- client = null;
320
- }
321
- }
322
- return {
323
- async init() {
324
- if (initialized) return;
325
- await connectAndCollectTools();
326
- initialized = true;
327
- },
328
- async initInBackground() {
329
- await this.init();
330
- const statuses = Array.from(serverStatuses.values());
331
- const connected = statuses.filter((s) => s.connected);
332
- const failed = statuses.filter((s) => !s.connected);
333
- return {
334
- connected,
335
- failed,
336
- skipped: [...config.skippedServers ?? []],
337
- totalTools: connected.reduce((sum, s) => sum + s.toolCount, 0)
338
- };
339
- },
340
- async reload() {
341
- await disconnect();
342
- config = applyExtraServers(loadMcpConfig(projectDir, configDirName));
343
- tools = {};
344
- serverStatuses = /* @__PURE__ */ new Map();
345
- stderrLogs = /* @__PURE__ */ new Map();
346
- initialized = false;
347
- await connectAndCollectTools();
348
- initialized = true;
349
- },
350
- async reconnectServer(name) {
351
- const cfg = config.mcpServers?.[name];
352
- if (!cfg) {
353
- return {
354
- name,
355
- connected: false,
356
- toolCount: 0,
357
- toolNames: [],
358
- transport: "stdio",
359
- error: `Server "${name}" not found in config`
360
- };
361
- }
362
- if (!client) {
363
- return {
364
- name,
365
- connected: false,
366
- toolCount: 0,
367
- toolNames: [],
368
- transport: getTransport(cfg),
369
- error: "MCP client not initialized"
370
- };
371
- }
372
- return connectSingleServer(name, cfg, () => client.reconnectServer(name));
373
- },
374
- async authenticateServer(name, options) {
375
- const cfg = config.mcpServers?.[name];
376
- if (!cfg) {
377
- return {
378
- name,
379
- connected: false,
380
- toolCount: 0,
381
- toolNames: [],
382
- transport: "stdio",
383
- error: `Server "${name}" not found in config`
384
- };
385
- }
386
- if (!client) {
387
- return {
388
- name,
389
- connected: false,
390
- toolCount: 0,
391
- toolNames: [],
392
- transport: getTransport(cfg),
393
- error: "MCP client not initialized"
394
- };
395
- }
396
- if (getTransport(cfg) !== "http") {
397
- return {
398
- name,
399
- connected: false,
400
- toolCount: 0,
401
- toolNames: [],
402
- transport: "stdio",
403
- error: `Server "${name}" uses stdio transport, which does not support OAuth`
404
- };
405
- }
406
- const def = serverDefs[name];
407
- if (def?.url && !def.authProvider) {
408
- def.authProvider = createOAuthProvider(name, { ...cfg, oauth: DEFAULT_OAUTH_CONFIG });
409
- }
410
- if (authenticatingServers.has(name)) {
411
- const current = serverStatuses.get(name);
412
- return {
413
- name,
414
- connected: current?.connected ?? false,
415
- connecting: current?.connecting,
416
- needsAuth: current?.needsAuth,
417
- toolCount: current?.toolCount ?? 0,
418
- toolNames: current?.toolNames ?? [],
419
- transport: current?.transport ?? getTransport(cfg),
420
- error: `Authentication for "${name}" is already in progress`
421
- };
422
- }
423
- if (options?.onAuthorizationUrl) {
424
- authUrlHandlers.set(name, options.onAuthorizationUrl);
425
- }
426
- authenticatingServers.add(name);
427
- cancelledAuthServers.delete(name);
428
- try {
429
- const result = await connectSingleServer(
430
- name,
431
- cfg,
432
- () => client.authenticate(name, options?.timeoutMs === void 0 ? void 0 : { timeoutMs: options.timeoutMs })
433
- );
434
- const finalStatus = cancelledAuthServers.has(name) && !result.connected ? { ...result, cancelled: true } : result;
435
- serverStatuses.set(name, finalStatus);
436
- return finalStatus;
437
- } finally {
438
- authUrlHandlers.delete(name);
439
- authenticatingServers.delete(name);
440
- cancelledAuthServers.delete(name);
441
- }
442
- },
443
- async cancelServerAuthentication(name) {
444
- if (!client) {
445
- return false;
446
- }
447
- cancelledAuthServers.add(name);
448
- const cancelled = await client.cancelAuthentication(name);
449
- if (!cancelled) {
450
- cancelledAuthServers.delete(name);
451
- }
452
- return cancelled;
453
- },
454
- disconnect,
455
- getTools() {
456
- return { ...tools };
457
- },
458
- hasServers() {
459
- const hasConfigured = config.mcpServers !== void 0 && Object.keys(config.mcpServers).length > 0;
460
- const hasSkipped = config.skippedServers !== void 0 && config.skippedServers.length > 0;
461
- return hasConfigured || hasSkipped;
462
- },
463
- getServerStatuses() {
464
- return Array.from(serverStatuses.values(), withAuthenticating);
465
- },
466
- getSkippedServers() {
467
- return [...config.skippedServers ?? []];
468
- },
469
- getConfigPaths() {
470
- return {
471
- project: getProjectMcpPath(projectDir, configDirName),
472
- global: getGlobalMcpPath(configDirName),
473
- claude: getClaudeSettingsPath(projectDir)
474
- };
475
- },
476
- getConfig() {
477
- return config;
478
- },
479
- getServerLogs(name) {
480
- return [...stderrLogs.get(name) ?? []];
481
- }
482
- };
85
+ /** Merge programmatic servers into a base config (highest priority). */
86
+ const applyExtraServers = (base) => {
87
+ if (!extraServers || Object.keys(extraServers).length === 0) return base;
88
+ return {
89
+ ...base,
90
+ mcpServers: {
91
+ ...base.mcpServers,
92
+ ...extraServers
93
+ }
94
+ };
95
+ };
96
+ let config = applyExtraServers(loadMcpConfig(projectDir, configDirName));
97
+ let client = null;
98
+ let serverDefs = {};
99
+ let tools = {};
100
+ let serverStatuses = /* @__PURE__ */ new Map();
101
+ let stderrLogs = /* @__PURE__ */ new Map();
102
+ let initialized = false;
103
+ /** Per-server handlers that receive the OAuth authorization URL during authenticateServer(). */
104
+ const authUrlHandlers = /* @__PURE__ */ new Map();
105
+ /**
106
+ * Servers with an OAuth authorization flow currently in flight. Owned by the
107
+ * manager (not the TUI) so the state survives a `/mcp` selector being closed
108
+ * and reopened — the reopened selector reads it back off the server status and
109
+ * can still offer "Cancel authentication".
110
+ */
111
+ const authenticatingServers = /* @__PURE__ */ new Set();
112
+ /**
113
+ * Servers whose in-flight authentication was cancelled by the caller. Set by
114
+ * cancelServerAuthentication() so the resolving authenticateServer() call can
115
+ * mark its failed status as a deliberate cancel rather than a genuine failure.
116
+ * This lives on the manager (not the TUI selector) so the signal survives the
117
+ * selector being closed and reopened mid-flow.
118
+ */
119
+ const cancelledAuthServers = /* @__PURE__ */ new Set();
120
+ /** Overlay the manager-owned `authenticating` flag onto a status snapshot. */
121
+ const withAuthenticating = (status) => authenticatingServers.has(status.name) ? {
122
+ ...status,
123
+ authenticating: true
124
+ } : status;
125
+ const MAX_STDERR_LINES = 200;
126
+ /** Hook into a server's stderr stream and buffer its output. */
127
+ function captureStderr(serverName) {
128
+ if (!client || typeof client.getServerStderr !== "function") return;
129
+ const stream = client.getServerStderr(serverName);
130
+ if (!stream) return;
131
+ let buffer = "";
132
+ const lines = stderrLogs.get(serverName) ?? [];
133
+ stderrLogs.set(serverName, lines);
134
+ stream.on("data", (chunk) => {
135
+ buffer += chunk.toString();
136
+ const parts = buffer.split("\n");
137
+ buffer = parts.pop();
138
+ for (const line of parts) if (line.trim()) {
139
+ lines.push(line);
140
+ if (lines.length > MAX_STDERR_LINES) lines.shift();
141
+ }
142
+ });
143
+ stream.on("end", () => {
144
+ if (buffer.trim()) {
145
+ lines.push(buffer);
146
+ if (lines.length > MAX_STDERR_LINES) lines.shift();
147
+ }
148
+ });
149
+ }
150
+ function createOAuthProvider(name, cfg) {
151
+ const oauth = cfg.oauth ?? (existsSync(getOAuthStoragePath(projectDir, name, cfg)) ? DEFAULT_OAUTH_CONFIG : void 0);
152
+ if (!oauth) return void 0;
153
+ const redirectUrl = resolveOAuthRedirectUrl(oauth);
154
+ return new MCPOAuthClientProvider({
155
+ redirectUrl,
156
+ clientMetadata: {
157
+ redirect_uris: [redirectUrl],
158
+ client_name: oauth.clientName ?? `Mastra Code MCP ${name}`,
159
+ grant_types: ["authorization_code", "refresh_token"],
160
+ response_types: ["code"],
161
+ ...oauth.scopes?.length ? { scope: oauth.scopes.join(" ") } : {}
162
+ },
163
+ clientInformation: oauth.clientId ? {
164
+ client_id: oauth.clientId,
165
+ ...oauth.clientSecret ? { client_secret: oauth.clientSecret } : {}
166
+ } : void 0,
167
+ storage: new FileOAuthStorage(getOAuthStoragePath(projectDir, name, cfg)),
168
+ onRedirectToAuthorization: (url) => {
169
+ authUrlHandlers.get(name)?.(url.toString());
170
+ }
171
+ });
172
+ }
173
+ function buildServerDefs(servers) {
174
+ const defs = {};
175
+ for (const [name, cfg] of Object.entries(servers)) if ("url" in cfg) {
176
+ const httpCfg = cfg;
177
+ defs[name] = {
178
+ url: new URL(httpCfg.url),
179
+ requestInit: httpCfg.headers ? { headers: httpCfg.headers } : void 0,
180
+ authProvider: createOAuthProvider(name, httpCfg)
181
+ };
182
+ } else defs[name] = {
183
+ command: cfg.command,
184
+ args: cfg.args,
185
+ env: cfg.env,
186
+ stderr: "pipe"
187
+ };
188
+ return defs;
189
+ }
190
+ async function connectAndCollectTools() {
191
+ const servers = config.mcpServers;
192
+ if (!servers || Object.keys(servers).length === 0) return;
193
+ const serverNames = Object.keys(servers);
194
+ for (const name of serverNames) serverStatuses.set(name, {
195
+ name,
196
+ connected: false,
197
+ connecting: true,
198
+ toolCount: 0,
199
+ toolNames: [],
200
+ transport: getTransport(servers[name])
201
+ });
202
+ serverDefs = buildServerDefs(servers);
203
+ client = new MCPClient({
204
+ id: "mastra-code-mcp",
205
+ servers: serverDefs,
206
+ timeout: MASTRACODE_MCP_TIMEOUT_MS
207
+ });
208
+ try {
209
+ const { toolsets, errors } = await client.listToolsetsWithErrors();
210
+ const typedToolsets = toolsets;
211
+ for (const [serverName, serverTools] of Object.entries(typedToolsets)) for (const [toolName, toolConfig] of Object.entries(serverTools)) tools[`${serverName}_${toolName}`] = toolConfig;
212
+ for (const name of serverNames) {
213
+ const serverTools = typedToolsets[name];
214
+ if (serverTools && Object.keys(serverTools).length > 0) {
215
+ const toolNames = Object.keys(serverTools).map((t) => `${name}_${t}`);
216
+ serverStatuses.set(name, {
217
+ name,
218
+ connected: true,
219
+ toolCount: toolNames.length,
220
+ toolNames,
221
+ transport: getTransport(servers[name])
222
+ });
223
+ } else {
224
+ const error = errors[name] ?? "Failed to connect";
225
+ serverStatuses.set(name, {
226
+ name,
227
+ connected: false,
228
+ toolCount: 0,
229
+ toolNames: [],
230
+ transport: getTransport(servers[name]),
231
+ error,
232
+ ...serverNeedsAuth(name, servers[name], error) ? { needsAuth: true } : {}
233
+ });
234
+ }
235
+ }
236
+ for (const name of serverNames) captureStderr(name);
237
+ } catch (error) {
238
+ const errMsg = error instanceof Error ? error.message : String(error);
239
+ for (const name of serverNames) serverStatuses.set(name, {
240
+ name,
241
+ connected: false,
242
+ toolCount: 0,
243
+ toolNames: [],
244
+ transport: getTransport(servers[name]),
245
+ error: errMsg,
246
+ ...serverNeedsAuth(name, servers[name], errMsg) ? { needsAuth: true } : {}
247
+ });
248
+ }
249
+ }
250
+ /**
251
+ * Whether a failed HTTP server is blocked on OAuth authorization.
252
+ *
253
+ * Provider-backed servers report the exact state tracked by `@mastra/mcp`.
254
+ * Bare `url` entries carry no provider until the user authenticates, so the
255
+ * signal is a 401 in the connect error — surfaced either as the status text
256
+ * or as the RFC 6750 `invalid_token` bearer error code in the response body.
257
+ */
258
+ function serverNeedsAuth(name, cfg, error) {
259
+ if (getTransport(cfg) !== "http") return false;
260
+ if (client?.getServerAuthState?.(name) === "needs-auth") return true;
261
+ if (serverDefs[name]?.authProvider) return false;
262
+ return error !== void 0 && /\b401\b|unauthorized|invalid_token/i.test(error);
263
+ }
264
+ /**
265
+ * Runs a single-server connect action (reconnect or authenticate), then
266
+ * refreshes that server's tools and status from the client.
267
+ */
268
+ async function connectSingleServer(name, cfg, connect) {
269
+ const transport = getTransport(cfg);
270
+ const prefix = `${name}_`;
271
+ for (const key of Object.keys(tools)) if (key.startsWith(prefix)) delete tools[key];
272
+ stderrLogs.delete(name);
273
+ serverStatuses.set(name, {
274
+ name,
275
+ connected: false,
276
+ connecting: true,
277
+ toolCount: 0,
278
+ toolNames: [],
279
+ transport
280
+ });
281
+ try {
282
+ await connect();
283
+ captureStderr(name);
284
+ const { toolsets, errors } = await client.listToolsetsWithErrors();
285
+ const serverTools = toolsets[name];
286
+ const serverError = errors[name];
287
+ if (serverError) {
288
+ const status = {
289
+ name,
290
+ connected: false,
291
+ toolCount: 0,
292
+ toolNames: [],
293
+ transport,
294
+ error: serverError,
295
+ ...serverNeedsAuth(name, cfg, serverError) ? { needsAuth: true } : {}
296
+ };
297
+ serverStatuses.set(name, status);
298
+ return status;
299
+ } else if (serverTools && Object.keys(serverTools).length > 0) {
300
+ const toolNames = Object.keys(serverTools).map((t) => `${name}_${t}`);
301
+ for (const [toolName, toolConfig] of Object.entries(serverTools)) tools[`${name}_${toolName}`] = toolConfig;
302
+ const status = {
303
+ name,
304
+ connected: true,
305
+ toolCount: toolNames.length,
306
+ toolNames,
307
+ transport
308
+ };
309
+ serverStatuses.set(name, status);
310
+ return status;
311
+ } else {
312
+ const status = {
313
+ name,
314
+ connected: false,
315
+ toolCount: 0,
316
+ toolNames: [],
317
+ transport,
318
+ error: "Failed to connect"
319
+ };
320
+ serverStatuses.set(name, status);
321
+ return status;
322
+ }
323
+ } catch (error) {
324
+ const errMsg = error instanceof Error ? error.message : String(error);
325
+ const status = {
326
+ name,
327
+ connected: false,
328
+ toolCount: 0,
329
+ toolNames: [],
330
+ transport,
331
+ error: errMsg,
332
+ ...serverNeedsAuth(name, cfg, errMsg) ? { needsAuth: true } : {}
333
+ };
334
+ serverStatuses.set(name, status);
335
+ return status;
336
+ }
337
+ }
338
+ async function disconnect() {
339
+ if (client) {
340
+ try {
341
+ await client.disconnect();
342
+ } catch {}
343
+ client = null;
344
+ }
345
+ }
346
+ return {
347
+ async init() {
348
+ if (initialized) return;
349
+ await connectAndCollectTools();
350
+ initialized = true;
351
+ },
352
+ async initInBackground() {
353
+ await this.init();
354
+ const statuses = Array.from(serverStatuses.values());
355
+ const connected = statuses.filter((s) => s.connected);
356
+ return {
357
+ connected,
358
+ failed: statuses.filter((s) => !s.connected),
359
+ skipped: [...config.skippedServers ?? []],
360
+ totalTools: connected.reduce((sum, s) => sum + s.toolCount, 0)
361
+ };
362
+ },
363
+ async reload() {
364
+ await disconnect();
365
+ config = applyExtraServers(loadMcpConfig(projectDir, configDirName));
366
+ tools = {};
367
+ serverStatuses = /* @__PURE__ */ new Map();
368
+ stderrLogs = /* @__PURE__ */ new Map();
369
+ initialized = false;
370
+ await connectAndCollectTools();
371
+ initialized = true;
372
+ },
373
+ async reconnectServer(name) {
374
+ const cfg = config.mcpServers?.[name];
375
+ if (!cfg) return {
376
+ name,
377
+ connected: false,
378
+ toolCount: 0,
379
+ toolNames: [],
380
+ transport: "stdio",
381
+ error: `Server "${name}" not found in config`
382
+ };
383
+ if (!client) return {
384
+ name,
385
+ connected: false,
386
+ toolCount: 0,
387
+ toolNames: [],
388
+ transport: getTransport(cfg),
389
+ error: "MCP client not initialized"
390
+ };
391
+ return connectSingleServer(name, cfg, () => client.reconnectServer(name));
392
+ },
393
+ async authenticateServer(name, options) {
394
+ const cfg = config.mcpServers?.[name];
395
+ if (!cfg) return {
396
+ name,
397
+ connected: false,
398
+ toolCount: 0,
399
+ toolNames: [],
400
+ transport: "stdio",
401
+ error: `Server "${name}" not found in config`
402
+ };
403
+ if (!client) return {
404
+ name,
405
+ connected: false,
406
+ toolCount: 0,
407
+ toolNames: [],
408
+ transport: getTransport(cfg),
409
+ error: "MCP client not initialized"
410
+ };
411
+ if (getTransport(cfg) !== "http") return {
412
+ name,
413
+ connected: false,
414
+ toolCount: 0,
415
+ toolNames: [],
416
+ transport: "stdio",
417
+ error: `Server "${name}" uses stdio transport, which does not support OAuth`
418
+ };
419
+ const def = serverDefs[name];
420
+ if (def?.url && !def.authProvider) def.authProvider = createOAuthProvider(name, {
421
+ ...cfg,
422
+ oauth: DEFAULT_OAUTH_CONFIG
423
+ });
424
+ if (authenticatingServers.has(name)) {
425
+ const current = serverStatuses.get(name);
426
+ return {
427
+ name,
428
+ connected: current?.connected ?? false,
429
+ connecting: current?.connecting,
430
+ needsAuth: current?.needsAuth,
431
+ toolCount: current?.toolCount ?? 0,
432
+ toolNames: current?.toolNames ?? [],
433
+ transport: current?.transport ?? getTransport(cfg),
434
+ error: `Authentication for "${name}" is already in progress`
435
+ };
436
+ }
437
+ if (options?.onAuthorizationUrl) authUrlHandlers.set(name, options.onAuthorizationUrl);
438
+ authenticatingServers.add(name);
439
+ cancelledAuthServers.delete(name);
440
+ try {
441
+ const result = await connectSingleServer(name, cfg, () => client.authenticate(name, options?.timeoutMs === void 0 ? void 0 : { timeoutMs: options.timeoutMs }));
442
+ const finalStatus = cancelledAuthServers.has(name) && !result.connected ? {
443
+ ...result,
444
+ cancelled: true
445
+ } : result;
446
+ serverStatuses.set(name, finalStatus);
447
+ return finalStatus;
448
+ } finally {
449
+ authUrlHandlers.delete(name);
450
+ authenticatingServers.delete(name);
451
+ cancelledAuthServers.delete(name);
452
+ }
453
+ },
454
+ async cancelServerAuthentication(name) {
455
+ if (!client) return false;
456
+ cancelledAuthServers.add(name);
457
+ const cancelled = await client.cancelAuthentication(name);
458
+ if (!cancelled) cancelledAuthServers.delete(name);
459
+ return cancelled;
460
+ },
461
+ disconnect,
462
+ getTools() {
463
+ return { ...tools };
464
+ },
465
+ hasServers() {
466
+ const hasConfigured = config.mcpServers !== void 0 && Object.keys(config.mcpServers).length > 0;
467
+ const hasSkipped = config.skippedServers !== void 0 && config.skippedServers.length > 0;
468
+ return hasConfigured || hasSkipped;
469
+ },
470
+ getServerStatuses() {
471
+ return Array.from(serverStatuses.values(), withAuthenticating);
472
+ },
473
+ getSkippedServers() {
474
+ return [...config.skippedServers ?? []];
475
+ },
476
+ getConfigPaths() {
477
+ return {
478
+ project: getProjectMcpPath(projectDir, configDirName),
479
+ global: getGlobalMcpPath(configDirName),
480
+ claude: getClaudeSettingsPath(projectDir)
481
+ };
482
+ },
483
+ getConfig() {
484
+ return config;
485
+ },
486
+ getServerLogs(name) {
487
+ return [...stderrLogs.get(name) ?? []];
488
+ }
489
+ };
483
490
  }
484
- export {
485
- createMcpManager
486
- };
491
+ //#endregion
492
+ export { createMcpManager };
493
+
487
494
  //# sourceMappingURL=manager.js.map