diff --git a/packages/plugins/google-discovery/src/react/AddGoogleDiscoverySource.tsx b/packages/plugins/google-discovery/src/react/AddGoogleDiscoverySource.tsx
index 6d9491f53..ee6ab4071 100644
--- a/packages/plugins/google-discovery/src/react/AddGoogleDiscoverySource.tsx
+++ b/packages/plugins/google-discovery/src/react/AddGoogleDiscoverySource.tsx
@@ -7,7 +7,7 @@ import * as Schema from "effect/Schema";
import { sourceWriteKeys } from "@executor-js/react/api/reactivity-keys";
import { useScope, useUserScope } from "@executor-js/react/api/scope-context";
import type { SecretPickerSecret } from "@executor-js/react/plugins/secret-picker";
-import { CreatableSecretPicker } from "@executor-js/react/plugins/secret-header-auth";
+import { CreatableSecretPicker } from "@executor-js/react/plugins/creatable-secret-picker";
import { useSecretPickerSecrets } from "@executor-js/react/plugins/use-secret-picker-secrets";
import type { ScopeId } from "@executor-js/sdk";
import { Badge } from "@executor-js/react/components/badge";
diff --git a/packages/plugins/graphql/src/react/AddGraphqlSource.tsx b/packages/plugins/graphql/src/react/AddGraphqlSource.tsx
index 8d2ea5e97..3e076f693 100644
--- a/packages/plugins/graphql/src/react/AddGraphqlSource.tsx
+++ b/packages/plugins/graphql/src/react/AddGraphqlSource.tsx
@@ -7,7 +7,7 @@ import * as Schema from "effect/Schema";
import { useScope } from "@executor-js/react/api/scope-context";
import { sourceWriteKeys } from "@executor-js/react/api/reactivity-keys";
import {
- HttpCredentialsEditor,
+ HttpCredentials,
httpCredentialsValid,
serializeScopedHttpCredentials,
serializeHttpCredentials,
@@ -177,7 +177,7 @@ export default function AddGraphqlSource(props: {
-
+ >
+
+
+
{/* Temporarily hidden while we revisit GraphQL OAuth discovery and UX. */}
diff --git a/packages/plugins/graphql/src/react/EditGraphqlSource.tsx b/packages/plugins/graphql/src/react/EditGraphqlSource.tsx
index a57cc5acd..199f23742 100644
--- a/packages/plugins/graphql/src/react/EditGraphqlSource.tsx
+++ b/packages/plugins/graphql/src/react/EditGraphqlSource.tsx
@@ -12,7 +12,7 @@ import { useScope, useScopeStack } from "@executor-js/react/api/scope-context";
import { connectionWriteKeys, sourceWriteKeys } from "@executor-js/react/api/reactivity-keys";
import { useSecretPickerSecrets } from "@executor-js/react/plugins/use-secret-picker-secrets";
import {
- HttpCredentialsEditor,
+ HttpCredentials,
serializeHttpCredentials,
serializeScopedHttpCredentials,
type HttpCredentialsState,
@@ -191,7 +191,7 @@ function EditForm(props: {
namespaceReadOnly
/>
-
+ >
+
+
+
{/* Temporarily hidden while we revisit GraphQL OAuth discovery and UX. */}
diff --git a/packages/plugins/mcp/src/react/AddMcpSource.tsx b/packages/plugins/mcp/src/react/AddMcpSource.tsx
index 043ce4395..36153bc57 100644
--- a/packages/plugins/mcp/src/react/AddMcpSource.tsx
+++ b/packages/plugins/mcp/src/react/AddMcpSource.tsx
@@ -1,4 +1,4 @@
-import { useReducer, useCallback, useEffect, useRef, useState, type ReactNode } from "react";
+import { useReducer, useCallback, useEffect, useRef, useState } from "react";
import { useAtomSet } from "@effect/atom-react";
import * as Exit from "effect/Exit";
import * as Match from "effect/Match";
@@ -10,20 +10,18 @@ import { Button } from "@executor-js/react/components/button";
import {
CardStack,
CardStackContent,
- CardStackEntry,
CardStackEntryField,
} from "@executor-js/react/components/card-stack";
import { FieldLabel } from "@executor-js/react/components/field";
import { FilterTabs } from "@executor-js/react/components/filter-tabs";
import { FloatActions } from "@executor-js/react/components/float-actions";
import { Input } from "@executor-js/react/components/input";
-import { Label } from "@executor-js/react/components/label";
import { Spinner } from "@executor-js/react/components/spinner";
import { Textarea } from "@executor-js/react/components/textarea";
import {
emptyHttpCredentials,
+ HttpCredentials,
httpCredentialsValid,
- HttpCredentialsEditor,
serializeScopedHttpCredentials,
serializeHttpCredentials,
} from "@executor-js/react/plugins/http-credentials";
@@ -40,11 +38,8 @@ import {
useOAuthPopupFlow,
type OAuthCompletionPayload,
} from "@executor-js/react/plugins/oauth-sign-in";
-import {
- CredentialControlField,
- CredentialUsageRow,
- useCredentialTargetScope,
-} from "@executor-js/react/plugins/credential-target-scope";
+import { useCredentialTargetScope } from "@executor-js/react/plugins/credential-target-scope";
+import { OAuthConnectionControl } from "@executor-js/react/plugins/source-oauth-connection";
type RemoteAuthMode = "none" | "oauth2";
import { sourceWriteKeys } from "@executor-js/react/api/reactivity-keys";
@@ -87,11 +82,6 @@ type ProbeResult = {
serverName: string | null;
};
-type PlainHeader = {
- name: string;
- value: string;
-};
-
type State =
| { step: "url"; url: string }
| { step: "probing"; url: string; probe: ProbeResult | null }
@@ -306,7 +296,6 @@ export default function AddMcpSource(props: {
});
const [remoteAuthMode, setRemoteAuthMode] = useState("none");
- const [remoteHeaders, setRemoteHeaders] = useState([]);
const [remoteCredentials, setRemoteCredentials] = useState(() => emptyHttpCredentials());
const probe = "probe" in state ? state.probe : null;
@@ -321,18 +310,10 @@ export default function AddMcpSource(props: {
const isOAuthBusy =
state.step === "oauth-starting" || state.step === "oauth-waiting" || oauth.busy;
const canUseNone = probe?.requiresOAuth !== true || probe.supportsDynamicRegistration === false;
- const remoteHeadersComplete = remoteHeaders.every(
- (header) => header.name.trim() && header.value.trim(),
- );
const remoteCredentialsComplete = httpCredentialsValid(remoteCredentials);
const authReady = remoteAuthMode === "none" ? canUseNone : tokens !== null;
const canAdd =
- Boolean(probe) &&
- authReady &&
- remoteHeadersComplete &&
- remoteCredentialsComplete &&
- !isAdding &&
- !isOAuthBusy;
+ Boolean(probe) && authReady && remoteCredentialsComplete && !isAdding && !isOAuthBusy;
// Probe failures are shown inline on the URL field; other failures
// (OAuth start, add source) render in the bottom error block.
const probeError = state.step === "error" && state.probe === null ? state.error : null;
@@ -442,19 +423,10 @@ export default function AddMcpSource(props: {
connectionSlot: MCP_OAUTH_CONNECTION_SLOT,
}
: { kind: "none" as const };
- const headers = Object.fromEntries(
- remoteHeaders
- .map((header) => [header.name.trim(), header.value.trim()] as const)
- .filter(([name, value]) => name && value),
- );
const credentials = serializeScopedHttpCredentials(
remoteCredentials,
requestCredentialTargetScope,
);
- const remoteRequestHeaders: Record = {
- ...headers,
- ...credentials.headers,
- };
const displayName = remoteIdentity.name.trim() || probe.serverName || probe.name;
const slugNamespace = slugifyNamespace(remoteIdentity.namespace);
const exit = await doAdd({
@@ -470,7 +442,9 @@ export default function AddMcpSource(props: {
remoteAuthMode === "oauth2" && tokens
? oauthCredentialTargetScope
: requestCredentialTargetScope,
- ...(Object.keys(remoteRequestHeaders).length > 0 ? { headers: remoteRequestHeaders } : {}),
+ ...(Object.keys(credentials.headers).length > 0
+ ? { headers: credentials.headers as Record }
+ : {}),
...(Object.keys(credentials.queryParams).length > 0
? { queryParams: credentials.queryParams }
: {}),
@@ -488,7 +462,6 @@ export default function AddMcpSource(props: {
}, [
probe,
remoteAuthMode,
- remoteHeaders,
remoteCredentials,
remoteIdentity,
tokens,
@@ -606,7 +579,7 @@ export default function AddMcpSource(props: {
onRetry={handleProbe}
/>
-
+ >
+
+
+
{/* Authentication */}
{probe && (
@@ -640,187 +612,42 @@ export default function AddMcpSource(props: {
{remoteAuthMode === "oauth2" && (
- {
+ {
setOAuthCredentialTargetScope(targetScope);
dispatch({ type: "oauth-reset" });
}}
- label="Connection saved to"
- help="Choose who can use the OAuth connection."
- >
-
- {!tokens &&
- state.step === "probed" &&
- (probe.supportsDynamicRegistration ? (
-
- ) : (
-
- 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.
-