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