mastracode 0.31.1-alpha.8 → 0.32.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +93 -0
- package/dist/{chunk-EXOGBKXL.js → chunk-FAXDM2KQ.js} +183 -36
- package/dist/chunk-FAXDM2KQ.js.map +1 -0
- package/dist/{chunk-D7H6UQ7E.cjs → chunk-T6G7GFIL.cjs} +184 -37
- package/dist/chunk-T6G7GFIL.cjs.map +1 -0
- package/dist/cli.cjs +6 -6
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/tui/commands/goal.d.ts.map +1 -1
- package/dist/tui/commands/mcp.d.ts.map +1 -1
- package/dist/tui/components/login-dialog.d.ts.map +1 -1
- package/dist/tui/components/mcp-selector.d.ts +17 -0
- package/dist/tui/components/mcp-selector.d.ts.map +1 -1
- package/dist/tui/handlers/agent-lifecycle.d.ts.map +1 -1
- package/dist/tui/mastra-tui.d.ts.map +1 -1
- package/dist/tui/open-url.d.ts +10 -0
- package/dist/tui/open-url.d.ts.map +1 -0
- package/dist/tui.cjs +18 -18
- package/dist/tui.js +1 -1
- package/package.json +17 -17
- package/dist/chunk-D7H6UQ7E.cjs.map +0 -1
- package/dist/chunk-EXOGBKXL.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,98 @@
|
|
|
1
1
|
# mastracode
|
|
2
2
|
|
|
3
|
+
## 0.32.0-alpha.13
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [[`c9e3521`](https://github.com/mastra-ai/mastra/commit/c9e3521628422db84e00a5ff1dea7426c8cce537)]:
|
|
8
|
+
- @mastra/pg@1.17.0-alpha.3
|
|
9
|
+
- @mastra/code-sdk@1.0.0-alpha.13
|
|
10
|
+
|
|
11
|
+
## 0.32.0-alpha.12
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Fixed local database cleanup across interactive, ACP, and headless exits. ([#19901](https://github.com/mastra-ai/mastra/pull/19901))
|
|
16
|
+
|
|
17
|
+
- Updated dependencies [[`6193d6d`](https://github.com/mastra-ai/mastra/commit/6193d6d4ae62ad68daaaf450992198e9e49493f1), [`c7d30cd`](https://github.com/mastra-ai/mastra/commit/c7d30cd86009c407df91105591f03cd6e3d2854d), [`ef03fbc`](https://github.com/mastra-ai/mastra/commit/ef03fbcc556bcbc04c9b3d06fab88771ecaa043c), [`ef03fbc`](https://github.com/mastra-ai/mastra/commit/ef03fbcc556bcbc04c9b3d06fab88771ecaa043c), [`6193d6d`](https://github.com/mastra-ai/mastra/commit/6193d6d4ae62ad68daaaf450992198e9e49493f1), [`a7bbe77`](https://github.com/mastra-ai/mastra/commit/a7bbe773577f60bc4761b534ef7ec6b476332dad), [`a7bbe77`](https://github.com/mastra-ai/mastra/commit/a7bbe773577f60bc4761b534ef7ec6b476332dad), [`4e68363`](https://github.com/mastra-ai/mastra/commit/4e683634f94ebd062d26a3bb6093a8dfc7263d37), [`9251370`](https://github.com/mastra-ai/mastra/commit/9251370ad413af464aa22d7566338bec5613e8de)]:
|
|
18
|
+
- @mastra/code-sdk@1.0.0-alpha.12
|
|
19
|
+
- @mastra/core@1.52.0-alpha.11
|
|
20
|
+
- @mastra/libsql@1.17.0-alpha.3
|
|
21
|
+
|
|
22
|
+
## 0.32.0-alpha.11
|
|
23
|
+
|
|
24
|
+
### Minor Changes
|
|
25
|
+
|
|
26
|
+
- Add browser-based OAuth authentication for HTTP MCP servers to Mastra Code. ([#19467](https://github.com/mastra-ai/mastra/pull/19467))
|
|
27
|
+
|
|
28
|
+
When an HTTP MCP server rejects a connection with an authorization error, the
|
|
29
|
+
`/mcp` selector now shows a "needs auth" badge and an **Authenticate** action.
|
|
30
|
+
Choosing it opens the provider's consent page in the browser and completes the
|
|
31
|
+
OAuth 2.1 authorization-code flow (PKCE + Dynamic Client Registration) over a
|
|
32
|
+
loopback callback server, persists the tokens, and reconnects — no manual
|
|
33
|
+
configuration required for a bare `{ "url": ... }` server entry. A **Cancel
|
|
34
|
+
authentication** action aborts an in-flight flow and returns the server to the
|
|
35
|
+
needs-auth state.
|
|
36
|
+
|
|
37
|
+
The server manager gains `authenticateServer(name)` and
|
|
38
|
+
`cancelServerAuthentication(name)`, `McpServerStatus` gains an optional
|
|
39
|
+
`needsAuth` flag, and the OAuth `redirectUrl` in MCP server config is now
|
|
40
|
+
optional (it defaults to a stable loopback URL). The config also accepts
|
|
41
|
+
`callbackPort` as a shorthand that synthesizes
|
|
42
|
+
`http://localhost:<callbackPort>/callback`, the Claude Code / Codex
|
|
43
|
+
convention, so configs written for those clients (like Slack's official MCP
|
|
44
|
+
plugin config) work verbatim. `callbackPort` and `redirectUrl` are mutually
|
|
45
|
+
exclusive.
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
const server = manager.getServerStatuses().find(s => s.name === 'supabase');
|
|
49
|
+
if (server?.needsAuth) {
|
|
50
|
+
// Opens the consent page in the browser, completes the OAuth flow, and
|
|
51
|
+
// resolves with the reconnected server status.
|
|
52
|
+
const status = await manager.authenticateServer('supabase', {
|
|
53
|
+
onAuthorizationUrl: url => openInBrowser(url),
|
|
54
|
+
});
|
|
55
|
+
console.log(status.connected);
|
|
56
|
+
|
|
57
|
+
// Abort an abandoned browser flow and return the server to needs-auth:
|
|
58
|
+
// await manager.cancelServerAuthentication('supabase')
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Patch Changes
|
|
63
|
+
|
|
64
|
+
- Updated dependencies [[`6341b72`](https://github.com/mastra-ai/mastra/commit/6341b720fa80e65731cbbd7d88d1088f4c5b9914)]:
|
|
65
|
+
- @mastra/code-sdk@1.0.0-alpha.11
|
|
66
|
+
|
|
67
|
+
## 0.31.1-alpha.10
|
|
68
|
+
|
|
69
|
+
### Patch Changes
|
|
70
|
+
|
|
71
|
+
- dependencies updates: ([#19813](https://github.com/mastra-ai/mastra/pull/19813))
|
|
72
|
+
- Updated dependency [`@ai-sdk/amazon-bedrock@^3.0.107` ↗︎](https://www.npmjs.com/package/@ai-sdk/amazon-bedrock/v/3.0.107) (from `^3.0.105`, in `dependencies`)
|
|
73
|
+
- Updated dependency [`@ai-sdk/anthropic@^3.0.98` ↗︎](https://www.npmjs.com/package/@ai-sdk/anthropic/v/3.0.98) (from `^3.0.96`, in `dependencies`)
|
|
74
|
+
- Updated dependency [`@ai-sdk/openai@^3.0.86` ↗︎](https://www.npmjs.com/package/@ai-sdk/openai/v/3.0.86) (from `^3.0.84`, in `dependencies`)
|
|
75
|
+
- Updated dependency [`@ai-sdk/openai-compatible@^2.0.62` ↗︎](https://www.npmjs.com/package/@ai-sdk/openai-compatible/v/2.0.62) (from `^2.0.59`, in `dependencies`)
|
|
76
|
+
- Updated dependency [`ai@^6.0.230` ↗︎](https://www.npmjs.com/package/ai/v/6.0.230) (from `^6.0.225`, in `dependencies`)
|
|
77
|
+
|
|
78
|
+
- Preserved Mastra Code's displayed active goal time across pauses, approval waits, and thread reloads. ([#19837](https://github.com/mastra-ai/mastra/pull/19837))
|
|
79
|
+
|
|
80
|
+
- Updated dependencies [[`41a5392`](https://github.com/mastra-ai/mastra/commit/41a5392d9f6c5e18d6b227f0fc0ddf49c50774e9), [`41a5392`](https://github.com/mastra-ai/mastra/commit/41a5392d9f6c5e18d6b227f0fc0ddf49c50774e9), [`b4b7ea8`](https://github.com/mastra-ai/mastra/commit/b4b7ea8733f033fc441ea47ed03f6afb17ec2248), [`675fbff`](https://github.com/mastra-ai/mastra/commit/675fbff84d3274391b33e852f76083c38a5514e5), [`da009e1`](https://github.com/mastra-ai/mastra/commit/da009e1aacd89ed94b8d1b2af09c9d4fe7c4db49), [`b4b7ea8`](https://github.com/mastra-ai/mastra/commit/b4b7ea8733f033fc441ea47ed03f6afb17ec2248), [`35c2181`](https://github.com/mastra-ai/mastra/commit/35c2181e6a50e47c90ba36260db7c9723d54696f), [`232fcbc`](https://github.com/mastra-ai/mastra/commit/232fcbc14fce625dd672ba043329c0b732c62be2), [`b4b7ea8`](https://github.com/mastra-ai/mastra/commit/b4b7ea8733f033fc441ea47ed03f6afb17ec2248), [`675fbff`](https://github.com/mastra-ai/mastra/commit/675fbff84d3274391b33e852f76083c38a5514e5), [`6deac4a`](https://github.com/mastra-ai/mastra/commit/6deac4a520750d807a2154333bf1b91a2df958a5), [`c328769`](https://github.com/mastra-ai/mastra/commit/c3287698ff8ef98dba86d415faa566fa3e5f4d56), [`232fcbc`](https://github.com/mastra-ai/mastra/commit/232fcbc14fce625dd672ba043329c0b732c62be2), [`3491666`](https://github.com/mastra-ai/mastra/commit/34916663c4fdd43b48c21f4ab2d5fb6dcccc94f9)]:
|
|
81
|
+
- @mastra/code-sdk@1.0.0-alpha.10
|
|
82
|
+
- @mastra/core@1.52.0-alpha.10
|
|
83
|
+
- @mastra/libsql@1.17.0-alpha.2
|
|
84
|
+
- @mastra/pg@1.17.0-alpha.2
|
|
85
|
+
- @mastra/observability@1.16.2-alpha.1
|
|
86
|
+
- @mastra/mcp@1.15.0-alpha.0
|
|
87
|
+
|
|
88
|
+
## 0.31.1-alpha.9
|
|
89
|
+
|
|
90
|
+
### Patch Changes
|
|
91
|
+
|
|
92
|
+
- Updated dependencies [[`0a2c22c`](https://github.com/mastra-ai/mastra/commit/0a2c22c902604439ec490319e14c17f331e0c84c), [`3a8024c`](https://github.com/mastra-ai/mastra/commit/3a8024ce615f8aa89479c0d71fe61d10bb0040be)]:
|
|
93
|
+
- @mastra/core@1.52.0-alpha.9
|
|
94
|
+
- @mastra/code-sdk@0.2.0-alpha.9
|
|
95
|
+
|
|
3
96
|
## 0.31.1-alpha.8
|
|
4
97
|
|
|
5
98
|
### Patch Changes
|
|
@@ -1240,9 +1240,6 @@ async function startGoal(ctx, objective, judgeModelId, maxTurns, options = {}) {
|
|
|
1240
1240
|
return;
|
|
1241
1241
|
}
|
|
1242
1242
|
state.planStartedGoalId = void 0;
|
|
1243
|
-
if (options.trigger === "none") {
|
|
1244
|
-
goalManager.resetActiveTimer();
|
|
1245
|
-
}
|
|
1246
1243
|
if (shouldPersistToCreatedThread) {
|
|
1247
1244
|
goalManager.persistOnNextThreadCreate();
|
|
1248
1245
|
}
|
|
@@ -2459,7 +2456,14 @@ var FAILED_ACTIONS = [
|
|
|
2459
2456
|
{ label: "View logs", key: "logs" },
|
|
2460
2457
|
{ label: "Reconnect", key: "reconnect" }
|
|
2461
2458
|
];
|
|
2459
|
+
var NEEDS_AUTH_ACTIONS = [
|
|
2460
|
+
{ label: "Authenticate", key: "authenticate" },
|
|
2461
|
+
{ label: "View error", key: "error" },
|
|
2462
|
+
{ label: "View logs", key: "logs" },
|
|
2463
|
+
{ label: "Reconnect", key: "reconnect" }
|
|
2464
|
+
];
|
|
2462
2465
|
var CONNECTING_ACTIONS = [{ label: "Waiting for connection...", key: "none" }];
|
|
2466
|
+
var AUTHENTICATING_ACTIONS = [{ label: "Cancel authentication", key: "cancel-authenticate" }];
|
|
2463
2467
|
var McpSelectorComponent = class extends Box {
|
|
2464
2468
|
listContainer;
|
|
2465
2469
|
statuses;
|
|
@@ -2468,6 +2472,8 @@ var McpSelectorComponent = class extends Box {
|
|
|
2468
2472
|
getStatusesCallback;
|
|
2469
2473
|
onReloadAllCallback;
|
|
2470
2474
|
onReconnectServerCallback;
|
|
2475
|
+
onAuthenticateServerCallback;
|
|
2476
|
+
onCancelAuthenticateServerCallback;
|
|
2471
2477
|
getServerLogsCallback;
|
|
2472
2478
|
showInfoCallback;
|
|
2473
2479
|
onCloseCallback;
|
|
@@ -2481,6 +2487,13 @@ var McpSelectorComponent = class extends Box {
|
|
|
2481
2487
|
_detailView = false;
|
|
2482
2488
|
// Loading state during reload
|
|
2483
2489
|
_reloading = false;
|
|
2490
|
+
// Names of servers with an in-flight OAuth flow (so their sub-menu offers a
|
|
2491
|
+
// cancel path while they show as connecting).
|
|
2492
|
+
_authenticating = /* @__PURE__ */ new Set();
|
|
2493
|
+
// Names of servers the user is actively cancelling. The authenticate flow
|
|
2494
|
+
// resolves with a failed status when cancelled, so we track this to suppress
|
|
2495
|
+
// the misleading "Failed to authenticate" toast on a deliberate cancel.
|
|
2496
|
+
_cancelling = /* @__PURE__ */ new Set();
|
|
2484
2497
|
// Focusable implementation
|
|
2485
2498
|
_focused = false;
|
|
2486
2499
|
get focused() {
|
|
@@ -2497,6 +2510,8 @@ var McpSelectorComponent = class extends Box {
|
|
|
2497
2510
|
this.getStatusesCallback = options.getStatuses;
|
|
2498
2511
|
this.onReloadAllCallback = options.onReloadAll;
|
|
2499
2512
|
this.onReconnectServerCallback = options.onReconnectServer;
|
|
2513
|
+
this.onAuthenticateServerCallback = options.onAuthenticateServer;
|
|
2514
|
+
this.onCancelAuthenticateServerCallback = options.onCancelAuthenticateServer;
|
|
2500
2515
|
this.getServerLogsCallback = options.getServerLogs;
|
|
2501
2516
|
this.showInfoCallback = options.showInfo;
|
|
2502
2517
|
this.onCloseCallback = options.onClose;
|
|
@@ -2531,12 +2546,18 @@ var McpSelectorComponent = class extends Box {
|
|
|
2531
2546
|
if (this._reloading) {
|
|
2532
2547
|
icon = theme.fg("warning", "\u27F3");
|
|
2533
2548
|
stateText = theme.fg("warning", "reconnecting...");
|
|
2549
|
+
} else if (this.isAuthenticating(status)) {
|
|
2550
|
+
icon = theme.fg("warning", "\u27F3");
|
|
2551
|
+
stateText = theme.fg("warning", "authenticating \u2014 Enter to cancel");
|
|
2534
2552
|
} else if (status.connecting) {
|
|
2535
2553
|
icon = theme.fg("warning", "\u27F3");
|
|
2536
2554
|
stateText = theme.fg("warning", "connecting...");
|
|
2537
2555
|
} else if (status.connected) {
|
|
2538
2556
|
icon = theme.fg("success", "\u2714");
|
|
2539
2557
|
stateText = theme.fg("success", "connected");
|
|
2558
|
+
} else if (status.needsAuth) {
|
|
2559
|
+
icon = theme.fg("warning", "\u26A0");
|
|
2560
|
+
stateText = theme.fg("warning", "needs auth");
|
|
2540
2561
|
} else {
|
|
2541
2562
|
icon = theme.fg("error", "\u2717");
|
|
2542
2563
|
stateText = theme.fg("error", "failed");
|
|
@@ -2575,10 +2596,20 @@ var McpSelectorComponent = class extends Box {
|
|
|
2575
2596
|
}
|
|
2576
2597
|
this.tui.requestRender();
|
|
2577
2598
|
}
|
|
2599
|
+
/**
|
|
2600
|
+
* Whether an OAuth flow is in flight for this server. True if either the local
|
|
2601
|
+
* set (this selector instance started the flow) or the manager-owned status
|
|
2602
|
+
* flag (survives close/reopen) says so.
|
|
2603
|
+
*/
|
|
2604
|
+
isAuthenticating(status) {
|
|
2605
|
+
return status.authenticating === true || this._authenticating.has(status.name);
|
|
2606
|
+
}
|
|
2607
|
+
isBusy() {
|
|
2608
|
+
return this.statuses.some((s) => s.connecting || this.isAuthenticating(s)) || this._authenticating.size > 0;
|
|
2609
|
+
}
|
|
2578
2610
|
startPollingIfNeeded() {
|
|
2579
2611
|
if (this.pollTimer) return;
|
|
2580
|
-
|
|
2581
|
-
if (!hasConnecting) return;
|
|
2612
|
+
if (!this.isBusy()) return;
|
|
2582
2613
|
this.pollTimer = setInterval(() => {
|
|
2583
2614
|
if (this._detailView || this._reloading) return;
|
|
2584
2615
|
const fresh = this.getStatusesCallback();
|
|
@@ -2589,7 +2620,7 @@ var McpSelectorComponent = class extends Box {
|
|
|
2589
2620
|
this.selectedIndex = Math.max(0, total - 1);
|
|
2590
2621
|
}
|
|
2591
2622
|
this.updateList();
|
|
2592
|
-
if (!this.
|
|
2623
|
+
if (!this.isBusy()) {
|
|
2593
2624
|
this.stopPolling();
|
|
2594
2625
|
}
|
|
2595
2626
|
}, 500);
|
|
@@ -2646,10 +2677,14 @@ var McpSelectorComponent = class extends Box {
|
|
|
2646
2677
|
openSubMenu() {
|
|
2647
2678
|
const status = this.statuses[this.selectedIndex];
|
|
2648
2679
|
if (!status) return;
|
|
2649
|
-
if (status
|
|
2680
|
+
if (this.isAuthenticating(status)) {
|
|
2681
|
+
this.subMenuActions = AUTHENTICATING_ACTIONS;
|
|
2682
|
+
} else if (status.connecting) {
|
|
2650
2683
|
this.subMenuActions = CONNECTING_ACTIONS;
|
|
2651
2684
|
} else if (status.connected) {
|
|
2652
2685
|
this.subMenuActions = CONNECTED_ACTIONS;
|
|
2686
|
+
} else if (status.needsAuth) {
|
|
2687
|
+
this.subMenuActions = NEEDS_AUTH_ACTIONS;
|
|
2653
2688
|
} else {
|
|
2654
2689
|
this.subMenuActions = FAILED_ACTIONS;
|
|
2655
2690
|
}
|
|
@@ -2697,6 +2732,16 @@ var McpSelectorComponent = class extends Box {
|
|
|
2697
2732
|
this.doReconnectServer(status);
|
|
2698
2733
|
break;
|
|
2699
2734
|
}
|
|
2735
|
+
case "authenticate": {
|
|
2736
|
+
this.subMenuOpen = false;
|
|
2737
|
+
this.doAuthenticateServer(status);
|
|
2738
|
+
break;
|
|
2739
|
+
}
|
|
2740
|
+
case "cancel-authenticate": {
|
|
2741
|
+
this.subMenuOpen = false;
|
|
2742
|
+
this.doCancelAuthentication(status);
|
|
2743
|
+
break;
|
|
2744
|
+
}
|
|
2700
2745
|
}
|
|
2701
2746
|
}
|
|
2702
2747
|
doReloadAll() {
|
|
@@ -2705,6 +2750,11 @@ var McpSelectorComponent = class extends Box {
|
|
|
2705
2750
|
this.onReloadAllCallback().then((result) => {
|
|
2706
2751
|
this.statuses = result.statuses;
|
|
2707
2752
|
this.skipped = result.skipped;
|
|
2753
|
+
const liveNames = new Set(result.statuses.map((s) => s.name));
|
|
2754
|
+
for (const name of this._authenticating) {
|
|
2755
|
+
if (!liveNames.has(name)) this._authenticating.delete(name);
|
|
2756
|
+
}
|
|
2757
|
+
this._cancelling.clear();
|
|
2708
2758
|
const total = this.getTotalItems();
|
|
2709
2759
|
if (this.selectedIndex >= total) {
|
|
2710
2760
|
this.selectedIndex = Math.max(0, total - 1);
|
|
@@ -2713,7 +2763,11 @@ var McpSelectorComponent = class extends Box {
|
|
|
2713
2763
|
const totalTools = connected.reduce((sum, s) => sum + s.toolCount, 0);
|
|
2714
2764
|
this.showInfoCallback(`MCP: Reloaded. ${connected.length} server(s) connected, ${totalTools} tool(s).`);
|
|
2715
2765
|
for (const s of result.statuses.filter((s2) => !s2.connected)) {
|
|
2716
|
-
|
|
2766
|
+
if (s.needsAuth) {
|
|
2767
|
+
this.showInfoCallback(`MCP: \u26A0 "${s.name}" needs authentication \u2192 run /mcp to authenticate`);
|
|
2768
|
+
} else {
|
|
2769
|
+
this.showInfoCallback(`MCP: Failed to connect to "${s.name}": ${s.error ?? "Unknown error"}`);
|
|
2770
|
+
}
|
|
2717
2771
|
}
|
|
2718
2772
|
}).catch(() => {
|
|
2719
2773
|
this.showInfoCallback("MCP: Reload failed. Retrying may help.");
|
|
@@ -2770,6 +2824,81 @@ var McpSelectorComponent = class extends Box {
|
|
|
2770
2824
|
}
|
|
2771
2825
|
});
|
|
2772
2826
|
}
|
|
2827
|
+
doAuthenticateServer(status) {
|
|
2828
|
+
if (status.connecting) return;
|
|
2829
|
+
const name = status.name;
|
|
2830
|
+
const idx = this.statuses.findIndex((s) => s.name === name);
|
|
2831
|
+
if (idx >= 0) {
|
|
2832
|
+
this.statuses[idx] = {
|
|
2833
|
+
name,
|
|
2834
|
+
connected: false,
|
|
2835
|
+
connecting: true,
|
|
2836
|
+
toolCount: 0,
|
|
2837
|
+
toolNames: [],
|
|
2838
|
+
transport: status.transport
|
|
2839
|
+
};
|
|
2840
|
+
}
|
|
2841
|
+
this._authenticating.add(name);
|
|
2842
|
+
if (idx >= 0) {
|
|
2843
|
+
this.selectedIndex = idx;
|
|
2844
|
+
}
|
|
2845
|
+
this.openSubMenu();
|
|
2846
|
+
this.startPollingIfNeeded();
|
|
2847
|
+
this.showInfoCallback(`MCP: Authenticating "${name}" \u2014 complete the sign-in in your browser.`);
|
|
2848
|
+
this.onAuthenticateServerCallback(name).then((updated) => {
|
|
2849
|
+
if (this._reloading) return;
|
|
2850
|
+
const i = this.statuses.findIndex((s) => s.name === name);
|
|
2851
|
+
if (i >= 0) {
|
|
2852
|
+
this.statuses[i] = updated;
|
|
2853
|
+
}
|
|
2854
|
+
if (updated.connected) {
|
|
2855
|
+
this.showInfoCallback(`MCP: Authenticated "${name}" \u2014 ${updated.toolCount} tool(s)`);
|
|
2856
|
+
} else if (!updated.cancelled && !this._cancelling.has(name)) {
|
|
2857
|
+
this.showInfoCallback(`MCP: Failed to authenticate "${name}": ${updated.error ?? "Unknown error"}`);
|
|
2858
|
+
}
|
|
2859
|
+
}).catch((err) => {
|
|
2860
|
+
if (this._reloading) return;
|
|
2861
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
2862
|
+
const i = this.statuses.findIndex((s) => s.name === name);
|
|
2863
|
+
if (i >= 0) {
|
|
2864
|
+
this.statuses[i] = {
|
|
2865
|
+
name,
|
|
2866
|
+
connected: false,
|
|
2867
|
+
connecting: false,
|
|
2868
|
+
toolCount: 0,
|
|
2869
|
+
toolNames: [],
|
|
2870
|
+
transport: status.transport,
|
|
2871
|
+
error: errMsg,
|
|
2872
|
+
needsAuth: true
|
|
2873
|
+
};
|
|
2874
|
+
}
|
|
2875
|
+
if (!this._cancelling.has(name)) {
|
|
2876
|
+
this.showInfoCallback(`MCP: Failed to authenticate "${name}": ${errMsg}`);
|
|
2877
|
+
}
|
|
2878
|
+
}).finally(() => {
|
|
2879
|
+
this._authenticating.delete(name);
|
|
2880
|
+
this._cancelling.delete(name);
|
|
2881
|
+
if (this.subMenuOpen && this.statuses[this.selectedIndex]?.name === name) {
|
|
2882
|
+
this.subMenuOpen = false;
|
|
2883
|
+
}
|
|
2884
|
+
if (!this._reloading) {
|
|
2885
|
+
this.updateList();
|
|
2886
|
+
}
|
|
2887
|
+
});
|
|
2888
|
+
}
|
|
2889
|
+
doCancelAuthentication(status) {
|
|
2890
|
+
const name = status.name;
|
|
2891
|
+
if (!this.isAuthenticating(status)) return;
|
|
2892
|
+
this._cancelling.add(name);
|
|
2893
|
+
this.showInfoCallback(`MCP: Cancelling authentication for "${name}"...`);
|
|
2894
|
+
this.updateList();
|
|
2895
|
+
this.onCancelAuthenticateServerCallback(name).then((cancelled) => {
|
|
2896
|
+
if (cancelled) {
|
|
2897
|
+
this.showInfoCallback(`MCP: Cancelled authentication for "${name}".`);
|
|
2898
|
+
}
|
|
2899
|
+
}).catch(() => {
|
|
2900
|
+
});
|
|
2901
|
+
}
|
|
2773
2902
|
showToolList(status) {
|
|
2774
2903
|
this.listContainer.clear();
|
|
2775
2904
|
this.listContainer.addChild(
|
|
@@ -2935,6 +3064,22 @@ function notify(state, reason, message) {
|
|
|
2935
3064
|
hookManager: state.hookManager
|
|
2936
3065
|
});
|
|
2937
3066
|
}
|
|
3067
|
+
function openUrlInBrowser(url) {
|
|
3068
|
+
let parsed;
|
|
3069
|
+
try {
|
|
3070
|
+
parsed = new URL(url);
|
|
3071
|
+
} catch {
|
|
3072
|
+
return;
|
|
3073
|
+
}
|
|
3074
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
3075
|
+
return;
|
|
3076
|
+
}
|
|
3077
|
+
const [cmd, args] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["rundll32", ["url.dll,FileProtocolHandler", url]] : ["xdg-open", [url]];
|
|
3078
|
+
const child = spawn(cmd, args, { stdio: "ignore", detached: true });
|
|
3079
|
+
child.on("error", () => {
|
|
3080
|
+
});
|
|
3081
|
+
child.unref();
|
|
3082
|
+
}
|
|
2938
3083
|
|
|
2939
3084
|
// src/tui/commands/mcp.ts
|
|
2940
3085
|
async function handleMcpCommand(ctx, args) {
|
|
@@ -2977,8 +3122,8 @@ Example mcp.json:
|
|
|
2977
3122
|
}
|
|
2978
3123
|
}
|
|
2979
3124
|
|
|
2980
|
-
|
|
2981
|
-
|
|
3125
|
+
Servers that require OAuth can be added with just a "url" \u2014
|
|
3126
|
+
authenticate them from the /mcp selector.`
|
|
2982
3127
|
);
|
|
2983
3128
|
return;
|
|
2984
3129
|
}
|
|
@@ -3003,6 +3148,20 @@ Note: For dynamic auth (token refresh), use a stdio wrapper.
|
|
|
3003
3148
|
onReconnectServer: async (name) => {
|
|
3004
3149
|
return mm.reconnectServer(name);
|
|
3005
3150
|
},
|
|
3151
|
+
onAuthenticateServer: async (name) => {
|
|
3152
|
+
return mm.authenticateServer(name, {
|
|
3153
|
+
onAuthorizationUrl: (url) => {
|
|
3154
|
+
showInfo(ctx.state, `MCP: To authenticate "${name}", open:
|
|
3155
|
+
${url}`);
|
|
3156
|
+
if (process.env.MASTRA_MCP_OAUTH_NO_BROWSER !== "1") {
|
|
3157
|
+
openUrlInBrowser(url);
|
|
3158
|
+
}
|
|
3159
|
+
}
|
|
3160
|
+
});
|
|
3161
|
+
},
|
|
3162
|
+
onCancelAuthenticateServer: async (name) => {
|
|
3163
|
+
return mm.cancelServerAuthentication(name);
|
|
3164
|
+
},
|
|
3006
3165
|
getServerLogs: (name) => {
|
|
3007
3166
|
return mm.getServerLogs(name);
|
|
3008
3167
|
},
|
|
@@ -3028,7 +3187,11 @@ async function reloadServers(ctx) {
|
|
|
3028
3187
|
const totalTools = connected.reduce((sum, s) => sum + s.toolCount, 0);
|
|
3029
3188
|
ctx.showInfo(`MCP: Reloaded. ${connected.length} server(s) connected, ${totalTools} tool(s).`);
|
|
3030
3189
|
for (const s of statuses.filter((s2) => !s2.connected)) {
|
|
3031
|
-
|
|
3190
|
+
if (s.needsAuth) {
|
|
3191
|
+
ctx.showInfo(`MCP: \u26A0 "${s.name}" needs authentication \u2192 run /mcp to authenticate`);
|
|
3192
|
+
} else {
|
|
3193
|
+
ctx.showInfo(`MCP: Failed to connect to "${s.name}": ${s.error}`);
|
|
3194
|
+
}
|
|
3032
3195
|
}
|
|
3033
3196
|
} catch (error) {
|
|
3034
3197
|
ctx.showError(`MCP reload failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -3046,8 +3209,8 @@ function showTextStatus(ctx) {
|
|
|
3046
3209
|
lines.push(` Claude: ${paths.claude}`);
|
|
3047
3210
|
lines.push("");
|
|
3048
3211
|
for (const status of statuses) {
|
|
3049
|
-
const icon = status.connecting ? "\u27F3" : status.connected ? "\u2713" : "\u2717";
|
|
3050
|
-
const state = status.connecting ? "connecting..." : status.connected ? "connected" : `error: ${status.error}`;
|
|
3212
|
+
const icon = status.authenticating ? "\u26A0" : status.connecting ? "\u27F3" : status.connected ? "\u2713" : status.needsAuth ? "\u26A0" : "\u2717";
|
|
3213
|
+
const state = status.authenticating ? "authenticating \u2014 cancel via /mcp" : status.connecting ? "connecting..." : status.connected ? "connected" : status.needsAuth ? "needs auth \u2014 authenticate via /mcp" : `error: ${status.error}`;
|
|
3051
3214
|
lines.push(` ${icon} ${status.name} [${status.transport}] (${state})`);
|
|
3052
3215
|
if (status.toolNames.length > 0) {
|
|
3053
3216
|
for (const toolName of status.toolNames) {
|
|
@@ -13598,22 +13761,6 @@ Run /browser on to apply.`);
|
|
|
13598
13761
|
}
|
|
13599
13762
|
ctx.showInfo(summary.join("\n"));
|
|
13600
13763
|
}
|
|
13601
|
-
function openUrlInBrowser(url) {
|
|
13602
|
-
let parsed;
|
|
13603
|
-
try {
|
|
13604
|
-
parsed = new URL(url);
|
|
13605
|
-
} catch {
|
|
13606
|
-
return;
|
|
13607
|
-
}
|
|
13608
|
-
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
13609
|
-
return;
|
|
13610
|
-
}
|
|
13611
|
-
const [cmd, args] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["rundll32", ["url.dll,FileProtocolHandler", url]] : ["xdg-open", [url]];
|
|
13612
|
-
const child = spawn(cmd, args, { stdio: "ignore", detached: true });
|
|
13613
|
-
child.on("error", () => {
|
|
13614
|
-
});
|
|
13615
|
-
child.unref();
|
|
13616
|
-
}
|
|
13617
13764
|
var LoginDialogComponent = class extends Box {
|
|
13618
13765
|
constructor(tui, providerId, onComplete) {
|
|
13619
13766
|
super(2, 1, (text) => theme.bg("overlayBg", text));
|
|
@@ -15549,7 +15696,6 @@ function pruneChatContainer(state) {
|
|
|
15549
15696
|
// src/tui/handlers/agent-lifecycle.ts
|
|
15550
15697
|
function handleAgentStart(ctx) {
|
|
15551
15698
|
const { state } = ctx;
|
|
15552
|
-
state.goalManager.startActiveTimer();
|
|
15553
15699
|
getCurrentGitBranchAsync(state.projectInfo.rootPath).then((freshBranch) => {
|
|
15554
15700
|
if (freshBranch) {
|
|
15555
15701
|
state.projectInfo.gitBranch = freshBranch;
|
|
@@ -15566,7 +15712,6 @@ function handleAgentStart(ctx) {
|
|
|
15566
15712
|
}
|
|
15567
15713
|
function handleAgentEnd(ctx) {
|
|
15568
15714
|
const { state } = ctx;
|
|
15569
|
-
state.goalManager.stopActiveTimer();
|
|
15570
15715
|
if (state.gradientAnimator) {
|
|
15571
15716
|
state.gradientAnimator.fadeOut();
|
|
15572
15717
|
}
|
|
@@ -15646,7 +15791,6 @@ function drainQueuedAction(ctx) {
|
|
|
15646
15791
|
}
|
|
15647
15792
|
function handleAgentAborted(ctx) {
|
|
15648
15793
|
const { state } = ctx;
|
|
15649
|
-
state.goalManager.stopActiveTimer();
|
|
15650
15794
|
if (state.gradientAnimator) {
|
|
15651
15795
|
state.gradientAnimator.fadeOut();
|
|
15652
15796
|
}
|
|
@@ -15683,7 +15827,6 @@ function handleAgentAborted(ctx) {
|
|
|
15683
15827
|
}
|
|
15684
15828
|
function handleAgentError(ctx) {
|
|
15685
15829
|
const { state } = ctx;
|
|
15686
|
-
state.goalManager.stopActiveTimer();
|
|
15687
15830
|
if (state.gradientAnimator) {
|
|
15688
15831
|
state.gradientAnimator.fadeOut();
|
|
15689
15832
|
}
|
|
@@ -20773,7 +20916,11 @@ var MastraTUI = class _MastraTUI {
|
|
|
20773
20916
|
if (this.state.mcpManager?.hasServers()) {
|
|
20774
20917
|
this.state.mcpManager.initInBackground().then((result) => {
|
|
20775
20918
|
for (const s of result.failed) {
|
|
20776
|
-
|
|
20919
|
+
if (s.needsAuth) {
|
|
20920
|
+
showInfo(this.state, `MCP: \u26A0 "${s.name}" needs authentication \u2192 run /mcp to authenticate`);
|
|
20921
|
+
} else {
|
|
20922
|
+
showInfo(this.state, `MCP: Failed to connect to "${s.name}": ${s.error}`);
|
|
20923
|
+
}
|
|
20777
20924
|
}
|
|
20778
20925
|
for (const s of result.skipped) {
|
|
20779
20926
|
showInfo(this.state, `MCP: Skipped "${s.name}": ${s.reason}`);
|
|
@@ -21644,5 +21791,5 @@ Would you like to update now?`;
|
|
|
21644
21791
|
};
|
|
21645
21792
|
|
|
21646
21793
|
export { AssistantMessageComponent, LoginDialogComponent, LoginSelectorComponent, MastraTUI, ModelSelectorComponent, OMProgressComponent, ToolExecutionComponentEnhanced, UserMessageComponent, applyThemeMode, createTUIState, detectTerminalTheme, formatOMStatus, getEditorTheme, getMarkdownTheme, getThemeMode, mastra, restoreTerminalForeground, theme };
|
|
21647
|
-
//# sourceMappingURL=chunk-
|
|
21648
|
-
//# sourceMappingURL=chunk-
|
|
21794
|
+
//# sourceMappingURL=chunk-FAXDM2KQ.js.map
|
|
21795
|
+
//# sourceMappingURL=chunk-FAXDM2KQ.js.map
|