Skip to content

Commit d248e52

Browse files
jchangxclaude
andcommitted
Clean up DCR entries on OAuth revoke using profile-aware logic
Export CleanupOrphanedDCREntries so it can be called from the revoke command. After revoking tokens, the CLI now checks whether the server is still in any profile before deleting its DCR entry. This replaces the catalog-based IsRemoteOAuthServer check which missed community servers without oauth.providers metadata. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 2c4ac22 commit d248e52

File tree

2 files changed

+19
-24
lines changed

2 files changed

+19
-24
lines changed

cmd/docker-mcp/oauth/revoke.go

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import (
44
"context"
55
"fmt"
66

7-
"github.com/docker/mcp-gateway/pkg/catalog"
7+
"github.com/docker/mcp-gateway/pkg/db"
88
"github.com/docker/mcp-gateway/pkg/desktop"
99
pkgoauth "github.com/docker/mcp-gateway/pkg/oauth"
10+
"github.com/docker/mcp-gateway/pkg/workingset"
1011
)
1112

1213
func Revoke(ctx context.Context, app string) error {
@@ -25,28 +26,21 @@ func Revoke(ctx context.Context, app string) error {
2526
func revokeDesktopMode(ctx context.Context, app string) error {
2627
client := desktop.NewAuthClient()
2728

28-
// Get catalog to check if this is a remote OAuth server
29-
catalogData, err := catalog.GetWithOptions(ctx, true, nil)
30-
if err != nil {
31-
return fmt.Errorf("failed to get catalog: %w", err)
32-
}
33-
34-
server, found := catalogData.Servers[app]
35-
isRemoteOAuth := found && server.IsRemoteOAuthServer()
36-
3729
// Revoke tokens
3830
if err := client.DeleteOAuthApp(ctx, app); err != nil {
3931
return fmt.Errorf("failed to revoke OAuth access: %w", err)
4032
}
4133

42-
// For remote OAuth servers, also delete DCR client
43-
if isRemoteOAuth {
44-
if err := client.DeleteDCRClient(ctx, app); err != nil {
45-
return fmt.Errorf("failed to remove DCR client: %w", err)
46-
}
34+
fmt.Printf("OAuth access revoked for %s\n", app)
35+
36+
// Clean up DCR entry if the server is not in any profile.
37+
// If the server is still in a profile, keep the DCR entry so it
38+
// remains visible in the OAuth UI for re-authorization.
39+
dao, err := db.New()
40+
if err == nil {
41+
workingset.CleanupOrphanedDCREntries(ctx, dao, []string{app})
4742
}
4843

49-
fmt.Printf("OAuth access revoked for %s\n", app)
5044
return nil
5145
}
5246

pkg/workingset/server.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,17 +95,18 @@ func RemoveServers(ctx context.Context, dao db.DAO, id string, serverNames []str
9595
namesToRemove[name] = true
9696
}
9797

98-
originalCount := len(workingSet.Servers)
98+
removedNames := make([]string, 0)
9999
filtered := make([]Server, 0, len(workingSet.Servers))
100100
for _, server := range workingSet.Servers {
101101
// TODO: Remove when Snapshot is required
102-
if server.Snapshot == nil || !namesToRemove[server.Snapshot.Server.Name] {
102+
if server.Snapshot != nil && namesToRemove[server.Snapshot.Server.Name] {
103+
removedNames = append(removedNames, server.Snapshot.Server.Name)
104+
} else {
103105
filtered = append(filtered, server)
104106
}
105107
}
106108

107-
removedCount := originalCount - len(filtered)
108-
if removedCount == 0 {
109+
if len(removedNames) == 0 {
109110
return fmt.Errorf("no matching servers found to remove")
110111
}
111112

@@ -120,10 +121,10 @@ func RemoveServers(ctx context.Context, dao db.DAO, id string, serverNames []str
120121
return fmt.Errorf("failed to update profile: %w", err)
121122
}
122123

123-
fmt.Printf("Removed %d server(s) from profile %s\n", removedCount, id)
124+
fmt.Printf("Removed %d server(s) from profile %s\n", len(removedNames), id)
124125

125126
// Clean up DCR entries for removed servers not in any other profile
126-
cleanupOrphanedDCREntries(ctx, dao, serverNames)
127+
CleanupOrphanedDCREntries(ctx, dao, removedNames)
127128

128129
return nil
129130
}
@@ -136,9 +137,9 @@ type dcrClient interface {
136137
DeleteDCRClient(ctx context.Context, app string) error
137138
}
138139

139-
// cleanupOrphanedDCREntries removes DCR entries for servers that no longer
140+
// CleanupOrphanedDCREntries removes DCR entries for servers that no longer
140141
// exist in any profile. This prevents stale OAuth entries from accumulating.
141-
func cleanupOrphanedDCREntries(ctx context.Context, dao db.DAO, serverNames []string) {
142+
func CleanupOrphanedDCREntries(ctx context.Context, dao db.DAO, serverNames []string) {
142143
if oauth.IsCEMode() {
143144
return
144145
}

0 commit comments

Comments
 (0)