Skip to content

Commit 5b19b89

Browse files
committed
refactor: remove client active/inactive status tracking
The has_active_tokens field and clients_with_tokens in-memory set tracked whether clients had been issued tokens to show Active/Inactive status badges in the UI. This status was unreliable (in-memory only, lost on restart) and not needed. Removes the status badges from the clients page, the tracking state from the gateway, and the field from both gateway and Tauri response structs. Signed-off-by: Mohammod Al Amin Ashik <maa.ashik00@gmail.com>
1 parent a4919db commit 5b19b89

7 files changed

Lines changed: 52 additions & 106 deletions

File tree

apps/desktop/src-tauri/src/commands/oauth.rs

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -668,28 +668,25 @@ pub async fn get_oauth_clients(
668668
// Map to response format
669669
let client_infos: Vec<OAuthClientInfo> = clients
670670
.into_iter()
671-
.map(|client| {
672-
OAuthClientInfo {
673-
client_id: client.client_id,
674-
registration_type: client.registration_type.as_str().to_string(),
675-
client_name: client.client_name,
676-
client_alias: client.client_alias,
677-
redirect_uris: client.redirect_uris,
678-
scope: client.scope,
679-
approved: client.approved,
680-
logo_uri: client.logo_uri,
681-
client_uri: client.client_uri,
682-
software_id: client.software_id,
683-
software_version: client.software_version,
684-
metadata_url: client.metadata_url,
685-
metadata_cached_at: client.metadata_cached_at,
686-
metadata_cache_ttl: client.metadata_cache_ttl,
687-
connection_mode: client.connection_mode,
688-
locked_space_id: client.locked_space_id,
689-
last_seen: client.last_seen,
690-
created_at: client.created_at,
691-
has_active_tokens: false, // TODO: Check if client has active tokens
692-
}
671+
.map(|client| OAuthClientInfo {
672+
client_id: client.client_id,
673+
registration_type: client.registration_type.as_str().to_string(),
674+
client_name: client.client_name,
675+
client_alias: client.client_alias,
676+
redirect_uris: client.redirect_uris,
677+
scope: client.scope,
678+
approved: client.approved,
679+
logo_uri: client.logo_uri,
680+
client_uri: client.client_uri,
681+
software_id: client.software_id,
682+
software_version: client.software_version,
683+
metadata_url: client.metadata_url,
684+
metadata_cached_at: client.metadata_cached_at,
685+
metadata_cache_ttl: client.metadata_cache_ttl,
686+
connection_mode: client.connection_mode,
687+
locked_space_id: client.locked_space_id,
688+
last_seen: client.last_seen,
689+
created_at: client.created_at,
693690
})
694691
.collect();
695692

@@ -763,7 +760,6 @@ pub struct OAuthClientInfo {
763760
pub locked_space_id: Option<String>,
764761
pub last_seen: Option<String>,
765762
pub created_at: String,
766-
pub has_active_tokens: bool,
767763
}
768764

769765
/// Request to update client settings
@@ -837,7 +833,6 @@ pub async fn update_oauth_client(
837833
locked_space_id: updated_client.locked_space_id,
838834
last_seen: updated_client.last_seen,
839835
created_at: updated_client.created_at,
840-
has_active_tokens: false,
841836
})
842837
}
843838

apps/desktop/src/features/clients/ClientsPage.tsx

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import {
1111
Lock,
1212
Unlock,
1313
HelpCircle,
14-
Wifi,
15-
WifiOff,
1614
RefreshCw,
1715
Settings,
1816
Trash2,
@@ -649,21 +647,6 @@ export default function ClientsPage() {
649647
</div>
650648
</div>
651649

652-
{/* Status Badge */}
653-
<div className="mb-4">
654-
<span className={`inline-flex items-center gap-2 text-sm px-3 py-1.5 rounded-full font-medium ${
655-
client.has_active_tokens
656-
? 'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400'
657-
: 'bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400'
658-
}`}>
659-
{client.has_active_tokens ? (
660-
<><Wifi className="h-4 w-4" /> Active</>
661-
) : (
662-
<><WifiOff className="h-4 w-4" /> Inactive</>
663-
)}
664-
</span>
665-
</div>
666-
667650
{/* Connection Mode */}
668651
<div className="flex items-center gap-2.5 text-sm text-[rgb(var(--foreground))] mb-2">
669652
<ModeIcon className={`h-4 w-4 ${modeInfo.color}`} />
@@ -722,25 +705,11 @@ export default function ClientsPage() {
722705
</button>
723706
</div>
724707

725-
{/* Quick Status */}
726-
<div className="flex items-center gap-2 flex-wrap">
727-
<span className={`inline-flex items-center gap-1.5 text-xs px-2.5 py-1 rounded-full font-medium ${
728-
selectedClient.has_active_tokens
729-
? 'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400'
730-
: 'bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400'
731-
}`}>
732-
{selectedClient.has_active_tokens ? (
733-
<><Wifi className="h-3 w-3" /> Connected</>
734-
) : (
735-
<><WifiOff className="h-3 w-3" /> Inactive</>
736-
)}
708+
{selectedClient.software_version && (
709+
<span className="text-xs text-[rgb(var(--muted))] px-2.5 py-1 bg-[rgb(var(--background))] rounded-full inline-block mt-1">
710+
v{selectedClient.software_version}
737711
</span>
738-
{selectedClient.software_version && (
739-
<span className="text-xs text-[rgb(var(--muted))] px-2.5 py-1 bg-[rgb(var(--background))] rounded-full">
740-
v{selectedClient.software_version}
741-
</span>
742-
)}
743-
</div>
712+
)}
744713
</div>
745714

746715
{/* Scrollable Content */}

apps/desktop/src/lib/api/gateway.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ export interface OAuthClient {
131131
locked_space_id: string | null;
132132
last_seen: string | null;
133133
created_at: string;
134-
has_active_tokens: boolean;
135134
}
136135

137136
/**

crates/mcpmux-gateway/src/server/handlers.rs

Lines changed: 21 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -602,12 +602,9 @@ pub async fn oauth_token(
602602
let client_id_for_tracking = pending.client_id.clone();
603603
drop(gateway_state);
604604

605-
// Track that this client has active tokens and emit event
605+
// Update last_seen and emit event
606606
{
607-
let mut gateway_state = state.write().await;
608-
gateway_state
609-
.clients_with_tokens
610-
.insert(client_id_for_tracking.clone());
607+
let gateway_state = state.read().await;
611608

612609
// Update last_seen in database
613610
if let Some(repo) = gateway_state.inbound_client_repository() {
@@ -949,7 +946,6 @@ pub struct OAuthClientInfoResponse {
949946
pub locked_space_id: Option<String>,
950947
pub last_seen: Option<String>,
951948
pub created_at: String,
952-
pub has_active_tokens: bool,
953949
}
954950

955951
/// List all registered OAuth clients
@@ -969,28 +965,24 @@ pub async fn oauth_list_clients(
969965
Ok(db_clients) => {
970966
let clients: Vec<OAuthClientInfoResponse> = db_clients
971967
.into_iter()
972-
.map(|c| {
973-
let has_active = gateway_state.clients_with_tokens.contains(&c.client_id);
974-
OAuthClientInfoResponse {
975-
client_id: c.client_id,
976-
registration_type: c.registration_type.as_str().to_string(),
977-
client_name: c.client_name,
978-
client_alias: c.client_alias,
979-
redirect_uris: c.redirect_uris,
980-
scope: c.scope,
981-
logo_uri: c.logo_uri,
982-
client_uri: c.client_uri,
983-
software_id: c.software_id,
984-
software_version: c.software_version,
985-
metadata_url: c.metadata_url,
986-
metadata_cached_at: c.metadata_cached_at,
987-
metadata_cache_ttl: c.metadata_cache_ttl,
988-
connection_mode: c.connection_mode,
989-
locked_space_id: c.locked_space_id,
990-
last_seen: c.last_seen,
991-
created_at: c.created_at,
992-
has_active_tokens: has_active,
993-
}
968+
.map(|c| OAuthClientInfoResponse {
969+
client_id: c.client_id,
970+
registration_type: c.registration_type.as_str().to_string(),
971+
client_name: c.client_name,
972+
client_alias: c.client_alias,
973+
redirect_uris: c.redirect_uris,
974+
scope: c.scope,
975+
logo_uri: c.logo_uri,
976+
client_uri: c.client_uri,
977+
software_id: c.software_id,
978+
software_version: c.software_version,
979+
metadata_url: c.metadata_url,
980+
metadata_cached_at: c.metadata_cached_at,
981+
metadata_cache_ttl: c.metadata_cache_ttl,
982+
connection_mode: c.connection_mode,
983+
locked_space_id: c.locked_space_id,
984+
last_seen: c.last_seen,
985+
created_at: c.created_at,
994986
})
995987
.collect();
996988
info!("[OAuth] Listed {} clients from database", clients.len());
@@ -1213,9 +1205,6 @@ pub async fn oauth_update_client(
12131205
.await
12141206
{
12151207
Ok(Some(client)) => {
1216-
let has_active = gateway_state
1217-
.clients_with_tokens
1218-
.contains(&client.client_id);
12191208
let response = OAuthClientInfoResponse {
12201209
client_id: client.client_id,
12211210
registration_type: client.registration_type.as_str().to_string(),
@@ -1234,7 +1223,6 @@ pub async fn oauth_update_client(
12341223
locked_space_id: client.locked_space_id,
12351224
last_seen: client.last_seen,
12361225
created_at: client.created_at,
1237-
has_active_tokens: has_active,
12381226
};
12391227
info!("[OAuth] Client updated: {}", response.client_id);
12401228
Json(response).into_response()
@@ -1264,7 +1252,7 @@ pub async fn oauth_delete_client(
12641252
) -> Response {
12651253
info!("[OAuth] Deleting client: {}", client_id);
12661254

1267-
let mut gateway_state = state.write().await;
1255+
let gateway_state = state.read().await;
12681256

12691257
let Some(repo) = gateway_state.inbound_client_repository() else {
12701258
warn!("[OAuth] Database not available for client deletion");
@@ -1273,8 +1261,6 @@ pub async fn oauth_delete_client(
12731261

12741262
match repo.delete_client(&client_id).await {
12751263
Ok(true) => {
1276-
// Remove from active tokens set
1277-
gateway_state.clients_with_tokens.remove(&client_id);
12781264
info!("[OAuth] Client deleted: {}", client_id);
12791265
StatusCode::NO_CONTENT.into_response()
12801266
}

crates/mcpmux-gateway/src/server/state.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ pub struct GatewayState {
5151
pub oauth_tokens: HashMap<String, super::super::oauth::OAuthToken>,
5252
/// Pending authorization codes (code -> PendingAuthorization)
5353
pub pending_authorizations: HashMap<String, PendingAuthorization>,
54-
/// Set of client_ids that have been issued tokens (for "active" status)
55-
pub clients_with_tokens: std::collections::HashSet<String>,
5654
/// JWT signing secret (for issuing access tokens)
5755
pub jwt_signing_secret: Option<Zeroizing<[u8; JWT_SECRET_SIZE]>>,
5856
/// Database connection (for persistent OAuth storage)
@@ -74,7 +72,6 @@ impl GatewayState {
7472
access_keys: HashMap::new(),
7573
oauth_tokens: HashMap::new(),
7674
pending_authorizations: HashMap::new(),
77-
clients_with_tokens: std::collections::HashSet::new(),
7875
jwt_signing_secret: None,
7976
db: None,
8077
inbound_client_repository: None,

scripts/take-screenshots.cjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,8 @@ const FEATURE_SETS = [
138138
];
139139

140140
const OAUTH_CLIENTS = [
141-
{ client_id: 'cursor-001', registration_type: 'dcr', client_name: 'Cursor', client_alias: null, redirect_uris: ['http://localhost:9315/callback'], scope: null, approved: true, logo_uri: null, client_uri: null, software_id: 'cursor', software_version: '0.45.0', metadata_url: null, metadata_cached_at: null, metadata_cache_ttl: null, connection_mode: 'follow_active', locked_space_id: null, last_seen: '2026-02-07T09:30:00Z', created_at: '2026-01-20T10:00:00Z', has_active_tokens: true },
142-
{ client_id: 'vscode-001', registration_type: 'dcr', client_name: 'VS Code', client_alias: null, redirect_uris: ['http://localhost:9315/callback'], scope: null, approved: true, logo_uri: null, client_uri: null, software_id: 'vscode', software_version: '1.96.0', metadata_url: null, metadata_cached_at: null, metadata_cache_ttl: null, connection_mode: 'follow_active', locked_space_id: null, last_seen: '2026-02-07T08:45:00Z', created_at: '2026-01-22T10:00:00Z', has_active_tokens: true },
141+
{ client_id: 'cursor-001', registration_type: 'dcr', client_name: 'Cursor', client_alias: null, redirect_uris: ['http://localhost:9315/callback'], scope: null, approved: true, logo_uri: null, client_uri: null, software_id: 'cursor', software_version: '0.45.0', metadata_url: null, metadata_cached_at: null, metadata_cache_ttl: null, connection_mode: 'follow_active', locked_space_id: null, last_seen: '2026-02-07T09:30:00Z', created_at: '2026-01-20T10:00:00Z' },
142+
{ client_id: 'vscode-001', registration_type: 'dcr', client_name: 'VS Code', client_alias: null, redirect_uris: ['http://localhost:9315/callback'], scope: null, approved: true, logo_uri: null, client_uri: null, software_id: 'vscode', software_version: '1.96.0', metadata_url: null, metadata_cached_at: null, metadata_cache_ttl: null, connection_mode: 'follow_active', locked_space_id: null, last_seen: '2026-02-07T08:45:00Z', created_at: '2026-01-22T10:00:00Z' },
143143
];
144144

145145
function mkRegistry(id, name, desc, alias, icon, categories, auth, transportType, publisher, caps, hostingType, badges) {

tests/e2e/specs/clients.spec.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,18 +55,18 @@ test.describe('Clients Page', () => {
5555
});
5656

5757
test.describe('Client Details', () => {
58-
test('should show client connection status', async ({ page }) => {
58+
test('should show client details', async ({ page }) => {
5959
const dashboard = new DashboardPage(page);
6060
await dashboard.navigate();
6161
await page.locator('nav button:has-text("Clients")').click();
62-
62+
6363
const clientCards = page.locator('[class*="rounded"][class*="border"]');
6464
const count = await clientCards.count();
65-
65+
6666
if (count > 0) {
67-
// Clients should have status indicators
68-
const statusIndicator = page.locator('[class*="bg-green"], [class*="bg-red"], text=/connected|active/i');
69-
// May or may not be visible
67+
// Clients should have connection mode indicators
68+
const firstCard = clientCards.first();
69+
await expect(firstCard).toBeVisible();
7070
}
7171
});
7272

0 commit comments

Comments
 (0)