@burdenoff/microfe-botmanor 2026.1027.2 → 2026.1028.1

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 (91) hide show
  1. package/dist/botlit/BotlitRoutes.js +142 -132
  2. package/dist/botlit/BotlitRoutes.js.map +1 -1
  3. package/dist/botlit/components/AgentApprovalPanel.js +144 -126
  4. package/dist/botlit/components/AgentApprovalPanel.js.map +1 -1
  5. package/dist/botlit/components/ModelRegistrationPanel.js +4 -4
  6. package/dist/botlit/components/RetentionStatusPanel.js +95 -0
  7. package/dist/botlit/components/RetentionStatusPanel.js.map +1 -0
  8. package/dist/botlit/components/VersionHistoryPanel.js +92 -83
  9. package/dist/botlit/components/VersionHistoryPanel.js.map +1 -1
  10. package/dist/botlit/hooks/index.js +1 -0
  11. package/dist/botlit/hooks/useRetention.js +31 -0
  12. package/dist/botlit/hooks/useRetention.js.map +1 -0
  13. package/dist/botlit/pages/A2AAgentDetailPage.js +212 -203
  14. package/dist/botlit/pages/A2AAgentDetailPage.js.map +1 -1
  15. package/dist/botlit/pages/A2ARegistryPage.js +129 -117
  16. package/dist/botlit/pages/A2ARegistryPage.js.map +1 -1
  17. package/dist/botlit/pages/AgentApprovalsPage.js +122 -110
  18. package/dist/botlit/pages/AgentApprovalsPage.js.map +1 -1
  19. package/dist/botlit/pages/AgentBuilderPage.js +18 -18
  20. package/dist/botlit/pages/AgentDetailPage.js +298 -273
  21. package/dist/botlit/pages/AgentDetailPage.js.map +1 -1
  22. package/dist/botlit/pages/AgentsListPage.js +145 -121
  23. package/dist/botlit/pages/AgentsListPage.js.map +1 -1
  24. package/dist/botlit/pages/BotChannelsTab.js +238 -226
  25. package/dist/botlit/pages/BotChannelsTab.js.map +1 -1
  26. package/dist/botlit/pages/BotDetailPage.js +307 -288
  27. package/dist/botlit/pages/BotDetailPage.js.map +1 -1
  28. package/dist/botlit/pages/BotWorkflowTab.js +125 -116
  29. package/dist/botlit/pages/BotWorkflowTab.js.map +1 -1
  30. package/dist/botlit/pages/BotsListPage.js +159 -144
  31. package/dist/botlit/pages/BotsListPage.js.map +1 -1
  32. package/dist/botlit/pages/BucketsPage.js +279 -258
  33. package/dist/botlit/pages/BucketsPage.js.map +1 -1
  34. package/dist/botlit/pages/ChannelDetailPage.js +346 -328
  35. package/dist/botlit/pages/ChannelDetailPage.js.map +1 -1
  36. package/dist/botlit/pages/ChannelRoutesPage.js +10 -10
  37. package/dist/botlit/pages/ChannelsPage.js +163 -148
  38. package/dist/botlit/pages/ChannelsPage.js.map +1 -1
  39. package/dist/botlit/pages/DashboardPage.js +129 -114
  40. package/dist/botlit/pages/DashboardPage.js.map +1 -1
  41. package/dist/botlit/pages/ExecutionDetailPage.js +145 -139
  42. package/dist/botlit/pages/ExecutionDetailPage.js.map +1 -1
  43. package/dist/botlit/pages/ExecutionsPage.js +14 -14
  44. package/dist/botlit/pages/InstalledPackagesPage.js +245 -227
  45. package/dist/botlit/pages/InstalledPackagesPage.js.map +1 -1
  46. package/dist/botlit/pages/KnowledgeBaseDetailPage.js +168 -156
  47. package/dist/botlit/pages/KnowledgeBaseDetailPage.js.map +1 -1
  48. package/dist/botlit/pages/KnowledgeBasesPage.js +91 -79
  49. package/dist/botlit/pages/KnowledgeBasesPage.js.map +1 -1
  50. package/dist/botlit/pages/MCPServerDetailPage.js +200 -188
  51. package/dist/botlit/pages/MCPServerDetailPage.js.map +1 -1
  52. package/dist/botlit/pages/MCPServersPage.js +170 -155
  53. package/dist/botlit/pages/MCPServersPage.js.map +1 -1
  54. package/dist/botlit/pages/PoliciesPage.js +115 -104
  55. package/dist/botlit/pages/PoliciesPage.js.map +1 -1
  56. package/dist/botlit/pages/PolicyDetailPage.js +368 -324
  57. package/dist/botlit/pages/PolicyDetailPage.js.map +1 -1
  58. package/dist/botlit/pages/PromptStudioPage.js +106 -97
  59. package/dist/botlit/pages/PromptStudioPage.js.map +1 -1
  60. package/dist/botlit/pages/PromptTemplateDetailPage.js +359 -347
  61. package/dist/botlit/pages/PromptTemplateDetailPage.js.map +1 -1
  62. package/dist/botlit/pages/PromptTemplatesPage.js +127 -112
  63. package/dist/botlit/pages/PromptTemplatesPage.js.map +1 -1
  64. package/dist/botlit/pages/RetrievalProfileDetailPage.js +219 -210
  65. package/dist/botlit/pages/RetrievalProfileDetailPage.js.map +1 -1
  66. package/dist/botlit/pages/RetrievalProfilesPage.js +112 -103
  67. package/dist/botlit/pages/RetrievalProfilesPage.js.map +1 -1
  68. package/dist/botlit/pages/SettingsPage.js +264 -252
  69. package/dist/botlit/pages/SettingsPage.js.map +1 -1
  70. package/dist/botlit/pages/SkillDetailPage.js +235 -226
  71. package/dist/botlit/pages/SkillDetailPage.js.map +1 -1
  72. package/dist/botlit/pages/SkillsPage.js +115 -106
  73. package/dist/botlit/pages/SkillsPage.js.map +1 -1
  74. package/dist/botlit/pages/StorePackageDetailPage.js +194 -188
  75. package/dist/botlit/pages/StorePackageDetailPage.js.map +1 -1
  76. package/dist/botlit/pages/StorePage.js +161 -155
  77. package/dist/botlit/pages/StorePage.js.map +1 -1
  78. package/dist/botlit/permissions/PermissionRequired.js +45 -0
  79. package/dist/botlit/permissions/PermissionRequired.js.map +1 -0
  80. package/dist/botlit/permissions/botmanorPermissions.js +72 -0
  81. package/dist/botlit/permissions/botmanorPermissions.js.map +1 -0
  82. package/dist/botlit/permissions/index.js +3 -0
  83. package/dist/botlit/permissions/useBotmanorPermissions.js +19 -0
  84. package/dist/botlit/permissions/useBotmanorPermissions.js.map +1 -0
  85. package/dist/botlit/utils/policyConfig.js +67 -42
  86. package/dist/botlit/utils/policyConfig.js.map +1 -1
  87. package/dist/generated/global-types.js.map +1 -1
  88. package/dist/generated/wspace-operations.js +90 -54
  89. package/dist/generated/wspace-operations.js.map +1 -1
  90. package/dist/generated/wspace-types.js.map +1 -1
  91. package/package.json +1 -1
@@ -2,314 +2,329 @@ import { useTr as e } from "../../shared/hooks/useTr.js";
2
2
  import { useBotlit as t } from "../providers/BotlitProvider.js";
3
3
  import { isMCPServerHealthy as n, mcpServerDescription as r, mcpServerEndpoint as i, useCreateMCPServer as a, useDeleteMCPServer as o, useMCPServers as s, useTestMCPConnection as c } from "../hooks/useMCPServers.js";
4
4
  import { formatRelativeTime as l } from "../utils/formatters.js";
5
- import { PageLayout as u } from "../components/PageLayout.js";
6
- import { Card as d, CardContent as f, CardDescription as p, CardHeader as m, CardTitle as h } from "../components/Card.js";
7
- import { Button as g } from "../components/Button.js";
8
- import { Badge as _, StatusBadge as v } from "../components/Badge.js";
9
- import { EmptyState as y } from "../components/EmptyState.js";
10
- import { FormField as b, Input as x } from "../components/Input.js";
11
- import { ErrorState as S } from "../components/ErrorState.js";
12
- import { useState as C } from "react";
13
- import { GlassCard as w, PagePurpose as T } from "@burdenoff/fe-libs/ui";
14
- import { jsx as E, jsxs as D } from "react/jsx-runtime";
15
- import { Plug as O, PlugZap as k, Plus as A, Settings as j, Trash2 as M } from "lucide-react";
16
- import { toast as N } from "sonner";
5
+ import { BOTMANOR_PERMISSIONS as u } from "../permissions/botmanorPermissions.js";
6
+ import { BotmanorPermissionGate as d } from "../permissions/useBotmanorPermissions.js";
7
+ import { PageLayout as f } from "../components/PageLayout.js";
8
+ import { Button as p } from "../components/Button.js";
9
+ import "../permissions/index.js";
10
+ import { Card as m, CardContent as h, CardDescription as g, CardHeader as _, CardTitle as v } from "../components/Card.js";
11
+ import { Badge as y, StatusBadge as b } from "../components/Badge.js";
12
+ import { EmptyState as x } from "../components/EmptyState.js";
13
+ import { FormField as S, Input as C } from "../components/Input.js";
14
+ import { ErrorState as w } from "../components/ErrorState.js";
15
+ import { useState as T } from "react";
16
+ import { GlassCard as E, PagePurpose as D } from "@burdenoff/fe-libs/ui";
17
+ import { jsx as O, jsxs as k } from "react/jsx-runtime";
18
+ import { Plug as A, PlugZap as j, Plus as M, Settings as N, Trash2 as P } from "lucide-react";
19
+ import { toast as F } from "sonner";
17
20
  //#region src/botlit/pages/MCPServersPage.tsx
18
- var P = () => {
19
- let P = e(), { navigateTo: F } = t(), { data: I, loading: L, error: R, refetch: z } = s(), [B, V] = a(), [H, U] = o(), [W, G] = c(), [K, q] = C(!1), [J, Y] = C({
21
+ var I = () => {
22
+ let I = e(), { navigateTo: L } = t(), { data: R, loading: z, error: B, refetch: V } = s(), [H, U] = a(), [W, G] = o(), [K, q] = c(), [J, Y] = T(!1), [X, Z] = T({
20
23
  name: "",
21
24
  description: "",
22
25
  transport: "HTTP_JSON",
23
26
  baseUrl: ""
24
- }), X = async () => {
25
- if (!(!J.name || !J.baseUrl)) {
27
+ }), Q = async () => {
28
+ if (!(!X.name || !X.baseUrl)) {
26
29
  try {
27
- await B({
28
- name: J.name,
29
- type: J.transport,
30
+ await H({
31
+ name: X.name,
32
+ type: X.transport,
30
33
  config: {
31
- url: J.baseUrl,
32
- description: J.description
34
+ url: X.baseUrl,
35
+ description: X.description
33
36
  }
34
37
  });
35
38
  } catch (e) {
36
- N.error(e instanceof Error ? e.message : P("botlit.mcpServers.toast.connectError", "Failed to connect MCP server"));
39
+ F.error(e instanceof Error ? e.message : I("botlit.mcpServers.toast.connectError", "Failed to connect MCP server"));
37
40
  return;
38
41
  }
39
- N.success(P("botlit.mcpServers.toast.connectSuccess", "Connected \"{{name}}\"", { name: J.name })), z(), Y({
42
+ F.success(I("botlit.mcpServers.toast.connectSuccess", "Connected \"{{name}}\"", { name: X.name })), V(), Z({
40
43
  name: "",
41
44
  description: "",
42
45
  transport: "HTTP_JSON",
43
46
  baseUrl: ""
44
- }), q(!1);
47
+ }), Y(!1);
45
48
  }
46
- }, Z = async (e) => {
49
+ }, $ = async (e) => {
47
50
  try {
48
- await H(e.id), N.success(P("botlit.mcpServers.toast.disconnectSuccess", "Disconnected \"{{name}}\"", { name: e.name })), z();
51
+ await W(e.id), F.success(I("botlit.mcpServers.toast.disconnectSuccess", "Disconnected \"{{name}}\"", { name: e.name })), V();
49
52
  } catch (e) {
50
- N.error(e instanceof Error ? e.message : P("botlit.mcpServers.toast.disconnectError", "Failed to disconnect MCP server"));
53
+ F.error(e instanceof Error ? e.message : I("botlit.mcpServers.toast.disconnectError", "Failed to disconnect MCP server"));
51
54
  }
52
- }, Q = async (e) => {
55
+ }, ee = async (e) => {
53
56
  try {
54
- await W(e.id) ? N.success(P("botlit.mcpServers.toast.reachable", "\"{{name}}\" is reachable", { name: e.name })) : N.error(P("botlit.mcpServers.toast.unreachable", "\"{{name}}\" did not respond", { name: e.name })), z();
57
+ await K(e.id) ? F.success(I("botlit.mcpServers.toast.reachable", "\"{{name}}\" is reachable", { name: e.name })) : F.error(I("botlit.mcpServers.toast.unreachable", "\"{{name}}\" did not respond", { name: e.name })), V();
55
58
  } catch (e) {
56
- N.error(e instanceof Error ? e.message : P("botlit.mcpServers.toast.testError", "Failed to test MCP connection"));
59
+ F.error(e instanceof Error ? e.message : I("botlit.mcpServers.toast.testError", "Failed to test MCP connection"));
57
60
  }
58
61
  };
59
- return /* @__PURE__ */ E(u, {
60
- title: P("botlit.mcpServers.title", "MCP Servers"),
61
- description: P("botlit.mcpServers.description", "Connect Model Context Protocol servers to extend agent capabilities"),
62
- actions: /* @__PURE__ */ E(g, {
63
- leftIcon: /* @__PURE__ */ E(A, { size: 16 }),
64
- onClick: () => q(!0),
65
- children: P("botlit.mcpServers.actions.add", "Add MCP Server")
62
+ return /* @__PURE__ */ O(f, {
63
+ title: I("botlit.mcpServers.title", "MCP Servers"),
64
+ description: I("botlit.mcpServers.description", "Connect Model Context Protocol servers to extend agent capabilities"),
65
+ actions: /* @__PURE__ */ O(d, {
66
+ permission: u.MCP_CREATE,
67
+ children: /* @__PURE__ */ O(p, {
68
+ leftIcon: /* @__PURE__ */ O(M, { size: 16 }),
69
+ onClick: () => Y(!0),
70
+ children: I("botlit.mcpServers.actions.add", "Add MCP Server")
71
+ })
66
72
  }),
67
- children: /* @__PURE__ */ D("div", {
73
+ children: /* @__PURE__ */ k("div", {
68
74
  className: "space-y-6",
69
75
  children: [
70
- /* @__PURE__ */ E(T, {
71
- icon: /* @__PURE__ */ E(O, { size: 18 }),
72
- children: P("botlit.mcpServers.purpose", "MCP (Model Context Protocol) servers are how your agents reach the outside world — they expose real tools an agent can call, like searching the web, reading a GitHub repo, querying a database or posting to Slack. Connect a server here and its tools become available to your agents (gated by your tool policies), turning a chatbot into something that can take action.")
76
+ /* @__PURE__ */ O(D, {
77
+ icon: /* @__PURE__ */ O(A, { size: 18 }),
78
+ children: I("botlit.mcpServers.purpose", "MCP (Model Context Protocol) servers are how your agents reach the outside world — they expose real tools an agent can call, like searching the web, reading a GitHub repo, querying a database or posting to Slack. Connect a server here and its tools become available to your agents (gated by your tool policies), turning a chatbot into something that can take action.")
73
79
  }),
74
- L ? /* @__PURE__ */ E("div", {
80
+ z ? /* @__PURE__ */ O("div", {
75
81
  className: "grid grid-cols-1 md:grid-cols-2 gap-4",
76
82
  children: [
77
83
  1,
78
84
  2,
79
85
  3
80
- ].map((e) => /* @__PURE__ */ E("div", { className: "h-48 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg" }, e))
81
- }) : R ? /* @__PURE__ */ E(S, {
86
+ ].map((e) => /* @__PURE__ */ O("div", { className: "h-48 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg" }, e))
87
+ }) : B ? /* @__PURE__ */ O(w, {
82
88
  resource: "MCP servers",
83
- error: R,
84
- onRetry: () => void z()
85
- }) : I.length > 0 ? /* @__PURE__ */ E("div", {
89
+ error: B,
90
+ onRetry: () => void V()
91
+ }) : R.length > 0 ? /* @__PURE__ */ O("div", {
86
92
  className: "grid grid-cols-1 md:grid-cols-2 gap-4",
87
- children: I.map((e) => /* @__PURE__ */ D(d, { children: [/* @__PURE__ */ D(m, {
93
+ children: R.map((e) => /* @__PURE__ */ k(m, { children: [/* @__PURE__ */ k(_, {
88
94
  className: "flex flex-row items-start justify-between",
89
- children: [/* @__PURE__ */ D("div", {
95
+ children: [/* @__PURE__ */ k("div", {
90
96
  className: "flex items-start gap-3",
91
- children: [/* @__PURE__ */ E("div", {
97
+ children: [/* @__PURE__ */ O("div", {
92
98
  className: `p-2 rounded-lg ${n(e.status) ? "bg-status-success-bg-subtle" : "bg-bg-sunken"}`,
93
- children: n(e.status) ? /* @__PURE__ */ E(k, { className: "h-5 w-5 text-status-success-text" }) : /* @__PURE__ */ E(O, { className: "h-5 w-5 text-text-secondary" })
94
- }), /* @__PURE__ */ D("div", { children: [/* @__PURE__ */ E(h, {
99
+ children: n(e.status) ? /* @__PURE__ */ O(j, { className: "h-5 w-5 text-status-success-text" }) : /* @__PURE__ */ O(A, { className: "h-5 w-5 text-text-secondary" })
100
+ }), /* @__PURE__ */ k("div", { children: [/* @__PURE__ */ O(v, {
95
101
  className: "text-base",
96
102
  children: e.name
97
- }), /* @__PURE__ */ E(p, { children: r(e) })] })]
98
- }), /* @__PURE__ */ E(v, { status: e.status })]
99
- }), /* @__PURE__ */ E(f, { children: /* @__PURE__ */ D("div", {
103
+ }), /* @__PURE__ */ O(g, { children: r(e) })] })]
104
+ }), /* @__PURE__ */ O(b, { status: e.status })]
105
+ }), /* @__PURE__ */ O(h, { children: /* @__PURE__ */ k("div", {
100
106
  className: "space-y-4",
101
107
  children: [
102
- /* @__PURE__ */ D("div", {
108
+ /* @__PURE__ */ k("div", {
103
109
  className: "flex flex-wrap items-center gap-4 text-sm",
104
- children: [/* @__PURE__ */ E(_, {
110
+ children: [/* @__PURE__ */ O(y, {
105
111
  variant: "outline",
106
112
  className: "capitalize",
107
113
  children: e.type.toLowerCase().replace("_", " ")
108
- }), e.lastConnectedAt && /* @__PURE__ */ D("span", {
114
+ }), e.lastConnectedAt && /* @__PURE__ */ k("span", {
109
115
  className: "text-text-secondary",
110
116
  children: [
111
- P("botlit.botsList.createdLabel", "Created"),
117
+ I("botlit.botsList.createdLabel", "Created"),
112
118
  " ",
113
119
  l(e.lastConnectedAt)
114
120
  ]
115
121
  })]
116
122
  }),
117
- i(e) && /* @__PURE__ */ E("p", {
123
+ i(e) && /* @__PURE__ */ O("p", {
118
124
  className: "truncate text-sm text-text-secondary",
119
125
  children: i(e)
120
126
  }),
121
- e.errorMessage && /* @__PURE__ */ E("p", {
127
+ e.errorMessage && /* @__PURE__ */ O("p", {
122
128
  className: "text-sm text-status-error-text",
123
129
  children: e.errorMessage
124
130
  }),
125
- /* @__PURE__ */ D("div", {
131
+ /* @__PURE__ */ k("div", {
126
132
  className: "flex items-center gap-2 pt-2 border-t border-border-subtle",
127
133
  children: [
128
- /* @__PURE__ */ E(g, {
129
- variant: "outline",
130
- size: "sm",
131
- onClick: () => void Q(e),
132
- isLoading: G.loading,
133
- children: P("botlit.mcpServers.actions.testConnection", "Test connection")
134
+ /* @__PURE__ */ O(d, {
135
+ permission: u.MCP_TEST,
136
+ children: /* @__PURE__ */ O(p, {
137
+ variant: "outline",
138
+ size: "sm",
139
+ onClick: () => void ee(e),
140
+ isLoading: q.loading,
141
+ children: I("botlit.mcpServers.actions.testConnection", "Test connection")
142
+ })
134
143
  }),
135
- /* @__PURE__ */ E(g, {
144
+ /* @__PURE__ */ O(p, {
136
145
  variant: "ghost",
137
146
  size: "sm",
138
- leftIcon: /* @__PURE__ */ E(j, { size: 14 }),
139
- onClick: () => F(`mcp/${e.id}`),
140
- children: P("botlit.mcpServers.actions.configure", "Configure")
147
+ leftIcon: /* @__PURE__ */ O(N, { size: 14 }),
148
+ onClick: () => L(`mcp/${e.id}`),
149
+ children: I("botlit.mcpServers.actions.configure", "Configure")
141
150
  }),
142
- /* @__PURE__ */ E(g, {
143
- variant: "ghost",
144
- size: "icon",
145
- className: "ml-auto",
146
- "aria-label": `Disconnect ${e.name}`,
147
- onClick: () => void Z(e),
148
- isLoading: U.loading,
149
- children: /* @__PURE__ */ E(M, { size: 16 })
151
+ /* @__PURE__ */ O(d, {
152
+ permission: u.MCP_DELETE,
153
+ children: /* @__PURE__ */ O(p, {
154
+ variant: "ghost",
155
+ size: "icon",
156
+ className: "ml-auto",
157
+ "aria-label": `Disconnect ${e.name}`,
158
+ onClick: () => void $(e),
159
+ isLoading: G.loading,
160
+ children: /* @__PURE__ */ O(P, { size: 16 })
161
+ })
150
162
  })
151
163
  ]
152
164
  })
153
165
  ]
154
166
  }) })] }, e.id))
155
- }) : /* @__PURE__ */ E(y, {
167
+ }) : /* @__PURE__ */ O(x, {
156
168
  illustration: "empty-generic",
157
- title: P("botlit.mcpServers.empty.title", "No MCP servers connected"),
158
- description: P("botlit.mcpServers.empty.description", "Connect MCP servers to give your agents access to external tools and resources."),
159
- action: /* @__PURE__ */ E(g, {
160
- leftIcon: /* @__PURE__ */ E(A, { size: 16 }),
161
- onClick: () => q(!0),
162
- children: P("botlit.mcpServers.actions.add", "Add MCP Server")
169
+ title: I("botlit.mcpServers.empty.title", "No MCP servers connected"),
170
+ description: I("botlit.mcpServers.empty.description", "Connect MCP servers to give your agents access to external tools and resources."),
171
+ action: /* @__PURE__ */ O(d, {
172
+ permission: u.MCP_CREATE,
173
+ children: /* @__PURE__ */ O(p, {
174
+ leftIcon: /* @__PURE__ */ O(M, { size: 16 }),
175
+ onClick: () => Y(!0),
176
+ children: I("botlit.mcpServers.actions.add", "Add MCP Server")
177
+ })
163
178
  })
164
179
  }),
165
- /* @__PURE__ */ D(w, {
180
+ /* @__PURE__ */ k(E, {
166
181
  treatment: "glass",
167
182
  glow: !0,
168
183
  className: "p-6",
169
- children: [/* @__PURE__ */ D("div", {
184
+ children: [/* @__PURE__ */ k("div", {
170
185
  className: "mb-4",
171
- children: [/* @__PURE__ */ E("h2", {
186
+ children: [/* @__PURE__ */ O("h2", {
172
187
  className: "text-lg font-semibold tracking-tight text-text-primary",
173
- children: P("botlit.mcpServers.presets.title", "Popular MCP Servers")
174
- }), /* @__PURE__ */ E("p", {
188
+ children: I("botlit.mcpServers.presets.title", "Popular MCP Servers")
189
+ }), /* @__PURE__ */ O("p", {
175
190
  className: "text-sm text-text-secondary",
176
- children: P("botlit.mcpServers.presets.description", "Quick-add common MCP servers")
191
+ children: I("botlit.mcpServers.presets.description", "Quick-add common MCP servers")
177
192
  })]
178
- }), /* @__PURE__ */ E("div", {
193
+ }), /* @__PURE__ */ O("div", {
179
194
  className: "grid grid-cols-1 md:grid-cols-3 gap-4",
180
195
  children: [
181
196
  {
182
- name: P("botlit.mcpServers.presets.github", "GitHub"),
183
- description: P("botlit.mcpServers.presets.githubDesc", "Repository management and code operations"),
197
+ name: I("botlit.mcpServers.presets.github", "GitHub"),
198
+ description: I("botlit.mcpServers.presets.githubDesc", "Repository management and code operations"),
184
199
  baseUrl: "https://mcp.github.com"
185
200
  },
186
201
  {
187
- name: P("botlit.mcpServers.presets.filesystem", "Filesystem"),
188
- description: P("botlit.mcpServers.presets.filesystemDesc", "Local file system access"),
202
+ name: I("botlit.mcpServers.presets.filesystem", "Filesystem"),
203
+ description: I("botlit.mcpServers.presets.filesystemDesc", "Local file system access"),
189
204
  baseUrl: "http://localhost:3001"
190
205
  },
191
206
  {
192
- name: P("botlit.mcpServers.presets.braveSearch", "Brave Search"),
193
- description: P("botlit.mcpServers.presets.braveSearchDesc", "Web search capabilities"),
207
+ name: I("botlit.mcpServers.presets.braveSearch", "Brave Search"),
208
+ description: I("botlit.mcpServers.presets.braveSearchDesc", "Web search capabilities"),
194
209
  baseUrl: "https://mcp.search.brave.com"
195
210
  },
196
211
  {
197
- name: P("botlit.mcpServers.presets.postgres", "PostgreSQL"),
198
- description: P("botlit.mcpServers.presets.postgresDesc", "Database queries and management"),
212
+ name: I("botlit.mcpServers.presets.postgres", "PostgreSQL"),
213
+ description: I("botlit.mcpServers.presets.postgresDesc", "Database queries and management"),
199
214
  baseUrl: "http://localhost:3002"
200
215
  },
201
216
  {
202
- name: P("botlit.mcpServers.presets.slack", "Slack"),
203
- description: P("botlit.mcpServers.presets.slackDesc", "Slack messaging integration"),
217
+ name: I("botlit.mcpServers.presets.slack", "Slack"),
218
+ description: I("botlit.mcpServers.presets.slackDesc", "Slack messaging integration"),
204
219
  baseUrl: "https://mcp.slack.com"
205
220
  },
206
221
  {
207
- name: P("botlit.mcpServers.presets.puppeteer", "Puppeteer"),
208
- description: P("botlit.mcpServers.presets.puppeteerDesc", "Browser automation"),
222
+ name: I("botlit.mcpServers.presets.puppeteer", "Puppeteer"),
223
+ description: I("botlit.mcpServers.presets.puppeteerDesc", "Browser automation"),
209
224
  baseUrl: "http://localhost:3003"
210
225
  }
211
- ].map((e) => /* @__PURE__ */ D("button", {
226
+ ].map((e) => /* @__PURE__ */ k("button", {
212
227
  className: "p-4 text-left border border-border-subtle rounded-lg hover:bg-accent transition-colors",
213
228
  onClick: () => {
214
- Y({
229
+ Z({
215
230
  name: e.name,
216
231
  description: e.description,
217
232
  transport: "HTTP_JSON",
218
233
  baseUrl: e.baseUrl
219
- }), q(!0);
234
+ }), Y(!0);
220
235
  },
221
- children: [/* @__PURE__ */ E("p", {
236
+ children: [/* @__PURE__ */ O("p", {
222
237
  className: "font-medium",
223
238
  children: e.name
224
- }), /* @__PURE__ */ E("p", {
239
+ }), /* @__PURE__ */ O("p", {
225
240
  className: "text-sm text-text-secondary mt-1",
226
241
  children: e.description
227
242
  })]
228
243
  }, e.name))
229
244
  })]
230
245
  }),
231
- K && /* @__PURE__ */ E("div", {
246
+ J && /* @__PURE__ */ O("div", {
232
247
  className: "fixed inset-0 bg-black/50 flex items-center justify-center z-50",
233
- children: /* @__PURE__ */ D(d, {
248
+ children: /* @__PURE__ */ k(m, {
234
249
  className: "w-full max-w-lg",
235
- children: [/* @__PURE__ */ D(m, { children: [/* @__PURE__ */ E(h, { children: P("botlit.mcpServers.form.title", "Add MCP Server") }), /* @__PURE__ */ E(p, { children: P("botlit.mcpServers.form.description", "Connect a new MCP server") })] }), /* @__PURE__ */ D(f, {
250
+ children: [/* @__PURE__ */ k(_, { children: [/* @__PURE__ */ O(v, { children: I("botlit.mcpServers.form.title", "Add MCP Server") }), /* @__PURE__ */ O(g, { children: I("botlit.mcpServers.form.description", "Connect a new MCP server") })] }), /* @__PURE__ */ k(h, {
236
251
  className: "space-y-4",
237
252
  children: [
238
- /* @__PURE__ */ E(b, {
239
- label: P("botlit.mcpServers.form.nameLabel", "Server Name"),
253
+ /* @__PURE__ */ O(S, {
254
+ label: I("botlit.mcpServers.form.nameLabel", "Server Name"),
240
255
  required: !0,
241
- children: /* @__PURE__ */ E(x, {
242
- placeholder: P("botlit.mcpServers.form.namePlaceholder", "e.g., GitHub"),
243
- value: J.name,
244
- onChange: (e) => Y({
245
- ...J,
256
+ children: /* @__PURE__ */ O(C, {
257
+ placeholder: I("botlit.mcpServers.form.namePlaceholder", "e.g., GitHub"),
258
+ value: X.name,
259
+ onChange: (e) => Z({
260
+ ...X,
246
261
  name: e.target.value
247
262
  })
248
263
  })
249
264
  }),
250
- /* @__PURE__ */ E(b, {
251
- label: P("botlit.mcpServers.form.descriptionLabel", "Description"),
252
- children: /* @__PURE__ */ E(x, {
253
- placeholder: P("botlit.mcpServers.form.descriptionPlaceholder", "What does this server do?"),
254
- value: J.description,
255
- onChange: (e) => Y({
256
- ...J,
265
+ /* @__PURE__ */ O(S, {
266
+ label: I("botlit.mcpServers.form.descriptionLabel", "Description"),
267
+ children: /* @__PURE__ */ O(C, {
268
+ placeholder: I("botlit.mcpServers.form.descriptionPlaceholder", "What does this server do?"),
269
+ value: X.description,
270
+ onChange: (e) => Z({
271
+ ...X,
257
272
  description: e.target.value
258
273
  })
259
274
  })
260
275
  }),
261
- /* @__PURE__ */ E(b, {
262
- label: P("botlit.mcpServers.form.transportLabel", "Transport"),
263
- children: /* @__PURE__ */ D("select", {
276
+ /* @__PURE__ */ O(S, {
277
+ label: I("botlit.mcpServers.form.transportLabel", "Transport"),
278
+ children: /* @__PURE__ */ k("select", {
264
279
  className: "flex h-10 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm",
265
- value: J.transport,
266
- onChange: (e) => Y({
267
- ...J,
280
+ value: X.transport,
281
+ onChange: (e) => Z({
282
+ ...X,
268
283
  transport: e.target.value
269
284
  }),
270
285
  children: [
271
- /* @__PURE__ */ E("option", {
286
+ /* @__PURE__ */ O("option", {
272
287
  value: "HTTP_JSON",
273
288
  children: "HTTP JSON"
274
289
  }),
275
- /* @__PURE__ */ E("option", {
290
+ /* @__PURE__ */ O("option", {
276
291
  value: "JSON_RPC",
277
292
  children: "JSON RPC"
278
293
  }),
279
- /* @__PURE__ */ E("option", {
294
+ /* @__PURE__ */ O("option", {
280
295
  value: "SSE",
281
296
  children: "Server-Sent Events"
282
297
  }),
283
- /* @__PURE__ */ E("option", {
298
+ /* @__PURE__ */ O("option", {
284
299
  value: "CUSTOM",
285
300
  children: "Custom"
286
301
  })
287
302
  ]
288
303
  })
289
304
  }),
290
- /* @__PURE__ */ E(b, {
291
- label: P("botlit.mcpServers.form.baseUrlLabel", "Base URL"),
305
+ /* @__PURE__ */ O(S, {
306
+ label: I("botlit.mcpServers.form.baseUrlLabel", "Base URL"),
292
307
  required: !0,
293
- children: /* @__PURE__ */ E(x, {
294
- placeholder: P("botlit.mcpServers.form.baseUrlPlaceholder", "e.g., https://mcp.example.com"),
295
- value: J.baseUrl,
296
- onChange: (e) => Y({
297
- ...J,
308
+ children: /* @__PURE__ */ O(C, {
309
+ placeholder: I("botlit.mcpServers.form.baseUrlPlaceholder", "e.g., https://mcp.example.com"),
310
+ value: X.baseUrl,
311
+ onChange: (e) => Z({
312
+ ...X,
298
313
  baseUrl: e.target.value
299
314
  })
300
315
  })
301
316
  }),
302
- /* @__PURE__ */ D("div", {
317
+ /* @__PURE__ */ k("div", {
303
318
  className: "flex justify-end gap-2 pt-4",
304
- children: [/* @__PURE__ */ E(g, {
319
+ children: [/* @__PURE__ */ O(p, {
305
320
  variant: "outline",
306
- onClick: () => q(!1),
307
- children: P("botlit.mcpServers.actions.cancel", "Cancel")
308
- }), /* @__PURE__ */ E(g, {
309
- onClick: X,
310
- isLoading: V.loading,
311
- disabled: !J.name || !J.baseUrl,
312
- children: P("botlit.mcpServers.actions.connect", "Connect")
321
+ onClick: () => Y(!1),
322
+ children: I("botlit.mcpServers.actions.cancel", "Cancel")
323
+ }), /* @__PURE__ */ O(p, {
324
+ onClick: Q,
325
+ isLoading: U.loading,
326
+ disabled: !X.name || !X.baseUrl,
327
+ children: I("botlit.mcpServers.actions.connect", "Connect")
313
328
  })]
314
329
  })
315
330
  ]
@@ -321,6 +336,6 @@ var P = () => {
321
336
  });
322
337
  };
323
338
  //#endregion
324
- export { P as MCPServersPage };
339
+ export { I as MCPServersPage };
325
340
 
326
341
  //# sourceMappingURL=MCPServersPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MCPServersPage.js","names":[],"sources":["../../../src/botlit/pages/MCPServersPage.tsx"],"sourcesContent":["/**\n * MCP Servers Page\n * @module botlit/pages\n */\n\nimport type { FC } from 'react';\nimport { useState } from 'react';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport { Plus, Plug, PlugZap, Settings, Trash2 } from 'lucide-react';\nimport { toast } from 'sonner';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { PagePurpose, GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../components/PageLayout';\nimport { Card, CardHeader, CardTitle, CardContent, CardDescription } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { Input, FormField } from '../components/Input';\nimport { Badge, StatusBadge } from '../components/Badge';\nimport { EmptyState } from '../components/EmptyState';\nimport { ErrorState } from '../components/ErrorState';\nimport {\n useMCPServers,\n useCreateMCPServer,\n useDeleteMCPServer,\n useTestMCPConnection,\n isMCPServerHealthy,\n mcpServerDescription,\n mcpServerEndpoint,\n type MCPServerRecord,\n} from '../hooks/useMCPServers';\nimport { formatRelativeTime } from '../utils/formatters';\nimport type { MCPTransport } from '../types';\n\nexport const MCPServersPage: FC = () => {\n const t = useTr();\n const { navigateTo } = useBotlit();\n const { data: servers, loading, error, refetch } = useMCPServers();\n const [connectServer, connectResult] = useCreateMCPServer();\n const [deleteServer, deleteResult] = useDeleteMCPServer();\n const [testConnection, testResult] = useTestMCPConnection();\n const [showAddModal, setShowAddModal] = useState(false);\n const [newServer, setNewServer] = useState({\n name: '',\n description: '',\n transport: 'HTTP_JSON' as MCPTransport,\n baseUrl: '',\n });\n\n const handleConnect = async () => {\n if (!newServer.name || !newServer.baseUrl) return;\n\n try {\n await connectServer({\n name: newServer.name,\n type: newServer.transport,\n config: {\n url: newServer.baseUrl,\n description: newServer.description,\n },\n });\n } catch (err) {\n // Keep the dialog open so the operator can correct and retry — closing it\n // here is what made failed writes look like successes.\n toast.error(\n err instanceof Error\n ? err.message\n : t('botlit.mcpServers.toast.connectError', 'Failed to connect MCP server')\n );\n return;\n }\n\n toast.success(\n t('botlit.mcpServers.toast.connectSuccess', 'Connected \"{{name}}\"', {\n name: newServer.name,\n })\n );\n void refetch();\n setNewServer({ name: '', description: '', transport: 'HTTP_JSON', baseUrl: '' });\n setShowAddModal(false);\n };\n\n const handleDisconnect = async (server: MCPServerRecord) => {\n try {\n await deleteServer(server.id);\n toast.success(\n t('botlit.mcpServers.toast.disconnectSuccess', 'Disconnected \"{{name}}\"', {\n name: server.name,\n })\n );\n void refetch();\n } catch (err) {\n toast.error(\n err instanceof Error\n ? err.message\n : t('botlit.mcpServers.toast.disconnectError', 'Failed to disconnect MCP server')\n );\n }\n };\n\n const handleTest = async (server: MCPServerRecord) => {\n try {\n const ok = await testConnection(server.id);\n if (ok) {\n toast.success(\n t('botlit.mcpServers.toast.reachable', '\"{{name}}\" is reachable', {\n name: server.name,\n })\n );\n } else {\n toast.error(\n t('botlit.mcpServers.toast.unreachable', '\"{{name}}\" did not respond', {\n name: server.name,\n })\n );\n }\n void refetch();\n } catch (err) {\n toast.error(\n err instanceof Error\n ? err.message\n : t('botlit.mcpServers.toast.testError', 'Failed to test MCP connection')\n );\n }\n };\n\n return (\n <PageLayout\n title={t('botlit.mcpServers.title', 'MCP Servers')}\n description={t(\n 'botlit.mcpServers.description',\n 'Connect Model Context Protocol servers to extend agent capabilities'\n )}\n actions={\n <Button leftIcon={<Plus size={16} />} onClick={() => setShowAddModal(true)}>\n {t('botlit.mcpServers.actions.add', 'Add MCP Server')}\n </Button>\n }\n >\n <div className=\"space-y-6\">\n <PagePurpose icon={<Plug size={18} />}>\n {t(\n 'botlit.mcpServers.purpose',\n 'MCP (Model Context Protocol) servers are how your agents reach the outside world — they expose real tools an agent can call, like searching the web, reading a GitHub repo, querying a database or posting to Slack. Connect a server here and its tools become available to your agents (gated by your tool policies), turning a chatbot into something that can take action.'\n )}\n </PagePurpose>\n\n {/* Server List */}\n {loading ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {[1, 2, 3].map((i) => (\n <div\n key={i}\n className=\"h-48 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg\"\n />\n ))}\n </div>\n ) : error ? (\n <ErrorState resource=\"MCP servers\" error={error} onRetry={() => void refetch()} />\n ) : servers.length > 0 ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {servers.map((server: MCPServerRecord) => (\n <Card key={server.id}>\n <CardHeader className=\"flex flex-row items-start justify-between\">\n <div className=\"flex items-start gap-3\">\n <div\n className={`p-2 rounded-lg ${\n isMCPServerHealthy(server.status)\n ? 'bg-status-success-bg-subtle'\n : 'bg-bg-sunken'\n }`}\n >\n {isMCPServerHealthy(server.status) ? (\n <PlugZap className=\"h-5 w-5 text-status-success-text\" />\n ) : (\n <Plug className=\"h-5 w-5 text-text-secondary\" />\n )}\n </div>\n <div>\n <CardTitle className=\"text-base\">{server.name}</CardTitle>\n <CardDescription>{mcpServerDescription(server)}</CardDescription>\n </div>\n </div>\n <StatusBadge status={server.status} />\n </CardHeader>\n <CardContent>\n <div className=\"space-y-4\">\n {/* Transport Info */}\n <div className=\"flex flex-wrap items-center gap-4 text-sm\">\n <Badge variant=\"outline\" className=\"capitalize\">\n {server.type.toLowerCase().replace('_', ' ')}\n </Badge>\n {server.lastConnectedAt && (\n <span className=\"text-text-secondary\">\n {t('botlit.botsList.createdLabel', 'Created')}{' '}\n {formatRelativeTime(server.lastConnectedAt)}\n </span>\n )}\n </div>\n\n {/* Endpoint */}\n {mcpServerEndpoint(server) && (\n <p className=\"truncate text-sm text-text-secondary\">\n {mcpServerEndpoint(server)}\n </p>\n )}\n\n {server.errorMessage && (\n <p className=\"text-sm text-status-error-text\">{server.errorMessage}</p>\n )}\n\n {/* Actions */}\n <div className=\"flex items-center gap-2 pt-2 border-t border-border-subtle\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void handleTest(server)}\n isLoading={testResult.loading}\n >\n {t('botlit.mcpServers.actions.testConnection', 'Test connection')}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n leftIcon={<Settings size={14} />}\n onClick={() => navigateTo(`mcp/${server.id}`)}\n >\n {t('botlit.mcpServers.actions.configure', 'Configure')}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"ml-auto\"\n aria-label={`Disconnect ${server.name}`}\n onClick={() => void handleDisconnect(server)}\n isLoading={deleteResult.loading}\n >\n <Trash2 size={16} />\n </Button>\n </div>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-generic\"\n title={t('botlit.mcpServers.empty.title', 'No MCP servers connected')}\n description={t(\n 'botlit.mcpServers.empty.description',\n 'Connect MCP servers to give your agents access to external tools and resources.'\n )}\n action={\n <Button leftIcon={<Plus size={16} />} onClick={() => setShowAddModal(true)}>\n {t('botlit.mcpServers.actions.add', 'Add MCP Server')}\n </Button>\n }\n />\n )}\n\n {/* Available MCP Servers */}\n <GlassCard treatment=\"glass\" glow className=\"p-6\">\n <div className=\"mb-4\">\n <h2 className=\"text-lg font-semibold tracking-tight text-text-primary\">\n {t('botlit.mcpServers.presets.title', 'Popular MCP Servers')}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {t('botlit.mcpServers.presets.description', 'Quick-add common MCP servers')}\n </p>\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n {[\n {\n name: t('botlit.mcpServers.presets.github', 'GitHub'),\n description: t(\n 'botlit.mcpServers.presets.githubDesc',\n 'Repository management and code operations'\n ),\n baseUrl: 'https://mcp.github.com',\n },\n {\n name: t('botlit.mcpServers.presets.filesystem', 'Filesystem'),\n description: t(\n 'botlit.mcpServers.presets.filesystemDesc',\n 'Local file system access'\n ),\n baseUrl: 'http://localhost:3001',\n },\n {\n name: t('botlit.mcpServers.presets.braveSearch', 'Brave Search'),\n description: t(\n 'botlit.mcpServers.presets.braveSearchDesc',\n 'Web search capabilities'\n ),\n baseUrl: 'https://mcp.search.brave.com',\n },\n {\n name: t('botlit.mcpServers.presets.postgres', 'PostgreSQL'),\n description: t(\n 'botlit.mcpServers.presets.postgresDesc',\n 'Database queries and management'\n ),\n baseUrl: 'http://localhost:3002',\n },\n {\n name: t('botlit.mcpServers.presets.slack', 'Slack'),\n description: t(\n 'botlit.mcpServers.presets.slackDesc',\n 'Slack messaging integration'\n ),\n baseUrl: 'https://mcp.slack.com',\n },\n {\n name: t('botlit.mcpServers.presets.puppeteer', 'Puppeteer'),\n description: t('botlit.mcpServers.presets.puppeteerDesc', 'Browser automation'),\n baseUrl: 'http://localhost:3003',\n },\n ].map((preset) => (\n <button\n key={preset.name}\n className=\"p-4 text-left border border-border-subtle rounded-lg hover:bg-accent transition-colors\"\n onClick={() => {\n setNewServer({\n name: preset.name,\n description: preset.description,\n transport: 'HTTP_JSON',\n baseUrl: preset.baseUrl,\n });\n setShowAddModal(true);\n }}\n >\n <p className=\"font-medium\">{preset.name}</p>\n <p className=\"text-sm text-text-secondary mt-1\">{preset.description}</p>\n </button>\n ))}\n </div>\n </GlassCard>\n\n {/* Add Server Modal */}\n {showAddModal && (\n <div className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50\">\n <Card className=\"w-full max-w-lg\">\n <CardHeader>\n <CardTitle>{t('botlit.mcpServers.form.title', 'Add MCP Server')}</CardTitle>\n <CardDescription>\n {t('botlit.mcpServers.form.description', 'Connect a new MCP server')}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <FormField label={t('botlit.mcpServers.form.nameLabel', 'Server Name')} required>\n <Input\n placeholder={t('botlit.mcpServers.form.namePlaceholder', 'e.g., GitHub')}\n value={newServer.name}\n onChange={(e) => setNewServer({ ...newServer, name: e.target.value })}\n />\n </FormField>\n <FormField label={t('botlit.mcpServers.form.descriptionLabel', 'Description')}>\n <Input\n placeholder={t(\n 'botlit.mcpServers.form.descriptionPlaceholder',\n 'What does this server do?'\n )}\n value={newServer.description}\n onChange={(e) => setNewServer({ ...newServer, description: e.target.value })}\n />\n </FormField>\n <FormField label={t('botlit.mcpServers.form.transportLabel', 'Transport')}>\n <select\n className=\"flex h-10 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm\"\n value={newServer.transport}\n onChange={(e) =>\n setNewServer({ ...newServer, transport: e.target.value as MCPTransport })\n }\n >\n <option value=\"HTTP_JSON\">HTTP JSON</option>\n <option value=\"JSON_RPC\">JSON RPC</option>\n <option value=\"SSE\">Server-Sent Events</option>\n <option value=\"CUSTOM\">Custom</option>\n </select>\n </FormField>\n <FormField label={t('botlit.mcpServers.form.baseUrlLabel', 'Base URL')} required>\n <Input\n placeholder={t(\n 'botlit.mcpServers.form.baseUrlPlaceholder',\n 'e.g., https://mcp.example.com'\n )}\n value={newServer.baseUrl}\n onChange={(e) => setNewServer({ ...newServer, baseUrl: e.target.value })}\n />\n </FormField>\n <div className=\"flex justify-end gap-2 pt-4\">\n <Button variant=\"outline\" onClick={() => setShowAddModal(false)}>\n {t('botlit.mcpServers.actions.cancel', 'Cancel')}\n </Button>\n <Button\n onClick={handleConnect}\n isLoading={connectResult.loading}\n disabled={!newServer.name || !newServer.baseUrl}\n >\n {t('botlit.mcpServers.actions.connect', 'Connect')}\n </Button>\n </div>\n </CardContent>\n </Card>\n </div>\n )}\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"MCPServersPage.js","names":[],"sources":["../../../src/botlit/pages/MCPServersPage.tsx"],"sourcesContent":["/**\n * MCP Servers Page\n * @module botlit/pages\n */\n\nimport type { FC } from 'react';\nimport { useState } from 'react';\nimport { useBotlit } from '../providers/BotlitProvider';\nimport { Plus, Plug, PlugZap, Settings, Trash2 } from 'lucide-react';\nimport { toast } from 'sonner';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { PagePurpose, GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../components/PageLayout';\nimport { Card, CardHeader, CardTitle, CardContent, CardDescription } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { Input, FormField } from '../components/Input';\nimport { Badge, StatusBadge } from '../components/Badge';\nimport { EmptyState } from '../components/EmptyState';\nimport { ErrorState } from '../components/ErrorState';\nimport {\n useMCPServers,\n useCreateMCPServer,\n useDeleteMCPServer,\n useTestMCPConnection,\n isMCPServerHealthy,\n mcpServerDescription,\n mcpServerEndpoint,\n type MCPServerRecord,\n} from '../hooks/useMCPServers';\nimport { formatRelativeTime } from '../utils/formatters';\nimport type { MCPTransport } from '../types';\nimport { BOTMANOR_PERMISSIONS, BotmanorPermissionGate } from '../permissions';\n\nexport const MCPServersPage: FC = () => {\n const t = useTr();\n const { navigateTo } = useBotlit();\n const { data: servers, loading, error, refetch } = useMCPServers();\n const [connectServer, connectResult] = useCreateMCPServer();\n const [deleteServer, deleteResult] = useDeleteMCPServer();\n const [testConnection, testResult] = useTestMCPConnection();\n const [showAddModal, setShowAddModal] = useState(false);\n const [newServer, setNewServer] = useState({\n name: '',\n description: '',\n transport: 'HTTP_JSON' as MCPTransport,\n baseUrl: '',\n });\n\n const handleConnect = async () => {\n if (!newServer.name || !newServer.baseUrl) return;\n\n try {\n await connectServer({\n name: newServer.name,\n type: newServer.transport,\n config: {\n url: newServer.baseUrl,\n description: newServer.description,\n },\n });\n } catch (err) {\n // Keep the dialog open so the operator can correct and retry — closing it\n // here is what made failed writes look like successes.\n toast.error(\n err instanceof Error\n ? err.message\n : t('botlit.mcpServers.toast.connectError', 'Failed to connect MCP server')\n );\n return;\n }\n\n toast.success(\n t('botlit.mcpServers.toast.connectSuccess', 'Connected \"{{name}}\"', {\n name: newServer.name,\n })\n );\n void refetch();\n setNewServer({ name: '', description: '', transport: 'HTTP_JSON', baseUrl: '' });\n setShowAddModal(false);\n };\n\n const handleDisconnect = async (server: MCPServerRecord) => {\n try {\n await deleteServer(server.id);\n toast.success(\n t('botlit.mcpServers.toast.disconnectSuccess', 'Disconnected \"{{name}}\"', {\n name: server.name,\n })\n );\n void refetch();\n } catch (err) {\n toast.error(\n err instanceof Error\n ? err.message\n : t('botlit.mcpServers.toast.disconnectError', 'Failed to disconnect MCP server')\n );\n }\n };\n\n const handleTest = async (server: MCPServerRecord) => {\n try {\n const ok = await testConnection(server.id);\n if (ok) {\n toast.success(\n t('botlit.mcpServers.toast.reachable', '\"{{name}}\" is reachable', {\n name: server.name,\n })\n );\n } else {\n toast.error(\n t('botlit.mcpServers.toast.unreachable', '\"{{name}}\" did not respond', {\n name: server.name,\n })\n );\n }\n void refetch();\n } catch (err) {\n toast.error(\n err instanceof Error\n ? err.message\n : t('botlit.mcpServers.toast.testError', 'Failed to test MCP connection')\n );\n }\n };\n\n return (\n <PageLayout\n title={t('botlit.mcpServers.title', 'MCP Servers')}\n description={t(\n 'botlit.mcpServers.description',\n 'Connect Model Context Protocol servers to extend agent capabilities'\n )}\n actions={\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.MCP_CREATE}>\n <Button leftIcon={<Plus size={16} />} onClick={() => setShowAddModal(true)}>\n {t('botlit.mcpServers.actions.add', 'Add MCP Server')}\n </Button>\n </BotmanorPermissionGate>\n }\n >\n <div className=\"space-y-6\">\n <PagePurpose icon={<Plug size={18} />}>\n {t(\n 'botlit.mcpServers.purpose',\n 'MCP (Model Context Protocol) servers are how your agents reach the outside world — they expose real tools an agent can call, like searching the web, reading a GitHub repo, querying a database or posting to Slack. Connect a server here and its tools become available to your agents (gated by your tool policies), turning a chatbot into something that can take action.'\n )}\n </PagePurpose>\n\n {/* Server List */}\n {loading ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {[1, 2, 3].map((i) => (\n <div\n key={i}\n className=\"h-48 bg-bg-sunken motion-safe:animate-vc-shimmer rounded-lg\"\n />\n ))}\n </div>\n ) : error ? (\n <ErrorState resource=\"MCP servers\" error={error} onRetry={() => void refetch()} />\n ) : servers.length > 0 ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {servers.map((server: MCPServerRecord) => (\n <Card key={server.id}>\n <CardHeader className=\"flex flex-row items-start justify-between\">\n <div className=\"flex items-start gap-3\">\n <div\n className={`p-2 rounded-lg ${\n isMCPServerHealthy(server.status)\n ? 'bg-status-success-bg-subtle'\n : 'bg-bg-sunken'\n }`}\n >\n {isMCPServerHealthy(server.status) ? (\n <PlugZap className=\"h-5 w-5 text-status-success-text\" />\n ) : (\n <Plug className=\"h-5 w-5 text-text-secondary\" />\n )}\n </div>\n <div>\n <CardTitle className=\"text-base\">{server.name}</CardTitle>\n <CardDescription>{mcpServerDescription(server)}</CardDescription>\n </div>\n </div>\n <StatusBadge status={server.status} />\n </CardHeader>\n <CardContent>\n <div className=\"space-y-4\">\n {/* Transport Info */}\n <div className=\"flex flex-wrap items-center gap-4 text-sm\">\n <Badge variant=\"outline\" className=\"capitalize\">\n {server.type.toLowerCase().replace('_', ' ')}\n </Badge>\n {server.lastConnectedAt && (\n <span className=\"text-text-secondary\">\n {t('botlit.botsList.createdLabel', 'Created')}{' '}\n {formatRelativeTime(server.lastConnectedAt)}\n </span>\n )}\n </div>\n\n {/* Endpoint */}\n {mcpServerEndpoint(server) && (\n <p className=\"truncate text-sm text-text-secondary\">\n {mcpServerEndpoint(server)}\n </p>\n )}\n\n {server.errorMessage && (\n <p className=\"text-sm text-status-error-text\">{server.errorMessage}</p>\n )}\n\n {/* Actions */}\n <div className=\"flex items-center gap-2 pt-2 border-t border-border-subtle\">\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.MCP_TEST}>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void handleTest(server)}\n isLoading={testResult.loading}\n >\n {t('botlit.mcpServers.actions.testConnection', 'Test connection')}\n </Button>\n </BotmanorPermissionGate>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n leftIcon={<Settings size={14} />}\n onClick={() => navigateTo(`mcp/${server.id}`)}\n >\n {t('botlit.mcpServers.actions.configure', 'Configure')}\n </Button>\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.MCP_DELETE}>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"ml-auto\"\n aria-label={`Disconnect ${server.name}`}\n onClick={() => void handleDisconnect(server)}\n isLoading={deleteResult.loading}\n >\n <Trash2 size={16} />\n </Button>\n </BotmanorPermissionGate>\n </div>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-generic\"\n title={t('botlit.mcpServers.empty.title', 'No MCP servers connected')}\n description={t(\n 'botlit.mcpServers.empty.description',\n 'Connect MCP servers to give your agents access to external tools and resources.'\n )}\n action={\n <BotmanorPermissionGate permission={BOTMANOR_PERMISSIONS.MCP_CREATE}>\n <Button leftIcon={<Plus size={16} />} onClick={() => setShowAddModal(true)}>\n {t('botlit.mcpServers.actions.add', 'Add MCP Server')}\n </Button>\n </BotmanorPermissionGate>\n }\n />\n )}\n\n {/* Available MCP Servers */}\n <GlassCard treatment=\"glass\" glow className=\"p-6\">\n <div className=\"mb-4\">\n <h2 className=\"text-lg font-semibold tracking-tight text-text-primary\">\n {t('botlit.mcpServers.presets.title', 'Popular MCP Servers')}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {t('botlit.mcpServers.presets.description', 'Quick-add common MCP servers')}\n </p>\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n {[\n {\n name: t('botlit.mcpServers.presets.github', 'GitHub'),\n description: t(\n 'botlit.mcpServers.presets.githubDesc',\n 'Repository management and code operations'\n ),\n baseUrl: 'https://mcp.github.com',\n },\n {\n name: t('botlit.mcpServers.presets.filesystem', 'Filesystem'),\n description: t(\n 'botlit.mcpServers.presets.filesystemDesc',\n 'Local file system access'\n ),\n baseUrl: 'http://localhost:3001',\n },\n {\n name: t('botlit.mcpServers.presets.braveSearch', 'Brave Search'),\n description: t(\n 'botlit.mcpServers.presets.braveSearchDesc',\n 'Web search capabilities'\n ),\n baseUrl: 'https://mcp.search.brave.com',\n },\n {\n name: t('botlit.mcpServers.presets.postgres', 'PostgreSQL'),\n description: t(\n 'botlit.mcpServers.presets.postgresDesc',\n 'Database queries and management'\n ),\n baseUrl: 'http://localhost:3002',\n },\n {\n name: t('botlit.mcpServers.presets.slack', 'Slack'),\n description: t(\n 'botlit.mcpServers.presets.slackDesc',\n 'Slack messaging integration'\n ),\n baseUrl: 'https://mcp.slack.com',\n },\n {\n name: t('botlit.mcpServers.presets.puppeteer', 'Puppeteer'),\n description: t('botlit.mcpServers.presets.puppeteerDesc', 'Browser automation'),\n baseUrl: 'http://localhost:3003',\n },\n ].map((preset) => (\n <button\n key={preset.name}\n className=\"p-4 text-left border border-border-subtle rounded-lg hover:bg-accent transition-colors\"\n onClick={() => {\n setNewServer({\n name: preset.name,\n description: preset.description,\n transport: 'HTTP_JSON',\n baseUrl: preset.baseUrl,\n });\n setShowAddModal(true);\n }}\n >\n <p className=\"font-medium\">{preset.name}</p>\n <p className=\"text-sm text-text-secondary mt-1\">{preset.description}</p>\n </button>\n ))}\n </div>\n </GlassCard>\n\n {/* Add Server Modal */}\n {showAddModal && (\n <div className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50\">\n <Card className=\"w-full max-w-lg\">\n <CardHeader>\n <CardTitle>{t('botlit.mcpServers.form.title', 'Add MCP Server')}</CardTitle>\n <CardDescription>\n {t('botlit.mcpServers.form.description', 'Connect a new MCP server')}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <FormField label={t('botlit.mcpServers.form.nameLabel', 'Server Name')} required>\n <Input\n placeholder={t('botlit.mcpServers.form.namePlaceholder', 'e.g., GitHub')}\n value={newServer.name}\n onChange={(e) => setNewServer({ ...newServer, name: e.target.value })}\n />\n </FormField>\n <FormField label={t('botlit.mcpServers.form.descriptionLabel', 'Description')}>\n <Input\n placeholder={t(\n 'botlit.mcpServers.form.descriptionPlaceholder',\n 'What does this server do?'\n )}\n value={newServer.description}\n onChange={(e) => setNewServer({ ...newServer, description: e.target.value })}\n />\n </FormField>\n <FormField label={t('botlit.mcpServers.form.transportLabel', 'Transport')}>\n <select\n className=\"flex h-10 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm\"\n value={newServer.transport}\n onChange={(e) =>\n setNewServer({ ...newServer, transport: e.target.value as MCPTransport })\n }\n >\n <option value=\"HTTP_JSON\">HTTP JSON</option>\n <option value=\"JSON_RPC\">JSON RPC</option>\n <option value=\"SSE\">Server-Sent Events</option>\n <option value=\"CUSTOM\">Custom</option>\n </select>\n </FormField>\n <FormField label={t('botlit.mcpServers.form.baseUrlLabel', 'Base URL')} required>\n <Input\n placeholder={t(\n 'botlit.mcpServers.form.baseUrlPlaceholder',\n 'e.g., https://mcp.example.com'\n )}\n value={newServer.baseUrl}\n onChange={(e) => setNewServer({ ...newServer, baseUrl: e.target.value })}\n />\n </FormField>\n <div className=\"flex justify-end gap-2 pt-4\">\n <Button variant=\"outline\" onClick={() => setShowAddModal(false)}>\n {t('botlit.mcpServers.actions.cancel', 'Cancel')}\n </Button>\n <Button\n onClick={handleConnect}\n isLoading={connectResult.loading}\n disabled={!newServer.name || !newServer.baseUrl}\n >\n {t('botlit.mcpServers.actions.connect', 'Connect')}\n </Button>\n </div>\n </CardContent>\n </Card>\n </div>\n )}\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}