@openhands/agent-canvas 1.0.0-beta.4 → 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.
- package/README.md +2 -2
- package/build/assets/{automations-list-rMki-8au.js → automations-list-6FDbI5dc.js} +1 -1
- package/build/assets/{home-XxBpNOVq.js → home-e-egNUXZ.js} +1 -1
- package/build/assets/install-server-modal-DHlbgqVH.js +1 -0
- package/build/assets/{manifest-a1d22045.js → manifest-3bf30d69.js} +1 -1
- package/build/assets/{mcp-D2onbwVk.js → mcp-ByeBfdfU.js} +1 -1
- package/build/assets/{recommended-automations-launcher-BQChv2rc.js → recommended-automations-launcher-CgV8FyPK.js} +1 -1
- package/build/assets/{root-35yk2E_M.js → root-dNntxffj.js} +1 -1
- package/build/assets/vendor~home~mcp~automations-list-Cs-TO3fK.js +1 -0
- package/build/index.html +3 -3
- package/dist/components/features/mcp-page/install-server-modal.cjs +1 -1
- package/dist/components/features/mcp-page/install-server-modal.cjs.map +1 -1
- package/dist/components/features/mcp-page/install-server-modal.js +92 -81
- package/dist/components/features/mcp-page/install-server-modal.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.js +3 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/airtable.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.js +3 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/apify.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.js +3 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/brave-search.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.js +3 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/clickhouse.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.js +3 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/elevenlabs.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.js +3 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/exa.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.js +3 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/figma.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.js +3 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/firecrawl.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/github.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/github.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/github.js +3 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/github.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.js +3 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/kagi.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.js +3 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/mongodb.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.js +3 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/neon.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js +3 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/notion.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.js +2 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/obsidian.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.js +2 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/redis.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.js +3 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/resend.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.js +8 -7
- package/dist/node_modules/@openhands/extensions/integrations/catalog/slack.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.js +2 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/supabase.js.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.cjs +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.cjs.map +1 -1
- package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.js +4 -2
- package/dist/node_modules/@openhands/extensions/integrations/catalog/tavily.js.map +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.cjs.map +1 -1
- package/dist/package.js +2 -2
- package/dist/package.js.map +1 -1
- package/package.json +2 -2
- package/build/assets/install-server-modal-f31_CLrW.js +0 -1
- 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
|
|
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
|
|
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
|
|
43
|
+
} else v(n) && (t.api_key = "");
|
|
33
44
|
return {
|
|
34
45
|
values: t,
|
|
35
46
|
errors: {}
|
|
36
47
|
};
|
|
37
48
|
}
|
|
38
|
-
function
|
|
39
|
-
let { t:
|
|
40
|
-
|
|
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
|
-
})),
|
|
50
|
-
},
|
|
60
|
+
})), M(null);
|
|
61
|
+
}, L = (e) => {
|
|
51
62
|
switch (e.error_kind) {
|
|
52
|
-
case "timeout": return
|
|
53
|
-
case "connection": return
|
|
54
|
-
default: return
|
|
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
|
-
},
|
|
57
|
-
|
|
67
|
+
}, R = (e) => {
|
|
68
|
+
D(e, {
|
|
58
69
|
onSuccess: (r) => {
|
|
59
70
|
if (!r.ok) {
|
|
60
|
-
|
|
71
|
+
M(L(r));
|
|
61
72
|
return;
|
|
62
73
|
}
|
|
63
|
-
|
|
74
|
+
T(e, {
|
|
64
75
|
onSuccess: () => {
|
|
65
|
-
n(
|
|
76
|
+
n(w(t.MCP$INSTALL_SUCCESS)), C?.(x), S();
|
|
66
77
|
},
|
|
67
78
|
onError: (e) => {
|
|
68
|
-
|
|
79
|
+
M(c(e) || w(t.ERROR$GENERIC));
|
|
69
80
|
}
|
|
70
81
|
});
|
|
71
82
|
},
|
|
72
83
|
onError: (e) => {
|
|
73
|
-
|
|
84
|
+
M(c(e) || w(t.ERROR$GENERIC));
|
|
74
85
|
}
|
|
75
86
|
});
|
|
76
|
-
},
|
|
77
|
-
if (
|
|
78
|
-
let e =
|
|
79
|
-
if (n && !
|
|
80
|
-
|
|
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:
|
|
93
|
+
errors: { api_key: w(t.MCP$ERROR_FIELD_REQUIRED) }
|
|
83
94
|
}));
|
|
84
95
|
return;
|
|
85
96
|
}
|
|
86
|
-
|
|
87
|
-
id: `${
|
|
88
|
-
type:
|
|
89
|
-
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
|
-
},
|
|
93
|
-
if (
|
|
94
|
-
let e =
|
|
95
|
-
for (let r of e.envFields ?? []) r.required && !(
|
|
96
|
-
for (let r of e.argFields ?? []) r.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
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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:
|
|
125
|
-
"aria-label":
|
|
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":
|
|
129
|
-
onSubmit: (e) => (e.preventDefault(),
|
|
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:
|
|
144
|
+
onClose: S,
|
|
134
145
|
testId: "mcp-install-modal-close",
|
|
135
|
-
disabled:
|
|
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:
|
|
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:
|
|
154
|
+
children: x.name
|
|
144
155
|
}), /* @__PURE__ */ h("p", {
|
|
145
156
|
className: "text-xs text-tertiary-light",
|
|
146
|
-
children:
|
|
157
|
+
children: x.description
|
|
147
158
|
})]
|
|
148
159
|
})]
|
|
149
160
|
}),
|
|
150
|
-
|
|
161
|
+
x.installHint && /* @__PURE__ */ h("p", {
|
|
151
162
|
className: "text-xs text-tertiary-light",
|
|
152
|
-
children:
|
|
163
|
+
children: x.installHint
|
|
153
164
|
}),
|
|
154
|
-
|
|
155
|
-
href:
|
|
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:
|
|
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 (
|
|
165
|
-
let e =
|
|
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:
|
|
171
|
-
value:
|
|
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:
|
|
182
|
-
value:
|
|
183
|
-
onChange: (e) =>
|
|
184
|
-
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
|
-
}),
|
|
199
|
+
}), k.errors.api_key && /* @__PURE__ */ h("p", {
|
|
189
200
|
className: "text-xs text-red-500",
|
|
190
|
-
children:
|
|
201
|
+
children: k.errors.api_key
|
|
191
202
|
})]
|
|
192
203
|
}) : null] });
|
|
193
204
|
}
|
|
194
|
-
if (
|
|
195
|
-
let e =
|
|
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:
|
|
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:
|
|
216
|
-
onChange: (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
|
-
|
|
237
|
+
k.errors[e.key] && /* @__PURE__ */ h("p", {
|
|
227
238
|
className: "text-xs text-red-500",
|
|
228
|
-
children:
|
|
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:
|
|
241
|
-
onChange: (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
|
-
|
|
262
|
+
k.errors[e.key] && /* @__PURE__ */ h("p", {
|
|
252
263
|
className: "text-xs text-red-500",
|
|
253
|
-
children:
|
|
264
|
+
children: k.errors[e.key]
|
|
254
265
|
})
|
|
255
266
|
]
|
|
256
267
|
}, e.key))
|
|
257
268
|
] });
|
|
258
269
|
})()
|
|
259
270
|
}),
|
|
260
|
-
|
|
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:
|
|
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:
|
|
281
|
+
onClick: S,
|
|
271
282
|
testId: "mcp-install-cancel",
|
|
272
|
-
children:
|
|
283
|
+
children: w(t.BUTTON$CANCEL)
|
|
273
284
|
}), /* @__PURE__ */ h(o, {
|
|
274
285
|
type: "submit",
|
|
275
286
|
variant: "primary",
|
|
276
|
-
isDisabled:
|
|
287
|
+
isDisabled: F,
|
|
277
288
|
testId: "mcp-install-submit",
|
|
278
|
-
children:
|
|
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 {
|
|
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":";;;;;;;;;;;;;;;;AAiCA,SAAS,EACP,GACS;AAIT,QAHI,GAAQ,UAAU,SAAS,WAAW,GAAQ,UAAU,SAAS,QAC5D,KAEF;EAAC;EAAW;EAAU;EAAQ,CAAC,SAAS,EAAO,KAAK,SAAS;;AAGtE,SAAS,EAAqB,GAAiD;AAI7E,QAHI,EAAO,UAAU,SAAS,UACrB,EAAO,KAAK,kBAAkB,KAEhC,EAAO,KAAK,kBAAkB,EAAO,UAAU,kBAAkB;;AAG1E,SAAS,EAAiB,GAAqC;CAC7D,IAAM,IAAiC,EAAE,EACnC,IAAS,EAAkC,EAAM,EACjD,IAAW,GAAQ;AACzB,KAAI,GAAU,SAAS,SAAS;AAC9B,OAAK,IAAM,KAAS,EAAS,aAAa,EAAE,CAC1C,GAAO,EAAM,OAAO;AAEtB,OAAK,IAAM,KAAS,EAAS,aAAa,EAAE,CAC1C,GAAO,EAAM,OAAO;QAEb,EAA2B,EAAO,KAC3C,EAAO,UAAU;AAEnB,QAAO;EAAE;EAAQ,QAAQ,EAAE;EAAE;;AAS/B,SAAgB,EAAmB,EACjC,UACA,YACA,gBAC0B;CAC1B,IAAM,EAAE,SAAM,EAAe,YAAY,EACnC,EAAE,QAAQ,GAAc,WAAW,MAAa,GAAiB,EACjE,EAAE,QAAQ,GAAe,WAAW,MAAc,GAAkB,EAEpE,CAAC,GAAO,KAAY,EAAM,eAC9B,EAAiB,EAAM,CACxB,EACK,CAAC,GAAa,KAAkB,EAAM,SAAwB,KAAK,EACnE,IAAS,EAAkC,EAAM,EACjD,IAAW,GAAQ,WAEnB,IAAY,KAAa,GAEzB,KAAY,GAAa,MAAkB;AAK/C,EAJA,GAAU,OAAU;GAClB,QAAQ;IAAE,GAAG,EAAK;KAAS,IAAM;IAAO;GACxC,QAAQ;IAAE,GAAG,EAAK;KAAS,IAAM;IAAM;GACxC,EAAE,EACH,EAAe,KAAK;IAGhB,KAAwB,MAAoC;AAChE,UAAQ,EAAQ,YAAhB;GACE,KAAK,UACH,QAAO,EAAE,EAAQ,uBAAuB;GAC1C,KAAK,aACH,QAAO,EAAE,EAAQ,0BAA0B;GAC7C,QACE,QAAO,EAAE,EAAQ,wBAAwB,EAAE,OAAO,EAAQ,OAAO,CAAC;;IAIlE,KAAgB,MAA6B;AACjD,IAAc,GAAS;GACrB,YAAY,MAAW;AACrB,QAAI,CAAC,EAAO,IAAI;AACd,OAAe,EAAqB,EAAO,CAAC;AAE5C;;AAEF,MAAa,GAAS;KACpB,iBAAiB;AAGf,MAFA,EAAoB,EAAE,EAAQ,oBAAoB,CAAC,EACnD,IAAY,EAAM,EAClB,GAAS;;KAEX,UAAU,MAAiB;AAEzB,QADgB,EAA0B,EAC3B,IAAW,EAAE,EAAQ,cAAc,CAAC;;KAEtD,CAAC;;GAEJ,UAAU,MAAiB;AAEzB,MADgB,EAA0B,EAC3B,IAAW,EAAE,EAAQ,cAAc,CAAC;;GAEtD,CAAC;IAQE,UAA+B;AAMnC,MAHI,GAAU,SAAS,WAAW,GAAU,SAAS,SAGjD,CAAC,EAAQ;EACb,IAAM,IAAS,EAAM,OAAO,SAAS,MAAM,IAAI,IACzC,IAAkB,EAA2B,EAAO;AAC1D,MAAI,KAAmB,CAAC,EAAqB,EAAO,IAAI,CAAC,GAAQ;AAC/D,MAAU,OAAU;IAClB,GAAG;IACH,QAAQ,EAAE,SAAS,EAAE,EAAQ,yBAAyB,EAAE;IACzD,EAAE;AACH;;AAQF,IAAa;GALX,IAAI,GAAG,EAAS,KAAK,GAAG,GAAQ;GAChC,MAAM,EAAS;GACf,KAAK,EAAS;GACd,GAAI,KAAmB,KAAU,EAAE,SAAS,GAAQ;GAEzC,CAAQ;IAGjB,UAA0B;AAC9B,MAAI,GAAU,SAAS,QAAS;EAChC,IAAM,IAAQ,GACR,IAAwC,EAAE;AAEhD,OAAK,IAAM,KAAS,EAAM,aAAa,EAAE,CACvC,CAAI,EAAM,YAAY,EAAE,EAAM,OAAO,EAAM,QAAQ,IAAI,MAAM,KAC3D,EAAO,EAAM,OAAO,EAAE,EAAQ,yBAAyB;AAG3D,OAAK,IAAM,KAAS,EAAM,aAAa,EAAE,CACvC,CAAI,EAAM,YAAY,EAAE,EAAM,OAAO,EAAM,QAAQ,IAAI,MAAM,KAC3D,EAAO,EAAM,OAAO,EAAE,EAAQ,yBAAyB;AAG3D,MAAI,OAAO,OAAO,EAAO,CAAC,KAAK,QAAQ,EAAE;AACvC,MAAU,OAAU;IAAE,GAAG;IAAM;IAAQ,EAAE;AACzC;;EAGF,IAAM,IAA8B,EAAE;AACtC,OAAK,IAAM,KAAS,EAAM,aAAa,EAAE,EAAE;GACzC,IAAM,IAAI,EAAM,OAAO,EAAM,MAAM,MAAM;AACzC,GAAI,MAAG,EAAI,EAAM,OAAO;;EAE1B,IAAM,IAAsB,EAAE;AAC9B,OAAK,IAAM,KAAS,EAAM,aAAa,EAAE,EAAE;GACzC,IAAM,IAAI,EAAM,OAAO,EAAM,MAAM,MAAM;AACzC,OAAI,QAEG,IAAM,KAAS,EAAE,MAAM,MAAM,CAChC,CAAI,KAAO,EAAU,KAAK,EAAM;;AAatC,IAAa;GAPX,IAAI,SAAS,GAAQ;GACrB,MAAM;GACN,MAAM,EAAM;GACZ,SAAS,EAAM;GACf,MAAM,CAAC,GAAG,EAAM,MAAM,GAAG,EAAU;GACnC,GAAI,OAAO,KAAK,EAAI,CAAC,SAAS,KAAK,EAAE,QAAK;GAE/B,CAAQ;;AAiHvB,QACE,kBAAC,GAAD;EAAwB;EAAS,cAAY,EAAM;YACjD,kBAAC,QAAD;GACE,eAAY;GACZ,uBAAqB,EAAM;GAC3B,WAnHgB,OACpB,EAAM,gBAAgB,EACtB,EAAe,KAAK,EAChB,GAAU,SAAS,WAAW,GAAU,SAAS,QAC5C,GAAwB,GAE1B,GAAmB;GA8GtB,WAAU;aAJZ;IAME,kBAAC,GAAD;KACW;KACT,QAAO;KACP,UAAU;KACV,CAAA;IACF,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD,EAAqB,UAAS,CAAA,EAC9B,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,MAAD;OAAI,WAAU;iBAAyB,EAAM;OAAU,CAAA,EACvD,kBAAC,KAAD;OAAG,WAAU;iBAA+B,EAAM;OAAgB,CAAA,CAC9D;QACF;;IAEL,EAAM,eACL,kBAAC,KAAD;KAAG,WAAU;eAA+B,EAAM;KAAgB,CAAA;IAGnE,EAAM,WACL,kBAAC,KAAD;KACE,MAAM,EAAM;KACZ,QAAO;KACP,KAAI;KACJ,WAAU;eAET,EAAE,EAAQ,cAAc;KACvB,CAAA;IAGN,kBAAC,OAAD;KAAK,WAAU;sBAzIM;AACzB,UAAI,GAAU,SAAS,WAAW,GAAU,SAAS,OAAO;OAC1D,IAAM,IAAyB,EAA2B,EAAO,EAC3D,IAAiB,IAAS,EAAqB,EAAO,GAAG;AAC/D,cACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;QACE,QAAO;QACP,MAAK;QACL,MAAK;QACL,OAAO,EAAE,EAAQ,iBAAiB;QAClC,OAAO,EAAS;QAChB,gBAAgB;QAChB,YAAA;QACA,WAAU;QACV,CAAA,EACD,IACC,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SACE,QAAO;SACP,MAAK;SACL,MAAK;SACL,OAAO,EAAE,EAAQ,qBAAqB;SACtC,OAAO,EAAM,OAAO,WAAW;SAC/B,WAAW,MAAM,EAAS,WAAW,EAAE;SACvC,aAAa,EAAE,EAAQ,iCAAiC;SACxD,iBAAiB;SACjB,UAAU,CAAC;SACX,WAAU;SACV,CAAA,EACD,EAAM,OAAO,WACZ,kBAAC,KAAD;SAAG,WAAU;mBAAwB,EAAM,OAAO;SAAY,CAAA,CAE5D;YACJ,KACH,EAAA,CAAA;;AAIP,UAAI,GAAU,SAAS,QAAS,QAAO;MACvC,IAAM,IAAQ;AACd,aACE,kBAAA,GAAA,EAAA,UAAA;OACE,kBAAC,GAAD;QACE,QAAO;QACP,MAAK;QACL,MAAK;QACL,OAAO,EAAE,EAAQ,kBAAkB;QACnC,OAAO,GAAG,EAAM,QAAQ,GAAG,EAAM,KAAK,KAAK,IAAI,GAAG,MAAM;QACxD,gBAAgB;QAChB,YAAA;QACA,WAAU;QACV,CAAA;QACA,EAAM,aAAa,EAAE,EAAE,KAAK,MAC5B,kBAAC,OAAD;QAAqB,WAAU;kBAA/B;SACE,kBAAC,GAAD;UACE,QAAQ,qBAAqB,EAAM;UACnC,MAAM,EAAM;UACZ,MAAM,EAAM,SAAS,aAAa,aAAa;UAC/C,OAAO,EAAM;UACb,OAAO,EAAM,OAAO,EAAM,QAAQ;UAClC,WAAW,MAAM,EAAS,EAAM,KAAK,EAAE;UACvC,aAAa,EAAM;UACnB,UAAU,EAAM;UAChB,iBAAiB,CAAC,EAAM;UACxB,WAAU;UACV,CAAA;SACD,EAAM,cACL,kBAAC,KAAD;UAAG,WAAU;oBAA6B,EAAM;UAAe,CAAA;SAEhE,EAAM,OAAO,EAAM,QAClB,kBAAC,KAAD;UAAG,WAAU;oBAAwB,EAAM,OAAO,EAAM;UAAS,CAAA;SAE/D;UAnBI,EAAM,IAmBV,CACN;QACA,EAAM,aAAa,EAAE,EAAE,KAAK,MAC5B,kBAAC,OAAD;QAAqB,WAAU;kBAA/B;SACE,kBAAC,GAAD;UACE,QAAQ,qBAAqB,EAAM;UACnC,MAAM,EAAM;UACZ,MAAM,EAAM,SAAS,aAAa,aAAa;UAC/C,OAAO,EAAM;UACb,OAAO,EAAM,OAAO,EAAM,QAAQ;UAClC,WAAW,MAAM,EAAS,EAAM,KAAK,EAAE;UACvC,aAAa,EAAM;UACnB,UAAU,EAAM;UAChB,iBAAiB,CAAC,EAAM;UACxB,WAAU;UACV,CAAA;SACD,EAAM,cACL,kBAAC,KAAD;UAAG,WAAU;oBAA6B,EAAM;UAAe,CAAA;SAEhE,EAAM,OAAO,EAAM,QAClB,kBAAC,KAAD;UAAG,WAAU;oBAAwB,EAAM,OAAO,EAAM;UAAS,CAAA;SAE/D;UAnBI,EAAM,IAmBV,CACN;OACD,EAAA,CAAA;SAwCmD;KAAO,CAAA;IAE1D,KACC,kBAAC,KAAD;KACE,eAAY;KACZ,WAAU;eAET;KACC,CAAA;IAGN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MACE,MAAK;MACL,SAAQ;MACR,SAAS;MACT,QAAO;gBAEN,EAAE,EAAQ,cAAc;MACb,CAAA,EACd,kBAAC,GAAD;MACE,MAAK;MACL,SAAQ;MACR,YAAY;MACZ,QAAO;gBAGH,EADH,IACK,EAAQ,gBACV,IACI,EAAQ,kBACR,EAAQ,mBAAmB;MACvB,CAAA,CACV;;IACD;;EACO,CAAA"}
|
|
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":""}
|