@executor-js/plugin-mcp 1.4.33 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/AddMcpSource-4LLERUW5.js +602 -0
  2. package/dist/AddMcpSource-4LLERUW5.js.map +1 -0
  3. package/dist/EditMcpSource-GKJRP75X.js +313 -0
  4. package/dist/EditMcpSource-GKJRP75X.js.map +1 -0
  5. package/dist/McpAccountsPanel-UX7MHEIG.js +132 -0
  6. package/dist/McpAccountsPanel-UX7MHEIG.js.map +1 -0
  7. package/dist/api/group.d.ts +79 -143
  8. package/dist/api/index.d.ts +99 -155
  9. package/dist/chunk-2TXHTMKM.js +1298 -0
  10. package/dist/chunk-2TXHTMKM.js.map +1 -0
  11. package/dist/chunk-6OEQZ72N.js +124 -0
  12. package/dist/chunk-6OEQZ72N.js.map +1 -0
  13. package/dist/chunk-7FJ3PUUL.js +21 -0
  14. package/dist/chunk-7FJ3PUUL.js.map +1 -0
  15. package/dist/chunk-N4EAF5CA.js +146 -0
  16. package/dist/chunk-N4EAF5CA.js.map +1 -0
  17. package/dist/client.js +9 -9
  18. package/dist/client.js.map +1 -1
  19. package/dist/core.js +36 -26
  20. package/dist/index.js +2 -2
  21. package/dist/promise.d.ts +1 -1
  22. package/dist/react/AddMcpSource.d.ts +1 -1
  23. package/dist/react/McpAccountsPanel.d.ts +6 -0
  24. package/dist/react/McpRemoteSourceFields.d.ts +4 -2
  25. package/dist/react/McpSignInButton.d.ts +2 -0
  26. package/dist/react/atoms.d.ts +93 -313
  27. package/dist/react/auth-method-config.d.ts +8 -0
  28. package/dist/react/client.d.ts +78 -142
  29. package/dist/react/index.d.ts +3 -3
  30. package/dist/react/source-plugin.d.ts +5 -5
  31. package/dist/sdk/connection.d.ts +4 -4
  32. package/dist/sdk/errors.d.ts +0 -19
  33. package/dist/sdk/index.d.ts +4 -3
  34. package/dist/sdk/invoke.d.ts +9 -16
  35. package/dist/sdk/plugin.d.ts +101 -236
  36. package/dist/sdk/types.d.ts +25 -130
  37. package/package.json +5 -4
  38. package/dist/AddMcpSource-PADMBVX2.js +0 -688
  39. package/dist/AddMcpSource-PADMBVX2.js.map +0 -1
  40. package/dist/EditMcpSource-L5GC2B4J.js +0 -281
  41. package/dist/EditMcpSource-L5GC2B4J.js.map +0 -1
  42. package/dist/McpSourceSummary-LE3WXFUE.js +0 -170
  43. package/dist/McpSourceSummary-LE3WXFUE.js.map +0 -1
  44. package/dist/chunk-6OYEXHU3.js +0 -156
  45. package/dist/chunk-6OYEXHU3.js.map +0 -1
  46. package/dist/chunk-FMTVLO5L.js +0 -179
  47. package/dist/chunk-FMTVLO5L.js.map +0 -1
  48. package/dist/chunk-LEGVPKYH.js +0 -2391
  49. package/dist/chunk-LEGVPKYH.js.map +0 -1
  50. package/dist/chunk-ZIRGIRGP.js +0 -115
  51. package/dist/chunk-ZIRGIRGP.js.map +0 -1
  52. package/dist/react/McpSourceSummary.d.ts +0 -5
  53. package/dist/sdk/binding-store.d.ts +0 -31
  54. package/dist/sdk/stored-source.d.ts +0 -42
  55. /package/dist/{sdk/connection-pool.test.d.ts → react/auth-method-config.test.d.ts} +0 -0
  56. /package/dist/sdk/{cross-user-isolation.test.d.ts → describe-auth-methods.test.d.ts} +0 -0
  57. /package/dist/sdk/{per-user-auth-isolation.test.d.ts → owner-isolation.test.d.ts} +0 -0
@@ -1,688 +0,0 @@
1
- import {
2
- mcpPresets
3
- } from "./chunk-TW44CBXJ.js";
4
- import {
5
- McpRemoteSourceFields
6
- } from "./chunk-ZIRGIRGP.js";
7
- import {
8
- addMcpSourceOptimistic,
9
- probeMcpEndpoint
10
- } from "./chunk-FMTVLO5L.js";
11
- import "./chunk-6OYEXHU3.js";
12
-
13
- // src/react/AddMcpSource.tsx
14
- import { useReducer, useCallback, useEffect, useRef, useState } from "react";
15
- import { useAtomSet } from "@effect/atom-react";
16
- import * as Exit from "effect/Exit";
17
- import * as Match from "effect/Match";
18
- import * as Option from "effect/Option";
19
- import * as Schema from "effect/Schema";
20
- import { useScope } from "@executor-js/react/api/scope-context";
21
- import { Button } from "@executor-js/react/components/button";
22
- import {
23
- CardStack,
24
- CardStackContent,
25
- CardStackEntryField
26
- } from "@executor-js/react/components/card-stack";
27
- import { FieldLabel } from "@executor-js/react/components/field";
28
- import { FilterTabs } from "@executor-js/react/components/filter-tabs";
29
- import { FloatActions } from "@executor-js/react/components/float-actions";
30
- import { Input } from "@executor-js/react/components/input";
31
- import { Spinner } from "@executor-js/react/components/spinner";
32
- import { Textarea } from "@executor-js/react/components/textarea";
33
- import {
34
- emptyHttpCredentials,
35
- httpCredentialsValid,
36
- HttpCredentialsEditor,
37
- serializeConfigureHttpCredentials,
38
- serializeHttpCredentials,
39
- serializeTemplateHttpCredentials
40
- } from "@executor-js/react/plugins/http-credentials";
41
- import {
42
- sourceDisplayNameFromUrl,
43
- slugifyNamespace,
44
- SourceIdentityFields,
45
- useSourceIdentity
46
- } from "@executor-js/react/plugins/source-identity";
47
- import { useSecretPickerSecrets } from "@executor-js/react/plugins/use-secret-picker-secrets";
48
- import {
49
- oauthCallbackUrl,
50
- oauthConnectionId,
51
- useOAuthPopupFlow
52
- } from "@executor-js/react/plugins/oauth-sign-in";
53
- import {
54
- CredentialControlField,
55
- CredentialUsageRow,
56
- useCredentialTargetScope
57
- } from "@executor-js/react/plugins/credential-target-scope";
58
- import {
59
- defaultHeaderAuthPresets
60
- } from "@executor-js/react/plugins/secret-header-auth";
61
- import { sourceWriteKeys } from "@executor-js/react/api/reactivity-keys";
62
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
63
- var mcpHeaderPresets = [
64
- { key: "text", label: "Plaintext header", name: "", valueKind: "text" },
65
- ...defaultHeaderAuthPresets
66
- ];
67
- var ErrorMessage = Schema.Struct({ message: Schema.String });
68
- var decodeErrorMessage = Schema.decodeUnknownOption(ErrorMessage);
69
- var STDIO_ENV_ESCAPE_REPLACEMENTS = {
70
- "\\": "\\",
71
- n: "\n",
72
- r: "\r",
73
- t: " ",
74
- '"': '"'
75
- };
76
- var errorMessageFromExit = (exit, fallback) => Option.match(Option.flatMap(Exit.findErrorOption(exit), decodeErrorMessage), {
77
- onNone: () => fallback,
78
- onSome: ({ message }) => message
79
- });
80
- function findPreset(id) {
81
- if (!id) return void 0;
82
- return mcpPresets.find((p) => p.id === id);
83
- }
84
- var init = { step: "url", url: "" };
85
- function reducer(state, action) {
86
- return Match.value(action).pipe(
87
- Match.discriminator("type")("set-url", (a) => ({ step: "url", url: a.url })),
88
- Match.discriminator("type")(
89
- "probe-start",
90
- () => ({
91
- step: "probing",
92
- url: state.url,
93
- probe: "probe" in state ? state.probe : null
94
- })
95
- ),
96
- Match.discriminator("type")(
97
- "probe-ok",
98
- (a) => ({ step: "probed", url: state.url, probe: a.probe })
99
- ),
100
- Match.discriminator("type")(
101
- "probe-fail",
102
- (a) => ({
103
- step: "error",
104
- url: state.url,
105
- probe: null,
106
- tokens: null,
107
- error: a.error
108
- })
109
- ),
110
- Match.discriminator("type")("oauth-start", () => {
111
- if (state.step !== "probed" && state.step !== "error") return state;
112
- return {
113
- step: "oauth-starting",
114
- url: state.url,
115
- probe: state.step === "probed" ? state.probe : state.probe
116
- };
117
- }),
118
- Match.discriminator("type")("oauth-waiting", (a) => {
119
- if (state.step !== "oauth-starting") return state;
120
- return {
121
- step: "oauth-waiting",
122
- url: state.url,
123
- probe: state.probe,
124
- sessionId: a.sessionId
125
- };
126
- }),
127
- Match.discriminator("type")("oauth-ok", (a) => {
128
- if (state.step !== "oauth-waiting") return state;
129
- return {
130
- step: "oauth-done",
131
- url: state.url,
132
- probe: state.probe,
133
- tokens: a.tokens
134
- };
135
- }),
136
- Match.discriminator("type")("oauth-fail", (a) => {
137
- if (state.step !== "oauth-starting" && state.step !== "oauth-waiting") return state;
138
- return {
139
- step: "error",
140
- url: state.url,
141
- probe: state.probe,
142
- tokens: null,
143
- error: a.error
144
- };
145
- }),
146
- Match.discriminator("type")("oauth-cancelled", () => {
147
- if (state.step !== "oauth-waiting") return state;
148
- return { step: "probed", url: state.url, probe: state.probe };
149
- }),
150
- Match.discriminator("type")("oauth-reset", () => {
151
- if ("probe" in state && state.probe) {
152
- return { step: "probed", url: state.url, probe: state.probe };
153
- }
154
- return state;
155
- }),
156
- Match.discriminator("type")("add-start", () => {
157
- const tokens = state.step === "oauth-done" ? state.tokens : state.step === "probed" ? null : null;
158
- const probe = "probe" in state ? state.probe : null;
159
- if (!probe) return state;
160
- return { step: "adding", url: state.url, probe, tokens };
161
- }),
162
- Match.discriminator("type")("add-fail", (a) => {
163
- if (state.step !== "adding") return state;
164
- return {
165
- step: "error",
166
- url: state.url,
167
- probe: state.probe,
168
- tokens: state.tokens,
169
- error: a.error
170
- };
171
- }),
172
- Match.discriminator("type")("retry", () => {
173
- if (state.step !== "error") return state;
174
- return state.probe ? state.tokens ? {
175
- step: "oauth-done",
176
- url: state.url,
177
- probe: state.probe,
178
- tokens: state.tokens
179
- } : { step: "probed", url: state.url, probe: state.probe } : { step: "url", url: state.url };
180
- }),
181
- Match.exhaustive
182
- );
183
- }
184
- function AddMcpSource(props) {
185
- const allowStdio = props.allowStdio ?? false;
186
- const rawPreset = findPreset(props.initialPreset);
187
- const preset = rawPreset?.transport === "stdio" && !allowStdio ? void 0 : rawPreset;
188
- const isStdioPreset = preset?.transport === "stdio";
189
- const [transport, setTransport] = useState(
190
- isStdioPreset && allowStdio ? "stdio" : "remote"
191
- );
192
- const [stdioCommand, setStdioCommand] = useState(isStdioPreset ? preset.command : "");
193
- const [stdioArgs, setStdioArgs] = useState(
194
- isStdioPreset && preset.args ? preset.args.join(" ") : ""
195
- );
196
- const [stdioEnv, setStdioEnv] = useState("");
197
- const stdioIdentity = useSourceIdentity({
198
- fallbackName: isStdioPreset ? preset.name : stdioCommand
199
- });
200
- const [stdioAdding, setStdioAdding] = useState(false);
201
- const [stdioError, setStdioError] = useState(null);
202
- const remoteUrl = !isStdioPreset && preset?.transport === void 0 && preset?.url ? preset.url : props.initialUrl ?? "";
203
- const [state, dispatch] = useReducer(
204
- reducer,
205
- remoteUrl ? { step: "url", url: remoteUrl } : init
206
- );
207
- const scopeId = useScope();
208
- const { credentialTargetScope: requestCredentialTargetScope } = useCredentialTargetScope();
209
- const {
210
- credentialTargetScope: oauthCredentialTargetScope,
211
- setCredentialTargetScope: setOAuthCredentialTargetScope,
212
- credentialScopeOptions
213
- } = useCredentialTargetScope();
214
- const doProbe = useAtomSet(probeMcpEndpoint, { mode: "promiseExit" });
215
- const doAdd = useAtomSet(addMcpSourceOptimistic(scopeId), {
216
- mode: "promiseExit"
217
- });
218
- const secretList = useSecretPickerSecrets();
219
- const oauth = useOAuthPopupFlow({
220
- popupName: "mcp-oauth",
221
- popupBlockedMessage: "OAuth popup was blocked",
222
- detectPopupClosed: false,
223
- startErrorMessage: "Failed to start OAuth"
224
- });
225
- const [remoteAuthMode, setRemoteAuthMode] = useState("none");
226
- const [remoteCredentials, setRemoteCredentials] = useState(() => emptyHttpCredentials());
227
- const probe = "probe" in state ? state.probe : null;
228
- const tokens = "tokens" in state ? state.tokens : null;
229
- const remoteIdentity = useSourceIdentity({
230
- fallbackName: sourceDisplayNameFromUrl(state.url, "MCP") ?? probe?.serverName ?? probe?.name ?? ""
231
- });
232
- const isProbing = state.step === "probing";
233
- const isAdding = state.step === "adding";
234
- const isOAuthBusy = state.step === "oauth-starting" || state.step === "oauth-waiting" || oauth.busy;
235
- const canUseNone = probe?.requiresOAuth !== true || probe.supportsDynamicRegistration === false;
236
- const remoteCredentialsComplete = httpCredentialsValid(remoteCredentials);
237
- const authReady = remoteAuthMode === "none" ? canUseNone : tokens !== null;
238
- const canAdd = Boolean(probe) && authReady && remoteCredentialsComplete && !isAdding && !isOAuthBusy;
239
- const probeError = state.step === "error" && state.probe === null ? state.error : null;
240
- const otherError = state.step === "error" && state.probe !== null ? state.error : null;
241
- const handleProbe = useCallback(async () => {
242
- dispatch({ type: "probe-start" });
243
- const { headers, queryParams } = serializeHttpCredentials(remoteCredentials);
244
- const exit = await doProbe({
245
- params: { scopeId },
246
- payload: {
247
- endpoint: state.url.trim(),
248
- ...Object.keys(headers).length > 0 ? { headers } : {},
249
- ...Object.keys(queryParams).length > 0 ? { queryParams } : {}
250
- }
251
- });
252
- if (Exit.isFailure(exit)) {
253
- dispatch({
254
- type: "probe-fail",
255
- error: errorMessageFromExit(exit, "Failed to connect")
256
- });
257
- return;
258
- }
259
- setRemoteAuthMode(exit.value.requiresOAuth ? "oauth2" : "none");
260
- dispatch({ type: "probe-ok", probe: exit.value });
261
- }, [state.url, scopeId, doProbe, remoteCredentials]);
262
- const handleProbeRef = useRef(handleProbe);
263
- handleProbeRef.current = handleProbe;
264
- useEffect(() => {
265
- if (transport !== "remote") return;
266
- if (state.step !== "url") return;
267
- const trimmed = state.url.trim();
268
- if (!trimmed) return;
269
- const handle = setTimeout(() => {
270
- handleProbeRef.current();
271
- }, 400);
272
- return () => clearTimeout(handle);
273
- }, [transport, state.step, state.url]);
274
- const handleRemoteCredentialsChange = useCallback((next) => {
275
- setRemoteCredentials(next);
276
- }, []);
277
- const handleOAuth = useCallback(async () => {
278
- dispatch({ type: "oauth-start" });
279
- const namespaceSlug = slugifyNamespace(remoteIdentity.namespace) || slugifyNamespace(probe?.namespace ?? "") || "mcp";
280
- const { headers, queryParams } = serializeHttpCredentials(remoteCredentials);
281
- await oauth.start({
282
- payload: {
283
- endpoint: state.url.trim(),
284
- ...Object.keys(headers).length > 0 ? { headers } : {},
285
- ...Object.keys(queryParams).length > 0 ? { queryParams } : {},
286
- redirectUrl: oauthCallbackUrl(),
287
- connectionId: oauthConnectionId({
288
- pluginId: "mcp",
289
- namespace: namespaceSlug
290
- }),
291
- tokenScope: oauthCredentialTargetScope,
292
- strategy: { kind: "dynamic-dcr" },
293
- pluginId: "mcp",
294
- identityLabel: `${remoteIdentity.name.trim() || probe?.serverName || probe?.name || "MCP"} OAuth`
295
- },
296
- onSuccess: (result) => {
297
- dispatch({
298
- type: "oauth-ok",
299
- tokens: {
300
- connectionId: result.connectionId,
301
- expiresAt: result.expiresAt,
302
- scope: result.scope
303
- }
304
- });
305
- },
306
- onAuthorizationStarted: (result) => dispatch({ type: "oauth-waiting", sessionId: result.sessionId }),
307
- onError: (error) => dispatch({ type: "oauth-fail", error })
308
- });
309
- }, [state.url, remoteIdentity, probe, remoteCredentials, oauth, oauthCredentialTargetScope]);
310
- const handleCancelOAuth = useCallback(() => {
311
- oauth.cancel();
312
- dispatch({ type: "oauth-cancelled" });
313
- }, [oauth]);
314
- const handleAddRemote = useCallback(async () => {
315
- if (!probe) return;
316
- dispatch({ type: "add-start" });
317
- const templateCredentials = serializeTemplateHttpCredentials(remoteCredentials);
318
- const configureCredentials = serializeConfigureHttpCredentials(
319
- remoteCredentials,
320
- requestCredentialTargetScope
321
- );
322
- const remoteRequestHeaders = templateCredentials.headers;
323
- const hasInitialCredentials = Object.keys(configureCredentials.headers).length > 0 || Object.keys(configureCredentials.queryParams).length > 0 || remoteAuthMode === "oauth2" && tokens;
324
- const displayName = remoteIdentity.name.trim() || probe.serverName || probe.name;
325
- const slugNamespace = slugifyNamespace(remoteIdentity.namespace);
326
- const exit = await doAdd({
327
- params: { scopeId },
328
- payload: {
329
- transport: "remote",
330
- name: displayName,
331
- namespace: slugNamespace || void 0,
332
- endpoint: state.url.trim(),
333
- ...Object.keys(remoteRequestHeaders).length > 0 ? { headers: remoteRequestHeaders } : {},
334
- ...Object.keys(templateCredentials.queryParams).length > 0 ? {
335
- queryParams: templateCredentials.queryParams
336
- } : {},
337
- ...hasInitialCredentials ? {
338
- credentials: {
339
- scope: requestCredentialTargetScope,
340
- ...Object.keys(configureCredentials.headers).length > 0 ? {
341
- headers: configureCredentials.headers
342
- } : {},
343
- ...Object.keys(configureCredentials.queryParams).length > 0 ? {
344
- queryParams: configureCredentials.queryParams
345
- } : {},
346
- ...remoteAuthMode === "oauth2" && tokens ? {
347
- auth: {
348
- oauth2: {
349
- connection: {
350
- kind: "connection",
351
- connectionId: tokens.connectionId
352
- }
353
- }
354
- }
355
- } : {}
356
- }
357
- } : {}
358
- },
359
- reactivityKeys: sourceWriteKeys
360
- });
361
- if (Exit.isFailure(exit)) {
362
- dispatch({
363
- type: "add-fail",
364
- error: errorMessageFromExit(exit, "Failed to add source")
365
- });
366
- return;
367
- }
368
- props.onComplete();
369
- }, [
370
- probe,
371
- remoteAuthMode,
372
- remoteCredentials,
373
- remoteIdentity,
374
- tokens,
375
- state.url,
376
- doAdd,
377
- props,
378
- scopeId,
379
- requestCredentialTargetScope
380
- ]);
381
- const parseStdioArgs = (raw) => {
382
- if (!raw.trim()) return [];
383
- const args = [];
384
- const regex = /[^\s"]+|"([^"]*)"/g;
385
- let match2;
386
- while ((match2 = regex.exec(raw)) !== null) {
387
- args.push(match2[1] ?? match2[0]);
388
- }
389
- return args;
390
- };
391
- const parseStdioEnvValue = (raw) => {
392
- const value2 = raw.trim();
393
- if (value2.length < 2) return value2;
394
- const quote = value2[0];
395
- if (quote !== '"' && quote !== "'" || value2[value2.length - 1] !== quote) {
396
- return value2;
397
- }
398
- const inner = value2.slice(1, -1);
399
- if (quote === "'") return inner;
400
- return inner.replace(
401
- /\\([\\nrt"])/g,
402
- (_, escaped) => STDIO_ENV_ESCAPE_REPLACEMENTS[escaped] ?? escaped
403
- );
404
- };
405
- const parseStdioEnv = (raw) => {
406
- if (!raw.trim()) return void 0;
407
- const env = {};
408
- for (const line of raw.split("\n")) {
409
- const eq = line.indexOf("=");
410
- if (eq > 0) {
411
- env[line.slice(0, eq).trim()] = parseStdioEnvValue(line.slice(eq + 1));
412
- }
413
- }
414
- return Object.keys(env).length > 0 ? env : void 0;
415
- };
416
- const handleAddStdio = useCallback(async () => {
417
- const cmd = stdioCommand.trim();
418
- if (!cmd) return;
419
- setStdioAdding(true);
420
- setStdioError(null);
421
- const displayName = stdioIdentity.name.trim() || cmd;
422
- const slugNamespace = slugifyNamespace(stdioIdentity.namespace);
423
- const exit = await doAdd({
424
- params: { scopeId },
425
- payload: {
426
- transport: "stdio",
427
- name: displayName,
428
- namespace: slugNamespace || void 0,
429
- command: cmd,
430
- args: parseStdioArgs(stdioArgs),
431
- env: parseStdioEnv(stdioEnv)
432
- },
433
- reactivityKeys: sourceWriteKeys
434
- });
435
- if (Exit.isFailure(exit)) {
436
- setStdioError(errorMessageFromExit(exit, "Failed to add source"));
437
- setStdioAdding(false);
438
- return;
439
- }
440
- props.onComplete();
441
- }, [stdioCommand, stdioArgs, stdioEnv, stdioIdentity, doAdd, scopeId, props]);
442
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col gap-6", children: [
443
- /* @__PURE__ */ jsxs("div", { children: [
444
- /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-foreground", children: "Add MCP Source" }),
445
- /* @__PURE__ */ jsx("p", { className: "mt-1 text-[13px] text-muted-foreground", children: "Connect to an MCP server to discover and use its tools." })
446
- ] }),
447
- allowStdio && /* @__PURE__ */ jsxs("div", { className: "flex gap-1 rounded-lg border border-border bg-muted/30 p-1", children: [
448
- /* @__PURE__ */ jsx(
449
- Button,
450
- {
451
- variant: "ghost",
452
- type: "button",
453
- onClick: () => setTransport("remote"),
454
- className: `flex-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors ${transport === "remote" ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
455
- children: "Remote"
456
- }
457
- ),
458
- /* @__PURE__ */ jsx(
459
- Button,
460
- {
461
- variant: "ghost",
462
- type: "button",
463
- onClick: () => setTransport("stdio"),
464
- className: `flex-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors ${transport === "stdio" ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
465
- children: "Stdio"
466
- }
467
- )
468
- ] }),
469
- transport === "remote" ? /* @__PURE__ */ jsxs(Fragment, { children: [
470
- /* @__PURE__ */ jsx(
471
- McpRemoteSourceFields,
472
- {
473
- url: state.url,
474
- onUrlChange: (url) => dispatch({ type: "set-url", url }),
475
- identity: remoteIdentity,
476
- preview: probe,
477
- probing: isProbing,
478
- error: probeError,
479
- onRetry: handleProbe
480
- }
481
- ),
482
- /* @__PURE__ */ jsx(
483
- HttpCredentialsEditor,
484
- {
485
- credentials: remoteCredentials,
486
- onChange: handleRemoteCredentialsChange,
487
- existingSecrets: secretList,
488
- sourceName: remoteIdentity.name,
489
- targetScope: requestCredentialTargetScope,
490
- credentialScopeOptions,
491
- bindingScopeOptions: credentialScopeOptions,
492
- headerPresets: mcpHeaderPresets,
493
- labels: {
494
- headers: "Request headers",
495
- queryParams: "Query parameters"
496
- }
497
- }
498
- ),
499
- probe && /* @__PURE__ */ jsxs("section", { className: "space-y-2.5", children: [
500
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
501
- /* @__PURE__ */ jsx(FieldLabel, { children: "Authentication" }),
502
- /* @__PURE__ */ jsx(
503
- FilterTabs,
504
- {
505
- tabs: probe.requiresOAuth && probe.supportsDynamicRegistration ? [{ value: "oauth2", label: "OAuth" }] : [
506
- { value: "none", label: "None" },
507
- { value: "oauth2", label: "OAuth" }
508
- ],
509
- value: remoteAuthMode,
510
- onChange: setRemoteAuthMode
511
- }
512
- )
513
- ] }),
514
- remoteAuthMode === "oauth2" && /* @__PURE__ */ jsx(
515
- CredentialUsageRow,
516
- {
517
- value: oauthCredentialTargetScope,
518
- options: credentialScopeOptions,
519
- onChange: (targetScope) => {
520
- setOAuthCredentialTargetScope(targetScope);
521
- dispatch({ type: "oauth-reset" });
522
- },
523
- label: "Connection saved to",
524
- help: "Choose who can use the OAuth connection.",
525
- children: /* @__PURE__ */ jsxs(
526
- CredentialControlField,
527
- {
528
- label: "Connect via OAuth",
529
- help: "Start the provider OAuth flow.",
530
- children: [
531
- !tokens && state.step === "probed" && (probe.supportsDynamicRegistration ? /* @__PURE__ */ jsx(
532
- Button,
533
- {
534
- type: "button",
535
- onClick: handleOAuth,
536
- variant: "outline",
537
- className: "w-full",
538
- children: "Sign in"
539
- }
540
- ) : /* @__PURE__ */ jsx("div", { className: "rounded-md border border-border bg-muted/30 px-3 py-2 text-xs text-muted-foreground", children: "This server requires OAuth, but its authorization server does not support dynamic client registration. Use request headers with a bearer token, or save the source and connect a supported OAuth connection later." })),
541
- !tokens && state.step === "oauth-starting" && /* @__PURE__ */ jsxs("div", { className: "flex min-h-9 items-center gap-2 rounded-md border border-border bg-muted/30 px-3 py-2", children: [
542
- /* @__PURE__ */ jsx(Spinner, { className: "size-3.5" }),
543
- /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "Starting authorization..." })
544
- ] }),
545
- !tokens && state.step === "oauth-waiting" && /* @__PURE__ */ jsxs("div", { className: "flex min-h-9 items-center gap-2 rounded-md border border-blue-500/30 bg-blue-500/5 px-3 py-2", children: [
546
- /* @__PURE__ */ jsx(Spinner, { className: "size-3.5 text-blue-500" }),
547
- /* @__PURE__ */ jsx("span", { className: "text-xs text-blue-600 dark:text-blue-400", children: "Waiting for authorization..." }),
548
- /* @__PURE__ */ jsx(
549
- Button,
550
- {
551
- type: "button",
552
- variant: "ghost",
553
- size: "sm",
554
- onClick: handleCancelOAuth,
555
- className: "ml-auto h-7 px-2 text-xs",
556
- children: "Cancel"
557
- }
558
- )
559
- ] }),
560
- tokens && /* @__PURE__ */ jsxs("div", { className: "flex min-h-9 items-center gap-2 rounded-md border border-emerald-500/30 bg-emerald-500/5 px-3 py-2", children: [
561
- /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "none", className: "size-3.5 text-emerald-500", children: /* @__PURE__ */ jsx(
562
- "path",
563
- {
564
- d: "M3 8.5l3 3 7-7",
565
- stroke: "currentColor",
566
- strokeWidth: "1.5",
567
- strokeLinecap: "round",
568
- strokeLinejoin: "round"
569
- }
570
- ) }),
571
- /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-emerald-600 dark:text-emerald-400", children: "Authenticated" })
572
- ] })
573
- ]
574
- }
575
- )
576
- }
577
- )
578
- ] }),
579
- otherError && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
580
- /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2", children: /* @__PURE__ */ jsx("p", { className: "text-[12px] text-destructive", children: otherError }) }),
581
- /* @__PURE__ */ jsx(
582
- Button,
583
- {
584
- type: "button",
585
- variant: "outline",
586
- size: "sm",
587
- onClick: () => dispatch({ type: "retry" }),
588
- className: "text-xs",
589
- children: "Try again"
590
- }
591
- )
592
- ] }),
593
- /* @__PURE__ */ jsxs(FloatActions, { children: [
594
- /* @__PURE__ */ jsx(
595
- Button,
596
- {
597
- type: "button",
598
- variant: "ghost",
599
- onClick: () => {
600
- oauth.cancel();
601
- props.onCancel();
602
- },
603
- disabled: isAdding,
604
- children: "Cancel"
605
- }
606
- ),
607
- (probe || isProbing) && /* @__PURE__ */ jsx(Button, { type: "button", onClick: handleAddRemote, disabled: !canAdd, children: isAdding ? /* @__PURE__ */ jsxs(Fragment, { children: [
608
- /* @__PURE__ */ jsx(Spinner, { className: "size-3.5" }),
609
- " Adding\u2026"
610
- ] }) : "Add source" })
611
- ] })
612
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
613
- /* @__PURE__ */ jsx(CardStack, { children: /* @__PURE__ */ jsxs(CardStackContent, { className: "border-t-0", children: [
614
- /* @__PURE__ */ jsx(
615
- CardStackEntryField,
616
- {
617
- label: "Command",
618
- description: "- The executable to run (e.g. npx, uvx, node).",
619
- children: /* @__PURE__ */ jsx(
620
- Input,
621
- {
622
- value: stdioCommand,
623
- onChange: (e) => setStdioCommand(e.target.value),
624
- placeholder: "npx",
625
- className: "font-mono text-sm"
626
- }
627
- )
628
- }
629
- ),
630
- /* @__PURE__ */ jsx(
631
- CardStackEntryField,
632
- {
633
- label: "Arguments",
634
- description: "- Space-separated arguments passed to the command.",
635
- children: /* @__PURE__ */ jsx(
636
- Input,
637
- {
638
- value: stdioArgs,
639
- onChange: (e) => setStdioArgs(e.target.value),
640
- placeholder: "-y chrome-devtools-mcp@latest",
641
- className: "font-mono text-sm"
642
- }
643
- )
644
- }
645
- ),
646
- /* @__PURE__ */ jsx(
647
- CardStackEntryField,
648
- {
649
- label: "Environment variables",
650
- description: "- One per line, KEY=value format.",
651
- children: /* @__PURE__ */ jsx(
652
- Textarea,
653
- {
654
- value: stdioEnv,
655
- onChange: (e) => setStdioEnv(e.target.value),
656
- placeholder: "KEY=value\nANOTHER=value",
657
- rows: 3,
658
- maxRows: 10,
659
- className: "font-mono text-sm"
660
- }
661
- )
662
- }
663
- )
664
- ] }) }),
665
- /* @__PURE__ */ jsx(SourceIdentityFields, { identity: stdioIdentity, namePlaceholder: "My MCP Server" }),
666
- stdioError && /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2", children: /* @__PURE__ */ jsx("p", { className: "text-[12px] text-destructive", children: stdioError }) }),
667
- /* @__PURE__ */ jsxs(FloatActions, { children: [
668
- /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", onClick: props.onCancel, disabled: stdioAdding, children: "Cancel" }),
669
- /* @__PURE__ */ jsx(
670
- Button,
671
- {
672
- type: "button",
673
- onClick: handleAddStdio,
674
- disabled: !stdioCommand.trim() || stdioAdding,
675
- children: stdioAdding ? /* @__PURE__ */ jsxs(Fragment, { children: [
676
- /* @__PURE__ */ jsx(Spinner, { className: "size-3.5" }),
677
- " Adding\u2026"
678
- ] }) : "Add source"
679
- }
680
- )
681
- ] })
682
- ] })
683
- ] });
684
- }
685
- export {
686
- AddMcpSource as default
687
- };
688
- //# sourceMappingURL=AddMcpSource-PADMBVX2.js.map