@openhands/agent-canvas 1.0.0-beta.5 → 1.0.0-beta.6

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 (97) hide show
  1. package/README.md +2 -2
  2. package/build/assets/{automations-list-rMki-8au.js → automations-list-6FDbI5dc.js} +1 -1
  3. package/build/assets/{home-XxBpNOVq.js → home-e-egNUXZ.js} +1 -1
  4. package/build/assets/install-server-modal-DHlbgqVH.js +1 -0
  5. package/build/assets/{manifest-d9077852.js → manifest-3bf30d69.js} +1 -1
  6. package/build/assets/{mcp-D2onbwVk.js → mcp-ByeBfdfU.js} +1 -1
  7. package/build/assets/{recommended-automations-launcher-BQChv2rc.js → recommended-automations-launcher-CgV8FyPK.js} +1 -1
  8. package/build/assets/{root-BgEbw3S0.js → root-dNntxffj.js} +1 -1
  9. package/build/assets/vendor~home~mcp~automations-list-Cs-TO3fK.js +1 -0
  10. package/build/index.html +3 -3
  11. package/dist/components/features/mcp-page/install-server-modal.cjs +1 -1
  12. package/dist/components/features/mcp-page/install-server-modal.cjs.map +1 -1
  13. package/dist/components/features/mcp-page/install-server-modal.js +92 -81
  14. package/dist/components/features/mcp-page/install-server-modal.js.map +1 -1
  15. package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.cjs +1 -1
  16. package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.cjs.map +1 -1
  17. package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.js +3 -1
  18. package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.js.map +1 -1
  19. package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.cjs +1 -1
  20. package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.cjs.map +1 -1
  21. package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.js +3 -1
  22. package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.js.map +1 -1
  23. package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.cjs +1 -1
  24. package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.cjs.map +1 -1
  25. package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.js +3 -1
  26. package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.js.map +1 -1
  27. package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.cjs +1 -1
  28. package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.cjs.map +1 -1
  29. package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.js +3 -1
  30. package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.js.map +1 -1
  31. package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.cjs +1 -1
  32. package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.cjs.map +1 -1
  33. package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.js +3 -1
  34. package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.js.map +1 -1
  35. package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.cjs +1 -1
  36. package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.cjs.map +1 -1
  37. package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.js +3 -1
  38. package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.js.map +1 -1
  39. package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.cjs +1 -1
  40. package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.cjs.map +1 -1
  41. package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.js +3 -1
  42. package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.js.map +1 -1
  43. package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.cjs +1 -1
  44. package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.cjs.map +1 -1
  45. package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.js +3 -1
  46. package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.js.map +1 -1
  47. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.cjs +1 -1
  48. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.cjs.map +1 -1
  49. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.js +3 -1
  50. package/dist/node_modules/@openhands/extensions/integrations/catalog/github.js.map +1 -1
  51. package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.cjs +1 -1
  52. package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.cjs.map +1 -1
  53. package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.js +3 -1
  54. package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.js.map +1 -1
  55. package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.cjs +1 -1
  56. package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.cjs.map +1 -1
  57. package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.js +3 -1
  58. package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.js.map +1 -1
  59. package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.cjs +1 -1
  60. package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.cjs.map +1 -1
  61. package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.js +3 -1
  62. package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.js.map +1 -1
  63. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs +1 -1
  64. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs.map +1 -1
  65. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js +3 -1
  66. package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js.map +1 -1
  67. package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.cjs +1 -1
  68. package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.cjs.map +1 -1
  69. package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.js +2 -1
  70. package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.js.map +1 -1
  71. package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.cjs +1 -1
  72. package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.cjs.map +1 -1
  73. package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.js +2 -1
  74. package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.js.map +1 -1
  75. package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.cjs +1 -1
  76. package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.cjs.map +1 -1
  77. package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.js +3 -1
  78. package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.js.map +1 -1
  79. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.cjs +1 -1
  80. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.cjs.map +1 -1
  81. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.js +8 -7
  82. package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.js.map +1 -1
  83. package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.cjs +1 -1
  84. package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.cjs.map +1 -1
  85. package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.js +2 -1
  86. package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.js.map +1 -1
  87. package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.cjs +1 -1
  88. package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.cjs.map +1 -1
  89. package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.js +4 -2
  90. package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.js.map +1 -1
  91. package/dist/package.cjs +1 -1
  92. package/dist/package.cjs.map +1 -1
  93. package/dist/package.js +2 -2
  94. package/dist/package.js.map +1 -1
  95. package/package.json +2 -2
  96. package/build/assets/install-server-modal-f31_CLrW.js +0 -1
  97. package/build/assets/vendor~home~mcp~automations-list-Ccy2I0KU.js +0 -1
@@ -15,29 +15,40 @@ import p from "react";
15
15
  import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
16
16
  //#region src/components/features/mcp-page/install-server-modal.tsx
17
17
  function _(e) {
18
+ let t = /\[([^\]]+)\]\(([^)]+)\)/g, n = [], r = 0;
19
+ for (let i of e.matchAll(t)) i.index > r && n.push(e.slice(r, i.index)), n.push(/* @__PURE__ */ h("a", {
20
+ href: /^https?:\/\//i.test(i[2]) ? i[2] : "#",
21
+ target: "_blank",
22
+ rel: "noreferrer",
23
+ className: "underline hover:text-white transition-colors",
24
+ children: i[1]
25
+ }, i.index)), r = i.index + i[0].length;
26
+ return r < e.length && n.push(e.slice(r)), n;
27
+ }
28
+ function v(e) {
18
29
  return e?.transport.kind !== "shttp" && e?.transport.kind !== "sse" ? !1 : [
19
30
  "api_key",
20
31
  "bearer",
21
32
  "basic"
22
33
  ].includes(e.auth.strategy);
23
34
  }
24
- function v(e) {
35
+ function y(e) {
25
36
  return e.transport.kind === "stdio" ? e.auth.apiKeyOptional ?? !1 : e.auth.apiKeyOptional ?? e.transport.apiKeyOptional ?? !1;
26
37
  }
27
- function y(e) {
38
+ function b(e) {
28
39
  let t = {}, n = l(e), r = n?.transport;
29
40
  if (r?.kind === "stdio") {
30
41
  for (let e of r.envFields ?? []) t[e.key] = "";
31
42
  for (let e of r.argFields ?? []) t[e.key] = "";
32
- } else _(n) && (t.api_key = "");
43
+ } else v(n) && (t.api_key = "");
33
44
  return {
34
45
  values: t,
35
46
  errors: {}
36
47
  };
37
48
  }
38
- function b({ entry: b, onClose: x, onSuccess: S }) {
39
- let { t: C } = e("openhands"), { mutate: w, isPending: T } = d(), { mutate: E, isPending: D } = f(), [O, k] = p.useState(() => y(b)), [A, j] = p.useState(null), M = l(b), N = M?.transport, P = D || T, F = (e, t) => {
40
- k((n) => ({
49
+ function x({ entry: x, onClose: S, onSuccess: C }) {
50
+ let { t: w } = e("openhands"), { mutate: T, isPending: E } = d(), { mutate: D, isPending: O } = f(), [k, A] = p.useState(() => b(x)), [j, M] = p.useState(null), N = l(x), P = N?.transport, F = O || E, I = (e, t) => {
51
+ A((n) => ({
41
52
  values: {
42
53
  ...n.values,
43
54
  [e]: t
@@ -46,56 +57,56 @@ function b({ entry: b, onClose: x, onSuccess: S }) {
46
57
  ...n.errors,
47
58
  [e]: null
48
59
  }
49
- })), j(null);
50
- }, I = (e) => {
60
+ })), M(null);
61
+ }, L = (e) => {
51
62
  switch (e.error_kind) {
52
- case "timeout": return C(t.MCP$TEST_ERROR_TIMEOUT);
53
- case "connection": return C(t.MCP$TEST_ERROR_CONNECTION);
54
- default: return C(t.MCP$TEST_ERROR_UNKNOWN, { error: e.error });
63
+ case "timeout": return w(t.MCP$TEST_ERROR_TIMEOUT);
64
+ case "connection": return w(t.MCP$TEST_ERROR_CONNECTION);
65
+ default: return w(t.MCP$TEST_ERROR_UNKNOWN, { error: e.error });
55
66
  }
56
- }, L = (e) => {
57
- E(e, {
67
+ }, R = (e) => {
68
+ D(e, {
58
69
  onSuccess: (r) => {
59
70
  if (!r.ok) {
60
- j(I(r));
71
+ M(L(r));
61
72
  return;
62
73
  }
63
- w(e, {
74
+ T(e, {
64
75
  onSuccess: () => {
65
- n(C(t.MCP$INSTALL_SUCCESS)), S?.(b), x();
76
+ n(w(t.MCP$INSTALL_SUCCESS)), C?.(x), S();
66
77
  },
67
78
  onError: (e) => {
68
- j(c(e) || C(t.ERROR$GENERIC));
79
+ M(c(e) || w(t.ERROR$GENERIC));
69
80
  }
70
81
  });
71
82
  },
72
83
  onError: (e) => {
73
- j(c(e) || C(t.ERROR$GENERIC));
84
+ M(c(e) || w(t.ERROR$GENERIC));
74
85
  }
75
86
  });
76
- }, R = () => {
77
- if (N?.kind !== "shttp" && N?.kind !== "sse" || !M) return;
78
- let e = O.values.api_key?.trim() ?? "", n = _(M);
79
- if (n && !v(M) && !e) {
80
- k((e) => ({
87
+ }, z = () => {
88
+ if (P?.kind !== "shttp" && P?.kind !== "sse" || !N) return;
89
+ let e = k.values.api_key?.trim() ?? "", n = v(N);
90
+ if (n && !y(N) && !e) {
91
+ A((e) => ({
81
92
  ...e,
82
- errors: { api_key: C(t.MCP$ERROR_FIELD_REQUIRED) }
93
+ errors: { api_key: w(t.MCP$ERROR_FIELD_REQUIRED) }
83
94
  }));
84
95
  return;
85
96
  }
86
- L({
87
- id: `${N.kind}-${r()}`,
88
- type: N.kind,
89
- url: N.url,
97
+ R({
98
+ id: `${P.kind}-${r()}`,
99
+ type: P.kind,
100
+ url: P.url,
90
101
  ...n && e && { api_key: e }
91
102
  });
92
- }, z = () => {
93
- if (N?.kind !== "stdio") return;
94
- let e = N, n = {};
95
- for (let r of e.envFields ?? []) r.required && !(O.values[r.key] ?? "").trim() && (n[r.key] = C(t.MCP$ERROR_FIELD_REQUIRED));
96
- for (let r of e.argFields ?? []) r.required && !(O.values[r.key] ?? "").trim() && (n[r.key] = C(t.MCP$ERROR_FIELD_REQUIRED));
103
+ }, B = () => {
104
+ if (P?.kind !== "stdio") return;
105
+ let e = P, n = {};
106
+ for (let r of e.envFields ?? []) r.required && !(k.values[r.key] ?? "").trim() && (n[r.key] = w(t.MCP$ERROR_FIELD_REQUIRED));
107
+ for (let r of e.argFields ?? []) r.required && !(k.values[r.key] ?? "").trim() && (n[r.key] = w(t.MCP$ERROR_FIELD_REQUIRED));
97
108
  if (Object.values(n).some(Boolean)) {
98
- k((e) => ({
109
+ A((e) => ({
99
110
  ...e,
100
111
  errors: n
101
112
  }));
@@ -103,15 +114,15 @@ function b({ entry: b, onClose: x, onSuccess: S }) {
103
114
  }
104
115
  let i = {};
105
116
  for (let t of e.envFields ?? []) {
106
- let e = O.values[t.key]?.trim();
117
+ let e = k.values[t.key]?.trim();
107
118
  e && (i[t.key] = e);
108
119
  }
109
120
  let a = [];
110
121
  for (let t of e.argFields ?? []) {
111
- let e = O.values[t.key]?.trim();
122
+ let e = k.values[t.key]?.trim();
112
123
  if (e) for (let t of e.split(/\s+/)) t && a.push(t);
113
124
  }
114
- L({
125
+ R({
115
126
  id: `stdio-${r()}`,
116
127
  type: "stdio",
117
128
  name: e.serverName,
@@ -121,54 +132,54 @@ function b({ entry: b, onClose: x, onSuccess: S }) {
121
132
  });
122
133
  };
123
134
  return /* @__PURE__ */ h(i, {
124
- onClose: x,
125
- "aria-label": b.name,
135
+ onClose: S,
136
+ "aria-label": x.name,
126
137
  children: /* @__PURE__ */ g("form", {
127
138
  "data-testid": "mcp-install-modal",
128
- "data-marketplace-id": b.id,
129
- onSubmit: (e) => (e.preventDefault(), j(null), N?.kind === "shttp" || N?.kind === "sse" ? R() : z()),
139
+ "data-marketplace-id": x.id,
140
+ onSubmit: (e) => (e.preventDefault(), M(null), P?.kind === "shttp" || P?.kind === "sse" ? z() : B()),
130
141
  className: "relative bg-base-secondary p-6 rounded-xl flex flex-col gap-4 border border-[var(--oh-border)] w-[520px] max-w-[90vw] max-h-[85vh] overflow-y-auto custom-scrollbar",
131
142
  children: [
132
143
  /* @__PURE__ */ h(a, {
133
- onClose: x,
144
+ onClose: S,
134
145
  testId: "mcp-install-modal-close",
135
- disabled: P
146
+ disabled: F
136
147
  }),
137
148
  /* @__PURE__ */ g("div", {
138
149
  className: "flex items-start gap-3 pr-6",
139
- children: [/* @__PURE__ */ h(u, { entry: b }), /* @__PURE__ */ g("div", {
150
+ children: [/* @__PURE__ */ h(u, { entry: x }), /* @__PURE__ */ g("div", {
140
151
  className: "flex flex-col flex-1",
141
152
  children: [/* @__PURE__ */ h("h2", {
142
153
  className: "text-lg font-semibold",
143
- children: b.name
154
+ children: x.name
144
155
  }), /* @__PURE__ */ h("p", {
145
156
  className: "text-xs text-tertiary-light",
146
- children: b.description
157
+ children: x.description
147
158
  })]
148
159
  })]
149
160
  }),
150
- b.installHint && /* @__PURE__ */ h("p", {
161
+ x.installHint && /* @__PURE__ */ h("p", {
151
162
  className: "text-xs text-tertiary-light",
152
- children: b.installHint
163
+ children: x.installHint
153
164
  }),
154
- b.docsUrl && /* @__PURE__ */ h("a", {
155
- href: b.docsUrl,
165
+ x.docsUrl && /* @__PURE__ */ h("a", {
166
+ href: x.docsUrl,
156
167
  target: "_blank",
157
168
  rel: "noreferrer",
158
169
  className: "text-xs text-[var(--oh-muted)] hover:text-white hover:underline self-start transition-colors",
159
- children: C(t.MCP$VIEW_DOCS)
170
+ children: w(t.MCP$VIEW_DOCS)
160
171
  }),
161
172
  /* @__PURE__ */ h("div", {
162
173
  className: "flex flex-col gap-3",
163
174
  children: (() => {
164
- if (N?.kind === "shttp" || N?.kind === "sse") {
165
- let e = _(M), n = M ? v(M) : !1;
175
+ if (P?.kind === "shttp" || P?.kind === "sse") {
176
+ let e = v(N), n = N ? y(N) : !1;
166
177
  return /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h(s, {
167
178
  testId: "mcp-install-field-url",
168
179
  name: "url",
169
180
  type: "url",
170
- label: C(t.SETTINGS$MCP_URL),
171
- value: N.url,
181
+ label: w(t.SETTINGS$MCP_URL),
182
+ value: P.url,
172
183
  onChange: () => {},
173
184
  isDisabled: !0,
174
185
  className: "w-full"
@@ -178,27 +189,27 @@ function b({ entry: b, onClose: x, onSuccess: S }) {
178
189
  testId: "mcp-install-field-api_key",
179
190
  name: "api_key",
180
191
  type: "password",
181
- label: C(t.SETTINGS$MCP_API_KEY),
182
- value: O.values.api_key ?? "",
183
- onChange: (e) => F("api_key", e),
184
- placeholder: C(t.SETTINGS$MCP_API_KEY_PLACEHOLDER),
192
+ label: w(t.SETTINGS$MCP_API_KEY),
193
+ value: k.values.api_key ?? "",
194
+ onChange: (e) => I("api_key", e),
195
+ placeholder: w(t.SETTINGS$MCP_API_KEY_PLACEHOLDER),
185
196
  showOptionalTag: n,
186
197
  required: !n,
187
198
  className: "w-full"
188
- }), O.errors.api_key && /* @__PURE__ */ h("p", {
199
+ }), k.errors.api_key && /* @__PURE__ */ h("p", {
189
200
  className: "text-xs text-red-500",
190
- children: O.errors.api_key
201
+ children: k.errors.api_key
191
202
  })]
192
203
  }) : null] });
193
204
  }
194
- if (N?.kind !== "stdio") return null;
195
- let e = N;
205
+ if (P?.kind !== "stdio") return null;
206
+ let e = P;
196
207
  return /* @__PURE__ */ g(m, { children: [
197
208
  /* @__PURE__ */ h(s, {
198
209
  testId: "mcp-install-field-command-readonly",
199
210
  name: "command-readonly",
200
211
  type: "text",
201
- label: C(t.MCP$COMMAND_LABEL),
212
+ label: w(t.MCP$COMMAND_LABEL),
202
213
  value: `${e.command} ${e.args.join(" ")}`.trim(),
203
214
  onChange: () => {},
204
215
  isDisabled: !0,
@@ -212,8 +223,8 @@ function b({ entry: b, onClose: x, onSuccess: S }) {
212
223
  name: e.key,
213
224
  type: e.type === "password" ? "password" : "text",
214
225
  label: e.label,
215
- value: O.values[e.key] ?? "",
216
- onChange: (t) => F(e.key, t),
226
+ value: k.values[e.key] ?? "",
227
+ onChange: (t) => I(e.key, t),
217
228
  placeholder: e.placeholder,
218
229
  required: e.required,
219
230
  showOptionalTag: !e.required,
@@ -221,11 +232,11 @@ function b({ entry: b, onClose: x, onSuccess: S }) {
221
232
  }),
222
233
  e.helperText && /* @__PURE__ */ h("p", {
223
234
  className: "text-xs text-tertiary-alt",
224
- children: e.helperText
235
+ children: _(e.helperText)
225
236
  }),
226
- O.errors[e.key] && /* @__PURE__ */ h("p", {
237
+ k.errors[e.key] && /* @__PURE__ */ h("p", {
227
238
  className: "text-xs text-red-500",
228
- children: O.errors[e.key]
239
+ children: k.errors[e.key]
229
240
  })
230
241
  ]
231
242
  }, e.key)),
@@ -237,8 +248,8 @@ function b({ entry: b, onClose: x, onSuccess: S }) {
237
248
  name: e.key,
238
249
  type: e.type === "password" ? "password" : "text",
239
250
  label: e.label,
240
- value: O.values[e.key] ?? "",
241
- onChange: (t) => F(e.key, t),
251
+ value: k.values[e.key] ?? "",
252
+ onChange: (t) => I(e.key, t),
242
253
  placeholder: e.placeholder,
243
254
  required: e.required,
244
255
  showOptionalTag: !e.required,
@@ -246,36 +257,36 @@ function b({ entry: b, onClose: x, onSuccess: S }) {
246
257
  }),
247
258
  e.helperText && /* @__PURE__ */ h("p", {
248
259
  className: "text-xs text-tertiary-alt",
249
- children: e.helperText
260
+ children: _(e.helperText)
250
261
  }),
251
- O.errors[e.key] && /* @__PURE__ */ h("p", {
262
+ k.errors[e.key] && /* @__PURE__ */ h("p", {
252
263
  className: "text-xs text-red-500",
253
- children: O.errors[e.key]
264
+ children: k.errors[e.key]
254
265
  })
255
266
  ]
256
267
  }, e.key))
257
268
  ] });
258
269
  })()
259
270
  }),
260
- A && /* @__PURE__ */ h("p", {
271
+ j && /* @__PURE__ */ h("p", {
261
272
  "data-testid": "mcp-install-modal-error",
262
273
  className: "text-sm text-red-500 whitespace-pre-wrap",
263
- children: A
274
+ children: j
264
275
  }),
265
276
  /* @__PURE__ */ g("div", {
266
277
  className: "flex justify-end gap-2 mt-2",
267
278
  children: [/* @__PURE__ */ h(o, {
268
279
  type: "button",
269
280
  variant: "secondary",
270
- onClick: x,
281
+ onClick: S,
271
282
  testId: "mcp-install-cancel",
272
- children: C(t.BUTTON$CANCEL)
283
+ children: w(t.BUTTON$CANCEL)
273
284
  }), /* @__PURE__ */ h(o, {
274
285
  type: "submit",
275
286
  variant: "primary",
276
- isDisabled: P,
287
+ isDisabled: F,
277
288
  testId: "mcp-install-submit",
278
- children: C(D ? t.MCP$VERIFYING : T ? t.SETTINGS$SAVING : t.MCP$INSTALL_BUTTON)
289
+ children: w(O ? t.MCP$VERIFYING : E ? t.SETTINGS$SAVING : t.MCP$INSTALL_BUTTON)
279
290
  })]
280
291
  })
281
292
  ]
@@ -283,6 +294,6 @@ function b({ entry: b, onClose: x, onSuccess: S }) {
283
294
  });
284
295
  }
285
296
  //#endregion
286
- export { b as InstallServerModal };
297
+ export { x as InstallServerModal };
287
298
 
288
299
  //# sourceMappingURL=install-server-modal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"install-server-modal.js","names":[],"sources":["../../../../src/components/features/mcp-page/install-server-modal.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { AxiosError } from \"axios\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport type { MCPTestFailure } from \"@openhands/typescript-client\";\nimport { ModalBackdrop } from \"#/components/shared/modals/modal-backdrop\";\nimport { ModalCloseButton } from \"#/components/shared/modals/modal-close-button\";\nimport { BrandButton } from \"#/components/features/settings/brand-button\";\nimport { SettingsInput } from \"#/components/features/settings/settings-input\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport type { IntegrationCatalogEntry as MarketplaceEntry } from \"@openhands/extensions/integrations\";\nimport { McpLogoBadge } from \"#/components/features/mcp-logo-badge\";\nimport { MCPServerConfig } from \"#/types/mcp-server\";\nimport { useAddMcpServer } from \"#/hooks/mutation/use-add-mcp-server\";\nimport { useTestMcpServer } from \"#/hooks/mutation/use-test-mcp-server\";\nimport { displaySuccessToast } from \"#/utils/custom-toast-handlers\";\nimport {\n getInstallableMcpConnectionOption,\n type McpMarketplaceConnectionOption,\n} from \"#/utils/mcp-marketplace-utils\";\nimport { retrieveAxiosErrorMessage } from \"#/utils/retrieve-axios-error-message\";\n\ninterface InstallServerModalProps {\n entry: MarketplaceEntry;\n onClose: () => void;\n onSuccess?: (entry: MarketplaceEntry) => void;\n}\n\ninterface FieldState {\n values: Record<string, string>;\n errors: Record<string, string | null>;\n}\n\nfunction optionNeedsCredentialField(\n option: McpMarketplaceConnectionOption | undefined,\n): boolean {\n if (option?.transport.kind !== \"shttp\" && option?.transport.kind !== \"sse\") {\n return false;\n }\n return [\"api_key\", \"bearer\", \"basic\"].includes(option.auth.strategy);\n}\n\nfunction isCredentialOptional(option: McpMarketplaceConnectionOption): boolean {\n if (option.transport.kind === \"stdio\") {\n return option.auth.apiKeyOptional ?? false;\n }\n return option.auth.apiKeyOptional ?? option.transport.apiKeyOptional ?? false;\n}\n\nfunction makeInitialState(entry: MarketplaceEntry): FieldState {\n const values: Record<string, string> = {};\n const option = getInstallableMcpConnectionOption(entry);\n const template = option?.transport;\n if (template?.kind === \"stdio\") {\n for (const field of template.envFields ?? []) {\n values[field.key] = \"\";\n }\n for (const field of template.argFields ?? []) {\n values[field.key] = \"\";\n }\n } else if (optionNeedsCredentialField(option)) {\n values.api_key = \"\";\n }\n return { values, errors: {} };\n}\n\n// The marketplace install modal is intentionally add-only: clicking\n// a catalog tile always appends a new server (the user might want\n// two Slack workspaces, two Postgres connections, etc.) even when\n// one of the same template kind is already installed. Editing an\n// existing server is reached via the installed-server-card's edit\n// button, which opens `CustomServerEditor` instead.\nexport function InstallServerModal({\n entry,\n onClose,\n onSuccess,\n}: InstallServerModalProps) {\n const { t } = useTranslation(\"openhands\");\n const { mutate: addMcpServer, isPending: isAdding } = useAddMcpServer();\n const { mutate: testMcpServer, isPending: isTesting } = useTestMcpServer();\n\n const [state, setState] = React.useState<FieldState>(() =>\n makeInitialState(entry),\n );\n const [globalError, setGlobalError] = React.useState<string | null>(null);\n const option = getInstallableMcpConnectionOption(entry);\n const template = option?.transport;\n\n const isPending = isTesting || isAdding;\n\n const setValue = (key: string, value: string) => {\n setState((prev) => ({\n values: { ...prev.values, [key]: value },\n errors: { ...prev.errors, [key]: null },\n }));\n setGlobalError(null);\n };\n\n const makeTestErrorMessage = (failure: MCPTestFailure): string => {\n switch (failure.error_kind) {\n case \"timeout\":\n return t(I18nKey.MCP$TEST_ERROR_TIMEOUT);\n case \"connection\":\n return t(I18nKey.MCP$TEST_ERROR_CONNECTION);\n default:\n return t(I18nKey.MCP$TEST_ERROR_UNKNOWN, { error: failure.error });\n }\n };\n\n const submitServer = (payload: MCPServerConfig) => {\n testMcpServer(payload, {\n onSuccess: (result) => {\n if (!result.ok) {\n setGlobalError(makeTestErrorMessage(result));\n // Modal stays open — do NOT call onClose.\n return;\n }\n addMcpServer(payload, {\n onSuccess: () => {\n displaySuccessToast(t(I18nKey.MCP$INSTALL_SUCCESS));\n onSuccess?.(entry);\n onClose();\n },\n onError: (err: unknown) => {\n const message = retrieveAxiosErrorMessage(err as AxiosError);\n setGlobalError(message || t(I18nKey.ERROR$GENERIC));\n },\n });\n },\n onError: (err: unknown) => {\n const message = retrieveAxiosErrorMessage(err as AxiosError);\n setGlobalError(message || t(I18nKey.ERROR$GENERIC));\n },\n });\n };\n\n // ------------------------------------------------------------------\n // Per-template submit handlers. Each is small and self-contained:\n // validate user input, build the payload, then hand off to\n // submitServer.\n // ------------------------------------------------------------------\n const handleHttpServerSubmit = () => {\n // TS narrows this branch to shttp|sse; the equality guard is a\n // runtime/defensive belt to make the helper safe in isolation.\n if (template?.kind !== \"shttp\" && template?.kind !== \"sse\") {\n return;\n }\n if (!option) return;\n const apiKey = state.values.api_key?.trim() ?? \"\";\n const needsCredential = optionNeedsCredentialField(option);\n if (needsCredential && !isCredentialOptional(option) && !apiKey) {\n setState((prev) => ({\n ...prev,\n errors: { api_key: t(I18nKey.MCP$ERROR_FIELD_REQUIRED) },\n }));\n return;\n }\n const payload: MCPServerConfig = {\n id: `${template.kind}-${uuidv4()}`,\n type: template.kind,\n url: template.url,\n ...(needsCredential && apiKey && { api_key: apiKey }),\n };\n submitServer(payload);\n };\n\n const handleStdioSubmit = () => {\n if (template?.kind !== \"stdio\") return;\n const stdio = template;\n const errors: Record<string, string | null> = {};\n\n for (const field of stdio.envFields ?? []) {\n if (field.required && !(state.values[field.key] ?? \"\").trim()) {\n errors[field.key] = t(I18nKey.MCP$ERROR_FIELD_REQUIRED);\n }\n }\n for (const field of stdio.argFields ?? []) {\n if (field.required && !(state.values[field.key] ?? \"\").trim()) {\n errors[field.key] = t(I18nKey.MCP$ERROR_FIELD_REQUIRED);\n }\n }\n if (Object.values(errors).some(Boolean)) {\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const env: Record<string, string> = {};\n for (const field of stdio.envFields ?? []) {\n const v = state.values[field.key]?.trim();\n if (v) env[field.key] = v;\n }\n const extraArgs: string[] = [];\n for (const field of stdio.argFields ?? []) {\n const v = state.values[field.key]?.trim();\n if (v) {\n // Filesystem-style multi-token input: split on whitespace.\n for (const token of v.split(/\\s+/)) {\n if (token) extraArgs.push(token);\n }\n }\n }\n\n const payload: MCPServerConfig = {\n id: `stdio-${uuidv4()}`,\n type: \"stdio\",\n name: stdio.serverName,\n command: stdio.command,\n args: [...stdio.args, ...extraArgs],\n ...(Object.keys(env).length > 0 && { env }),\n };\n submitServer(payload);\n };\n\n const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n setGlobalError(null);\n if (template?.kind === \"shttp\" || template?.kind === \"sse\") {\n return handleHttpServerSubmit();\n }\n return handleStdioSubmit();\n };\n\n const renderFields = () => {\n if (template?.kind === \"shttp\" || template?.kind === \"sse\") {\n const shouldRenderCredential = optionNeedsCredentialField(option);\n const apiKeyOptional = option ? isCredentialOptional(option) : false;\n return (\n <>\n <SettingsInput\n testId=\"mcp-install-field-url\"\n name=\"url\"\n type=\"url\"\n label={t(I18nKey.SETTINGS$MCP_URL)}\n value={template.url}\n onChange={() => {}}\n isDisabled\n className=\"w-full\"\n />\n {shouldRenderCredential ? (\n <div className=\"flex flex-col gap-1\">\n <SettingsInput\n testId=\"mcp-install-field-api_key\"\n name=\"api_key\"\n type=\"password\"\n label={t(I18nKey.SETTINGS$MCP_API_KEY)}\n value={state.values.api_key ?? \"\"}\n onChange={(v) => setValue(\"api_key\", v)}\n placeholder={t(I18nKey.SETTINGS$MCP_API_KEY_PLACEHOLDER)}\n showOptionalTag={apiKeyOptional}\n required={!apiKeyOptional}\n className=\"w-full\"\n />\n {state.errors.api_key && (\n <p className=\"text-xs text-red-500\">{state.errors.api_key}</p>\n )}\n </div>\n ) : null}\n </>\n );\n }\n\n if (template?.kind !== \"stdio\") return null;\n const stdio = template;\n return (\n <>\n <SettingsInput\n testId=\"mcp-install-field-command-readonly\"\n name=\"command-readonly\"\n type=\"text\"\n label={t(I18nKey.MCP$COMMAND_LABEL)}\n value={`${stdio.command} ${stdio.args.join(\" \")}`.trim()}\n onChange={() => {}}\n isDisabled\n className=\"w-full\"\n />\n {(stdio.envFields ?? []).map((field) => (\n <div key={field.key} className=\"flex flex-col gap-1\">\n <SettingsInput\n testId={`mcp-install-field-${field.key}`}\n name={field.key}\n type={field.type === \"password\" ? \"password\" : \"text\"}\n label={field.label}\n value={state.values[field.key] ?? \"\"}\n onChange={(v) => setValue(field.key, v)}\n placeholder={field.placeholder}\n required={field.required}\n showOptionalTag={!field.required}\n className=\"w-full\"\n />\n {field.helperText && (\n <p className=\"text-xs text-tertiary-alt\">{field.helperText}</p>\n )}\n {state.errors[field.key] && (\n <p className=\"text-xs text-red-500\">{state.errors[field.key]}</p>\n )}\n </div>\n ))}\n {(stdio.argFields ?? []).map((field) => (\n <div key={field.key} className=\"flex flex-col gap-1\">\n <SettingsInput\n testId={`mcp-install-field-${field.key}`}\n name={field.key}\n type={field.type === \"password\" ? \"password\" : \"text\"}\n label={field.label}\n value={state.values[field.key] ?? \"\"}\n onChange={(v) => setValue(field.key, v)}\n placeholder={field.placeholder}\n required={field.required}\n showOptionalTag={!field.required}\n className=\"w-full\"\n />\n {field.helperText && (\n <p className=\"text-xs text-tertiary-alt\">{field.helperText}</p>\n )}\n {state.errors[field.key] && (\n <p className=\"text-xs text-red-500\">{state.errors[field.key]}</p>\n )}\n </div>\n ))}\n </>\n );\n };\n\n return (\n <ModalBackdrop onClose={onClose} aria-label={entry.name}>\n <form\n data-testid=\"mcp-install-modal\"\n data-marketplace-id={entry.id}\n onSubmit={handleSubmit}\n className=\"relative bg-base-secondary p-6 rounded-xl flex flex-col gap-4 border border-[var(--oh-border)] w-[520px] max-w-[90vw] max-h-[85vh] overflow-y-auto custom-scrollbar\"\n >\n <ModalCloseButton\n onClose={onClose}\n testId=\"mcp-install-modal-close\"\n disabled={isPending}\n />\n <div className=\"flex items-start gap-3 pr-6\">\n <McpLogoBadge entry={entry} />\n <div className=\"flex flex-col flex-1\">\n <h2 className=\"text-lg font-semibold\">{entry.name}</h2>\n <p className=\"text-xs text-tertiary-light\">{entry.description}</p>\n </div>\n </div>\n\n {entry.installHint && (\n <p className=\"text-xs text-tertiary-light\">{entry.installHint}</p>\n )}\n\n {entry.docsUrl && (\n <a\n href={entry.docsUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"text-xs text-[var(--oh-muted)] hover:text-white hover:underline self-start transition-colors\"\n >\n {t(I18nKey.MCP$VIEW_DOCS)}\n </a>\n )}\n\n <div className=\"flex flex-col gap-3\">{renderFields()}</div>\n\n {globalError && (\n <p\n data-testid=\"mcp-install-modal-error\"\n className=\"text-sm text-red-500 whitespace-pre-wrap\"\n >\n {globalError}\n </p>\n )}\n\n <div className=\"flex justify-end gap-2 mt-2\">\n <BrandButton\n type=\"button\"\n variant=\"secondary\"\n onClick={onClose}\n testId=\"mcp-install-cancel\"\n >\n {t(I18nKey.BUTTON$CANCEL)}\n </BrandButton>\n <BrandButton\n type=\"submit\"\n variant=\"primary\"\n isDisabled={isPending}\n testId=\"mcp-install-submit\"\n >\n {isTesting\n ? t(I18nKey.MCP$VERIFYING)\n : isAdding\n ? t(I18nKey.SETTINGS$SAVING)\n : t(I18nKey.MCP$INSTALL_BUTTON)}\n </BrandButton>\n </div>\n </form>\n </ModalBackdrop>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"install-server-modal.js","names":[],"sources":["../../../../src/components/features/mcp-page/install-server-modal.tsx"],"sourcesContent":["import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { AxiosError } from \"axios\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport type { MCPTestFailure } from \"@openhands/typescript-client\";\nimport { ModalBackdrop } from \"#/components/shared/modals/modal-backdrop\";\nimport { ModalCloseButton } from \"#/components/shared/modals/modal-close-button\";\nimport { BrandButton } from \"#/components/features/settings/brand-button\";\nimport { SettingsInput } from \"#/components/features/settings/settings-input\";\nimport { I18nKey } from \"#/i18n/declaration\";\nimport type { IntegrationCatalogEntry as MarketplaceEntry } from \"@openhands/extensions/integrations\";\nimport { McpLogoBadge } from \"#/components/features/mcp-logo-badge\";\nimport { MCPServerConfig } from \"#/types/mcp-server\";\nimport { useAddMcpServer } from \"#/hooks/mutation/use-add-mcp-server\";\nimport { useTestMcpServer } from \"#/hooks/mutation/use-test-mcp-server\";\nimport { displaySuccessToast } from \"#/utils/custom-toast-handlers\";\nimport {\n getInstallableMcpConnectionOption,\n type McpMarketplaceConnectionOption,\n} from \"#/utils/mcp-marketplace-utils\";\nimport { retrieveAxiosErrorMessage } from \"#/utils/retrieve-axios-error-message\";\n\n/**\n * Renders a helperText string as React nodes, converting any `[text](url)`\n * markdown links into real `<a>` elements. Plain text segments are left as-is.\n * Only `http:` and `https:` URLs are rendered as links; anything else falls\n * back to `#` to guard against `javascript:` / `data:` XSS vectors.\n */\nfunction renderHelperText(text: string): React.ReactNode {\n const linkPattern = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n const parts: React.ReactNode[] = [];\n let lastIndex = 0;\n for (const match of text.matchAll(linkPattern)) {\n if (match.index > lastIndex) {\n parts.push(text.slice(lastIndex, match.index));\n }\n parts.push(\n <a\n key={match.index}\n href={/^https?:\\/\\//i.test(match[2]) ? match[2] : \"#\"}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"underline hover:text-white transition-colors\"\n >\n {match[1]}\n </a>,\n );\n lastIndex = match.index + match[0].length;\n }\n if (lastIndex < text.length) {\n parts.push(text.slice(lastIndex));\n }\n return parts;\n}\n\ninterface InstallServerModalProps {\n entry: MarketplaceEntry;\n onClose: () => void;\n onSuccess?: (entry: MarketplaceEntry) => void;\n}\n\ninterface FieldState {\n values: Record<string, string>;\n errors: Record<string, string | null>;\n}\n\nfunction optionNeedsCredentialField(\n option: McpMarketplaceConnectionOption | undefined,\n): boolean {\n if (option?.transport.kind !== \"shttp\" && option?.transport.kind !== \"sse\") {\n return false;\n }\n return [\"api_key\", \"bearer\", \"basic\"].includes(option.auth.strategy);\n}\n\nfunction isCredentialOptional(option: McpMarketplaceConnectionOption): boolean {\n if (option.transport.kind === \"stdio\") {\n return option.auth.apiKeyOptional ?? false;\n }\n return option.auth.apiKeyOptional ?? option.transport.apiKeyOptional ?? false;\n}\n\nfunction makeInitialState(entry: MarketplaceEntry): FieldState {\n const values: Record<string, string> = {};\n const option = getInstallableMcpConnectionOption(entry);\n const template = option?.transport;\n if (template?.kind === \"stdio\") {\n for (const field of template.envFields ?? []) {\n values[field.key] = \"\";\n }\n for (const field of template.argFields ?? []) {\n values[field.key] = \"\";\n }\n } else if (optionNeedsCredentialField(option)) {\n values.api_key = \"\";\n }\n return { values, errors: {} };\n}\n\n// The marketplace install modal is intentionally add-only: clicking\n// a catalog tile always appends a new server (the user might want\n// two Slack workspaces, two Postgres connections, etc.) even when\n// one of the same template kind is already installed. Editing an\n// existing server is reached via the installed-server-card's edit\n// button, which opens `CustomServerEditor` instead.\nexport function InstallServerModal({\n entry,\n onClose,\n onSuccess,\n}: InstallServerModalProps) {\n const { t } = useTranslation(\"openhands\");\n const { mutate: addMcpServer, isPending: isAdding } = useAddMcpServer();\n const { mutate: testMcpServer, isPending: isTesting } = useTestMcpServer();\n\n const [state, setState] = React.useState<FieldState>(() =>\n makeInitialState(entry),\n );\n const [globalError, setGlobalError] = React.useState<string | null>(null);\n const option = getInstallableMcpConnectionOption(entry);\n const template = option?.transport;\n\n const isPending = isTesting || isAdding;\n\n const setValue = (key: string, value: string) => {\n setState((prev) => ({\n values: { ...prev.values, [key]: value },\n errors: { ...prev.errors, [key]: null },\n }));\n setGlobalError(null);\n };\n\n const makeTestErrorMessage = (failure: MCPTestFailure): string => {\n switch (failure.error_kind) {\n case \"timeout\":\n return t(I18nKey.MCP$TEST_ERROR_TIMEOUT);\n case \"connection\":\n return t(I18nKey.MCP$TEST_ERROR_CONNECTION);\n default:\n return t(I18nKey.MCP$TEST_ERROR_UNKNOWN, { error: failure.error });\n }\n };\n\n const submitServer = (payload: MCPServerConfig) => {\n testMcpServer(payload, {\n onSuccess: (result) => {\n if (!result.ok) {\n setGlobalError(makeTestErrorMessage(result));\n // Modal stays open — do NOT call onClose.\n return;\n }\n addMcpServer(payload, {\n onSuccess: () => {\n displaySuccessToast(t(I18nKey.MCP$INSTALL_SUCCESS));\n onSuccess?.(entry);\n onClose();\n },\n onError: (err: unknown) => {\n const message = retrieveAxiosErrorMessage(err as AxiosError);\n setGlobalError(message || t(I18nKey.ERROR$GENERIC));\n },\n });\n },\n onError: (err: unknown) => {\n const message = retrieveAxiosErrorMessage(err as AxiosError);\n setGlobalError(message || t(I18nKey.ERROR$GENERIC));\n },\n });\n };\n\n // ------------------------------------------------------------------\n // Per-template submit handlers. Each is small and self-contained:\n // validate user input, build the payload, then hand off to\n // submitServer.\n // ------------------------------------------------------------------\n const handleHttpServerSubmit = () => {\n // TS narrows this branch to shttp|sse; the equality guard is a\n // runtime/defensive belt to make the helper safe in isolation.\n if (template?.kind !== \"shttp\" && template?.kind !== \"sse\") {\n return;\n }\n if (!option) return;\n const apiKey = state.values.api_key?.trim() ?? \"\";\n const needsCredential = optionNeedsCredentialField(option);\n if (needsCredential && !isCredentialOptional(option) && !apiKey) {\n setState((prev) => ({\n ...prev,\n errors: { api_key: t(I18nKey.MCP$ERROR_FIELD_REQUIRED) },\n }));\n return;\n }\n const payload: MCPServerConfig = {\n id: `${template.kind}-${uuidv4()}`,\n type: template.kind,\n url: template.url,\n ...(needsCredential && apiKey && { api_key: apiKey }),\n };\n submitServer(payload);\n };\n\n const handleStdioSubmit = () => {\n if (template?.kind !== \"stdio\") return;\n const stdio = template;\n const errors: Record<string, string | null> = {};\n\n for (const field of stdio.envFields ?? []) {\n if (field.required && !(state.values[field.key] ?? \"\").trim()) {\n errors[field.key] = t(I18nKey.MCP$ERROR_FIELD_REQUIRED);\n }\n }\n for (const field of stdio.argFields ?? []) {\n if (field.required && !(state.values[field.key] ?? \"\").trim()) {\n errors[field.key] = t(I18nKey.MCP$ERROR_FIELD_REQUIRED);\n }\n }\n if (Object.values(errors).some(Boolean)) {\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const env: Record<string, string> = {};\n for (const field of stdio.envFields ?? []) {\n const v = state.values[field.key]?.trim();\n if (v) env[field.key] = v;\n }\n const extraArgs: string[] = [];\n for (const field of stdio.argFields ?? []) {\n const v = state.values[field.key]?.trim();\n if (v) {\n // Filesystem-style multi-token input: split on whitespace.\n for (const token of v.split(/\\s+/)) {\n if (token) extraArgs.push(token);\n }\n }\n }\n\n const payload: MCPServerConfig = {\n id: `stdio-${uuidv4()}`,\n type: \"stdio\",\n name: stdio.serverName,\n command: stdio.command,\n args: [...stdio.args, ...extraArgs],\n ...(Object.keys(env).length > 0 && { env }),\n };\n submitServer(payload);\n };\n\n const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n setGlobalError(null);\n if (template?.kind === \"shttp\" || template?.kind === \"sse\") {\n return handleHttpServerSubmit();\n }\n return handleStdioSubmit();\n };\n\n const renderFields = () => {\n if (template?.kind === \"shttp\" || template?.kind === \"sse\") {\n const shouldRenderCredential = optionNeedsCredentialField(option);\n const apiKeyOptional = option ? isCredentialOptional(option) : false;\n return (\n <>\n <SettingsInput\n testId=\"mcp-install-field-url\"\n name=\"url\"\n type=\"url\"\n label={t(I18nKey.SETTINGS$MCP_URL)}\n value={template.url}\n onChange={() => {}}\n isDisabled\n className=\"w-full\"\n />\n {shouldRenderCredential ? (\n <div className=\"flex flex-col gap-1\">\n <SettingsInput\n testId=\"mcp-install-field-api_key\"\n name=\"api_key\"\n type=\"password\"\n label={t(I18nKey.SETTINGS$MCP_API_KEY)}\n value={state.values.api_key ?? \"\"}\n onChange={(v) => setValue(\"api_key\", v)}\n placeholder={t(I18nKey.SETTINGS$MCP_API_KEY_PLACEHOLDER)}\n showOptionalTag={apiKeyOptional}\n required={!apiKeyOptional}\n className=\"w-full\"\n />\n {state.errors.api_key && (\n <p className=\"text-xs text-red-500\">{state.errors.api_key}</p>\n )}\n </div>\n ) : null}\n </>\n );\n }\n\n if (template?.kind !== \"stdio\") return null;\n const stdio = template;\n return (\n <>\n <SettingsInput\n testId=\"mcp-install-field-command-readonly\"\n name=\"command-readonly\"\n type=\"text\"\n label={t(I18nKey.MCP$COMMAND_LABEL)}\n value={`${stdio.command} ${stdio.args.join(\" \")}`.trim()}\n onChange={() => {}}\n isDisabled\n className=\"w-full\"\n />\n {(stdio.envFields ?? []).map((field) => (\n <div key={field.key} className=\"flex flex-col gap-1\">\n <SettingsInput\n testId={`mcp-install-field-${field.key}`}\n name={field.key}\n type={field.type === \"password\" ? \"password\" : \"text\"}\n label={field.label}\n value={state.values[field.key] ?? \"\"}\n onChange={(v) => setValue(field.key, v)}\n placeholder={field.placeholder}\n required={field.required}\n showOptionalTag={!field.required}\n className=\"w-full\"\n />\n {field.helperText && (\n <p className=\"text-xs text-tertiary-alt\">\n {renderHelperText(field.helperText)}\n </p>\n )}\n {state.errors[field.key] && (\n <p className=\"text-xs text-red-500\">{state.errors[field.key]}</p>\n )}\n </div>\n ))}\n {(stdio.argFields ?? []).map((field) => (\n <div key={field.key} className=\"flex flex-col gap-1\">\n <SettingsInput\n testId={`mcp-install-field-${field.key}`}\n name={field.key}\n type={field.type === \"password\" ? \"password\" : \"text\"}\n label={field.label}\n value={state.values[field.key] ?? \"\"}\n onChange={(v) => setValue(field.key, v)}\n placeholder={field.placeholder}\n required={field.required}\n showOptionalTag={!field.required}\n className=\"w-full\"\n />\n {field.helperText && (\n <p className=\"text-xs text-tertiary-alt\">\n {renderHelperText(field.helperText)}\n </p>\n )}\n {state.errors[field.key] && (\n <p className=\"text-xs text-red-500\">{state.errors[field.key]}</p>\n )}\n </div>\n ))}\n </>\n );\n };\n\n return (\n <ModalBackdrop onClose={onClose} aria-label={entry.name}>\n <form\n data-testid=\"mcp-install-modal\"\n data-marketplace-id={entry.id}\n onSubmit={handleSubmit}\n className=\"relative bg-base-secondary p-6 rounded-xl flex flex-col gap-4 border border-[var(--oh-border)] w-[520px] max-w-[90vw] max-h-[85vh] overflow-y-auto custom-scrollbar\"\n >\n <ModalCloseButton\n onClose={onClose}\n testId=\"mcp-install-modal-close\"\n disabled={isPending}\n />\n <div className=\"flex items-start gap-3 pr-6\">\n <McpLogoBadge entry={entry} />\n <div className=\"flex flex-col flex-1\">\n <h2 className=\"text-lg font-semibold\">{entry.name}</h2>\n <p className=\"text-xs text-tertiary-light\">{entry.description}</p>\n </div>\n </div>\n\n {entry.installHint && (\n <p className=\"text-xs text-tertiary-light\">{entry.installHint}</p>\n )}\n\n {entry.docsUrl && (\n <a\n href={entry.docsUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"text-xs text-[var(--oh-muted)] hover:text-white hover:underline self-start transition-colors\"\n >\n {t(I18nKey.MCP$VIEW_DOCS)}\n </a>\n )}\n\n <div className=\"flex flex-col gap-3\">{renderFields()}</div>\n\n {globalError && (\n <p\n data-testid=\"mcp-install-modal-error\"\n className=\"text-sm text-red-500 whitespace-pre-wrap\"\n >\n {globalError}\n </p>\n )}\n\n <div className=\"flex justify-end gap-2 mt-2\">\n <BrandButton\n type=\"button\"\n variant=\"secondary\"\n onClick={onClose}\n testId=\"mcp-install-cancel\"\n >\n {t(I18nKey.BUTTON$CANCEL)}\n </BrandButton>\n <BrandButton\n type=\"submit\"\n variant=\"primary\"\n isDisabled={isPending}\n testId=\"mcp-install-submit\"\n >\n {isTesting\n ? t(I18nKey.MCP$VERIFYING)\n : isAdding\n ? t(I18nKey.SETTINGS$SAVING)\n : t(I18nKey.MCP$INSTALL_BUTTON)}\n </BrandButton>\n </div>\n </form>\n </ModalBackdrop>\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- require(`../../../../../_virtual/_rolldown/runtime.cjs`);var e={id:`airtable`,name:`Airtable`,description:`List bases, query records, and update fields across your Airtable workspace.`,docsUrl:`https://github.com/domdomegg/airtable-mcp-server`,iconBg:`#FCB400`,iconColor:`var(--oh-surface-deep)`,keywords:[`spreadsheet`,`database`,`records`,`bases`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`airtable`,command:`npx`,args:[`-y`,`airtable-mcp-server`],envFields:[{key:`AIRTABLE_API_KEY`,label:`Airtable personal access token`,type:`password`,required:!0}]},auth:{strategy:`api_key`}}]};exports.default=e;
1
+ require(`../../../../../_virtual/_rolldown/runtime.cjs`);var e={id:`airtable`,name:`Airtable`,description:`List bases, query records, and update fields across your Airtable workspace.`,docsUrl:`https://github.com/domdomegg/airtable-mcp-server`,iconBg:`#FCB400`,iconColor:`var(--oh-surface-deep)`,keywords:[`spreadsheet`,`database`,`records`,`bases`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`airtable`,command:`npx`,args:[`-y`,`airtable-mcp-server`],envFields:[{key:`AIRTABLE_API_KEY`,label:`Airtable personal access token`,type:`password`,required:!0,helperText:`Personal access token from your Airtable account.`,helperLink:`https://airtable.com/create/tokens`}]},auth:{strategy:`api_key`}}]};exports.default=e;
2
2
  //# sourceMappingURL=airtable.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"airtable.cjs","names":[],"sources":["../../../../../../node_modules/@openhands/extensions/integrations/catalog/airtable.json"],"sourcesContent":["{\n \"id\": \"airtable\",\n \"name\": \"Airtable\",\n \"description\": \"List bases, query records, and update fields across your Airtable workspace.\",\n \"docsUrl\": \"https://github.com/domdomegg/airtable-mcp-server\",\n \"iconBg\": \"#FCB400\",\n \"iconColor\": \"var(--oh-surface-deep)\",\n \"keywords\": [\n \"spreadsheet\",\n \"database\",\n \"records\",\n \"bases\"\n ],\n \"kind\": \"mcp\",\n \"defaultConnectionOptionId\": \"api\",\n \"connectionOptions\": [\n {\n \"id\": \"api\",\n \"provider\": \"mcp\",\n \"transport\": {\n \"kind\": \"stdio\",\n \"serverName\": \"airtable\",\n \"command\": \"npx\",\n \"args\": [\n \"-y\",\n \"airtable-mcp-server\"\n ],\n \"envFields\": [\n {\n \"key\": \"AIRTABLE_API_KEY\",\n \"label\": \"Airtable personal access token\",\n \"type\": \"password\",\n \"required\": true\n }\n ]\n },\n \"auth\": {\n \"strategy\": \"api_key\"\n }\n }\n ]\n}\n"],"x_google_ignoreList":[0],"mappings":""}
1
+ {"version":3,"file":"airtable.cjs","names":[],"sources":["../../../../../../node_modules/@openhands/extensions/integrations/catalog/airtable.json"],"sourcesContent":["{\n \"id\": \"airtable\",\n \"name\": \"Airtable\",\n \"description\": \"List bases, query records, and update fields across your Airtable workspace.\",\n \"docsUrl\": \"https://github.com/domdomegg/airtable-mcp-server\",\n \"iconBg\": \"#FCB400\",\n \"iconColor\": \"var(--oh-surface-deep)\",\n \"keywords\": [\n \"spreadsheet\",\n \"database\",\n \"records\",\n \"bases\"\n ],\n \"kind\": \"mcp\",\n \"defaultConnectionOptionId\": \"api\",\n \"connectionOptions\": [\n {\n \"id\": \"api\",\n \"provider\": \"mcp\",\n \"transport\": {\n \"kind\": \"stdio\",\n \"serverName\": \"airtable\",\n \"command\": \"npx\",\n \"args\": [\n \"-y\",\n \"airtable-mcp-server\"\n ],\n \"envFields\": [\n {\n \"key\": \"AIRTABLE_API_KEY\",\n \"label\": \"Airtable personal access token\",\n \"type\": \"password\",\n \"required\": true,\n \"helperText\": \"Personal access token from your Airtable account.\",\n \"helperLink\": \"https://airtable.com/create/tokens\"\n }\n ]\n },\n \"auth\": {\n \"strategy\": \"api_key\"\n }\n }\n ]\n}\n"],"x_google_ignoreList":[0],"mappings":""}
@@ -25,7 +25,9 @@ var e = {
25
25
  key: "AIRTABLE_API_KEY",
26
26
  label: "Airtable personal access token",
27
27
  type: "password",
28
- required: !0
28
+ required: !0,
29
+ helperText: "Personal access token from your Airtable account.",
30
+ helperLink: "https://airtable.com/create/tokens"
29
31
  }]
30
32
  },
31
33
  auth: { strategy: "api_key" }
@@ -1 +1 @@
1
- {"version":3,"file":"airtable.js","names":[],"sources":["../../../../../../node_modules/@openhands/extensions/integrations/catalog/airtable.json"],"sourcesContent":["{\n \"id\": \"airtable\",\n \"name\": \"Airtable\",\n \"description\": \"List bases, query records, and update fields across your Airtable workspace.\",\n \"docsUrl\": \"https://github.com/domdomegg/airtable-mcp-server\",\n \"iconBg\": \"#FCB400\",\n \"iconColor\": \"var(--oh-surface-deep)\",\n \"keywords\": [\n \"spreadsheet\",\n \"database\",\n \"records\",\n \"bases\"\n ],\n \"kind\": \"mcp\",\n \"defaultConnectionOptionId\": \"api\",\n \"connectionOptions\": [\n {\n \"id\": \"api\",\n \"provider\": \"mcp\",\n \"transport\": {\n \"kind\": \"stdio\",\n \"serverName\": \"airtable\",\n \"command\": \"npx\",\n \"args\": [\n \"-y\",\n \"airtable-mcp-server\"\n ],\n \"envFields\": [\n {\n \"key\": \"AIRTABLE_API_KEY\",\n \"label\": \"Airtable personal access token\",\n \"type\": \"password\",\n \"required\": true\n }\n ]\n },\n \"auth\": {\n \"strategy\": \"api_key\"\n }\n }\n ]\n}\n"],"x_google_ignoreList":[0],"mappings":""}
1
+ {"version":3,"file":"airtable.js","names":[],"sources":["../../../../../../node_modules/@openhands/extensions/integrations/catalog/airtable.json"],"sourcesContent":["{\n \"id\": \"airtable\",\n \"name\": \"Airtable\",\n \"description\": \"List bases, query records, and update fields across your Airtable workspace.\",\n \"docsUrl\": \"https://github.com/domdomegg/airtable-mcp-server\",\n \"iconBg\": \"#FCB400\",\n \"iconColor\": \"var(--oh-surface-deep)\",\n \"keywords\": [\n \"spreadsheet\",\n \"database\",\n \"records\",\n \"bases\"\n ],\n \"kind\": \"mcp\",\n \"defaultConnectionOptionId\": \"api\",\n \"connectionOptions\": [\n {\n \"id\": \"api\",\n \"provider\": \"mcp\",\n \"transport\": {\n \"kind\": \"stdio\",\n \"serverName\": \"airtable\",\n \"command\": \"npx\",\n \"args\": [\n \"-y\",\n \"airtable-mcp-server\"\n ],\n \"envFields\": [\n {\n \"key\": \"AIRTABLE_API_KEY\",\n \"label\": \"Airtable personal access token\",\n \"type\": \"password\",\n \"required\": true,\n \"helperText\": \"Personal access token from your Airtable account.\",\n \"helperLink\": \"https://airtable.com/create/tokens\"\n }\n ]\n },\n \"auth\": {\n \"strategy\": \"api_key\"\n }\n }\n ]\n}\n"],"x_google_ignoreList":[0],"mappings":""}
@@ -1,2 +1,2 @@
1
- require(`../../../../../_virtual/_rolldown/runtime.cjs`);var e={id:`apify`,name:`Apify Actors`,description:`Run any of Apify's 5,000+ Actors (scrapers, automations) from the agent.`,docsUrl:`https://docs.apify.com/platform/integrations/mcp`,iconBg:`#10b981`,keywords:[`scraping`,`automation`,`crawl`,`actors`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`apify`,command:`npx`,args:[`-y`,`@apify/actors-mcp-server`],envFields:[{key:`APIFY_TOKEN`,label:`Apify token`,type:`password`,required:!0}]},auth:{strategy:`api_key`}}]};exports.default=e;
1
+ require(`../../../../../_virtual/_rolldown/runtime.cjs`);var e={id:`apify`,name:`Apify Actors`,description:`Run any of Apify's 5,000+ Actors (scrapers, automations) from the agent.`,docsUrl:`https://docs.apify.com/platform/integrations/mcp`,iconBg:`#10b981`,keywords:[`scraping`,`automation`,`crawl`,`actors`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`apify`,command:`npx`,args:[`-y`,`@apify/actors-mcp-server`],envFields:[{key:`APIFY_TOKEN`,label:`Apify token`,type:`password`,required:!0,helperText:`API token from your Apify account settings.`,helperLink:`https://console.apify.com/account/integrations`}]},auth:{strategy:`api_key`}}]};exports.default=e;
2
2
  //# sourceMappingURL=apify.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"apify.cjs","names":[],"sources":["../../../../../../node_modules/@openhands/extensions/integrations/catalog/apify.json"],"sourcesContent":["{\n \"id\": \"apify\",\n \"name\": \"Apify Actors\",\n \"description\": \"Run any of Apify's 5,000+ Actors (scrapers, automations) from the agent.\",\n \"docsUrl\": \"https://docs.apify.com/platform/integrations/mcp\",\n \"iconBg\": \"#10b981\",\n \"keywords\": [\n \"scraping\",\n \"automation\",\n \"crawl\",\n \"actors\"\n ],\n \"kind\": \"mcp\",\n \"defaultConnectionOptionId\": \"api\",\n \"connectionOptions\": [\n {\n \"id\": \"api\",\n \"provider\": \"mcp\",\n \"transport\": {\n \"kind\": \"stdio\",\n \"serverName\": \"apify\",\n \"command\": \"npx\",\n \"args\": [\n \"-y\",\n \"@apify/actors-mcp-server\"\n ],\n \"envFields\": [\n {\n \"key\": \"APIFY_TOKEN\",\n \"label\": \"Apify token\",\n \"type\": \"password\",\n \"required\": true\n }\n ]\n },\n \"auth\": {\n \"strategy\": \"api_key\"\n }\n }\n ]\n}\n"],"x_google_ignoreList":[0],"mappings":""}
1
+ {"version":3,"file":"apify.cjs","names":[],"sources":["../../../../../../node_modules/@openhands/extensions/integrations/catalog/apify.json"],"sourcesContent":["{\n \"id\": \"apify\",\n \"name\": \"Apify Actors\",\n \"description\": \"Run any of Apify's 5,000+ Actors (scrapers, automations) from the agent.\",\n \"docsUrl\": \"https://docs.apify.com/platform/integrations/mcp\",\n \"iconBg\": \"#10b981\",\n \"keywords\": [\n \"scraping\",\n \"automation\",\n \"crawl\",\n \"actors\"\n ],\n \"kind\": \"mcp\",\n \"defaultConnectionOptionId\": \"api\",\n \"connectionOptions\": [\n {\n \"id\": \"api\",\n \"provider\": \"mcp\",\n \"transport\": {\n \"kind\": \"stdio\",\n \"serverName\": \"apify\",\n \"command\": \"npx\",\n \"args\": [\n \"-y\",\n \"@apify/actors-mcp-server\"\n ],\n \"envFields\": [\n {\n \"key\": \"APIFY_TOKEN\",\n \"label\": \"Apify token\",\n \"type\": \"password\",\n \"required\": true,\n \"helperText\": \"API token from your Apify account settings.\",\n \"helperLink\": \"https://console.apify.com/account/integrations\"\n }\n ]\n },\n \"auth\": {\n \"strategy\": \"api_key\"\n }\n }\n ]\n}\n"],"x_google_ignoreList":[0],"mappings":""}
@@ -24,7 +24,9 @@ var e = {
24
24
  key: "APIFY_TOKEN",
25
25
  label: "Apify token",
26
26
  type: "password",
27
- required: !0
27
+ required: !0,
28
+ helperText: "API token from your Apify account settings.",
29
+ helperLink: "https://console.apify.com/account/integrations"
28
30
  }]
29
31
  },
30
32
  auth: { strategy: "api_key" }
@@ -1 +1 @@
1
- {"version":3,"file":"apify.js","names":[],"sources":["../../../../../../node_modules/@openhands/extensions/integrations/catalog/apify.json"],"sourcesContent":["{\n \"id\": \"apify\",\n \"name\": \"Apify Actors\",\n \"description\": \"Run any of Apify's 5,000+ Actors (scrapers, automations) from the agent.\",\n \"docsUrl\": \"https://docs.apify.com/platform/integrations/mcp\",\n \"iconBg\": \"#10b981\",\n \"keywords\": [\n \"scraping\",\n \"automation\",\n \"crawl\",\n \"actors\"\n ],\n \"kind\": \"mcp\",\n \"defaultConnectionOptionId\": \"api\",\n \"connectionOptions\": [\n {\n \"id\": \"api\",\n \"provider\": \"mcp\",\n \"transport\": {\n \"kind\": \"stdio\",\n \"serverName\": \"apify\",\n \"command\": \"npx\",\n \"args\": [\n \"-y\",\n \"@apify/actors-mcp-server\"\n ],\n \"envFields\": [\n {\n \"key\": \"APIFY_TOKEN\",\n \"label\": \"Apify token\",\n \"type\": \"password\",\n \"required\": true\n }\n ]\n },\n \"auth\": {\n \"strategy\": \"api_key\"\n }\n }\n ]\n}\n"],"x_google_ignoreList":[0],"mappings":""}
1
+ {"version":3,"file":"apify.js","names":[],"sources":["../../../../../../node_modules/@openhands/extensions/integrations/catalog/apify.json"],"sourcesContent":["{\n \"id\": \"apify\",\n \"name\": \"Apify Actors\",\n \"description\": \"Run any of Apify's 5,000+ Actors (scrapers, automations) from the agent.\",\n \"docsUrl\": \"https://docs.apify.com/platform/integrations/mcp\",\n \"iconBg\": \"#10b981\",\n \"keywords\": [\n \"scraping\",\n \"automation\",\n \"crawl\",\n \"actors\"\n ],\n \"kind\": \"mcp\",\n \"defaultConnectionOptionId\": \"api\",\n \"connectionOptions\": [\n {\n \"id\": \"api\",\n \"provider\": \"mcp\",\n \"transport\": {\n \"kind\": \"stdio\",\n \"serverName\": \"apify\",\n \"command\": \"npx\",\n \"args\": [\n \"-y\",\n \"@apify/actors-mcp-server\"\n ],\n \"envFields\": [\n {\n \"key\": \"APIFY_TOKEN\",\n \"label\": \"Apify token\",\n \"type\": \"password\",\n \"required\": true,\n \"helperText\": \"API token from your Apify account settings.\",\n \"helperLink\": \"https://console.apify.com/account/integrations\"\n }\n ]\n },\n \"auth\": {\n \"strategy\": \"api_key\"\n }\n }\n ]\n}\n"],"x_google_ignoreList":[0],"mappings":""}
@@ -1,2 +1,2 @@
1
- require(`../../../../../_virtual/_rolldown/runtime.cjs`);var e={id:`brave-search`,name:`Brave Search`,description:`Privacy-first web and local search using the Brave Search API.`,docsUrl:`https://github.com/brave/brave-search-mcp-server`,iconBg:`#FB542B`,keywords:[`search`,`web`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`brave_search`,command:`npx`,args:[`-y`,`@brave/brave-search-mcp-server`,`--transport`,`stdio`],envFields:[{key:`BRAVE_API_KEY`,label:`Brave API key`,type:`password`,required:!0}]},auth:{strategy:`api_key`}}]};exports.default=e;
1
+ require(`../../../../../_virtual/_rolldown/runtime.cjs`);var e={id:`brave-search`,name:`Brave Search`,description:`Privacy-first web and local search using the Brave Search API.`,docsUrl:`https://github.com/brave/brave-search-mcp-server`,iconBg:`#FB542B`,keywords:[`search`,`web`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`brave_search`,command:`npx`,args:[`-y`,`@brave/brave-search-mcp-server`,`--transport`,`stdio`],envFields:[{key:`BRAVE_API_KEY`,label:`Brave API key`,type:`password`,required:!0,helperText:`API key from the Brave Search API portal.`,helperLink:`https://api-dashboard.search.brave.com/app/keys`}]},auth:{strategy:`api_key`}}]};exports.default=e;
2
2
  //# sourceMappingURL=brave-search.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"brave-search.cjs","names":[],"sources":["../../../../../../node_modules/@openhands/extensions/integrations/catalog/brave-search.json"],"sourcesContent":["{\n \"id\": \"brave-search\",\n \"name\": \"Brave Search\",\n \"description\": \"Privacy-first web and local search using the Brave Search API.\",\n \"docsUrl\": \"https://github.com/brave/brave-search-mcp-server\",\n \"iconBg\": \"#FB542B\",\n \"keywords\": [\n \"search\",\n \"web\"\n ],\n \"kind\": \"mcp\",\n \"defaultConnectionOptionId\": \"api\",\n \"connectionOptions\": [\n {\n \"id\": \"api\",\n \"provider\": \"mcp\",\n \"transport\": {\n \"kind\": \"stdio\",\n \"serverName\": \"brave_search\",\n \"command\": \"npx\",\n \"args\": [\n \"-y\",\n \"@brave/brave-search-mcp-server\",\n \"--transport\",\n \"stdio\"\n ],\n \"envFields\": [\n {\n \"key\": \"BRAVE_API_KEY\",\n \"label\": \"Brave API key\",\n \"type\": \"password\",\n \"required\": true\n }\n ]\n },\n \"auth\": {\n \"strategy\": \"api_key\"\n }\n }\n ]\n}\n"],"x_google_ignoreList":[0],"mappings":""}
1
+ {"version":3,"file":"brave-search.cjs","names":[],"sources":["../../../../../../node_modules/@openhands/extensions/integrations/catalog/brave-search.json"],"sourcesContent":["{\n \"id\": \"brave-search\",\n \"name\": \"Brave Search\",\n \"description\": \"Privacy-first web and local search using the Brave Search API.\",\n \"docsUrl\": \"https://github.com/brave/brave-search-mcp-server\",\n \"iconBg\": \"#FB542B\",\n \"keywords\": [\n \"search\",\n \"web\"\n ],\n \"kind\": \"mcp\",\n \"defaultConnectionOptionId\": \"api\",\n \"connectionOptions\": [\n {\n \"id\": \"api\",\n \"provider\": \"mcp\",\n \"transport\": {\n \"kind\": \"stdio\",\n \"serverName\": \"brave_search\",\n \"command\": \"npx\",\n \"args\": [\n \"-y\",\n \"@brave/brave-search-mcp-server\",\n \"--transport\",\n \"stdio\"\n ],\n \"envFields\": [\n {\n \"key\": \"BRAVE_API_KEY\",\n \"label\": \"Brave API key\",\n \"type\": \"password\",\n \"required\": true,\n \"helperText\": \"API key from the Brave Search API portal.\",\n \"helperLink\": \"https://api-dashboard.search.brave.com/app/keys\"\n }\n ]\n },\n \"auth\": {\n \"strategy\": \"api_key\"\n }\n }\n ]\n}\n"],"x_google_ignoreList":[0],"mappings":""}
@@ -24,7 +24,9 @@ var e = {
24
24
  key: "BRAVE_API_KEY",
25
25
  label: "Brave API key",
26
26
  type: "password",
27
- required: !0
27
+ required: !0,
28
+ helperText: "API key from the Brave Search API portal.",
29
+ helperLink: "https://api-dashboard.search.brave.com/app/keys"
28
30
  }]
29
31
  },
30
32
  auth: { strategy: "api_key" }
@@ -1 +1 @@
1
- {"version":3,"file":"brave-search.js","names":[],"sources":["../../../../../../node_modules/@openhands/extensions/integrations/catalog/brave-search.json"],"sourcesContent":["{\n \"id\": \"brave-search\",\n \"name\": \"Brave Search\",\n \"description\": \"Privacy-first web and local search using the Brave Search API.\",\n \"docsUrl\": \"https://github.com/brave/brave-search-mcp-server\",\n \"iconBg\": \"#FB542B\",\n \"keywords\": [\n \"search\",\n \"web\"\n ],\n \"kind\": \"mcp\",\n \"defaultConnectionOptionId\": \"api\",\n \"connectionOptions\": [\n {\n \"id\": \"api\",\n \"provider\": \"mcp\",\n \"transport\": {\n \"kind\": \"stdio\",\n \"serverName\": \"brave_search\",\n \"command\": \"npx\",\n \"args\": [\n \"-y\",\n \"@brave/brave-search-mcp-server\",\n \"--transport\",\n \"stdio\"\n ],\n \"envFields\": [\n {\n \"key\": \"BRAVE_API_KEY\",\n \"label\": \"Brave API key\",\n \"type\": \"password\",\n \"required\": true\n }\n ]\n },\n \"auth\": {\n \"strategy\": \"api_key\"\n }\n }\n ]\n}\n"],"x_google_ignoreList":[0],"mappings":""}
1
+ {"version":3,"file":"brave-search.js","names":[],"sources":["../../../../../../node_modules/@openhands/extensions/integrations/catalog/brave-search.json"],"sourcesContent":["{\n \"id\": \"brave-search\",\n \"name\": \"Brave Search\",\n \"description\": \"Privacy-first web and local search using the Brave Search API.\",\n \"docsUrl\": \"https://github.com/brave/brave-search-mcp-server\",\n \"iconBg\": \"#FB542B\",\n \"keywords\": [\n \"search\",\n \"web\"\n ],\n \"kind\": \"mcp\",\n \"defaultConnectionOptionId\": \"api\",\n \"connectionOptions\": [\n {\n \"id\": \"api\",\n \"provider\": \"mcp\",\n \"transport\": {\n \"kind\": \"stdio\",\n \"serverName\": \"brave_search\",\n \"command\": \"npx\",\n \"args\": [\n \"-y\",\n \"@brave/brave-search-mcp-server\",\n \"--transport\",\n \"stdio\"\n ],\n \"envFields\": [\n {\n \"key\": \"BRAVE_API_KEY\",\n \"label\": \"Brave API key\",\n \"type\": \"password\",\n \"required\": true,\n \"helperText\": \"API key from the Brave Search API portal.\",\n \"helperLink\": \"https://api-dashboard.search.brave.com/app/keys\"\n }\n ]\n },\n \"auth\": {\n \"strategy\": \"api_key\"\n }\n }\n ]\n}\n"],"x_google_ignoreList":[0],"mappings":""}
@@ -1,2 +1,2 @@
1
- require(`../../../../../_virtual/_rolldown/runtime.cjs`);var e={id:`clickhouse`,name:`ClickHouse`,description:`Run analytical SQL queries against a ClickHouse cluster.`,docsUrl:`https://github.com/ClickHouse/mcp-clickhouse`,iconBg:`#FFFF00`,iconColor:`var(--oh-surface-deep)`,keywords:[`analytics`,`olap`,`database`,`sql`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`clickhouse`,command:`uvx`,args:[`mcp-clickhouse`],envFields:[{key:`CLICKHOUSE_HOST`,label:`Host`,type:`text`,placeholder:`clickhouse.example.com`,required:!0},{key:`CLICKHOUSE_USER`,label:`Username`,type:`text`,required:!0},{key:`CLICKHOUSE_PASSWORD`,label:`Password`,type:`password`,required:!0}]},auth:{strategy:`api_key`}}]};exports.default=e;
1
+ require(`../../../../../_virtual/_rolldown/runtime.cjs`);var e={id:`clickhouse`,name:`ClickHouse`,description:`Run analytical SQL queries against a ClickHouse cluster.`,docsUrl:`https://github.com/ClickHouse/mcp-clickhouse`,iconBg:`#FFFF00`,iconColor:`var(--oh-surface-deep)`,keywords:[`analytics`,`olap`,`database`,`sql`],kind:`mcp`,defaultConnectionOptionId:`api`,connectionOptions:[{id:`api`,provider:`mcp`,transport:{kind:`stdio`,serverName:`clickhouse`,command:`uvx`,args:[`mcp-clickhouse`],envFields:[{key:`CLICKHOUSE_HOST`,label:`Host`,type:`text`,placeholder:`clickhouse.example.com`,required:!0},{key:`CLICKHOUSE_USER`,label:`Username`,type:`text`,required:!0},{key:`CLICKHOUSE_PASSWORD`,label:`Password`,type:`password`,required:!0,helperText:`Password for your ClickHouse user.`,helperLink:`https://clickhouse.com/docs/operations/access-rights`}]},auth:{strategy:`api_key`}}]};exports.default=e;
2
2
  //# sourceMappingURL=clickhouse.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"clickhouse.cjs","names":[],"sources":["../../../../../../node_modules/@openhands/extensions/integrations/catalog/clickhouse.json"],"sourcesContent":["{\n \"id\": \"clickhouse\",\n \"name\": \"ClickHouse\",\n \"description\": \"Run analytical SQL queries against a ClickHouse cluster.\",\n \"docsUrl\": \"https://github.com/ClickHouse/mcp-clickhouse\",\n \"iconBg\": \"#FFFF00\",\n \"iconColor\": \"var(--oh-surface-deep)\",\n \"keywords\": [\n \"analytics\",\n \"olap\",\n \"database\",\n \"sql\"\n ],\n \"kind\": \"mcp\",\n \"defaultConnectionOptionId\": \"api\",\n \"connectionOptions\": [\n {\n \"id\": \"api\",\n \"provider\": \"mcp\",\n \"transport\": {\n \"kind\": \"stdio\",\n \"serverName\": \"clickhouse\",\n \"command\": \"uvx\",\n \"args\": [\n \"mcp-clickhouse\"\n ],\n \"envFields\": [\n {\n \"key\": \"CLICKHOUSE_HOST\",\n \"label\": \"Host\",\n \"type\": \"text\",\n \"placeholder\": \"clickhouse.example.com\",\n \"required\": true\n },\n {\n \"key\": \"CLICKHOUSE_USER\",\n \"label\": \"Username\",\n \"type\": \"text\",\n \"required\": true\n },\n {\n \"key\": \"CLICKHOUSE_PASSWORD\",\n \"label\": \"Password\",\n \"type\": \"password\",\n \"required\": true\n }\n ]\n },\n \"auth\": {\n \"strategy\": \"api_key\"\n }\n }\n ]\n}\n"],"x_google_ignoreList":[0],"mappings":""}
1
+ {"version":3,"file":"clickhouse.cjs","names":[],"sources":["../../../../../../node_modules/@openhands/extensions/integrations/catalog/clickhouse.json"],"sourcesContent":["{\n \"id\": \"clickhouse\",\n \"name\": \"ClickHouse\",\n \"description\": \"Run analytical SQL queries against a ClickHouse cluster.\",\n \"docsUrl\": \"https://github.com/ClickHouse/mcp-clickhouse\",\n \"iconBg\": \"#FFFF00\",\n \"iconColor\": \"var(--oh-surface-deep)\",\n \"keywords\": [\n \"analytics\",\n \"olap\",\n \"database\",\n \"sql\"\n ],\n \"kind\": \"mcp\",\n \"defaultConnectionOptionId\": \"api\",\n \"connectionOptions\": [\n {\n \"id\": \"api\",\n \"provider\": \"mcp\",\n \"transport\": {\n \"kind\": \"stdio\",\n \"serverName\": \"clickhouse\",\n \"command\": \"uvx\",\n \"args\": [\n \"mcp-clickhouse\"\n ],\n \"envFields\": [\n {\n \"key\": \"CLICKHOUSE_HOST\",\n \"label\": \"Host\",\n \"type\": \"text\",\n \"placeholder\": \"clickhouse.example.com\",\n \"required\": true\n },\n {\n \"key\": \"CLICKHOUSE_USER\",\n \"label\": \"Username\",\n \"type\": \"text\",\n \"required\": true\n },\n {\n \"key\": \"CLICKHOUSE_PASSWORD\",\n \"label\": \"Password\",\n \"type\": \"password\",\n \"required\": true,\n \"helperText\": \"Password for your ClickHouse user.\",\n \"helperLink\": \"https://clickhouse.com/docs/operations/access-rights\"\n }\n ]\n },\n \"auth\": {\n \"strategy\": \"api_key\"\n }\n }\n ]\n}\n"],"x_google_ignoreList":[0],"mappings":""}