@executor-js/plugin-mcp 1.5.6 → 1.5.7
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/dist/{AddMcpSource-4LLERUW5.js → AddMcpSource-ZDNQ7F6I.js} +70 -97
- package/dist/AddMcpSource-ZDNQ7F6I.js.map +1 -0
- package/dist/EditMcpSource-75NJRWZR.js +178 -0
- package/dist/EditMcpSource-75NJRWZR.js.map +1 -0
- package/dist/McpAccountsPanel-QBCSCJE7.js +83 -0
- package/dist/McpAccountsPanel-QBCSCJE7.js.map +1 -0
- package/dist/api/group.d.ts +106 -15
- package/dist/api/index.d.ts +121 -15
- package/dist/{chunk-N4EAF5CA.js → chunk-3AOD4VAW.js} +74 -5
- package/dist/chunk-3AOD4VAW.js.map +1 -0
- package/dist/{chunk-6OEQZ72N.js → chunk-3H5Y7JCQ.js} +65 -11
- package/dist/chunk-3H5Y7JCQ.js.map +1 -0
- package/dist/{chunk-HSJWIVME.js → chunk-6BJ6MZF7.js} +110 -52
- package/dist/chunk-6BJ6MZF7.js.map +1 -0
- package/dist/client.js +3 -3
- package/dist/core.js +152 -5
- package/dist/core.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/react/atoms.d.ts +128 -26
- package/dist/react/auth-method-config.d.ts +22 -7
- package/dist/react/client.d.ts +103 -15
- package/dist/sdk/connection.d.ts +1 -1
- package/dist/sdk/index.d.ts +3 -1
- package/dist/sdk/invoke.d.ts +1 -1
- package/dist/sdk/migrate-config.d.ts +6 -0
- package/dist/sdk/migrate-config.test.d.ts +1 -0
- package/dist/sdk/multi-placement-auth.test.d.ts +1 -0
- package/dist/sdk/plugin.d.ts +92 -5
- package/dist/sdk/types.d.ts +105 -15
- package/package.json +4 -4
- package/dist/AddMcpSource-4LLERUW5.js.map +0 -1
- package/dist/EditMcpSource-GKJRP75X.js +0 -313
- package/dist/EditMcpSource-GKJRP75X.js.map +0 -1
- package/dist/McpAccountsPanel-UX7MHEIG.js +0 -132
- package/dist/McpAccountsPanel-UX7MHEIG.js.map +0 -1
- package/dist/chunk-6OEQZ72N.js.map +0 -1
- package/dist/chunk-7FJ3PUUL.js +0 -21
- package/dist/chunk-7FJ3PUUL.js.map +0 -1
- package/dist/chunk-HSJWIVME.js.map +0 -1
- package/dist/chunk-N4EAF5CA.js.map +0 -1
|
@@ -1,36 +1,29 @@
|
|
|
1
1
|
import {
|
|
2
2
|
mcpPresets
|
|
3
3
|
} from "./chunk-TW44CBXJ.js";
|
|
4
|
-
import {
|
|
5
|
-
mcpAuthTemplateFromEditorValue
|
|
6
|
-
} from "./chunk-7FJ3PUUL.js";
|
|
7
4
|
import {
|
|
8
5
|
addMcpServer,
|
|
6
|
+
mcpAuthMethodInputFromEditorValue,
|
|
7
|
+
mcpWireAuthInput,
|
|
9
8
|
probeMcpEndpoint
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-3AOD4VAW.js";
|
|
10
|
+
import "./chunk-3H5Y7JCQ.js";
|
|
12
11
|
|
|
13
12
|
// src/react/AddMcpSource.tsx
|
|
14
13
|
import { useReducer, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
15
|
-
import { useAtomSet
|
|
16
|
-
import { Link } from "@tanstack/react-router";
|
|
14
|
+
import { useAtomSet } from "@effect/atom-react";
|
|
17
15
|
import * as Exit from "effect/Exit";
|
|
18
16
|
import * as Match from "effect/Match";
|
|
19
|
-
import * as Option from "effect/Option";
|
|
20
|
-
import * as Predicate from "effect/Predicate";
|
|
21
|
-
import * as Schema from "effect/Schema";
|
|
22
|
-
import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
|
|
23
|
-
import { integrationsOptimisticAtom } from "@executor-js/react/api/atoms";
|
|
24
17
|
import { Button as Button2 } from "@executor-js/react/components/button";
|
|
25
18
|
import {
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
AuthMethodListEditor,
|
|
20
|
+
useAuthMethodList
|
|
21
|
+
} from "@executor-js/react/components/auth-method-list-editor";
|
|
28
22
|
import {
|
|
29
23
|
CardStack as CardStack2,
|
|
30
24
|
CardStackContent as CardStackContent2,
|
|
31
25
|
CardStackEntryField as CardStackEntryField2
|
|
32
26
|
} from "@executor-js/react/components/card-stack";
|
|
33
|
-
import { FieldLabel } from "@executor-js/react/components/field";
|
|
34
27
|
import { FloatActions } from "@executor-js/react/components/float-actions";
|
|
35
28
|
import { Input as Input2 } from "@executor-js/react/components/input";
|
|
36
29
|
import { Spinner } from "@executor-js/react/components/spinner";
|
|
@@ -41,6 +34,13 @@ import {
|
|
|
41
34
|
IntegrationIdentityFields,
|
|
42
35
|
useIntegrationIdentity
|
|
43
36
|
} from "@executor-js/react/plugins/integration-identity";
|
|
37
|
+
import {
|
|
38
|
+
addIntegrationErrorMessage,
|
|
39
|
+
errorMessageFromExit,
|
|
40
|
+
FormErrorAlert,
|
|
41
|
+
SlugCollisionAlert,
|
|
42
|
+
useSlugAlreadyExists
|
|
43
|
+
} from "@executor-js/react/lib/integration-add";
|
|
44
44
|
import { integrationWriteKeys } from "@executor-js/react/api/reactivity-keys";
|
|
45
45
|
|
|
46
46
|
// src/react/McpRemoteSourceFields.tsx
|
|
@@ -163,8 +163,6 @@ function McpRemoteSourceFields(props) {
|
|
|
163
163
|
|
|
164
164
|
// src/react/AddMcpSource.tsx
|
|
165
165
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
166
|
-
var ErrorMessage = Schema.Struct({ message: Schema.String });
|
|
167
|
-
var decodeErrorMessage = Schema.decodeUnknownOption(ErrorMessage);
|
|
168
166
|
var STDIO_ENV_ESCAPE_REPLACEMENTS = {
|
|
169
167
|
"\\": "\\",
|
|
170
168
|
n: "\n",
|
|
@@ -172,15 +170,6 @@ var STDIO_ENV_ESCAPE_REPLACEMENTS = {
|
|
|
172
170
|
t: " ",
|
|
173
171
|
'"': '"'
|
|
174
172
|
};
|
|
175
|
-
var errorMessageFromExit = (exit, fallback) => Option.match(Option.flatMap(Exit.findErrorOption(exit), decodeErrorMessage), {
|
|
176
|
-
onNone: () => fallback,
|
|
177
|
-
onSome: ({ message }) => message
|
|
178
|
-
});
|
|
179
|
-
var isIntegrationAlreadyExistsExit = (exit) => Option.match(Exit.findErrorOption(exit), {
|
|
180
|
-
onNone: () => false,
|
|
181
|
-
onSome: Predicate.isTagged("IntegrationAlreadyExistsError")
|
|
182
|
-
});
|
|
183
|
-
var integrationExistsMessage = (slug) => `An integration named "${slug}" already exists. To add more authentication, update your existing integration.`;
|
|
184
173
|
function findPreset(id) {
|
|
185
174
|
if (!id) return void 0;
|
|
186
175
|
return mcpPresets.find((p) => p.id === id);
|
|
@@ -256,23 +245,40 @@ function AddMcpSource(props) {
|
|
|
256
245
|
);
|
|
257
246
|
const doProbe = useAtomSet(probeMcpEndpoint, { mode: "promiseExit" });
|
|
258
247
|
const doAddServer = useAtomSet(addMcpServer, { mode: "promiseExit" });
|
|
259
|
-
const [authValue, setAuthValue] = useState({ kind: "none" });
|
|
260
248
|
const probe = "probe" in state ? state.probe : null;
|
|
261
|
-
const
|
|
249
|
+
const authMethodSeeds = useMemo(() => {
|
|
250
|
+
if (!probe) return [];
|
|
251
|
+
if (probe.requiresOAuth) {
|
|
252
|
+
return [
|
|
253
|
+
{
|
|
254
|
+
value: { kind: "oauth", authorizationUrl: "", tokenUrl: "", scopes: [] },
|
|
255
|
+
label: "Detected"
|
|
256
|
+
}
|
|
257
|
+
];
|
|
258
|
+
}
|
|
259
|
+
if (probe.requiresAuthentication) {
|
|
260
|
+
return [
|
|
261
|
+
{
|
|
262
|
+
value: {
|
|
263
|
+
kind: "apikey",
|
|
264
|
+
placements: [{ carrier: "header", name: "Authorization", prefix: "Bearer " }]
|
|
265
|
+
},
|
|
266
|
+
label: "Detected"
|
|
267
|
+
}
|
|
268
|
+
];
|
|
269
|
+
}
|
|
270
|
+
return [{ value: { kind: "none" }, label: "Detected" }];
|
|
271
|
+
}, [probe]);
|
|
272
|
+
const authMethodList = useAuthMethodList(authMethodSeeds);
|
|
262
273
|
const remoteIdentity = useIntegrationIdentity({
|
|
263
274
|
fallbackName: integrationDisplayNameFromUrl(state.url, "MCP") ?? probe?.serverName ?? probe?.name ?? ""
|
|
264
275
|
});
|
|
265
276
|
const isProbing = state.step === "probing";
|
|
266
277
|
const isAdding = state.step === "adding";
|
|
267
|
-
const integrationsResult = useAtomValue(integrationsOptimisticAtom);
|
|
268
|
-
const existingSlugs = useMemo(
|
|
269
|
-
() => AsyncResult.isSuccess(integrationsResult) ? integrationsResult.value.map((integration) => String(integration.slug)) : [],
|
|
270
|
-
[integrationsResult]
|
|
271
|
-
);
|
|
272
278
|
const remoteSlug = slugifyNamespace(remoteIdentity.namespace);
|
|
273
279
|
const stdioSlug = slugifyNamespace(stdioIdentity.namespace);
|
|
274
|
-
const remoteSlugExists =
|
|
275
|
-
const stdioSlugExists =
|
|
280
|
+
const remoteSlugExists = useSlugAlreadyExists(remoteSlug);
|
|
281
|
+
const stdioSlugExists = useSlugAlreadyExists(stdioSlug);
|
|
276
282
|
const canAdd = Boolean(probe) && !isAdding && !remoteSlugExists;
|
|
277
283
|
const probeError = state.step === "error" && state.probe === null ? state.error : null;
|
|
278
284
|
const otherError = state.step === "error" && state.probe !== null ? state.error : null;
|
|
@@ -288,12 +294,6 @@ function AddMcpSource(props) {
|
|
|
288
294
|
});
|
|
289
295
|
return;
|
|
290
296
|
}
|
|
291
|
-
setAuthValue(
|
|
292
|
-
exit.value.requiresOAuth ? { kind: "oauth", authorizationUrl: "", tokenUrl: "", scopes: [] } : exit.value.requiresAuthentication ? {
|
|
293
|
-
kind: "apikey",
|
|
294
|
-
placements: [{ carrier: "header", name: "Authorization", prefix: "Bearer " }]
|
|
295
|
-
} : { kind: "none" }
|
|
296
|
-
);
|
|
297
297
|
dispatch({ type: "probe-ok", probe: exit.value });
|
|
298
298
|
}, [state.url, doProbe]);
|
|
299
299
|
const handleProbeRef = useRef(handleProbe);
|
|
@@ -309,7 +309,7 @@ function AddMcpSource(props) {
|
|
|
309
309
|
return () => clearTimeout(handle);
|
|
310
310
|
}, [transport, state.step, state.url]);
|
|
311
311
|
const registerIntegration = useCallback(
|
|
312
|
-
async (
|
|
312
|
+
async (authenticationTemplate) => {
|
|
313
313
|
const displayName = remoteIdentity.name.trim() || probe?.serverName || probe?.name || "MCP";
|
|
314
314
|
const slug = slugifyNamespace(remoteIdentity.namespace) || void 0;
|
|
315
315
|
const exit = await doAddServer({
|
|
@@ -318,14 +318,14 @@ function AddMcpSource(props) {
|
|
|
318
318
|
name: displayName,
|
|
319
319
|
endpoint: state.url.trim(),
|
|
320
320
|
...slug ? { slug } : {},
|
|
321
|
-
|
|
321
|
+
authenticationTemplate
|
|
322
322
|
},
|
|
323
323
|
reactivityKeys: integrationWriteKeys
|
|
324
324
|
});
|
|
325
325
|
if (Exit.isFailure(exit)) {
|
|
326
326
|
dispatch({
|
|
327
327
|
type: "add-fail",
|
|
328
|
-
error:
|
|
328
|
+
error: addIntegrationErrorMessage(exit, slug ?? displayName, "Failed to add server")
|
|
329
329
|
});
|
|
330
330
|
return null;
|
|
331
331
|
}
|
|
@@ -336,17 +336,22 @@ function AddMcpSource(props) {
|
|
|
336
336
|
const handleAddRemote = useCallback(async () => {
|
|
337
337
|
if (!probe) return;
|
|
338
338
|
dispatch({ type: "add-start" });
|
|
339
|
-
const
|
|
339
|
+
const methods = authMethodList.rows.map(
|
|
340
|
+
(row) => mcpWireAuthInput(mcpAuthMethodInputFromEditorValue(row.value))
|
|
341
|
+
);
|
|
342
|
+
const slug = await registerIntegration(
|
|
343
|
+
methods.length > 0 ? methods : [{ kind: "none" }]
|
|
344
|
+
);
|
|
340
345
|
if (slug === null) return;
|
|
341
346
|
props.onComplete(slug);
|
|
342
|
-
}, [probe,
|
|
347
|
+
}, [probe, authMethodList.rows, registerIntegration, props]);
|
|
343
348
|
const parseStdioArgs = (raw) => {
|
|
344
349
|
if (!raw.trim()) return [];
|
|
345
350
|
const args = [];
|
|
346
351
|
const regex = /[^\s"]+|"([^"]*)"/g;
|
|
347
|
-
let
|
|
348
|
-
while ((
|
|
349
|
-
args.push(
|
|
352
|
+
let match;
|
|
353
|
+
while ((match = regex.exec(raw)) !== null) {
|
|
354
|
+
args.push(match[1] ?? match[0]);
|
|
350
355
|
}
|
|
351
356
|
return args;
|
|
352
357
|
};
|
|
@@ -394,9 +399,7 @@ function AddMcpSource(props) {
|
|
|
394
399
|
reactivityKeys: integrationWriteKeys
|
|
395
400
|
});
|
|
396
401
|
if (Exit.isFailure(exit)) {
|
|
397
|
-
setStdioError(
|
|
398
|
-
isIntegrationAlreadyExistsExit(exit) ? integrationExistsMessage(slug ?? displayName) : errorMessageFromExit(exit, "Failed to add server")
|
|
399
|
-
);
|
|
402
|
+
setStdioError(addIntegrationErrorMessage(exit, slug ?? displayName, "Failed to add server"));
|
|
400
403
|
setStdioAdding(false);
|
|
401
404
|
return;
|
|
402
405
|
}
|
|
@@ -442,20 +445,18 @@ function AddMcpSource(props) {
|
|
|
442
445
|
onRetry: handleProbe
|
|
443
446
|
}
|
|
444
447
|
),
|
|
445
|
-
probe && /* @__PURE__ */
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
)
|
|
456
|
-
] }),
|
|
448
|
+
probe && /* @__PURE__ */ jsx2(
|
|
449
|
+
AuthMethodListEditor,
|
|
450
|
+
{
|
|
451
|
+
list: authMethodList,
|
|
452
|
+
title: "How does this server authenticate?",
|
|
453
|
+
oauthMetadata: "discovered",
|
|
454
|
+
emptyHint: "No methods declared. Add a method, or add the server without auth and connect from the integration page later.",
|
|
455
|
+
footerHint: "Every method here is registered with the server. Connect an account from the integration page after adding."
|
|
456
|
+
}
|
|
457
|
+
),
|
|
457
458
|
otherError && /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
|
|
458
|
-
/* @__PURE__ */ jsx2(
|
|
459
|
+
/* @__PURE__ */ jsx2(FormErrorAlert, { message: otherError }),
|
|
459
460
|
/* @__PURE__ */ jsx2(
|
|
460
461
|
Button2,
|
|
461
462
|
{
|
|
@@ -468,21 +469,7 @@ function AddMcpSource(props) {
|
|
|
468
469
|
}
|
|
469
470
|
)
|
|
470
471
|
] }),
|
|
471
|
-
remoteSlugExists && !isAdding && /* @__PURE__ */ jsx2(
|
|
472
|
-
'An integration named "',
|
|
473
|
-
remoteSlug,
|
|
474
|
-
'" already exists. To add more authentication, update your existing integration.',
|
|
475
|
-
" ",
|
|
476
|
-
/* @__PURE__ */ jsx2(
|
|
477
|
-
Link,
|
|
478
|
-
{
|
|
479
|
-
to: "/integrations/$namespace",
|
|
480
|
-
params: { namespace: remoteSlug },
|
|
481
|
-
className: "font-medium underline underline-offset-2",
|
|
482
|
-
children: "Open it"
|
|
483
|
-
}
|
|
484
|
-
)
|
|
485
|
-
] }) }),
|
|
472
|
+
remoteSlugExists && !isAdding && /* @__PURE__ */ jsx2(SlugCollisionAlert, { slug: remoteSlug }),
|
|
486
473
|
/* @__PURE__ */ jsxs2(FloatActions, { children: [
|
|
487
474
|
/* @__PURE__ */ jsx2(
|
|
488
475
|
Button2,
|
|
@@ -553,22 +540,8 @@ function AddMcpSource(props) {
|
|
|
553
540
|
)
|
|
554
541
|
] }) }),
|
|
555
542
|
/* @__PURE__ */ jsx2(IntegrationIdentityFields, { identity: stdioIdentity, namePlaceholder: "My MCP Server" }),
|
|
556
|
-
stdioError && /* @__PURE__ */ jsx2(
|
|
557
|
-
stdioSlugExists && !stdioAdding && /* @__PURE__ */ jsx2(
|
|
558
|
-
'An integration named "',
|
|
559
|
-
stdioSlug,
|
|
560
|
-
'" already exists. To add more authentication, update your existing integration.',
|
|
561
|
-
" ",
|
|
562
|
-
/* @__PURE__ */ jsx2(
|
|
563
|
-
Link,
|
|
564
|
-
{
|
|
565
|
-
to: "/integrations/$namespace",
|
|
566
|
-
params: { namespace: stdioSlug },
|
|
567
|
-
className: "font-medium underline underline-offset-2",
|
|
568
|
-
children: "Open it"
|
|
569
|
-
}
|
|
570
|
-
)
|
|
571
|
-
] }) }),
|
|
543
|
+
stdioError && /* @__PURE__ */ jsx2(FormErrorAlert, { message: stdioError }),
|
|
544
|
+
stdioSlugExists && !stdioAdding && /* @__PURE__ */ jsx2(SlugCollisionAlert, { slug: stdioSlug }),
|
|
572
545
|
/* @__PURE__ */ jsxs2(FloatActions, { children: [
|
|
573
546
|
/* @__PURE__ */ jsx2(
|
|
574
547
|
Button2,
|
|
@@ -599,4 +572,4 @@ function AddMcpSource(props) {
|
|
|
599
572
|
export {
|
|
600
573
|
AddMcpSource as default
|
|
601
574
|
};
|
|
602
|
-
//# sourceMappingURL=AddMcpSource-
|
|
575
|
+
//# sourceMappingURL=AddMcpSource-ZDNQ7F6I.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/react/AddMcpSource.tsx","../src/react/McpRemoteSourceFields.tsx"],"sourcesContent":["import { useReducer, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useAtomSet } from \"@effect/atom-react\";\nimport * as Exit from \"effect/Exit\";\nimport * as Match from \"effect/Match\";\n\nimport { Button } from \"@executor-js/react/components/button\";\nimport {\n AuthMethodListEditor,\n useAuthMethodList,\n type AuthMethodRow,\n type AuthMethodSeed,\n} from \"@executor-js/react/components/auth-method-list-editor\";\nimport {\n CardStack,\n CardStackContent,\n CardStackEntryField,\n} from \"@executor-js/react/components/card-stack\";\nimport { FloatActions } from \"@executor-js/react/components/float-actions\";\nimport { Input } from \"@executor-js/react/components/input\";\nimport { Spinner } from \"@executor-js/react/components/spinner\";\nimport { Textarea } from \"@executor-js/react/components/textarea\";\nimport {\n integrationDisplayNameFromUrl,\n slugifyNamespace,\n IntegrationIdentityFields,\n useIntegrationIdentity,\n} from \"@executor-js/react/plugins/integration-identity\";\nimport {\n addIntegrationErrorMessage,\n errorMessageFromExit,\n FormErrorAlert,\n SlugCollisionAlert,\n useSlugAlreadyExists,\n} from \"@executor-js/react/lib/integration-add\";\n\nimport { integrationWriteKeys } from \"@executor-js/react/api/reactivity-keys\";\nimport type { McpAuthMethodInput } from \"../sdk/types\";\nimport { probeMcpEndpoint, addMcpServer } from \"./atoms\";\nimport { McpRemoteSourceFields } from \"./McpRemoteSourceFields\";\nimport { mcpAuthMethodInputFromEditorValue, mcpWireAuthInput } from \"./auth-method-config\";\nimport { mcpPresets, type McpPreset } from \"../sdk/presets\";\n\n// The remote add flow REGISTERS the server's declared auth methods through the\n// shared `AuthMethodListEditor` — accounts (the API key value / OAuth sign-in)\n// are added later from the integration's detail hub (P6: add without auth,\n// connect later). The probe SEEDS the list (detected OAuth → an OAuth row; a\n// 401 without OAuth → a bearer-header row; open server → a no-auth row) and\n// the user can add alternate methods (e.g. an API key alongside OAuth, or a\n// declared method on a server that advertises none).\n\nconst STDIO_ENV_ESCAPE_REPLACEMENTS: Readonly<Record<string, string>> = {\n \"\\\\\": \"\\\\\",\n n: \"\\n\",\n r: \"\\r\",\n t: \"\\t\",\n '\"': '\"',\n};\n\n// ---------------------------------------------------------------------------\n// Preset lookup\n// ---------------------------------------------------------------------------\n\nfunction findPreset(id: string | undefined): McpPreset | undefined {\n if (!id) return undefined;\n return mcpPresets.find((p) => p.id === id);\n}\n\n// ---------------------------------------------------------------------------\n// State machine (remote flow)\n// ---------------------------------------------------------------------------\n\ntype ProbeResult = {\n connected: boolean;\n requiresAuthentication: boolean;\n requiresOAuth: boolean;\n supportsDynamicRegistration: boolean;\n name: string;\n slug: string;\n toolCount: number | null;\n serverName: string | null;\n};\n\ntype State =\n | { step: \"url\"; url: string }\n | { step: \"probing\"; url: string; probe: ProbeResult | null }\n | { step: \"probed\"; url: string; probe: ProbeResult }\n | { step: \"adding\"; url: string; probe: ProbeResult }\n | {\n step: \"error\";\n url: string;\n probe: ProbeResult | null;\n error: string;\n };\n\ntype Action =\n | { type: \"set-url\"; url: string }\n | { type: \"probe-start\" }\n | { type: \"probe-ok\"; probe: ProbeResult }\n | { type: \"probe-fail\"; error: string }\n | { type: \"add-start\" }\n | { type: \"add-fail\"; error: string }\n | { type: \"retry\" };\n\nconst init: State = { step: \"url\", url: \"\" };\n\nfunction reducer(state: State, action: Action): State {\n return Match.value(action).pipe(\n Match.discriminator(\"type\")(\"set-url\", (a): State => ({ step: \"url\", url: a.url })),\n Match.discriminator(\"type\")(\n \"probe-start\",\n (): State => ({\n step: \"probing\",\n url: state.url,\n probe: \"probe\" in state ? state.probe : null,\n }),\n ),\n Match.discriminator(\"type\")(\n \"probe-ok\",\n (a): State => ({ step: \"probed\", url: state.url, probe: a.probe }),\n ),\n Match.discriminator(\"type\")(\n \"probe-fail\",\n (a): State => ({\n step: \"error\",\n url: state.url,\n probe: null,\n error: a.error,\n }),\n ),\n Match.discriminator(\"type\")(\"add-start\", (): State => {\n const probe = \"probe\" in state ? state.probe : null;\n if (!probe) return state;\n return { step: \"adding\", url: state.url, probe };\n }),\n Match.discriminator(\"type\")(\"add-fail\", (a): State => {\n if (state.step !== \"adding\") return state;\n return {\n step: \"error\",\n url: state.url,\n probe: state.probe,\n error: a.error,\n };\n }),\n Match.discriminator(\"type\")(\"retry\", (): State => {\n if (state.step !== \"error\") return state;\n return state.probe\n ? { step: \"probed\", url: state.url, probe: state.probe }\n : { step: \"url\", url: state.url };\n }),\n Match.exhaustive,\n );\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport default function AddMcpSource(props: {\n onComplete: (slug?: string) => void;\n onCancel: () => void;\n initialUrl?: string;\n initialPreset?: string;\n /** Whether the stdio transport is enabled on the server. */\n allowStdio?: boolean;\n}) {\n const allowStdio = props.allowStdio ?? false;\n const rawPreset = findPreset(props.initialPreset);\n // Drop stdio presets when stdio is disabled — the caller should have\n // already filtered these out, but defence-in-depth.\n const preset = rawPreset?.transport === \"stdio\" && !allowStdio ? undefined : rawPreset;\n const isStdioPreset = preset?.transport === \"stdio\";\n\n const [transport, setTransport] = useState<\"remote\" | \"stdio\">(\n isStdioPreset && allowStdio ? \"stdio\" : \"remote\",\n );\n\n // --- Stdio state ---\n const [stdioCommand, setStdioCommand] = useState(isStdioPreset ? preset.command : \"\");\n const [stdioArgs, setStdioArgs] = useState(\n isStdioPreset && preset.args ? preset.args.join(\" \") : \"\",\n );\n const [stdioEnv, setStdioEnv] = useState(\"\");\n const stdioIdentity = useIntegrationIdentity({\n fallbackName: isStdioPreset ? preset.name : stdioCommand,\n });\n const [stdioAdding, setStdioAdding] = useState(false);\n const [stdioError, setStdioError] = useState<string | null>(null);\n\n // --- Remote state ---\n const remoteUrl =\n !isStdioPreset && preset?.transport === undefined && preset?.url\n ? preset.url\n : (props.initialUrl ?? \"\");\n\n const [state, dispatch] = useReducer(\n reducer,\n remoteUrl ? { step: \"url\" as const, url: remoteUrl } : init,\n );\n\n const doProbe = useAtomSet(probeMcpEndpoint, { mode: \"promiseExit\" });\n const doAddServer = useAtomSet(addMcpServer, { mode: \"promiseExit\" });\n\n const probe = \"probe\" in state ? state.probe : null;\n\n // The probe seeds the method list: detected OAuth → an OAuth row; a 401\n // without OAuth metadata → a bearer-header row; an open server → a no-auth\n // row. The user can edit any row or add alternate methods alongside.\n const authMethodSeeds: readonly AuthMethodSeed[] = useMemo(() => {\n if (!probe) return [];\n if (probe.requiresOAuth) {\n return [\n {\n value: { kind: \"oauth\", authorizationUrl: \"\", tokenUrl: \"\", scopes: [] },\n label: \"Detected\",\n },\n ];\n }\n if (probe.requiresAuthentication) {\n return [\n {\n value: {\n kind: \"apikey\",\n placements: [{ carrier: \"header\", name: \"Authorization\", prefix: \"Bearer \" }],\n },\n label: \"Detected\",\n },\n ];\n }\n return [{ value: { kind: \"none\" }, label: \"Detected\" }];\n }, [probe]);\n const authMethodList = useAuthMethodList(authMethodSeeds);\n\n const remoteIdentity = useIntegrationIdentity({\n fallbackName:\n integrationDisplayNameFromUrl(state.url, \"MCP\") ?? probe?.serverName ?? probe?.name ?? \"\",\n });\n const isProbing = state.step === \"probing\";\n const isAdding = state.step === \"adding\";\n\n // Pre-empt the API's `IntegrationAlreadyExistsError`: adding an integration\n // whose slug already exists clobbers the existing one's connections/policies,\n // so the API blocks it. Surface that here from the tenant-scoped catalog list.\n // A blank derived namespace lets the server assign the slug, so only flag a\n // collision when the user-derived slug is non-empty.\n const remoteSlug = slugifyNamespace(remoteIdentity.namespace);\n const stdioSlug = slugifyNamespace(stdioIdentity.namespace);\n const remoteSlugExists = useSlugAlreadyExists(remoteSlug);\n const stdioSlugExists = useSlugAlreadyExists(stdioSlug);\n\n const canAdd = Boolean(probe) && !isAdding && !remoteSlugExists;\n // Probe failures are shown inline on the URL field; other failures\n // (add server) render in the bottom error block.\n const probeError = state.step === \"error\" && state.probe === null ? state.error : null;\n const otherError = state.step === \"error\" && state.probe !== null ? state.error : null;\n\n // ---- Remote actions ----\n\n const handleProbe = useCallback(async () => {\n dispatch({ type: \"probe-start\" });\n const exit = await doProbe({\n payload: { endpoint: state.url.trim() },\n });\n if (Exit.isFailure(exit)) {\n dispatch({\n type: \"probe-fail\",\n error: errorMessageFromExit(exit, \"Failed to connect\"),\n });\n return;\n }\n dispatch({ type: \"probe-ok\", probe: exit.value });\n }, [state.url, doProbe]);\n\n // Keep the latest handleProbe in a ref so the debounced effect can call it\n // without depending on its identity (which changes every render).\n const handleProbeRef = useRef(handleProbe);\n handleProbeRef.current = handleProbe;\n\n // Auto-probe whenever the URL changes (debounced) while we're on the\n // remote transport and not already probing/probed.\n useEffect(() => {\n if (transport !== \"remote\") return;\n if (state.step !== \"url\") return;\n const trimmed = state.url.trim();\n if (!trimmed) return;\n const handle = setTimeout(() => {\n handleProbeRef.current();\n }, 400);\n return () => clearTimeout(handle);\n }, [transport, state.step, state.url]);\n\n // Register the integration with the declared auth methods, returning the\n // assigned slug (or null on failure — an error is dispatched in that case).\n const registerIntegration = useCallback(\n async (authenticationTemplate: readonly McpAuthMethodInput[]): Promise<string | null> => {\n const displayName = remoteIdentity.name.trim() || probe?.serverName || probe?.name || \"MCP\";\n const slug = slugifyNamespace(remoteIdentity.namespace) || undefined;\n const exit = await doAddServer({\n payload: {\n transport: \"remote\" as const,\n name: displayName,\n endpoint: state.url.trim(),\n ...(slug ? { slug } : {}),\n authenticationTemplate,\n },\n reactivityKeys: integrationWriteKeys,\n });\n if (Exit.isFailure(exit)) {\n dispatch({\n type: \"add-fail\",\n error: addIntegrationErrorMessage(exit, slug ?? displayName, \"Failed to add server\"),\n });\n return null;\n }\n return exit.value.slug;\n },\n [doAddServer, probe, remoteIdentity, state.url],\n );\n\n const handleAddRemote = useCallback(async () => {\n if (!probe) return;\n dispatch({ type: \"add-start\" });\n // Every row registers as a declared method (a lone no-auth row registers\n // the open-server method). Slugs are assigned server-side by kind.\n const methods = authMethodList.rows.map((row: AuthMethodRow) =>\n mcpWireAuthInput(mcpAuthMethodInputFromEditorValue(row.value)),\n );\n const slug = await registerIntegration(\n methods.length > 0 ? methods : [{ kind: \"none\" as const }],\n );\n if (slug === null) return;\n props.onComplete(slug);\n }, [probe, authMethodList.rows, registerIntegration, props]);\n\n // ---- Stdio actions ----\n\n const parseStdioArgs = (raw: string): string[] => {\n if (!raw.trim()) return [];\n const args: string[] = [];\n const regex = /[^\\s\"]+|\"([^\"]*)\"/g;\n let match;\n while ((match = regex.exec(raw)) !== null) {\n args.push(match[1] ?? match[0]);\n }\n return args;\n };\n\n const parseStdioEnvValue = (raw: string): string => {\n const value = raw.trim();\n if (value.length < 2) return value;\n\n const quote = value[0];\n if ((quote !== '\"' && quote !== \"'\") || value[value.length - 1] !== quote) {\n return value;\n }\n\n const inner = value.slice(1, -1);\n if (quote === \"'\") return inner;\n\n return inner.replace(\n /\\\\([\\\\nrt\"])/g,\n (_, escaped: string) => STDIO_ENV_ESCAPE_REPLACEMENTS[escaped] ?? escaped,\n );\n };\n\n const parseStdioEnv = (raw: string): Record<string, string> | undefined => {\n if (!raw.trim()) return undefined;\n const env: Record<string, string> = {};\n for (const line of raw.split(\"\\n\")) {\n const eq = line.indexOf(\"=\");\n if (eq > 0) {\n env[line.slice(0, eq).trim()] = parseStdioEnvValue(line.slice(eq + 1));\n }\n }\n return Object.keys(env).length > 0 ? env : undefined;\n };\n\n const handleAddStdio = useCallback(async () => {\n const cmd = stdioCommand.trim();\n if (!cmd) return;\n setStdioAdding(true);\n setStdioError(null);\n const displayName = stdioIdentity.name.trim() || cmd;\n const slug = slugifyNamespace(stdioIdentity.namespace) || undefined;\n const exit = await doAddServer({\n payload: {\n transport: \"stdio\" as const,\n name: displayName,\n ...(slug ? { slug } : {}),\n command: cmd,\n args: parseStdioArgs(stdioArgs),\n env: parseStdioEnv(stdioEnv),\n },\n reactivityKeys: integrationWriteKeys,\n });\n if (Exit.isFailure(exit)) {\n setStdioError(addIntegrationErrorMessage(exit, slug ?? displayName, \"Failed to add server\"));\n setStdioAdding(false);\n return;\n }\n props.onComplete(exit.value.slug);\n }, [stdioCommand, stdioArgs, stdioEnv, stdioIdentity, doAddServer, props]);\n\n // ---- Render ----\n\n return (\n <div className=\"flex flex-1 flex-col gap-6\">\n <div>\n <h1 className=\"text-xl font-semibold text-foreground\">Add MCP Source</h1>\n <p className=\"mt-1 text-[13px] text-muted-foreground\">\n Connect to an MCP server to discover and use its tools.\n </p>\n </div>\n\n {/* Transport toggle — only shown when stdio is enabled server-side */}\n {allowStdio && (\n <div className=\"flex gap-1 rounded-lg border border-border bg-muted/30 p-1\">\n <Button\n variant=\"ghost\"\n type=\"button\"\n onClick={() => setTransport(\"remote\")}\n className={`flex-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors ${\n transport === \"remote\"\n ? \"bg-background text-foreground shadow-sm\"\n : \"text-muted-foreground hover:text-foreground\"\n }`}\n >\n Remote\n </Button>\n <Button\n variant=\"ghost\"\n type=\"button\"\n onClick={() => setTransport(\"stdio\")}\n className={`flex-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors ${\n transport === \"stdio\"\n ? \"bg-background text-foreground shadow-sm\"\n : \"text-muted-foreground hover:text-foreground\"\n }`}\n >\n Stdio\n </Button>\n </div>\n )}\n\n {transport === \"remote\" ? (\n <>\n <McpRemoteSourceFields\n url={state.url}\n onUrlChange={(url) => dispatch({ type: \"set-url\", url })}\n identity={remoteIdentity}\n preview={probe}\n probing={isProbing}\n error={probeError}\n onRetry={handleProbe}\n />\n\n {/* Authentication — declares the auth methods to register through the\n shared list editor. The credentials themselves (API key value /\n OAuth sign-in) are added from the integration's detail hub after\n adding. */}\n {probe && (\n <AuthMethodListEditor\n list={authMethodList}\n title=\"How does this server authenticate?\"\n oauthMetadata=\"discovered\"\n emptyHint=\"No methods declared. Add a method, or add the server without auth and connect from the integration page later.\"\n footerHint=\"Every method here is registered with the server. Connect an account from the integration page after adding.\"\n />\n )}\n\n {/* Error (add server). Probe errors show inline on the field. */}\n {otherError && (\n <div className=\"space-y-2\">\n <FormErrorAlert message={otherError} />\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => dispatch({ type: \"retry\" })}\n className=\"text-xs\"\n >\n Try again\n </Button>\n </div>\n )}\n\n {remoteSlugExists && !isAdding && <SlugCollisionAlert slug={remoteSlug} />}\n\n <FloatActions>\n <Button\n type=\"button\"\n variant=\"ghost\"\n onClick={() => props.onCancel()}\n disabled={isAdding}\n >\n Cancel\n </Button>\n {(probe || isProbing) && (\n <Button type=\"button\" onClick={handleAddRemote} disabled={!canAdd}>\n {isAdding ? (\n <>\n <Spinner className=\"size-3.5\" /> Adding…\n </>\n ) : (\n \"Add source\"\n )}\n </Button>\n )}\n </FloatActions>\n </>\n ) : (\n <>\n {/* Stdio form */}\n <CardStack>\n <CardStackContent className=\"border-t-0\">\n <CardStackEntryField\n label=\"Command\"\n description=\"- The executable to run (e.g. npx, uvx, node).\"\n >\n <Input\n value={stdioCommand}\n onChange={(e) => setStdioCommand((e.target as HTMLInputElement).value)}\n placeholder=\"npx\"\n className=\"font-mono text-sm\"\n />\n </CardStackEntryField>\n\n <CardStackEntryField\n label=\"Arguments\"\n description=\"- Space-separated arguments passed to the command.\"\n >\n <Input\n value={stdioArgs}\n onChange={(e) => setStdioArgs((e.target as HTMLInputElement).value)}\n placeholder=\"-y chrome-devtools-mcp@latest\"\n className=\"font-mono text-sm\"\n />\n </CardStackEntryField>\n\n <CardStackEntryField\n label=\"Environment variables\"\n description=\"- One per line, KEY=value format.\"\n >\n <Textarea\n value={stdioEnv}\n onChange={(e) => setStdioEnv((e.target as HTMLTextAreaElement).value)}\n placeholder={\"KEY=value\\nANOTHER=value\"}\n rows={3}\n maxRows={10}\n className=\"font-mono text-sm\"\n />\n </CardStackEntryField>\n </CardStackContent>\n </CardStack>\n\n <IntegrationIdentityFields identity={stdioIdentity} namePlaceholder=\"My MCP Server\" />\n\n {/* Stdio error */}\n {stdioError && <FormErrorAlert message={stdioError} />}\n\n {stdioSlugExists && !stdioAdding && <SlugCollisionAlert slug={stdioSlug} />}\n\n <FloatActions>\n <Button\n type=\"button\"\n variant=\"ghost\"\n onClick={() => props.onCancel()}\n disabled={stdioAdding}\n >\n Cancel\n </Button>\n <Button\n type=\"button\"\n onClick={handleAddStdio}\n disabled={!stdioCommand.trim() || stdioAdding || stdioSlugExists}\n >\n {stdioAdding ? (\n <>\n <Spinner className=\"size-3.5\" /> Adding…\n </>\n ) : (\n \"Add source\"\n )}\n </Button>\n </FloatActions>\n </>\n )}\n </div>\n );\n}\n","import { Badge } from \"@executor-js/react/components/badge\";\nimport {\n CardStack,\n CardStackContent,\n CardStackEntry,\n CardStackEntryActions,\n CardStackEntryContent,\n CardStackEntryDescription,\n CardStackEntryField,\n CardStackEntryMedia,\n CardStackEntryTitle,\n} from \"@executor-js/react/components/card-stack\";\nimport { FieldError } from \"@executor-js/react/components/field\";\nimport { Input } from \"@executor-js/react/components/input\";\nimport { Skeleton } from \"@executor-js/react/components/skeleton\";\nimport { IntegrationFavicon } from \"@executor-js/react/components/integration-favicon\";\nimport { IOSSpinner } from \"@executor-js/react/components/spinner\";\nimport { Button } from \"@executor-js/react/components/button\";\nimport {\n IntegrationIdentityFieldRows,\n type IntegrationIdentity,\n} from \"@executor-js/react/plugins/integration-identity\";\n\nexport type McpRemoteSourcePreview = {\n readonly name: string;\n readonly serverName: string | null;\n readonly connected: boolean;\n readonly requiresAuthentication: boolean;\n readonly requiresOAuth: boolean;\n readonly toolCount: number | null;\n};\n\nexport function McpRemoteSourceFields(props: {\n readonly url: string;\n readonly onUrlChange: (url: string) => void;\n readonly identity: IntegrationIdentity;\n readonly preview: McpRemoteSourcePreview | null;\n readonly probing?: boolean;\n readonly error?: string | null;\n readonly onRetry?: () => void;\n readonly namespaceReadOnly?: boolean;\n readonly urlDisabled?: boolean;\n}) {\n const previewDescription = props.preview\n ? props.preview.connected\n ? props.preview.toolCount === null\n ? null\n : `${props.preview.toolCount} tool${props.preview.toolCount !== 1 ? \"s\" : \"\"} available`\n : props.preview.requiresOAuth\n ? \"OAuth required to discover tools\"\n : props.preview.requiresAuthentication\n ? \"Authentication required to discover tools\"\n : \"Ready to add\"\n : null;\n\n if (props.preview) {\n return (\n <CardStack>\n <CardStackContent className=\"border-t-0\">\n <CardStackEntry>\n <CardStackEntryMedia>\n <IntegrationFavicon url={props.url} size={32} />\n </CardStackEntryMedia>\n <CardStackEntryContent>\n <CardStackEntryTitle>\n {props.preview.serverName ?? props.preview.name}\n </CardStackEntryTitle>\n {previewDescription ? (\n <CardStackEntryDescription>{previewDescription}</CardStackEntryDescription>\n ) : null}\n </CardStackEntryContent>\n <CardStackEntryActions>\n {props.preview.connected ? (\n <Badge\n variant=\"outline\"\n className=\"border-emerald-500/20 bg-emerald-500/10 text-[10px] text-emerald-600 dark:text-emerald-400\"\n >\n Connected\n </Badge>\n ) : props.preview.requiresOAuth ? (\n <Badge\n variant=\"outline\"\n className=\"border-amber-500/20 bg-amber-500/10 text-[10px] text-amber-600 dark:text-amber-400\"\n >\n OAuth required\n </Badge>\n ) : (\n <Badge\n variant=\"outline\"\n className=\"border-amber-500/20 bg-amber-500/10 text-[10px] text-amber-600 dark:text-amber-400\"\n >\n Auth required\n </Badge>\n )}\n </CardStackEntryActions>\n </CardStackEntry>\n <IntegrationIdentityFieldRows\n identity={props.identity}\n namePlaceholder=\"e.g. Linear\"\n namespaceReadOnly={props.namespaceReadOnly}\n />\n <CardStackEntryField label=\"Server URL\">\n <Input\n value={props.url}\n onChange={(e) => props.onUrlChange((e.target as HTMLInputElement).value)}\n placeholder=\"https://mcp.example.com\"\n className=\"w-full font-mono text-sm\"\n disabled={props.urlDisabled}\n />\n </CardStackEntryField>\n </CardStackContent>\n </CardStack>\n );\n }\n\n if (props.probing) {\n return (\n <CardStack>\n <CardStackContent className=\"border-t-0\">\n <CardStackEntry>\n <CardStackEntryMedia>\n <Skeleton className=\"size-4 rounded\" />\n </CardStackEntryMedia>\n <CardStackEntryContent>\n <Skeleton className=\"h-4 w-40\" />\n <Skeleton className=\"mt-1 h-3 w-32\" />\n </CardStackEntryContent>\n <CardStackEntryActions>\n <Skeleton className=\"h-4 w-20 rounded-full\" />\n </CardStackEntryActions>\n </CardStackEntry>\n </CardStackContent>\n </CardStack>\n );\n }\n\n return (\n <CardStack>\n <CardStackContent className=\"border-t-0\">\n <CardStackEntryField label=\"Server URL\">\n <div className=\"relative\">\n <Input\n value={props.url}\n onChange={(e) => props.onUrlChange((e.target as HTMLInputElement).value)}\n placeholder=\"https://mcp.example.com\"\n className=\"w-full pr-9 font-mono text-sm\"\n aria-invalid={props.error ? true : undefined}\n disabled={props.urlDisabled}\n />\n {props.probing && (\n <div className=\"pointer-events-none absolute right-2 top-1/2 -translate-y-1/2\">\n <IOSSpinner className=\"size-4\" />\n </div>\n )}\n </div>\n {props.error && (\n <div className=\"mt-2 space-y-2\">\n <FieldError>{props.error}</FieldError>\n {props.onRetry && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={props.onRetry}\n className=\"h-7 px-2 text-xs\"\n >\n Try again\n </Button>\n )}\n </div>\n )}\n </CardStackEntryField>\n </CardStackContent>\n </CardStack>\n );\n}\n"],"mappings":"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","names":["Button","CardStack","CardStackContent","CardStackEntryField","Input","jsx","jsxs","value","Button","CardStack","CardStackContent","CardStackEntryField","Input"]}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import {
|
|
2
|
+
configureMcpAuth,
|
|
3
|
+
editorValueFromMcpAuthMethod,
|
|
4
|
+
mcpAuthMethodInputFromEditorValue,
|
|
5
|
+
mcpServerAtom,
|
|
6
|
+
mcpWireAuthInput
|
|
7
|
+
} from "./chunk-3AOD4VAW.js";
|
|
8
|
+
import "./chunk-3H5Y7JCQ.js";
|
|
9
|
+
|
|
10
|
+
// src/react/EditMcpSource.tsx
|
|
11
|
+
import { useCallback, useMemo, useState } from "react";
|
|
12
|
+
import { useAtomValue, useAtomSet } from "@effect/atom-react";
|
|
13
|
+
import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
|
|
14
|
+
import * as Exit from "effect/Exit";
|
|
15
|
+
import { IntegrationSlug } from "@executor-js/sdk/shared";
|
|
16
|
+
import { apiKeyMethodLabel } from "@executor-js/sdk/http-auth";
|
|
17
|
+
import { integrationWriteKeys } from "@executor-js/react/api/reactivity-keys";
|
|
18
|
+
import {
|
|
19
|
+
AuthMethodListEditor,
|
|
20
|
+
useAuthMethodList
|
|
21
|
+
} from "@executor-js/react/components/auth-method-list-editor";
|
|
22
|
+
import { Button } from "@executor-js/react/components/button";
|
|
23
|
+
import {
|
|
24
|
+
CardStack,
|
|
25
|
+
CardStackContent,
|
|
26
|
+
CardStackEntry,
|
|
27
|
+
CardStackEntryContent,
|
|
28
|
+
CardStackEntryDescription,
|
|
29
|
+
CardStackEntryTitle
|
|
30
|
+
} from "@executor-js/react/components/card-stack";
|
|
31
|
+
import { Badge } from "@executor-js/react/components/badge";
|
|
32
|
+
import { FormErrorAlert } from "@executor-js/react/lib/integration-add";
|
|
33
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
34
|
+
var methodSeedLabel = (method) => {
|
|
35
|
+
if (method.kind === "oauth2") return "OAuth";
|
|
36
|
+
if (method.kind === "apikey") return apiKeyMethodLabel(method);
|
|
37
|
+
return "No authentication";
|
|
38
|
+
};
|
|
39
|
+
var samePlacements = (a, b) => {
|
|
40
|
+
const left = a ?? [];
|
|
41
|
+
const right = b ?? [];
|
|
42
|
+
if (left.length !== right.length) return false;
|
|
43
|
+
return left.every((placement, index) => {
|
|
44
|
+
const other = right[index];
|
|
45
|
+
return other !== void 0 && placement.carrier === other.carrier && placement.name === other.name && (placement.prefix ?? "") === (other.prefix ?? "") && (placement.variable ?? "") === (other.variable ?? "") && (placement.literal ?? null) === (other.literal ?? null);
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
function RemoteEdit(props) {
|
|
49
|
+
const { server } = props;
|
|
50
|
+
const doConfigureAuth = useAtomSet(configureMcpAuth, { mode: "promiseExit" });
|
|
51
|
+
const seeds = useMemo(
|
|
52
|
+
() => server.config.authenticationTemplate.map(
|
|
53
|
+
(method) => ({
|
|
54
|
+
value: editorValueFromMcpAuthMethod(method),
|
|
55
|
+
slug: method.slug,
|
|
56
|
+
label: methodSeedLabel(method)
|
|
57
|
+
})
|
|
58
|
+
),
|
|
59
|
+
[server.config.authenticationTemplate]
|
|
60
|
+
);
|
|
61
|
+
const list = useAuthMethodList(seeds);
|
|
62
|
+
const [saving, setSaving] = useState(false);
|
|
63
|
+
const [error, setError] = useState(null);
|
|
64
|
+
const editedMethods = useMemo(
|
|
65
|
+
() => list.rows.map((row) => {
|
|
66
|
+
const input = mcpAuthMethodInputFromEditorValue(row.value);
|
|
67
|
+
return row.seedSlug !== void 0 ? { ...input, slug: row.seedSlug } : input;
|
|
68
|
+
}),
|
|
69
|
+
[list.rows]
|
|
70
|
+
);
|
|
71
|
+
const methodsChanged = useMemo(() => {
|
|
72
|
+
const stored = server.config.authenticationTemplate;
|
|
73
|
+
if (editedMethods.length !== stored.length) return true;
|
|
74
|
+
return editedMethods.some((method, index) => {
|
|
75
|
+
const current = stored[index];
|
|
76
|
+
if (!current) return true;
|
|
77
|
+
if ((method.slug ?? "") !== current.slug) return true;
|
|
78
|
+
if (method.kind !== current.kind) return true;
|
|
79
|
+
if (method.kind === "apikey" && current.kind === "apikey") {
|
|
80
|
+
return !samePlacements(method.placements, current.placements);
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
});
|
|
84
|
+
}, [editedMethods, server.config.authenticationTemplate]);
|
|
85
|
+
const handleSave = useCallback(async () => {
|
|
86
|
+
setSaving(true);
|
|
87
|
+
setError(null);
|
|
88
|
+
const exit = await doConfigureAuth({
|
|
89
|
+
params: { slug: server.slug },
|
|
90
|
+
payload: {
|
|
91
|
+
authenticationTemplate: editedMethods.length > 0 ? editedMethods.map(mcpWireAuthInput) : [{ kind: "none" }],
|
|
92
|
+
mode: "replace"
|
|
93
|
+
},
|
|
94
|
+
reactivityKeys: integrationWriteKeys
|
|
95
|
+
});
|
|
96
|
+
if (Exit.isFailure(exit)) {
|
|
97
|
+
setError("Failed to update authentication methods");
|
|
98
|
+
setSaving(false);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
setSaving(false);
|
|
102
|
+
}, [doConfigureAuth, editedMethods, server.slug]);
|
|
103
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
104
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
105
|
+
/* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-foreground", children: "Edit MCP Source" }),
|
|
106
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "Manage how this MCP server authenticates. The endpoint is part of the server's identity \u2014 remove and re-add to change it. Accounts are added from the integration page." })
|
|
107
|
+
] }),
|
|
108
|
+
/* @__PURE__ */ jsx(CardStack, { children: /* @__PURE__ */ jsx(CardStackContent, { className: "border-t-0", children: /* @__PURE__ */ jsxs(CardStackEntry, { children: [
|
|
109
|
+
/* @__PURE__ */ jsxs(CardStackEntryContent, { children: [
|
|
110
|
+
/* @__PURE__ */ jsx(CardStackEntryTitle, { children: server.description || String(server.slug) }),
|
|
111
|
+
/* @__PURE__ */ jsx(CardStackEntryDescription, { className: "font-mono text-xs", children: server.config.endpoint })
|
|
112
|
+
] }),
|
|
113
|
+
/* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-xs", children: "remote" })
|
|
114
|
+
] }) }) }),
|
|
115
|
+
/* @__PURE__ */ jsx(
|
|
116
|
+
AuthMethodListEditor,
|
|
117
|
+
{
|
|
118
|
+
list,
|
|
119
|
+
title: "How does this server authenticate?",
|
|
120
|
+
oauthMetadata: "discovered",
|
|
121
|
+
emptyHint: "No methods declared. Add one, or save to mark this server as open (no authentication).",
|
|
122
|
+
footerHint: "Connections pick one of these methods. Removing a method detaches connections created against it."
|
|
123
|
+
}
|
|
124
|
+
),
|
|
125
|
+
methodsChanged ? /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", onClick: () => void handleSave(), disabled: saving, children: saving ? "Saving\u2026" : "Save authentication methods" }) }) : null,
|
|
126
|
+
error && /* @__PURE__ */ jsx(FormErrorAlert, { message: error }),
|
|
127
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-end border-t border-border pt-4", children: /* @__PURE__ */ jsx(Button, { onClick: props.onSave, children: "Done" }) })
|
|
128
|
+
] });
|
|
129
|
+
}
|
|
130
|
+
function StdioReadOnly(props) {
|
|
131
|
+
const { command, args } = props.server.config;
|
|
132
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
133
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
134
|
+
/* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-foreground", children: "Edit MCP Source" }),
|
|
135
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "Stdio MCP sources cannot be edited in the UI. Remove and recreate the source with the updated command." })
|
|
136
|
+
] }),
|
|
137
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-lg border border-border bg-card px-4 py-3", children: [
|
|
138
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
139
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-semibold text-card-foreground", children: String(props.server.slug) }),
|
|
140
|
+
/* @__PURE__ */ jsxs("p", { className: "mt-0.5 text-xs text-muted-foreground font-mono", children: [
|
|
141
|
+
command,
|
|
142
|
+
" ",
|
|
143
|
+
(args ?? []).join(" ")
|
|
144
|
+
] })
|
|
145
|
+
] }),
|
|
146
|
+
/* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-xs", children: "stdio" })
|
|
147
|
+
] }),
|
|
148
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-end border-t border-border pt-4", children: /* @__PURE__ */ jsx(Button, { onClick: props.onSave, children: "Done" }) })
|
|
149
|
+
] });
|
|
150
|
+
}
|
|
151
|
+
function EditMcpSource({
|
|
152
|
+
sourceId,
|
|
153
|
+
onSave
|
|
154
|
+
}) {
|
|
155
|
+
const slug = IntegrationSlug.make(sourceId);
|
|
156
|
+
const serverResult = useAtomValue(mcpServerAtom(slug));
|
|
157
|
+
const server = AsyncResult.isSuccess(serverResult) ? serverResult.value : null;
|
|
158
|
+
if (!AsyncResult.isSuccess(serverResult) || server === null) {
|
|
159
|
+
return /* @__PURE__ */ jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsxs("div", { children: [
|
|
160
|
+
/* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-foreground", children: "Edit MCP Source" }),
|
|
161
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "Loading configuration\u2026" })
|
|
162
|
+
] }) });
|
|
163
|
+
}
|
|
164
|
+
if (server.config.transport === "stdio") {
|
|
165
|
+
return /* @__PURE__ */ jsx(
|
|
166
|
+
StdioReadOnly,
|
|
167
|
+
{
|
|
168
|
+
server,
|
|
169
|
+
onSave
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
return /* @__PURE__ */ jsx(RemoteEdit, { server, onSave });
|
|
174
|
+
}
|
|
175
|
+
export {
|
|
176
|
+
EditMcpSource as default
|
|
177
|
+
};
|
|
178
|
+
//# sourceMappingURL=EditMcpSource-75NJRWZR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/react/EditMcpSource.tsx"],"sourcesContent":["import { useCallback, useMemo, useState } from \"react\";\nimport { useAtomValue, useAtomSet } from \"@effect/atom-react\";\nimport * as AsyncResult from \"effect/unstable/reactivity/AsyncResult\";\nimport * as Exit from \"effect/Exit\";\n\nimport { IntegrationSlug } from \"@executor-js/sdk/shared\";\nimport { apiKeyMethodLabel, type AuthPlacement } from \"@executor-js/sdk/http-auth\";\nimport { integrationWriteKeys } from \"@executor-js/react/api/reactivity-keys\";\nimport {\n AuthMethodListEditor,\n useAuthMethodList,\n type AuthMethodRow,\n type AuthMethodSeed,\n} from \"@executor-js/react/components/auth-method-list-editor\";\nimport { Button } from \"@executor-js/react/components/button\";\nimport {\n CardStack,\n CardStackContent,\n CardStackEntry,\n CardStackEntryContent,\n CardStackEntryDescription,\n CardStackEntryTitle,\n} from \"@executor-js/react/components/card-stack\";\nimport { Badge } from \"@executor-js/react/components/badge\";\nimport { FormErrorAlert } from \"@executor-js/react/lib/integration-add\";\n\nimport { configureMcpAuth, mcpServerAtom } from \"./atoms\";\nimport type {\n McpAuthMethod,\n McpCanonicalAuthMethodInput,\n McpIntegrationConfig,\n} from \"../sdk/types\";\nimport {\n editorValueFromMcpAuthMethod,\n mcpAuthMethodInputFromEditorValue,\n mcpWireAuthInput,\n} from \"./auth-method-config\";\n\ntype McpServer = {\n readonly slug: IntegrationSlug;\n readonly description: string;\n readonly kind: string;\n readonly canRemove: boolean;\n readonly canRefresh: boolean;\n readonly config: McpIntegrationConfig;\n};\n\ntype McpRemoteConfig = Extract<McpIntegrationConfig, { transport: \"remote\" }>;\n\nconst methodSeedLabel = (method: McpAuthMethod): string => {\n if (method.kind === \"oauth2\") return \"OAuth\";\n if (method.kind === \"apikey\") return apiKeyMethodLabel(method);\n return \"No authentication\";\n};\n\nconst samePlacements = (\n a: readonly AuthPlacement[] | undefined,\n b: readonly AuthPlacement[] | undefined,\n): boolean => {\n const left = a ?? [];\n const right = b ?? [];\n if (left.length !== right.length) return false;\n return left.every((placement: AuthPlacement, index: number) => {\n const other = right[index];\n return (\n other !== undefined &&\n placement.carrier === other.carrier &&\n placement.name === other.name &&\n (placement.prefix ?? \"\") === (other.prefix ?? \"\") &&\n (placement.variable ?? \"\") === (other.variable ?? \"\") &&\n (placement.literal ?? null) === (other.literal ?? null)\n );\n });\n};\n\n// ---------------------------------------------------------------------------\n// Remote edit — v2: the integration's endpoint is part of its identity\n// (opaque-to-core config); the editable surface is the declared auth-method\n// LIST, through the same shared editor as the add flow. Accounts (credentials)\n// are managed from the integration page's accounts hub.\n// ---------------------------------------------------------------------------\n\nfunction RemoteEdit(props: {\n server: McpServer & { config: McpRemoteConfig };\n onSave: () => void;\n}) {\n const { server } = props;\n const doConfigureAuth = useAtomSet(configureMcpAuth, { mode: \"promiseExit\" });\n\n const seeds = useMemo<readonly AuthMethodSeed[]>(\n () =>\n server.config.authenticationTemplate.map(\n (method: McpAuthMethod): AuthMethodSeed => ({\n value: editorValueFromMcpAuthMethod(method),\n slug: method.slug,\n label: methodSeedLabel(method),\n }),\n ),\n [server.config.authenticationTemplate],\n );\n const list = useAuthMethodList(seeds);\n\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // The edited methods, slugs preserved for seeded rows so existing\n // connections (bound by template slug) stay attached. New rows omit the\n // slug — the backend assigns kind-based ones.\n const editedMethods = useMemo<readonly McpCanonicalAuthMethodInput[]>(\n () =>\n list.rows.map((row: AuthMethodRow): McpCanonicalAuthMethodInput => {\n const input = mcpAuthMethodInputFromEditorValue(row.value);\n return row.seedSlug !== undefined ? { ...input, slug: row.seedSlug } : input;\n }),\n [list.rows],\n );\n\n const methodsChanged = useMemo(() => {\n const stored = server.config.authenticationTemplate;\n if (editedMethods.length !== stored.length) return true;\n return editedMethods.some((method: McpCanonicalAuthMethodInput, index: number) => {\n const current = stored[index];\n if (!current) return true;\n if ((method.slug ?? \"\") !== current.slug) return true;\n if (method.kind !== current.kind) return true;\n if (method.kind === \"apikey\" && current.kind === \"apikey\") {\n return !samePlacements(method.placements, current.placements);\n }\n return false;\n });\n }, [editedMethods, server.config.authenticationTemplate]);\n\n const handleSave = useCallback(async () => {\n setSaving(true);\n setError(null);\n const exit = await doConfigureAuth({\n params: { slug: server.slug },\n payload: {\n authenticationTemplate:\n editedMethods.length > 0\n ? editedMethods.map(mcpWireAuthInput)\n : [{ kind: \"none\" as const }],\n mode: \"replace\",\n },\n reactivityKeys: integrationWriteKeys,\n });\n if (Exit.isFailure(exit)) {\n setError(\"Failed to update authentication methods\");\n setSaving(false);\n return;\n }\n setSaving(false);\n }, [doConfigureAuth, editedMethods, server.slug]);\n\n return (\n <div className=\"space-y-6\">\n <div>\n <h1 className=\"text-xl font-semibold text-foreground\">Edit MCP Source</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n Manage how this MCP server authenticates. The endpoint is part of the server's identity —\n remove and re-add to change it. Accounts are added from the integration page.\n </p>\n </div>\n\n <CardStack>\n <CardStackContent className=\"border-t-0\">\n <CardStackEntry>\n <CardStackEntryContent>\n <CardStackEntryTitle>{server.description || String(server.slug)}</CardStackEntryTitle>\n <CardStackEntryDescription className=\"font-mono text-xs\">\n {server.config.endpoint}\n </CardStackEntryDescription>\n </CardStackEntryContent>\n <Badge variant=\"secondary\" className=\"text-xs\">\n remote\n </Badge>\n </CardStackEntry>\n </CardStackContent>\n </CardStack>\n\n <AuthMethodListEditor\n list={list}\n title=\"How does this server authenticate?\"\n oauthMetadata=\"discovered\"\n emptyHint=\"No methods declared. Add one, or save to mark this server as open (no authentication).\"\n footerHint=\"Connections pick one of these methods. Removing a method detaches connections created against it.\"\n />\n\n {methodsChanged ? (\n <div className=\"flex justify-end\">\n <Button type=\"button\" size=\"sm\" onClick={() => void handleSave()} disabled={saving}>\n {saving ? \"Saving…\" : \"Save authentication methods\"}\n </Button>\n </div>\n ) : null}\n\n {error && <FormErrorAlert message={error} />}\n\n <div className=\"flex items-center justify-end border-t border-border pt-4\">\n <Button onClick={props.onSave}>Done</Button>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Stdio read-only view\n// ---------------------------------------------------------------------------\n\nfunction StdioReadOnly(props: {\n server: McpServer & { config: Extract<McpIntegrationConfig, { transport: \"stdio\" }> };\n onSave: () => void;\n}) {\n const { command, args } = props.server.config;\n return (\n <div className=\"space-y-6\">\n <div>\n <h1 className=\"text-xl font-semibold text-foreground\">Edit MCP Source</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n Stdio MCP sources cannot be edited in the UI. Remove and recreate the source with the\n updated command.\n </p>\n </div>\n\n <div className=\"flex items-center gap-3 rounded-lg border border-border bg-card px-4 py-3\">\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-semibold text-card-foreground\">\n {String(props.server.slug)}\n </p>\n <p className=\"mt-0.5 text-xs text-muted-foreground font-mono\">\n {command} {(args ?? []).join(\" \")}\n </p>\n </div>\n <Badge variant=\"secondary\" className=\"text-xs\">\n stdio\n </Badge>\n </div>\n\n <div className=\"flex items-center justify-end border-t border-border pt-4\">\n <Button onClick={props.onSave}>Done</Button>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Main component — `sourceId` is the integration slug (v2).\n// ---------------------------------------------------------------------------\n\nexport default function EditMcpSource({\n sourceId,\n onSave,\n}: {\n readonly sourceId: string;\n readonly onSave: () => void;\n}) {\n const slug = IntegrationSlug.make(sourceId);\n const serverResult = useAtomValue(mcpServerAtom(slug));\n const server = AsyncResult.isSuccess(serverResult) ? serverResult.value : null;\n\n if (!AsyncResult.isSuccess(serverResult) || server === null) {\n return (\n <div className=\"space-y-6\">\n <div>\n <h1 className=\"text-xl font-semibold text-foreground\">Edit MCP Source</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">Loading configuration…</p>\n </div>\n </div>\n );\n }\n\n if (server.config.transport === \"stdio\") {\n return (\n <StdioReadOnly\n server={\n server as McpServer & { config: Extract<McpIntegrationConfig, { transport: \"stdio\" }> }\n }\n onSave={onSave}\n />\n );\n }\n\n return <RemoteEdit server={server as McpServer & { config: McpRemoteConfig }} onSave={onSave} />;\n}\n"],"mappings":"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","names":[]}
|