@@ -126,11 +152,37 @@ function AddSecretDialogContent(props: {
-
-
-
+
+
+
+
+
+
+ Scope
+ setTargetScope(ScopeId.make(value))}
+ >
+
+
+
+
+ {props.scopeOptions.map((option) => (
+
+ {option.label}
+
+ ))}
+
+
+
-
@@ -273,12 +325,21 @@ export function SecretsPage(props: {
const existingSecretIds = useMemo(
() =>
AsyncResult.match(secrets, {
- onInitial: () => [] as string[],
- onFailure: () => [] as string[],
- onSuccess: ({ value }) => value.map((secret) => secret.id),
+ onInitial: () => [] as { readonly id: string; readonly scopeId: ScopeId }[],
+ onFailure: () => [] as { readonly id: string; readonly scopeId: ScopeId }[],
+ onSuccess: ({ value }) =>
+ value.map((secret) => ({ id: secret.id, scopeId: secret.scopeId })),
}),
[secrets],
);
+ const scopeOptions = useMemo(
+ () =>
+ scopeStack.map((entry, index) => ({
+ value: entry.id,
+ label: index === 0 ? "Personal" : entry.name || "Organization",
+ })),
+ [scopeStack],
+ );
const doRemove = useAtomSet(removeSecretOptimistic(scopeId), {
mode: "promiseExit",
});
@@ -414,8 +475,9 @@ export function SecretsPage(props: {
onOpenChange={setAddOpen}
description={addSecretDescription}
storageOptions={storageOptions}
- existingSecretIds={existingSecretIds}
+ existingSecrets={existingSecretIds}
scopeId={formScopeId}
+ scopeOptions={scopeOptions}
prefill={props.prefill}
/>
From 01e8fd1dfffbd6fb5cd28475acb2fa2a2d5737f5 Mon Sep 17 00:00:00 2001
From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
Date: Tue, 19 May 2026 00:36:00 -0700
Subject: [PATCH 11/15] fix: explain secret handoff completion
---
packages/core/sdk/src/core-tools.ts | 8 +++++++-
packages/core/sdk/src/executor.test.ts | 6 +++++-
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/packages/core/sdk/src/core-tools.ts b/packages/core/sdk/src/core-tools.ts
index d0e51e5bf..9d2e7ab5c 100644
--- a/packages/core/sdk/src/core-tools.ts
+++ b/packages/core/sdk/src/core-tools.ts
@@ -58,6 +58,7 @@ const SecretsCreateInput = Schema.Struct({
const SecretsCreateOutput = Schema.Struct({
id: Schema.String,
url: Schema.String,
+ instructions: Schema.String,
});
const SecretPointerInput = Schema.Struct({
@@ -557,7 +558,12 @@ export const coreToolsPlugin = definePlugin((options: CoreToolsPluginOptions = {
url.searchParams.set("name", input.name);
url.searchParams.set("secretId", secretId);
if (input.provider) url.searchParams.set("provider", input.provider);
- return { id: secretId, url: url.toString() };
+ return {
+ id: secretId,
+ url: url.toString(),
+ instructions:
+ "The user needs to open this URL and set the secret value in the browser. Until the user saves the value there, this secret is only a placeholder and will not be available for binding. After the user saves it, call secrets.status for this id before using it in source configuration.",
+ };
}).pipe(
Effect.catchTags({
CoreToolsConfigurationError: ({ message }) =>
diff --git a/packages/core/sdk/src/executor.test.ts b/packages/core/sdk/src/executor.test.ts
index d6cf3227f..e7a6ecb53 100644
--- a/packages/core/sdk/src/executor.test.ts
+++ b/packages/core/sdk/src/executor.test.ts
@@ -557,7 +557,11 @@ describe("createExecutor", () => {
provider: "memory",
});
- expect(result).toMatchObject({ id: expect.any(String), url: expect.any(String) });
+ expect(result).toMatchObject({
+ id: expect.any(String),
+ url: expect.any(String),
+ instructions: expect.stringContaining("placeholder"),
+ });
const url = new URL((result as { readonly url: string }).url);
expect(url.origin).toBe("http://executor.test");
expect(url.pathname).toBe("/secrets");
From ab6b2a4c7c661740a2daf744f7a990705877f69f Mon Sep 17 00:00:00 2001
From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
Date: Tue, 19 May 2026 00:39:51 -0700
Subject: [PATCH 12/15] fix: explain oauth handoff completion
---
packages/core/sdk/src/core-tools.ts | 10 +++++++++-
packages/core/sdk/src/executor.test.ts | 2 ++
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/packages/core/sdk/src/core-tools.ts b/packages/core/sdk/src/core-tools.ts
index 9d2e7ab5c..9b597109d 100644
--- a/packages/core/sdk/src/core-tools.ts
+++ b/packages/core/sdk/src/core-tools.ts
@@ -283,6 +283,7 @@ const OAuthStartOutput = Schema.Struct({
sessionId: Schema.String,
authorizationUrl: Schema.NullOr(Schema.String),
completedConnection: Schema.NullOr(Schema.Struct({ connectionId: Schema.String })),
+ instructions: Schema.String,
});
const OAuthCancelInput = Schema.Struct({
@@ -932,7 +933,7 @@ export const coreToolsPlugin = definePlugin((options: CoreToolsPluginOptions = {
Effect.gen(function* () {
const webBaseUrl = yield* requireWebBaseUrl(options.webBaseUrl);
const tokenScope = yield* resolveScopeInput(ctx.scopes, input.scope);
- return yield* ctx.oauth.start({
+ const result = yield* ctx.oauth.start({
endpoint: input.endpoint,
headers: input.headers,
queryParams: input.queryParams,
@@ -943,6 +944,13 @@ export const coreToolsPlugin = definePlugin((options: CoreToolsPluginOptions = {
pluginId: input.pluginId,
identityLabel: input.identityLabel,
});
+ return {
+ ...result,
+ instructions:
+ result.authorizationUrl === null
+ ? "This OAuth flow completed without a browser handoff. Call connections.list to verify the connection id, then pass that connection id to the relevant source configuration tool."
+ : "The user needs to open this authorization URL in a browser and complete the OAuth/sign-in flow. Until the browser callback completes, no connection is available for binding. After the user finishes sign-in, call connections.list to find the connection id, then pass that connection id to the relevant source configuration tool.",
+ };
}).pipe(
Effect.catchTags({
CoreToolsConfigurationError: ({ message }) =>
diff --git a/packages/core/sdk/src/executor.test.ts b/packages/core/sdk/src/executor.test.ts
index e7a6ecb53..e663640e9 100644
--- a/packages/core/sdk/src/executor.test.ts
+++ b/packages/core/sdk/src/executor.test.ts
@@ -768,6 +768,7 @@ describe("createExecutor", () => {
expect(started).toMatchObject({
authorizationUrl: null,
completedConnection: { connectionId: "agent-oauth" },
+ instructions: expect.stringContaining("completed without a browser handoff"),
});
const listed = yield* executor.tools.invoke("executor.coreTools.connections.list", {});
@@ -864,6 +865,7 @@ describe("createExecutor", () => {
expect(started).toMatchObject({
authorizationUrl: expect.stringContaining(oauthServer.authorizationEndpoint),
completedConnection: null,
+ instructions: expect.stringContaining("open this authorization URL"),
});
const authorizationUrl = (started as { authorizationUrl: string }).authorizationUrl;
From 6cdf3b8e02b5bacbe473d96782d97b57a1d8ca4e Mon Sep 17 00:00:00 2001
From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
Date: Tue, 19 May 2026 00:44:07 -0700
Subject: [PATCH 13/15] fix: clarify oauth credential scope
---
packages/core/sdk/src/core-tools.ts | 16 ++++++++--------
packages/core/sdk/src/executor.test.ts | 8 ++++++--
.../plugins/google-discovery/src/sdk/plugin.ts | 4 ++--
packages/plugins/graphql/src/sdk/plugin.ts | 2 +-
packages/plugins/mcp/src/sdk/plugin.ts | 4 ++--
packages/plugins/openapi/src/sdk/plugin.ts | 2 +-
6 files changed, 20 insertions(+), 16 deletions(-)
diff --git a/packages/core/sdk/src/core-tools.ts b/packages/core/sdk/src/core-tools.ts
index 9b597109d..612f9d3d0 100644
--- a/packages/core/sdk/src/core-tools.ts
+++ b/packages/core/sdk/src/core-tools.ts
@@ -268,7 +268,7 @@ const OAuthProbeOutput = Schema.Struct({
});
const OAuthStartInput = Schema.Struct({
- scope: Schema.String,
+ credentialScope: Schema.optional(Schema.String),
endpoint: Schema.String,
connectionId: Schema.String,
pluginId: Schema.String,
@@ -287,7 +287,7 @@ const OAuthStartOutput = Schema.Struct({
});
const OAuthCancelInput = Schema.Struct({
- scope: Schema.String,
+ credentialScope: Schema.optional(Schema.String),
sessionId: Schema.String,
});
@@ -926,13 +926,13 @@ export const coreToolsPlugin = definePlugin((options: CoreToolsPluginOptions = {
tool({
name: "oauth.start",
description:
- "Start an OAuth flow and return the authorization URL the user must open in a browser. Never put OAuth passwords, authorization codes, or client secrets in chat. For confidential clients, first call `secrets.create` for client id/secret and pass those secret ids in the strategy. After the browser callback completes, call `connections.list`, then configure the source with the returned connection id.",
+ "Start an OAuth flow and return the authorization URL the user must open in a browser. `credentialScope` chooses where Executor stores the OAuth connection/token secrets; omit it only in a single-scope local executor, otherwise call `scopes.list` and ask whether the connection should be personal/user-scoped or organization-scoped. OAuth permission scopes belong in `strategy.scopes`. Never put OAuth passwords, authorization codes, or client secrets in chat. For confidential clients, first call `secrets.create` for client id/secret and pass those secret ids in the strategy. After the browser callback completes, call `connections.list`, then configure the source with the returned connection id.",
inputSchema: OAuthStartInputStd,
outputSchema: OAuthStartOutputStd,
execute: (input, { ctx }) =>
Effect.gen(function* () {
const webBaseUrl = yield* requireWebBaseUrl(options.webBaseUrl);
- const tokenScope = yield* resolveScopeInput(ctx.scopes, input.scope);
+ const tokenScope = yield* resolveScopeInput(ctx.scopes, input.credentialScope);
const result = yield* ctx.oauth.start({
endpoint: input.endpoint,
headers: input.headers,
@@ -948,8 +948,8 @@ export const coreToolsPlugin = definePlugin((options: CoreToolsPluginOptions = {
...result,
instructions:
result.authorizationUrl === null
- ? "This OAuth flow completed without a browser handoff. Call connections.list to verify the connection id, then pass that connection id to the relevant source configuration tool."
- : "The user needs to open this authorization URL in a browser and complete the OAuth/sign-in flow. Until the browser callback completes, no connection is available for binding. After the user finishes sign-in, call connections.list to find the connection id, then pass that connection id to the relevant source configuration tool.",
+ ? "This OAuth flow completed without a browser handoff. The OAuth connection/token secrets were saved to the selected credential scope. Call connections.list to verify the connection id, then pass that connection id to the relevant source configuration tool."
+ : "The user needs to open this authorization URL in a browser and complete the OAuth/sign-in flow. Until the browser callback completes, no connection is available for binding. After the user finishes sign-in, call connections.list to find the connection id, then pass that connection id to the relevant source configuration tool. The OAuth connection/token secrets are saved to the selected credential scope.",
};
}).pipe(
Effect.catchTags({
@@ -970,12 +970,12 @@ export const coreToolsPlugin = definePlugin((options: CoreToolsPluginOptions = {
tool({
name: "oauth.cancel",
description:
- "Cancel a pending OAuth browser handoff if the user declines or the wrong flow was started.",
+ "`credentialScope` must match where `oauth.start` saved the pending browser handoff. Cancel it if the user declines or the wrong flow was started.",
inputSchema: OAuthCancelInputStd,
outputSchema: OAuthCancelOutputStd,
execute: (input, { ctx }) =>
Effect.gen(function* () {
- const scope = yield* resolveScopeInput(ctx.scopes, input.scope);
+ const scope = yield* resolveScopeInput(ctx.scopes, input.credentialScope);
return yield* Effect.as(ctx.oauth.cancel(input.sessionId, scope), {
cancelled: true,
});
diff --git a/packages/core/sdk/src/executor.test.ts b/packages/core/sdk/src/executor.test.ts
index e663640e9..fbcd99962 100644
--- a/packages/core/sdk/src/executor.test.ts
+++ b/packages/core/sdk/src/executor.test.ts
@@ -751,8 +751,12 @@ describe("createExecutor", () => {
provider: "memory",
});
+ const schema = yield* executor.tools.schema("executor.coreTools.oauth.start");
+ expect(schema?.inputTypeScript).toContain("credentialScope?: string");
+ expect(schema?.inputTypeScript).not.toContain("scope: string; endpoint");
+
const started = yield* executor.tools.invoke("executor.coreTools.oauth.start", {
- scope: "test-scope",
+ credentialScope: "test-scope",
endpoint: oauthServer.resourceUrl,
connectionId: "agent-oauth",
pluginId: "test-plugin",
@@ -849,7 +853,7 @@ describe("createExecutor", () => {
});
const started = yield* executor.tools.invoke("executor.coreTools.oauth.start", {
- scope: "test",
+ credentialScope: "test",
endpoint: oauthServer.resourceUrl,
connectionId: "agent-browser-oauth",
pluginId: "test-plugin",
diff --git a/packages/plugins/google-discovery/src/sdk/plugin.ts b/packages/plugins/google-discovery/src/sdk/plugin.ts
index 281f8d3a8..bc8bf119a 100644
--- a/packages/plugins/google-discovery/src/sdk/plugin.ts
+++ b/packages/plugins/google-discovery/src/sdk/plugin.ts
@@ -564,7 +564,7 @@ export const googleDiscoveryPlugin = definePlugin(() => ({
tool({
name: "addSource",
description:
- 'Add a Google Discovery source and register its operations as tools. Executor chooses the source install scope (local scope locally, organization scope in cloud) and returns it as `source`. Recommended flow: call `probeDiscovery`, create any OAuth client id/client secret values through `secrets.create` at the user\'s chosen credential scope, call `oauth.start` in the browser for OAuth sources, then pass `{kind:"oauth2", connectionId, clientIdSecretId, clientSecretSecretId, scopes}` or `{kind:"none"}` here.',
+ 'Add a Google Discovery source and register its operations as tools. Executor chooses the source install scope (local scope locally, organization scope in cloud) and returns it as `source`. Recommended flow: call `probeDiscovery`, create any OAuth client id/client secret values through `secrets.create` at the user\'s chosen credential scope, call `oauth.start` with `credentialScope` set to the user\'s chosen personal or organization credential scope for OAuth sources, then pass `{kind:"oauth2", connectionId, clientIdSecretId, clientSecretSecretId, scopes}` or `{kind:"none"}` here.',
annotations: {
requiresApproval: true,
approvalDescription: "Add a Google Discovery source",
@@ -608,7 +608,7 @@ export const googleDiscoveryPlugin = definePlugin(() => ({
tool({
name: "configureSource",
description:
- "Configure an existing Google Discovery source with concrete fields. Use `source` returned by `googleDiscovery.addSource` or `sources.list`. For OAuth, call `oauth.start` in the browser first, then pass the returned connection id and client secret ids through `auth`.",
+ "Configure an existing Google Discovery source with concrete fields. Use `source` returned by `googleDiscovery.addSource` or `sources.list`. For OAuth, call `oauth.start` with the target `credentialScope` first, then pass the returned connection id and client secret ids through `auth`.",
annotations: {
requiresApproval: true,
approvalDescription: "Configure a Google Discovery source",
diff --git a/packages/plugins/graphql/src/sdk/plugin.ts b/packages/plugins/graphql/src/sdk/plugin.ts
index 1bd3e1985..938dd21ed 100644
--- a/packages/plugins/graphql/src/sdk/plugin.ts
+++ b/packages/plugins/graphql/src/sdk/plugin.ts
@@ -993,7 +993,7 @@ export const graphqlPlugin = definePlugin((options?: GraphqlPluginOptions) => {
tool({
name: "addSource",
description:
- "Add a GraphQL endpoint and register its operations as tools. Executor chooses the source install scope (local scope locally, organization scope in cloud) and returns it as `source`. For API keys or bearer tokens, first call `executor.coreTools.secrets.create` at the user's chosen credential scope and pass secret refs through `credentials`. For OAuth, start the browser flow with `executor.coreTools.oauth.start`, verify completion with `connections.list`, then bind the connection through `credentials` or `graphql.configureSource`.",
+ "Add a GraphQL endpoint and register its operations as tools. Executor chooses the source install scope (local scope locally, organization scope in cloud) and returns it as `source`. For API keys or bearer tokens, first call `executor.coreTools.secrets.create` at the user's chosen credential scope and pass secret refs through `credentials`. For OAuth, start the browser flow with `executor.coreTools.oauth.start` using `credentialScope` set to the user's chosen personal or organization credential scope, verify completion with `connections.list`, then bind the connection through `credentials` or `graphql.configureSource`.",
annotations: {
requiresApproval: true,
approvalDescription: "Add a GraphQL source",
diff --git a/packages/plugins/mcp/src/sdk/plugin.ts b/packages/plugins/mcp/src/sdk/plugin.ts
index 29bfea9d0..ab6df0be0 100644
--- a/packages/plugins/mcp/src/sdk/plugin.ts
+++ b/packages/plugins/mcp/src/sdk/plugin.ts
@@ -1716,7 +1716,7 @@ export const mcpPlugin = definePlugin((options?: McpPluginOptions) => {
tool({
name: "probeEndpoint",
description:
- "Probe a remote MCP endpoint before adding it. If the result requires OAuth, call `executor.coreTools.oauth.probe` and `executor.coreTools.oauth.start` first, then pass the resulting connection through `addSource` credentials or `mcp.configureSource`.",
+ "Probe a remote MCP endpoint before adding it. If the result requires OAuth, call `executor.coreTools.oauth.probe` and `executor.coreTools.oauth.start` with `credentialScope` set to the user's chosen personal or organization credential scope first, then pass the resulting connection through `addSource` credentials or `mcp.configureSource`.",
inputSchema: McpProbeEndpointInputStandardSchema,
outputSchema: McpProbeEndpointOutputStandardSchema,
execute: (input) =>
@@ -1744,7 +1744,7 @@ export const mcpPlugin = definePlugin((options?: McpPluginOptions) => {
tool({
name: "addSource",
description:
- "Add an MCP source and register its tools. Executor chooses the source install scope (local scope locally, organization scope in cloud) and returns it as `source`. For remote OAuth-protected servers, first use `probeEndpoint` and the core OAuth browser handoff (`oauth.probe`, `oauth.start`), then bind the completed connection with `mcp.configureSource` if needed. For header/API-key auth, first call `secrets.create` at the user's chosen credential scope so the value is entered in the browser, then pass the secret reference in `credentials`. Remote sources are still saved if discovery fails; inspect the returned `discovery` field and use `sources.refresh` after credentials or network access are fixed.",
+ "Add an MCP source and register its tools. Executor chooses the source install scope (local scope locally, organization scope in cloud) and returns it as `source`. For remote OAuth-protected servers, first use `probeEndpoint` and the core OAuth browser handoff (`oauth.probe`, `oauth.start` with the user's chosen `credentialScope`), then bind the completed connection with `mcp.configureSource` if needed. For header/API-key auth, first call `secrets.create` at the user's chosen credential scope so the value is entered in the browser, then pass the secret reference in `credentials`. Remote sources are still saved if discovery fails; inspect the returned `discovery` field and use `sources.refresh` after credentials or network access are fixed.",
annotations: {
requiresApproval: true,
approvalDescription: "Add an MCP source",
diff --git a/packages/plugins/openapi/src/sdk/plugin.ts b/packages/plugins/openapi/src/sdk/plugin.ts
index 6bcdb1dec..2dd322e70 100644
--- a/packages/plugins/openapi/src/sdk/plugin.ts
+++ b/packages/plugins/openapi/src/sdk/plugin.ts
@@ -1445,7 +1445,7 @@ export const openApiPlugin = definePlugin((options?: OpenApiPluginOptions) => {
tool({
name: "addSource",
description:
- "Add an OpenAPI source and register its operations as tools. Executor chooses the source install scope (local scope locally, organization scope in cloud) and returns it as `source`. Recommended flow: call `previewSpec`, choose or confirm namespace/name/baseUrl from the preview (baseUrl is only needed when the spec cannot infer one or the user wants an override), declare credential slots here for sensitive headers/query params, then call `secrets.create` and `openapi.configureSource` with the user's chosen credential scope for per-scope bindings. Use `oauth.start` for browser OAuth sign-in.",
+ "Add an OpenAPI source and register its operations as tools. Executor chooses the source install scope (local scope locally, organization scope in cloud) and returns it as `source`. Recommended flow: call `previewSpec`, choose or confirm namespace/name/baseUrl from the preview (baseUrl is only needed when the spec cannot infer one or the user wants an override), declare credential slots here for sensitive headers/query params, then call `secrets.create` and `openapi.configureSource` with the user's chosen credential scope for per-scope bindings. Use `oauth.start` with `credentialScope` set to the user's chosen personal or organization credential scope for browser OAuth sign-in.",
annotations: {
requiresApproval: true,
approvalDescription: "Add an OpenAPI source",
From be4669815a3212d1b45e142a392384b51c12f744 Mon Sep 17 00:00:00 2001
From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
Date: Tue, 19 May 2026 00:52:49 -0700
Subject: [PATCH 14/15] fix: satisfy core tools ci
---
.../src/sdk/__snapshots__/real-specs.test.ts.snap | 10 +++++-----
packages/react/src/pages/secrets.tsx | 3 ++-
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/packages/plugins/openapi/src/sdk/__snapshots__/real-specs.test.ts.snap b/packages/plugins/openapi/src/sdk/__snapshots__/real-specs.test.ts.snap
index 3cbb2e964..388289617 100644
--- a/packages/plugins/openapi/src/sdk/__snapshots__/real-specs.test.ts.snap
+++ b/packages/plugins/openapi/src/sdk/__snapshots__/real-specs.test.ts.snap
@@ -258,7 +258,7 @@ exports[`Real specs: Cloudflare API > preserves registered tool schema and TypeS
"AccessAppPolicyLink": "{ id?: AccessSchemasUuid; precedence?: AccessPrecedence; }",
"AccessAppPolicyRequest": "({ precedence?: AccessPrecedence; } & AccessPolicyReq)",
"AccessAppPolicyResponse": "(AccessPolicyResp & { precedence?: AccessPrecedence; })",
- "AccessAppReqEmbeddedPolicies": "{ policies?: (AccessAppPolicyLink | ({ [k: string]: unknown; } & AccessSchemasUuid) | ({ } & { id?: AccessSchemasUuid; } & AccessAppPolicyRequest))[]; }",
+ "AccessAppReqEmbeddedPolicies": "{ policies?: (AccessAppPolicyLink | ({ [k: string]: unknown; } & AccessSchemasUuid) | ({ [k: string]: unknown; } & { id?: AccessSchemasUuid; } & AccessAppPolicyRequest))[]; }",
"AccessAppReqEmbeddedScimConfig": "{ scim_config?: AccessScimConfig; }",
"AccessAppRequest": "SelfHostedApplication | SaaSApplication | BrowserSSHApplication | BrowserVNCApplication | AppLauncherApplication | DeviceEnrollmentPermissionsApplication | BrowserIsolationPermissionsApplication | GatewayIdentityProxyEndpointApplication | BookmarkApplication | InfrastructureApplication | BrowserRDPApplication | MCPServerApplication | MCPServerPortalApplication",
"AccessAppRespEmbeddedPolicies": "{ policies?: AccessAppPolicyResponse[]; }",
@@ -354,7 +354,7 @@ exports[`Real specs: Cloudflare API > preserves registered tool schema and TypeS
"AccessUuid": "string",
"AccessVncProps": "(SelfHostedApplication1 & { type?: (AccessType & { [k: string]: unknown; }); })",
"AccessWarpProps": "(AccessFeatureAppProps & { domain?: { [k: string]: unknown; }; name?: string; type?: (AccessType & { [k: string]: unknown; }); })",
- "AnyValidServiceToken": "{ any_valid_service_token: { }; }",
+ "AnyValidServiceToken": "{ any_valid_service_token: { [k: string]: unknown; }; }",
"AppLauncherApplication": "(AccessAppLauncherProps & AccessAppReqEmbeddedPolicies)",
"AppLauncherApplication1": "(AccessBasicAppResponseProps & AccessAppLauncherProps & AccessAppRespEmbeddedPolicies)",
"AuthenticationContext": "{ auth_context: { ac_id: string; id: string; identity_provider_id: string; }; }",
@@ -381,7 +381,7 @@ exports[`Real specs: Cloudflare API > preserves registered tool schema and TypeS
"Email": "{ email: { email: string; }; }",
"EmailDomain": "{ email_domain: { domain: string; }; }",
"EmailList": "{ email_list: { id: string; }; }",
- "Everyone": "{ everyone: { }; }",
+ "Everyone": "{ everyone: { [k: string]: unknown; }; }",
"ExternalEvaluation": "{ external_evaluation: { evaluate_url: string; keys_url: string; }; }",
"GatewayIdentityProxyEndpointApplication": "(AccessProxyEndpointProps & AccessAppReqEmbeddedPolicies)",
"GatewayIdentityProxyEndpointApplication1": "(AccessBasicAppResponseProps & AccessProxyEndpointProps & AccessAppRespEmbeddedPolicies)",
@@ -420,7 +420,7 @@ exports[`Real specs: Cloudflare API > preserves registered tool schema and TypeS
"ServiceToken": "{ service_token: { token_id: string; }; }",
"TargetCriteria": "{ port: AccessPort; target_attributes: AccessTargetAttributes; }",
"UserRiskScore": "{ user_risk_score: { user_risk_score: ["low" | "medium" | "high" | "unscored", ...(("low" | "medium" | "high" | "unscored"))[]]; }; }",
- "ValidCertificate": "{ certificate: { }; }",
+ "ValidCertificate": "{ certificate: { [k: string]: unknown; }; }",
"ViaMCPServerPortalDestination": "{ mcp_server_id?: string; type?: "via_mcp_server_portal"; }",
},
}
@@ -4325,7 +4325,7 @@ exports[`Real specs: Vercel API > preserves registered tool schema and TypeScrip
],
"type": "object",
},
- "outputTypeScript": "{ aliasAssignedAt?: number | false | true | null; alwaysRefuseToBuild?: false | true; build: { env: string[]; }; buildArtifactUrls?: string[]; builds?: { use: string; src?: string; config?: { [k: string]: unknown; }; }[]; env: string[]; inspectorUrl: string | null; isInConcurrentBuildsQueue: false | true; isInSystemBuildsQueue: false | true; projectSettings: { nodeVersion?: "24.x" | "22.x" | "20.x" | "18.x" | "16.x" | "14.x" | "12.x" | "10.x" | "8.10.x"; buildCommand?: string | null; devCommand?: string | null; framework?: "blitzjs" | "nextjs" | "gatsby" | "remix" | "react-router" | "astro" | "hexo" | "eleventy" | "docusaurus-2" | "docusaurus" | "preact" | "solidstart-1" | "solidstart" | "dojo" | "ember" | "vue" | "scully" | "ionic-angular" | "angular" | "polymer" | "svelte" | "sveltekit" | "sveltekit-1" | "ionic-react" | "create-react-app" | "gridsome" | "umijs" | "sapper" | "saber" | "stencil" | "nuxtjs" | "redwoodjs" | "hugo" | "jekyll" | "brunch" | "middleman" | "zola" | "hydrogen" | "vite" | "tanstack-start" | "vitepress" | "vuepress" | "parcel" | "fastapi" | "flask" | "fasthtml" | "django" | "ash" | "sanity-v3" | "sanity" | "storybook" | "nitro" | "hono" | "express" | "h3" | "koa" | "nestjs" | "elysia" | "fastify" | "xmcp" | "python" | "ruby" | "rust" | "axum" | "actix-web" | "node" | "go" | "services" | "mastra" | null; commandForIgnoringBuildStep?: string | null; installCommand?: string | null; outputDirectory?: string | null; speedInsights?: { id: string; enabledAt?: number; disabledAt?: number; canceledAt?: number; hasData?: false | true; paidAt?: number; }; webAnalytics?: { id: string; disabledAt?: number; canceledAt?: number; enabledAt?: number; hasData?: true; }; }; integrations?: { status: "skipped" | "pending" | "ready" | "error" | "timeout"; startedAt: number; claimedAt?: number; completedAt?: number; skippedAt?: number; skippedBy?: string; }; images?: { sizes?: number[]; qualities?: number[]; domains?: string[]; remotePatterns?: { protocol?: "http" | "https"; hostname: string; port?: string; pathname?: string; search?: string; }[]; localPatterns?: { pathname?: string; search?: string; }[]; minimumCacheTTL?: number; formats?: ("image/avif" | "image/webp")[]; dangerouslyAllowSVG?: false | true; contentSecurityPolicy?: string; contentDispositionType?: "inline" | "attachment"; }; alias?: string[]; aliasAssigned: false | true; bootedAt: number; buildingAt: number; buildContainerFinishedAt?: number; buildSkipped: false | true; creator: { uid: string; username?: string; avatar?: string; }; initReadyAt?: number; isFirstBranchDeployment?: false | true; lambdas?: { id: string; createdAt?: number; readyState?: "BUILDING" | "ERROR" | "INITIALIZING" | "READY"; entrypoint?: string | null; readyStateAt?: number; output: { path: string; functionName: string; }[]; }[]; public: false | true; ready?: number; status: "QUEUED" | "BUILDING" | "ERROR" | "BLOCKED" | "INITIALIZING" | "READY" | "CANCELED"; team?: { id: string; name: string; slug: string; avatar?: string; }; userAliases?: string[]; previewCommentsEnabled?: false | true; ttyBuildLogs?: false | true; customEnvironment?: { id: string; slug: string; type: "production" | "preview" | "development"; description?: string; branchMatcher?: { type: "endsWith" | "startsWith" | "equals"; pattern: string; }; domains?: { name: string; apexName: string; projectId: string; redirect?: string | null; redirectStatusCode?: 307 | 301 | 302 | 308 | null; gitBranch?: string | null; customEnvironmentId?: string | null; updatedAt?: number; createdAt?: number; verified: false | true; verification?: { type: string; domain: string; value: string; reason: string; }[]; }[]; currentDeploymentAliases?: string[]; createdAt: number; updatedAt: number; } | { id: string; }; oomReport?: "out-of-memory"; readyStateReason?: string; aliasWarning?: { code: string; message: string; link?: string; action?: string; } | null; id: string; createdAt: number; readyState: "QUEUED" | "BUILDING" | "ERROR" | "BLOCKED" | "INITIALIZING" | "READY" | "CANCELED"; name: string; type: "LAMBDAS"; aliasError?: { code: string; message: string; } | null; aliasFinal?: string | null; autoAssignCustomDomains?: false | true; automaticAliases?: string[]; buildErrorAt?: number; checksState?: "registered" | "running" | "completed"; checksConclusion?: "succeeded" | "failed" | "skipped" | "canceled"; deletedAt?: number | null; defaultRoute?: string; canceledAt?: number; errorCode?: string; errorLink?: string; errorMessage?: string | null; errorStep?: string; passiveRegions?: string[]; gitSource?: { type: "github"; repoId: string | number; ref?: string | null; sha?: string; prId?: number | null; } | { type: "github"; org: string; repo: string; ref?: string | null; sha?: string; prId?: number | null; } | { type: "github-custom-host"; host: string; repoId: string | number; ref?: string | null; sha?: string; prId?: number | null; } | { type: "github-custom-host"; host: string; org: string; repo: string; ref?: string | null; sha?: string; prId?: number | null; } | { type: "github-limited"; repoId: string | number; ref?: string | null; sha?: string; prId?: number | null; } | { type: "github-limited"; org: string; repo: string; ref?: string | null; sha?: string; prId?: number | null; } | { type: "gitlab"; projectId: string | number; ref?: string | null; sha?: string; prId?: number | null; } | { type: "bitbucket"; workspaceUuid?: string; repoUuid: string; ref?: string | null; sha?: string; prId?: number | null; } | { type: "bitbucket"; owner: string; slug: string; ref?: string | null; sha?: string; prId?: number | null; } | { type: "vercel"; org?: string; repo?: string; sha: string; repoPushedAt?: number; ref?: string | null; prId?: number | null; } | { type: "custom"; ref: string; sha: string; gitUrl: string; } | { type: "github"; ref: string; sha: string; repoId: number; org?: string; repo?: string; } | { type: "github-custom-host"; host: string; ref: string; sha: string; repoId: number; org?: string; repo?: string; } | { type: "github-limited"; ref: string; sha: string; repoId: number; org?: string; repo?: string; } | { type: "gitlab"; ref: string; sha: string; projectId: number; } | { type: "bitbucket"; ref: string; sha: string; owner?: string; slug?: string; workspaceUuid: string; repoUuid: string; } | { type: "vercel"; ref: string; sha: string; org: string; repo: string; repoPushedAt?: number; }; manualProvisioning?: { state: "PENDING" | "COMPLETE" | "TIMEOUT"; completedAt?: number; }; meta: { [k: string]: string; }; originCacheRegion?: string; nodeVersion?: "24.x" | "22.x" | "20.x" | "18.x" | "16.x" | "14.x" | "12.x" | "10.x" | "8.10.x"; project?: { id: string; name: string; framework?: string | null; }; prebuilt?: false | true; readySubstate?: "STAGED" | "ROLLING" | "PROMOTED"; regions: string[]; softDeletedByRetention?: false | true; source?: "api-trigger-git-deploy" | "cli" | "clone/repo" | "git" | "import" | "import/repo" | "redeploy" | "v0-web"; target?: "staging" | "production" | null; undeletedAt?: number; url: string; userConfiguredDeploymentId?: string; version: 2; oidcTokenClaims?: { iss: string; sub: string; scope: string; aud: string; owner: string; owner_id: string; project: string; project_id: string; environment: string; custom_environment_id?: string; plan?: string; }; projectId: string; plan: "pro" | "enterprise" | "hobby"; platform?: { source: { name: string; }; origin: { type: "id" | "url"; value: string; }; creator: { name: string; avatar?: string; }; meta?: { [k: string]: string; }; }; connectBuildsEnabled?: false | true; connectConfigurationId?: string; createdIn: string; crons?: { schedule: string; path: string; }[]; functions?: { [k: string]: { architecture?: "x86_64" | "arm64"; memory?: number; maxDuration?: number | "max"; regions?: string[]; functionFailoverRegions?: string[]; runtime?: string; includeFiles?: string; excludeFiles?: string; experimentalTriggers?: ({ type: "queue/v1beta"; consumer: string; topic: string; maxDeliveries?: number; retryAfterSeconds?: number; initialDelaySeconds?: number; maxConcurrency?: number; } | { type: "queue/v2beta"; topic: string; maxDeliveries?: number; retryAfterSeconds?: number; initialDelaySeconds?: number; maxConcurrency?: number; })[]; supportsCancellation?: false | true; }; } | null; monorepoManager?: string | null; ownerId: string; passiveConnectConfigurationId?: string; routes: ({ src: string; dest?: string; headers?: { [k: string]: string; }; methods?: string[]; continue?: (false | true); override?: (false | true); caseSensitive?: (false | true); check?: (false | true); important?: (false | true); status?: number; has?: ({ type: "host"; value: (string | { eq?: (string | number); neq?: string; inc?: string[]; ninc?: string[]; pre?: string; suf?: string; re?: string; gt?: number; gte?: number; lt?: number; lte?: number; }); } | { type: ("header" | "cookie" | "query"); key: string; value?: (string | { eq?: (string | number); neq?: string; inc?: string[]; ninc?: string[]; pre?: string; suf?: string; re?: string; gt?: number; gte?: number; lt?: number; lte?: number; }); })[]; missing?: ({ type: "host"; value: (string | { eq?: (string | number); neq?: string; inc?: string[]; ninc?: string[]; pre?: string; suf?: string; re?: string; gt?: number; gte?: number; lt?: number; lte?: number; }); } | { type: ("header" | "cookie" | "query"); key: string; value?: (string | { eq?: (string | number); neq?: string; inc?: string[]; ninc?: string[]; pre?: string; suf?: string; re?: string; gt?: number; gte?: number; lt?: number; lte?: number; }); })[]; mitigate?: { action: ("challenge" | "deny"); }; transforms?: { type: ("request.headers" | "request.query" | "response.headers"); op: ("append" | "set" | "delete"); target: { key: (string | { eq?: (string | number); neq?: string; inc?: string[]; ninc?: string[]; pre?: string; suf?: string; gt?: number; gte?: number; lt?: number; lte?: number; }); }; args?: (string | string[]); env?: string[]; }[]; env?: string[]; locale?: { redirect?: { [k: string]: string; }; cookie?: string; }; source?: string; destination?: string; statusCode?: number; middlewarePath?: string; middlewareRawSrc?: string[]; middleware?: number; respectOriginCacheControl?: (false | true); } | { handle: ("error" | "filesystem" | "hit" | "miss" | "rewrite" | "resource"); src?: string; dest?: string; status?: number; } | { src: string; continue: (false | true); middleware: 0; })[] | null; gitRepo?: { namespace: string; projectId: number; type: "gitlab"; url: string; path: string; defaultBranch: string; name: string; private: false | true; ownerType: "team" | "user"; } | { org: string; repo: string; repoId: number; type: "github"; repoOwnerId: number; path: string; defaultBranch: string; name: string; private: false | true; ownerType: "team" | "user"; } | { owner: string; repoUuid: string; slug: string; type: "bitbucket"; workspaceUuid: string; path: string; defaultBranch: string; name: string; private: false | true; ownerType: "team" | "user"; } | { org: string; repo: string; type: "vercel"; path: string; defaultBranch: string; name: string; private: false | true; ownerType: "team" | "user"; } | null; flags?: { definitions: { [k: string]: { options?: { value: FlagJSONValue; label?: string; }[]; url?: string; description?: string; }; }; } | { }[]; microfrontends?: { isDefaultApp?: false; defaultAppProjectName: string; defaultRoute?: string; groupIds: [string, ...(string)[]]; } | { isDefaultApp: true; mfeConfigUploadState?: "success" | "waiting_on_build" | "no_config"; defaultAppProjectName: string; defaultRoute?: string; groupIds: [string, ...(string)[]]; }; config?: { version?: number; functionType: "standard" | "fluid"; functionMemoryType: "standard" | "standard_legacy" | "performance"; functionTimeout: number | null; secureComputePrimaryRegion: string | null; secureComputeFallbackRegion: string | null; isUsingActiveCPU?: false | true; resourceConfig?: { buildQueue?: { configuration?: "SKIP_NAMESPACE_QUEUE" | "WAIT_FOR_NAMESPACE_QUEUE"; }; elasticConcurrency?: "TEAM_SETTING" | "PROJECT_SETTING" | "SKIP_QUEUE"; buildMachine?: { purchaseType?: "enhanced" | "turbo" | "standard" | null; }; }; }; checks?: { "deployment-alias": { state: "succeeded" | "failed" | "pending"; startedAt: number; completedAt?: number; }; }; seatBlock?: { blockCode: "TEAM_ACCESS_REQUIRED" | "COMMIT_AUTHOR_REQUIRED"; userId?: string; isVerified?: false | true; gitUserId?: string | number; gitProvider?: "gitlab" | "bitbucket" | "github"; }; attribution?: { commitMeta?: { email?: string; name?: string; isVerified?: false | true; }; gitUser?: { id: string | number; login: string; type?: string; provider?: string; }; vercelUser?: { id: string; username: string; teamRoles?: string[]; }; }; }",
+ "outputTypeScript": "{ aliasAssignedAt?: number | false | true | null; alwaysRefuseToBuild?: false | true; build: { env: string[]; }; buildArtifactUrls?: string[]; builds?: { use: string; src?: string; config?: { [k: string]: unknown; }; }[]; env: string[]; inspectorUrl: string | null; isInConcurrentBuildsQueue: false | true; isInSystemBuildsQueue: false | true; projectSettings: { nodeVersion?: "24.x" | "22.x" | "20.x" | "18.x" | "16.x" | "14.x" | "12.x" | "10.x" | "8.10.x"; buildCommand?: string | null; devCommand?: string | null; framework?: "blitzjs" | "nextjs" | "gatsby" | "remix" | "react-router" | "astro" | "hexo" | "eleventy" | "docusaurus-2" | "docusaurus" | "preact" | "solidstart-1" | "solidstart" | "dojo" | "ember" | "vue" | "scully" | "ionic-angular" | "angular" | "polymer" | "svelte" | "sveltekit" | "sveltekit-1" | "ionic-react" | "create-react-app" | "gridsome" | "umijs" | "sapper" | "saber" | "stencil" | "nuxtjs" | "redwoodjs" | "hugo" | "jekyll" | "brunch" | "middleman" | "zola" | "hydrogen" | "vite" | "tanstack-start" | "vitepress" | "vuepress" | "parcel" | "fastapi" | "flask" | "fasthtml" | "django" | "ash" | "sanity-v3" | "sanity" | "storybook" | "nitro" | "hono" | "express" | "h3" | "koa" | "nestjs" | "elysia" | "fastify" | "xmcp" | "python" | "ruby" | "rust" | "axum" | "actix-web" | "node" | "go" | "services" | "mastra" | null; commandForIgnoringBuildStep?: string | null; installCommand?: string | null; outputDirectory?: string | null; speedInsights?: { id: string; enabledAt?: number; disabledAt?: number; canceledAt?: number; hasData?: false | true; paidAt?: number; }; webAnalytics?: { id: string; disabledAt?: number; canceledAt?: number; enabledAt?: number; hasData?: true; }; }; integrations?: { status: "skipped" | "pending" | "ready" | "error" | "timeout"; startedAt: number; claimedAt?: number; completedAt?: number; skippedAt?: number; skippedBy?: string; }; images?: { sizes?: number[]; qualities?: number[]; domains?: string[]; remotePatterns?: { protocol?: "http" | "https"; hostname: string; port?: string; pathname?: string; search?: string; }[]; localPatterns?: { pathname?: string; search?: string; }[]; minimumCacheTTL?: number; formats?: ("image/avif" | "image/webp")[]; dangerouslyAllowSVG?: false | true; contentSecurityPolicy?: string; contentDispositionType?: "inline" | "attachment"; }; alias?: string[]; aliasAssigned: false | true; bootedAt: number; buildingAt: number; buildContainerFinishedAt?: number; buildSkipped: false | true; creator: { uid: string; username?: string; avatar?: string; }; initReadyAt?: number; isFirstBranchDeployment?: false | true; lambdas?: { id: string; createdAt?: number; readyState?: "BUILDING" | "ERROR" | "INITIALIZING" | "READY"; entrypoint?: string | null; readyStateAt?: number; output: { path: string; functionName: string; }[]; }[]; public: false | true; ready?: number; status: "QUEUED" | "BUILDING" | "ERROR" | "BLOCKED" | "INITIALIZING" | "READY" | "CANCELED"; team?: { id: string; name: string; slug: string; avatar?: string; }; userAliases?: string[]; previewCommentsEnabled?: false | true; ttyBuildLogs?: false | true; customEnvironment?: { id: string; slug: string; type: "production" | "preview" | "development"; description?: string; branchMatcher?: { type: "endsWith" | "startsWith" | "equals"; pattern: string; }; domains?: { name: string; apexName: string; projectId: string; redirect?: string | null; redirectStatusCode?: 307 | 301 | 302 | 308 | null; gitBranch?: string | null; customEnvironmentId?: string | null; updatedAt?: number; createdAt?: number; verified: false | true; verification?: { type: string; domain: string; value: string; reason: string; }[]; }[]; currentDeploymentAliases?: string[]; createdAt: number; updatedAt: number; } | { id: string; }; oomReport?: "out-of-memory"; readyStateReason?: string; aliasWarning?: { code: string; message: string; link?: string; action?: string; } | null; id: string; createdAt: number; readyState: "QUEUED" | "BUILDING" | "ERROR" | "BLOCKED" | "INITIALIZING" | "READY" | "CANCELED"; name: string; type: "LAMBDAS"; aliasError?: { code: string; message: string; } | null; aliasFinal?: string | null; autoAssignCustomDomains?: false | true; automaticAliases?: string[]; buildErrorAt?: number; checksState?: "registered" | "running" | "completed"; checksConclusion?: "succeeded" | "failed" | "skipped" | "canceled"; deletedAt?: number | null; defaultRoute?: string; canceledAt?: number; errorCode?: string; errorLink?: string; errorMessage?: string | null; errorStep?: string; passiveRegions?: string[]; gitSource?: { type: "github"; repoId: string | number; ref?: string | null; sha?: string; prId?: number | null; } | { type: "github"; org: string; repo: string; ref?: string | null; sha?: string; prId?: number | null; } | { type: "github-custom-host"; host: string; repoId: string | number; ref?: string | null; sha?: string; prId?: number | null; } | { type: "github-custom-host"; host: string; org: string; repo: string; ref?: string | null; sha?: string; prId?: number | null; } | { type: "github-limited"; repoId: string | number; ref?: string | null; sha?: string; prId?: number | null; } | { type: "github-limited"; org: string; repo: string; ref?: string | null; sha?: string; prId?: number | null; } | { type: "gitlab"; projectId: string | number; ref?: string | null; sha?: string; prId?: number | null; } | { type: "bitbucket"; workspaceUuid?: string; repoUuid: string; ref?: string | null; sha?: string; prId?: number | null; } | { type: "bitbucket"; owner: string; slug: string; ref?: string | null; sha?: string; prId?: number | null; } | { type: "vercel"; org?: string; repo?: string; sha: string; repoPushedAt?: number; ref?: string | null; prId?: number | null; } | { type: "custom"; ref: string; sha: string; gitUrl: string; } | { type: "github"; ref: string; sha: string; repoId: number; org?: string; repo?: string; } | { type: "github-custom-host"; host: string; ref: string; sha: string; repoId: number; org?: string; repo?: string; } | { type: "github-limited"; ref: string; sha: string; repoId: number; org?: string; repo?: string; } | { type: "gitlab"; ref: string; sha: string; projectId: number; } | { type: "bitbucket"; ref: string; sha: string; owner?: string; slug?: string; workspaceUuid: string; repoUuid: string; } | { type: "vercel"; ref: string; sha: string; org: string; repo: string; repoPushedAt?: number; }; manualProvisioning?: { state: "PENDING" | "COMPLETE" | "TIMEOUT"; completedAt?: number; }; meta: { [k: string]: string; }; originCacheRegion?: string; nodeVersion?: "24.x" | "22.x" | "20.x" | "18.x" | "16.x" | "14.x" | "12.x" | "10.x" | "8.10.x"; project?: { id: string; name: string; framework?: string | null; }; prebuilt?: false | true; readySubstate?: "STAGED" | "ROLLING" | "PROMOTED"; regions: string[]; softDeletedByRetention?: false | true; source?: "api-trigger-git-deploy" | "cli" | "clone/repo" | "git" | "import" | "import/repo" | "redeploy" | "v0-web"; target?: "staging" | "production" | null; undeletedAt?: number; url: string; userConfiguredDeploymentId?: string; version: 2; oidcTokenClaims?: { iss: string; sub: string; scope: string; aud: string; owner: string; owner_id: string; project: string; project_id: string; environment: string; custom_environment_id?: string; plan?: string; }; projectId: string; plan: "pro" | "enterprise" | "hobby"; platform?: { source: { name: string; }; origin: { type: "id" | "url"; value: string; }; creator: { name: string; avatar?: string; }; meta?: { [k: string]: string; }; }; connectBuildsEnabled?: false | true; connectConfigurationId?: string; createdIn: string; crons?: { schedule: string; path: string; }[]; functions?: { [k: string]: { architecture?: "x86_64" | "arm64"; memory?: number; maxDuration?: number | "max"; regions?: string[]; functionFailoverRegions?: string[]; runtime?: string; includeFiles?: string; excludeFiles?: string; experimentalTriggers?: ({ type: "queue/v1beta"; consumer: string; topic: string; maxDeliveries?: number; retryAfterSeconds?: number; initialDelaySeconds?: number; maxConcurrency?: number; } | { type: "queue/v2beta"; topic: string; maxDeliveries?: number; retryAfterSeconds?: number; initialDelaySeconds?: number; maxConcurrency?: number; })[]; supportsCancellation?: false | true; }; } | null; monorepoManager?: string | null; ownerId: string; passiveConnectConfigurationId?: string; routes: ({ src: string; dest?: string; headers?: { [k: string]: string; }; methods?: string[]; continue?: (false | true); override?: (false | true); caseSensitive?: (false | true); check?: (false | true); important?: (false | true); status?: number; has?: ({ type: "host"; value: (string | { eq?: (string | number); neq?: string; inc?: string[]; ninc?: string[]; pre?: string; suf?: string; re?: string; gt?: number; gte?: number; lt?: number; lte?: number; }); } | { type: ("header" | "cookie" | "query"); key: string; value?: (string | { eq?: (string | number); neq?: string; inc?: string[]; ninc?: string[]; pre?: string; suf?: string; re?: string; gt?: number; gte?: number; lt?: number; lte?: number; }); })[]; missing?: ({ type: "host"; value: (string | { eq?: (string | number); neq?: string; inc?: string[]; ninc?: string[]; pre?: string; suf?: string; re?: string; gt?: number; gte?: number; lt?: number; lte?: number; }); } | { type: ("header" | "cookie" | "query"); key: string; value?: (string | { eq?: (string | number); neq?: string; inc?: string[]; ninc?: string[]; pre?: string; suf?: string; re?: string; gt?: number; gte?: number; lt?: number; lte?: number; }); })[]; mitigate?: { action: ("challenge" | "deny"); }; transforms?: { type: ("request.headers" | "request.query" | "response.headers"); op: ("append" | "set" | "delete"); target: { key: (string | { eq?: (string | number); neq?: string; inc?: string[]; ninc?: string[]; pre?: string; suf?: string; gt?: number; gte?: number; lt?: number; lte?: number; }); }; args?: (string | string[]); env?: string[]; }[]; env?: string[]; locale?: { redirect?: { [k: string]: string; }; cookie?: string; }; source?: string; destination?: string; statusCode?: number; middlewarePath?: string; middlewareRawSrc?: string[]; middleware?: number; respectOriginCacheControl?: (false | true); } | { handle: ("error" | "filesystem" | "hit" | "miss" | "rewrite" | "resource"); src?: string; dest?: string; status?: number; } | { src: string; continue: (false | true); middleware: 0; })[] | null; gitRepo?: { namespace: string; projectId: number; type: "gitlab"; url: string; path: string; defaultBranch: string; name: string; private: false | true; ownerType: "team" | "user"; } | { org: string; repo: string; repoId: number; type: "github"; repoOwnerId: number; path: string; defaultBranch: string; name: string; private: false | true; ownerType: "team" | "user"; } | { owner: string; repoUuid: string; slug: string; type: "bitbucket"; workspaceUuid: string; path: string; defaultBranch: string; name: string; private: false | true; ownerType: "team" | "user"; } | { org: string; repo: string; type: "vercel"; path: string; defaultBranch: string; name: string; private: false | true; ownerType: "team" | "user"; } | null; flags?: { definitions: { [k: string]: { options?: { value: FlagJSONValue; label?: string; }[]; url?: string; description?: string; }; }; } | { [k: string]: unknown; }[]; microfrontends?: { isDefaultApp?: false; defaultAppProjectName: string; defaultRoute?: string; groupIds: [string, ...(string)[]]; } | { isDefaultApp: true; mfeConfigUploadState?: "success" | "waiting_on_build" | "no_config"; defaultAppProjectName: string; defaultRoute?: string; groupIds: [string, ...(string)[]]; }; config?: { version?: number; functionType: "standard" | "fluid"; functionMemoryType: "standard" | "standard_legacy" | "performance"; functionTimeout: number | null; secureComputePrimaryRegion: string | null; secureComputeFallbackRegion: string | null; isUsingActiveCPU?: false | true; resourceConfig?: { buildQueue?: { configuration?: "SKIP_NAMESPACE_QUEUE" | "WAIT_FOR_NAMESPACE_QUEUE"; }; elasticConcurrency?: "TEAM_SETTING" | "PROJECT_SETTING" | "SKIP_QUEUE"; buildMachine?: { purchaseType?: "enhanced" | "turbo" | "standard" | null; }; }; }; checks?: { "deployment-alias": { state: "succeeded" | "failed" | "pending"; startedAt: number; completedAt?: number; }; }; seatBlock?: { blockCode: "TEAM_ACCESS_REQUIRED" | "COMMIT_AUTHOR_REQUIRED"; userId?: string; isVerified?: false | true; gitUserId?: string | number; gitProvider?: "gitlab" | "bitbucket" | "github"; }; attribution?: { commitMeta?: { email?: string; name?: string; isVerified?: false | true; }; gitUser?: { id: string | number; login: string; type?: string; provider?: string; }; vercelUser?: { id: string; username: string; teamRoles?: string[]; }; }; }",
"schemaDefinitionCount": 1,
"schemaDefinitionNames": [
"FlagJSONValue",
diff --git a/packages/react/src/pages/secrets.tsx b/packages/react/src/pages/secrets.tsx
index afffadcb7..c5c0522e3 100644
--- a/packages/react/src/pages/secrets.tsx
+++ b/packages/react/src/pages/secrets.tsx
@@ -29,6 +29,7 @@ import {
SelectTrigger,
SelectValue,
} from "../components/select";
+import { Label } from "../components/label";
import {
DropdownMenu,
DropdownMenuContent,
@@ -165,7 +166,7 @@ function AddSecretDialogContent(props: {
- Scope
+ Scope
setTargetScope(ScopeId.make(value))}
From dcdde226260cffbf0440a9a59cc195e5e79178ec Mon Sep 17 00:00:00 2001
From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
Date: Tue, 19 May 2026 01:14:23 -0700
Subject: [PATCH 15/15] fix: clarify preset and resume guidance
---
notes/source-setup-sdk-flow.md | 12 +++++++++
packages/core/execution/src/engine.ts | 25 +++++++++++++-----
packages/core/sdk/src/client.ts | 3 +++
packages/core/sdk/src/core-tools.ts | 3 ++-
packages/core/sdk/src/plugin.ts | 1 +
packages/hosts/mcp/src/server.test.ts | 29 +++++++++++++++++++++
packages/plugins/graphql/src/sdk/presets.ts | 6 +++++
packages/plugins/mcp/src/sdk/presets.ts | 12 +++++++++
8 files changed, 84 insertions(+), 7 deletions(-)
create mode 100644 notes/source-setup-sdk-flow.md
diff --git a/notes/source-setup-sdk-flow.md b/notes/source-setup-sdk-flow.md
new file mode 100644
index 000000000..ec01c25fd
--- /dev/null
+++ b/notes/source-setup-sdk-flow.md
@@ -0,0 +1,12 @@
+# Source setup orchestration
+
+The web source-add flow currently owns a lot of business logic that agents have
+to rediscover through low-level tools: preset lookup, URL-to-endpoint mapping,
+endpoint probing, OAuth strategy choice, connection id generation, browser
+handoff, credential binding, and final source registration.
+
+Longer term, consider moving this into an SDK-level source setup service so the
+frontend and agent tools share the same state machine. The frontend would render
+steps from the service, while agent tools would return the same state with
+model-facing `instructions` fields. Keep low-level plugin tools as escape
+hatches, but make common preset flows first-class.
diff --git a/packages/core/execution/src/engine.ts b/packages/core/execution/src/engine.ts
index 769cda661..aacb048fe 100644
--- a/packages/core/execution/src/engine.ts
+++ b/packages/core/execution/src/engine.ts
@@ -107,19 +107,31 @@ export const formatPausedExecution = (
const lines: string[] = [`Execution paused: ${req.message}`];
const isUrlElicitation = Predicate.isTagged(req, "UrlElicitation");
const isFormElicitation = Predicate.isTagged(req, "FormElicitation");
+ const requestedSchema = isFormElicitation ? req.requestedSchema : undefined;
+ const hasRequestedSchema =
+ requestedSchema !== undefined && Object.keys(requestedSchema).length > 0;
+ const instructions = isUrlElicitation
+ ? `The user needs to open this URL in a browser and complete the flow. After the user finishes, call the resume tool with executionId "${paused.id}" and action "accept".`
+ : hasRequestedSchema
+ ? `Ask the user for values matching requestedSchema. Then call the resume tool with executionId "${paused.id}", action "accept", and content matching requestedSchema. If the user declines, call resume with action "decline" or "cancel".`
+ : `This is a model-side confirmation gate; there is no browser form to open. Ask the user whether to approve the paused tool call. If the user approves, call the resume tool with executionId "${paused.id}" and action "accept". If the user declines, call resume with action "decline" or "cancel".`;
if (isUrlElicitation) {
lines.push(`\nOpen this URL in a browser:\n${req.url}`);
- lines.push("\nAfter the browser flow, resume with the executionId below:");
+ lines.push('\nAfter the browser flow, call the resume tool with action "accept".');
+ } else if (hasRequestedSchema) {
+ lines.push(
+ "\nAsk the user for a response matching the requested schema, then call the resume tool.",
+ );
+ lines.push(`\nRequested schema:\n${JSON.stringify(requestedSchema, null, 2)}`);
} else {
- lines.push("\nResume with the executionId below and a response matching the requested schema:");
- const schema = req.requestedSchema;
- if (schema && Object.keys(schema).length > 0) {
- lines.push(`\nRequested schema:\n${JSON.stringify(schema, null, 2)}`);
- }
+ lines.push(
+ '\nThis is a model-side confirmation gate; no browser form is waiting. Ask the user whether to approve, then call the resume tool with action "accept", "decline", or "cancel".',
+ );
}
lines.push(`\nexecutionId: ${paused.id}`);
+ lines.push(`\ninstructions: ${instructions}`);
return {
text: lines.join("\n"),
@@ -129,6 +141,7 @@ export const formatPausedExecution = (
interaction: {
kind: isUrlElicitation ? "url" : "form",
message: req.message,
+ instructions,
toolId: String(paused.elicitationContext.toolId),
args: paused.elicitationContext.args,
...(isUrlElicitation ? { url: req.url } : {}),
diff --git a/packages/core/sdk/src/client.ts b/packages/core/sdk/src/client.ts
index d52cec093..ed07cbd01 100644
--- a/packages/core/sdk/src/client.ts
+++ b/packages/core/sdk/src/client.ts
@@ -96,6 +96,9 @@ export interface SourcePreset {
/** URL passed as `initialUrl` to the add form. Omit for presets that
* don't use a URL (e.g. stdio MCP presets). */
readonly url?: string;
+ /** Endpoint passed to agent-facing probe/add tools when their schema
+ * uses `endpoint` instead of `url`. */
+ readonly endpoint?: string;
/** Optional icon URL (favicon, logo). */
readonly icon?: string;
/** Shown in the top-level grid on the sources page when true. */
diff --git a/packages/core/sdk/src/core-tools.ts b/packages/core/sdk/src/core-tools.ts
index 612f9d3d0..cdf70c6fd 100644
--- a/packages/core/sdk/src/core-tools.ts
+++ b/packages/core/sdk/src/core-tools.ts
@@ -122,6 +122,7 @@ const SourcePresetOutput = Schema.Struct({
name: Schema.String,
summary: Schema.String,
url: Schema.optional(Schema.String),
+ endpoint: Schema.optional(Schema.String),
icon: Schema.optional(Schema.String),
featured: Schema.optional(Schema.Boolean),
transport: Schema.optional(Schema.Literals(["remote", "stdio"])),
@@ -642,7 +643,7 @@ export const coreToolsPlugin = definePlugin((options: CoreToolsPluginOptions = {
tool({
name: "sources.presets",
description:
- "List the same popular source presets shown in Executor web's Connect dialog. Use this before asking the user what to connect; filter with `query` for names like GitHub, Stripe, Axiom, Google Calendar, Linear, or OpenAI. Use the returned `pluginId`, `url`, and optional stdio command to choose the matching add flow (`openapi.previewSpec`/`openapi.addSource`, `graphql.addSource`, `mcp.probeEndpoint`/`mcp.addSource`, or `googleDiscovery.probeDiscovery`/`googleDiscovery.addSource`).",
+ "List the same popular source presets shown in Executor web's Connect dialog. Use this before asking the user what to connect; filter with `query` for names like GitHub, Stripe, Axiom, Google Calendar, Linear, or OpenAI. For MCP and GraphQL presets, pass `endpoint` to the probe/add tools. For OpenAPI and Google Discovery presets, pass `url` to the preview/probe and add tools. For stdio MCP presets, use the returned command/args/env.",
inputSchema: SourcesPresetsInputStd,
outputSchema: SourcesPresetsOutputStd,
execute: (input, { ctx }) =>
diff --git a/packages/core/sdk/src/plugin.ts b/packages/core/sdk/src/plugin.ts
index 2972d92af..0f4723b92 100644
--- a/packages/core/sdk/src/plugin.ts
+++ b/packages/core/sdk/src/plugin.ts
@@ -448,6 +448,7 @@ export interface SourcePreset {
readonly name: string;
readonly summary: string;
readonly url?: string;
+ readonly endpoint?: string;
readonly icon?: string;
readonly featured?: boolean;
readonly transport?: "remote" | "stdio";
diff --git a/packages/hosts/mcp/src/server.test.ts b/packages/hosts/mcp/src/server.test.ts
index 8afef4ada..34a5b669e 100644
--- a/packages/hosts/mcp/src/server.test.ts
+++ b/packages/hosts/mcp/src/server.test.ts
@@ -559,6 +559,35 @@ describe("MCP host server — client without elicitation (pause/resume)", () =>
const structured = result.structuredContent as Record;
expect(structured?.executionId).toBe("exec_42");
expect(structured?.status).toBe("waiting_for_interaction");
+ const interaction = structured.interaction as Record;
+ expect(interaction.instructions).toContain(
+ "Ask the user for values matching requestedSchema",
+ );
+ });
+ });
+
+ it("default model resume mode explains empty form schemas as model-side confirmation", async () => {
+ const engine = makeStubEngine({
+ executeWithPause: () =>
+ Effect.succeed(
+ makePausedResult(
+ "exec_confirm",
+ FormElicitation.make({ message: "Confirm source add", requestedSchema: {} }),
+ ),
+ ),
+ });
+
+ await withClient(engine, NO_CAPS, async (client) => {
+ const result = await client.callTool({
+ name: "execute",
+ arguments: { code: "confirm-me" },
+ });
+
+ expect(textOf(result)).toContain("no browser form is waiting");
+ const structured = result.structuredContent as Record;
+ const interaction = structured.interaction as Record;
+ expect(interaction.instructions).toContain("model-side confirmation gate");
+ expect(interaction.instructions).toContain('action "accept"');
});
});
diff --git a/packages/plugins/graphql/src/sdk/presets.ts b/packages/plugins/graphql/src/sdk/presets.ts
index f53f474bc..b169573cf 100644
--- a/packages/plugins/graphql/src/sdk/presets.ts
+++ b/packages/plugins/graphql/src/sdk/presets.ts
@@ -3,6 +3,7 @@ export interface GraphqlPreset {
readonly name: string;
readonly summary: string;
readonly url: string;
+ readonly endpoint: string;
readonly icon?: string;
readonly featured?: boolean;
}
@@ -13,6 +14,7 @@ export const graphqlPresets: readonly GraphqlPreset[] = [
name: "GitHub GraphQL",
summary: "Repos, issues, PRs, and users via GitHub's GraphQL API.",
url: "https://api.github.com/graphql",
+ endpoint: "https://api.github.com/graphql",
icon: "https://github.com/favicon.ico",
featured: true,
},
@@ -21,6 +23,7 @@ export const graphqlPresets: readonly GraphqlPreset[] = [
name: "GitLab",
summary: "Projects, merge requests, pipelines, and users.",
url: "https://gitlab.com/api/graphql",
+ endpoint: "https://gitlab.com/api/graphql",
icon: "https://gitlab.com/favicon.ico",
featured: true,
},
@@ -29,6 +32,7 @@ export const graphqlPresets: readonly GraphqlPreset[] = [
name: "Linear",
summary: "Issues, projects, teams, and cycles.",
url: "https://api.linear.app/graphql",
+ endpoint: "https://api.linear.app/graphql",
icon: "https://linear.app/favicon.ico",
featured: true,
},
@@ -37,6 +41,7 @@ export const graphqlPresets: readonly GraphqlPreset[] = [
name: "Monday.com",
summary: "Boards, items, columns, and workspace automation.",
url: "https://api.monday.com/v2",
+ endpoint: "https://api.monday.com/v2",
icon: "https://monday.com/favicon.ico",
},
{
@@ -44,6 +49,7 @@ export const graphqlPresets: readonly GraphqlPreset[] = [
name: "AniList",
summary: "Anime and manga database — no auth required.",
url: "https://graphql.anilist.co",
+ endpoint: "https://graphql.anilist.co",
icon: "https://anilist.co/img/icons/favicon-32x32.png",
},
];
diff --git a/packages/plugins/mcp/src/sdk/presets.ts b/packages/plugins/mcp/src/sdk/presets.ts
index 564633040..a8f75ef91 100644
--- a/packages/plugins/mcp/src/sdk/presets.ts
+++ b/packages/plugins/mcp/src/sdk/presets.ts
@@ -3,6 +3,7 @@ export interface McpRemotePreset {
readonly name: string;
readonly summary: string;
readonly url: string;
+ readonly endpoint: string;
readonly icon?: string;
readonly featured?: boolean;
readonly transport?: undefined;
@@ -28,6 +29,7 @@ export const mcpPresets: readonly McpPreset[] = [
name: "DeepWiki",
summary: "Search and read documentation from any GitHub repo.",
url: "https://mcp.deepwiki.com/mcp",
+ endpoint: "https://mcp.deepwiki.com/mcp",
icon: "https://deepwiki.com/favicon.ico",
featured: true,
},
@@ -36,6 +38,7 @@ export const mcpPresets: readonly McpPreset[] = [
name: "Context7",
summary: "Up-to-date docs and code examples for any library.",
url: "https://mcp.context7.com/mcp",
+ endpoint: "https://mcp.context7.com/mcp",
icon: "https://context7.com/favicon.ico",
featured: true,
},
@@ -44,6 +47,7 @@ export const mcpPresets: readonly McpPreset[] = [
name: "Browserbase",
summary: "Cloud browser sessions for web scraping and automation.",
url: "https://mcp.browserbase.com/mcp",
+ endpoint: "https://mcp.browserbase.com/mcp",
icon: "https://www.browserbase.com/favicon.ico",
featured: true,
},
@@ -52,6 +56,7 @@ export const mcpPresets: readonly McpPreset[] = [
name: "Firecrawl",
summary: "Crawl and scrape websites into structured data.",
url: "https://mcp.firecrawl.dev/mcp",
+ endpoint: "https://mcp.firecrawl.dev/mcp",
icon: "https://www.firecrawl.dev/favicon.ico",
featured: true,
},
@@ -60,6 +65,7 @@ export const mcpPresets: readonly McpPreset[] = [
name: "Neon",
summary: "Serverless Postgres — branches, queries, and management.",
url: "https://mcp.neon.tech/mcp",
+ endpoint: "https://mcp.neon.tech/mcp",
icon: "https://neon.tech/favicon/favicon.ico",
featured: true,
},
@@ -68,6 +74,7 @@ export const mcpPresets: readonly McpPreset[] = [
name: "Axiom",
summary: "Query, analyze, and monitor your logs and event data.",
url: "https://mcp.axiom.co/mcp",
+ endpoint: "https://mcp.axiom.co/mcp",
icon: "https://axiom.co/favicon.ico",
featured: true,
},
@@ -76,6 +83,7 @@ export const mcpPresets: readonly McpPreset[] = [
name: "Stripe",
summary: "Manage payments, subscriptions, and billing via MCP.",
url: "https://mcp.stripe.com",
+ endpoint: "https://mcp.stripe.com",
icon: "https://stripe.com/favicon.ico",
featured: true,
},
@@ -84,6 +92,7 @@ export const mcpPresets: readonly McpPreset[] = [
name: "Linear",
summary: "Issues, projects, teams, and cycles via MCP.",
url: "https://mcp.linear.app/mcp",
+ endpoint: "https://mcp.linear.app/mcp",
icon: "https://linear.app/favicon.ico",
featured: true,
},
@@ -92,6 +101,7 @@ export const mcpPresets: readonly McpPreset[] = [
name: "Notion",
summary: "Databases, pages, blocks, and search via MCP.",
url: "https://mcp.notion.com/mcp",
+ endpoint: "https://mcp.notion.com/mcp",
icon: "https://www.notion.com/front-static/favicon.ico",
featured: true,
},
@@ -100,6 +110,7 @@ export const mcpPresets: readonly McpPreset[] = [
name: "Sentry",
summary: "Error monitoring, issues, and performance data.",
url: "https://mcp.sentry.dev/mcp",
+ endpoint: "https://mcp.sentry.dev/mcp",
icon: "https://sentry-brand.storage.googleapis.com/sentry-glyph-black.png",
},
{
@@ -107,6 +118,7 @@ export const mcpPresets: readonly McpPreset[] = [
name: "Cloudflare",
summary: "Workers, KV, D1, R2, and DNS management via MCP.",
url: "https://mcp.cloudflare.com/mcp",
+ endpoint: "https://mcp.cloudflare.com/mcp",
icon: "https://cloudflare.com/favicon.ico",
},
{