Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/clear-toolset-user-session-issuer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"server": minor
---

Add `toolsets.clearUserSessionIssuer` endpoint that unlinks any user_session_issuer attached to a toolset.
5 changes: 5 additions & 0 deletions .changeset/remove-user-session-issuer-button.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"dashboard": patch
---

Add admin-only "Remove user session issuer" button on the MCP authentication tab that unlinks the toolset's user_session_issuer via `toolsets.clearUserSessionIssuer`.
109 changes: 109 additions & 0 deletions .speakeasy/out.openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23037,6 +23037,115 @@ paths:
x-speakeasy-name-override: checkMCPSlugAvailability
x-speakeasy-react-hook:
name: CheckMCPSlugAvailability
/rpc/toolsets.clearUserSessionIssuer:
post:
description: Unlink the user_session_issuer from a toolset. No-op if the toolset has no user_session_issuer linked.
operationId: clearToolsetUserSessionIssuer
parameters:
- allowEmptyValue: true
description: The slug of the toolset to unlink
in: query
name: slug
required: true
schema:
description: A short url-friendly label that uniquely identifies a resource.
maxLength: 40
pattern: ^[a-z0-9_-]{1,128}$
type: string
- allowEmptyValue: true
description: Session header
in: header
name: Gram-Session
schema:
description: Session header
type: string
- allowEmptyValue: true
description: API Key header
in: header
name: Gram-Key
schema:
description: API Key header
type: string
- allowEmptyValue: true
description: project header
in: header
name: Gram-Project
schema:
description: project header
type: string
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Toolset'
description: OK response.
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: 'bad_request: request is invalid'
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: 'unauthorized: unauthorized access'
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: 'forbidden: permission denied'
"404":
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: 'not_found: resource not found'
"409":
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: 'conflict: resource already exists'
"415":
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: 'unsupported_media: unsupported media type'
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: 'invalid: request contains one or more invalidation fields'
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: 'unexpected: an unexpected error occurred'
"502":
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: 'gateway_error: an unexpected error occurred'
security:
- project_slug_header_Gram-Project: []
session_header_Gram-Session: []
- apikey_header_Gram-Key: []
project_slug_header_Gram-Project: []
- {}
summary: clearUserSessionIssuer toolsets
tags:
- toolsets
x-speakeasy-name-override: clearUserSessionIssuer
x-speakeasy-react-hook:
name: ClearToolsetUserSessionIssuer
/rpc/toolsets.clone:
post:
description: Clone an existing toolset with a new name
Expand Down
10 changes: 5 additions & 5 deletions .speakeasy/workflow.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cli/internal/api/toolsets.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func NewToolsetsClient(options *ToolsetsClientOptions) *ToolsetsClient {
h.AddOAuthProxyServer(),
h.UpdateOAuthProxyServer(),
h.SetUserSessionIssuer(),
h.ClearUserSessionIssuer(),
)

return &ToolsetsClient{client: client}
Expand Down
31 changes: 30 additions & 1 deletion client/dashboard/src/pages/mcp/MCPEnvironmentSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { useSession } from "@/contexts/Auth";
import { useIsAdmin, useSession } from "@/contexts/Auth";
import { useTelemetry } from "@/contexts/Telemetry";
import { useMissingRequiredEnvVars } from "@/hooks/useMissingEnvironmentVariables";
import { ONBOARD_EXTERNAL_MCP_TO_USER_SESSIONS_FLAG } from "@/lib/externalMcpUserSessions";
Expand All @@ -18,6 +18,7 @@ import {
invalidateAllGetMcpMetadata,
invalidateAllListEnvironments,
invalidateAllToolset,
useClearToolsetUserSessionIssuerMutation,
useCreateEnvironmentMutation,
useGetMcpMetadata,
useListEnvironments,
Expand Down Expand Up @@ -902,10 +903,23 @@ function OAuthSection({ toolset }: OAuthSectionProps) {
] = useState(false);

const telemetry = useTelemetry();
const isAdmin = useIsAdmin();
const queryClient = useQueryClient();

const { data: environmentsData } = useListEnvironments();
const environments = environmentsData?.environments ?? [];

const clearUserSessionIssuerMutation =
useClearToolsetUserSessionIssuerMutation({
onSuccess: () => {
invalidateAllToolset(queryClient);
toast.success("Removed user session issuer from toolset");
},
onError: (err) => {
toast.error(`Failed to remove user session issuer: ${err.message}`);
},
});

const loginSecured = !!toolset.userSessionIssuerSlug;
const isOAuthConnected = !!(
toolset?.oauthProxyServer || toolset?.externalOauthServer
Expand Down Expand Up @@ -973,6 +987,21 @@ function OAuthSection({ toolset }: OAuthSectionProps) {
<Badge.Text>Login Secured</Badge.Text>
</Badge>
)}
{userSessionIssuerWired && isAdmin && (
<Button
variant="tertiary"
size="sm"
className="text-muted-foreground hover:text-destructive hover:border-destructive"
disabled={clearUserSessionIssuerMutation.isPending}
onClick={() =>
clearUserSessionIssuerMutation.mutate({
request: { slug: toolset.slug },
})
}
>
<Button.Text>Remove user session issuer</Button.Text>
</Button>
)}
{showWireUserSessionIssuer && (
<Button
variant="tertiary"
Expand Down
36 changes: 31 additions & 5 deletions client/sdk/.speakeasy/gen.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions client/sdk/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading