Refine Browser naming and managed MCP UX

- Rename Browser Use surfaces to Browser
- Register Browser MCP under the new server name
- Mark CloudCLI-managed MCP servers read-only
- Adjust MCP stdio framing and sidebar footer sizing
This commit is contained in:
Simos Mikelatos
2026-06-17 19:18:23 +00:00
parent 9881e5e366
commit 59194d1502
17 changed files with 166 additions and 132 deletions

View File

@@ -71,7 +71,6 @@ function AppContentInner() {
setActiveTab,
setSidebarOpen,
setIsInputFocused,
setShowSettings,
openSettings,
refreshProjectsSilently,
registerOptimisticSession,
@@ -247,7 +246,7 @@ function AppContentInner() {
onSessionEstablished={(targetSessionId, context) =>
registerOptimisticSession({ sessionId: targetSessionId, ...context })
}
onShowSettings={() => setShowSettings(true)}
onShowSettings={openSettings}
externalMessageUpdate={externalMessageUpdate}
newSessionTrigger={newSessionTrigger}
/>

View File

@@ -17,6 +17,7 @@ import {
import { cn } from '../../../lib/utils';
import { Badge, Button } from '../../../shared/view/ui';
import { authenticatedFetch } from '../../../utils/api';
import type { SettingsMainTab } from '../../settings/types/types';
type BrowserUseStatus = {
enabled: boolean;
@@ -53,7 +54,7 @@ type BrowserUseSession = {
type BrowserUsePanelProps = {
isVisible: boolean;
onShowSettings?: () => void;
onShowSettings?: (tab?: SettingsMainTab) => void;
};
async function readJson<T>(response: Response): Promise<T> {
@@ -119,8 +120,8 @@ function getStatusDot(status: BrowserUseSession['status']): string {
}
const PROMPTS = [
'Use Browser Use to inspect the checkout flow and report any broken UI states.',
'Open <url> with Browser Use, interact with the page, and summarize what changed after each step.',
'Use Browser to inspect the checkout flow and report any broken UI states.',
'Open <url> with Browser, interact with the page, and summarize what changed after each step.',
];
export default function BrowserUsePanel({ isVisible, onShowSettings }: BrowserUsePanelProps) {
@@ -174,7 +175,7 @@ export default function BrowserUsePanel({ isVisible, onShowSettings }: BrowserUs
));
setError(null);
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to load Browser Use');
setError(err instanceof Error ? err.message : 'Failed to load Browser');
} finally {
setIsRefreshing(false);
}
@@ -192,7 +193,7 @@ export default function BrowserUsePanel({ isVisible, onShowSettings }: BrowserUs
await action();
await refresh();
} catch (err) {
setError(err instanceof Error ? err.message : 'Browser Use action failed');
setError(err instanceof Error ? err.message : 'Browser action failed');
} finally {
setIsBusy(false);
}
@@ -265,12 +266,12 @@ export default function BrowserUsePanel({ isVisible, onShowSettings }: BrowserUs
</div>
<div className="min-w-0">
<div className="text-sm font-semibold text-foreground">
{status?.enabled ? 'No browser sessions yet' : 'Browser Use is disabled'}
{status?.enabled ? 'No browser sessions yet' : 'Browser is disabled'}
</div>
<p className="mt-1 max-w-xl text-sm leading-6 text-muted-foreground">
{status?.enabled
? 'Agent browser sessions appear here while an AI task is using Browser Use.'
: 'Enable Browser Use in settings to let agents open monitored browser sessions.'}
? 'Agent browser sessions appear here while an AI task is using Browser.'
: 'Enable Browser in settings to let agents open monitored browser sessions.'}
</p>
</div>
</div>
@@ -345,7 +346,7 @@ export default function BrowserUsePanel({ isVisible, onShowSettings }: BrowserUs
<div className="min-w-0">
<div className="flex items-center gap-2">
<MonitorPlay className="h-4 w-4 text-primary" />
<h3 className="text-sm font-semibold text-foreground">Browser Use</h3>
<h3 className="text-sm font-semibold text-foreground">Browser</h3>
<Badge variant="outline" className={cn('text-[10px]', getRuntimeTone(status, isInstalling))}>
{runtimeLabel}
</Badge>
@@ -358,9 +359,9 @@ export default function BrowserUsePanel({ isVisible, onShowSettings }: BrowserUs
variant="ghost"
size="sm"
className="h-7 w-7 p-0"
onClick={onShowSettings}
title="Open Browser Use settings"
aria-label="Open Browser Use settings"
onClick={() => onShowSettings('browser')}
title="Open Browser settings"
aria-label="Open Browser settings"
>
<Settings className="h-3.5 w-3.5" />
</Button>

View File

@@ -7,6 +7,7 @@ import type {
SessionActivityMap,
} from '../../../hooks/useSessionProtection';
import type { SessionEstablishedContext, SessionNavigationOptions } from '../../chat/types/types';
import type { SettingsMainTab } from '../../settings/types/types';
export type TaskMasterTask = {
id: string | number;
@@ -53,7 +54,7 @@ export type MainContentProps = {
processingSessions: SessionActivityMap;
onNavigateToSession: (targetSessionId: string, options?: SessionNavigationOptions) => void;
onSessionEstablished: (sessionId: string, context: SessionEstablishedContext) => void;
onShowSettings: () => void;
onShowSettings: (tab?: SettingsMainTab) => void;
externalMessageUpdate: number;
newSessionTrigger: number;
};

View File

@@ -29,7 +29,7 @@ function getTabTitle(activeTab: AppTab, shouldShowTasksTab: boolean, t: (key: st
}
if (activeTab === 'browser') {
return 'Browser Use';
return 'Browser';
}
return 'Project';

View File

@@ -52,6 +52,11 @@ const getServerKey = (server: ProviderMcpServer): string => (
`${server.provider}:${server.scope}:${server.workspacePath || 'global'}:${server.name}`
);
// Servers prefixed with `cloudcli-` are written and removed automatically by a
// CloudCLI feature toggle (e.g. the Browser tab), not added by the user. They are
// shown read-only so users don't edit/delete them out of sync with the feature.
const isManagedServer = (server: ProviderMcpServer): boolean => server.name.startsWith('cloudcli-');
function ConfigLine({ label, children }: { label: string; children: string }) {
if (!children) {
return null;
@@ -195,6 +200,12 @@ export default function McpServers({ selectedProvider, currentProjects }: McpSer
{server.projectDisplayName}
</Badge>
)}
{isManagedServer(server) && (
<Badge variant="outline" className="gap-1 text-xs text-muted-foreground">
<Lock className="h-3 w-3" />
{t('mcpServers.managed.badge', { defaultValue: 'Managed' })}
</Badge>
)}
</div>
<div className="space-y-1 text-sm text-muted-foreground">
@@ -210,29 +221,38 @@ export default function McpServers({ selectedProvider, currentProjects }: McpSer
{server.envVars && server.envVars.length > 0 && (
<ConfigLine label="Env Vars">{server.envVars.join(', ')}</ConfigLine>
)}
{isManagedServer(server) && (
<div className="pt-1 text-xs italic text-muted-foreground">
{t('mcpServers.managed.hint', {
defaultValue: 'Managed by CloudCLI — control it from the feature\'s settings toggle.',
})}
</div>
)}
</div>
</div>
<div className="ml-4 flex items-center gap-2">
<Button
onClick={() => openForm(server)}
variant="ghost"
size="sm"
className="text-muted-foreground hover:text-foreground"
title={t('mcpServers.actions.edit')}
>
<Edit3 className="h-4 w-4" />
</Button>
<Button
onClick={() => deleteServer(server)}
variant="ghost"
size="sm"
className="text-red-600 hover:text-red-700"
title={t('mcpServers.actions.delete')}
>
<Trash2 className="h-4 w-4" />
</Button>
</div>
{!isManagedServer(server) && (
<div className="ml-4 flex items-center gap-2">
<Button
onClick={() => openForm(server)}
variant="ghost"
size="sm"
className="text-muted-foreground hover:text-foreground"
title={t('mcpServers.actions.edit')}
>
<Edit3 className="h-4 w-4" />
</Button>
<Button
onClick={() => deleteServer(server)}
variant="ghost"
size="sm"
className="text-red-600 hover:text-red-700"
title={t('mcpServers.actions.delete')}
>
<Trash2 className="h-4 w-4" />
</Button>
</div>
)}
</div>
</div>
))}

View File

@@ -33,7 +33,7 @@ export const SETTINGS_MAIN_TABS: SettingsMainTabMeta[] = [
{ id: 'git', label: 'Git', keywords: 'git github commits', icon: GitBranch },
{ id: 'api', label: 'API Tokens', keywords: 'api tokens auth keys', icon: KeyRound },
{ id: 'tasks', label: 'Tasks', keywords: 'tasks taskmaster', icon: ListChecks },
{ id: 'browser', label: 'Browser Use', keywords: 'browser use playwright chromium automation', icon: MonitorPlay },
{ id: 'browser', label: 'Browser', keywords: 'browser playwright chromium automation', icon: MonitorPlay },
{ id: 'notifications', label: 'Notifications', keywords: 'notifications alerts push', icon: Bell },
{ id: 'plugins', label: 'Plugins', keywords: 'plugins extensions integrations', icon: Plug },
{ id: 'about', label: 'About', keywords: 'about version info', icon: Info },

View File

@@ -52,7 +52,7 @@ export default function BrowserUseSettingsTab() {
useEffect(() => {
setIsLoading(true);
void loadState()
.catch((err) => setError(err instanceof Error ? err.message : 'Failed to load Browser Use settings'))
.catch((err) => setError(err instanceof Error ? err.message : 'Failed to load Browser settings'))
.finally(() => setIsLoading(false));
}, [loadState]);
@@ -69,7 +69,7 @@ export default function BrowserUseSettingsTab() {
window.dispatchEvent(new Event('browserUseSettingsChanged'));
await loadState();
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to save Browser Use settings');
setError(err instanceof Error ? err.message : 'Failed to save Browser settings');
} finally {
setIsSaving(false);
}
@@ -94,18 +94,18 @@ export default function BrowserUseSettingsTab() {
return (
<div className="space-y-8">
<SettingsSection
title="Browser Use"
description="Allow agents to create guarded Playwright browser sessions that you can monitor from the Browser Use tab."
title="Browser"
description="Allow agents to create guarded Playwright browser sessions that you can monitor from the Browser tab."
>
<SettingsCard divided>
<SettingsRow
label="Enable Browser Use"
description="Registers Browser Use for supported agents. Agents can create browser sessions; you can watch, stop, and delete them."
label="Enable Browser"
description="Registers Browser for supported agents. Agents can create browser sessions; you can watch, stop, and delete them."
>
<SettingsToggle
checked={settings.enabled}
onChange={(value) => void updateSettings({ enabled: value })}
ariaLabel="Enable Browser Use"
ariaLabel="Enable Browser"
disabled={isLoading || isSaving}
/>
</SettingsRow>
@@ -128,7 +128,7 @@ export default function BrowserUseSettingsTab() {
<div className="min-w-0 space-y-1">
<div className="text-sm font-medium text-foreground">Browser runtime required</div>
<p className="text-sm text-muted-foreground">
{status?.message || 'Install the browser runtime before agents can create Browser Use sessions.'}
{status?.message || 'Install the browser runtime before agents can create Browser sessions.'}
</p>
</div>

View File

@@ -69,7 +69,7 @@ export default function SidebarFooter({
onClick={onShowVersionModal}
>
<div className="relative flex-shrink-0">
<ArrowUpCircle className="w-4.5 h-4.5 text-blue-500 dark:text-blue-400" />
<ArrowUpCircle className="h-4 w-4 text-blue-500 dark:text-blue-400" />
<span className="absolute -right-0.5 -top-0.5 h-1.5 w-1.5 animate-pulse rounded-full bg-blue-500" />
</div>
<div className="min-w-0 flex-1 text-left">
@@ -145,12 +145,12 @@ export default function SidebarFooter({
href={GITHUB_ISSUES_URL}
target="_blank"
rel="noopener noreferrer"
className="flex h-12 w-full items-center gap-3.5 rounded-xl bg-muted/40 px-4 transition-all hover:bg-muted/60 active:scale-[0.98]"
className="flex h-10 w-full items-center gap-3 rounded-xl bg-muted/40 px-3.5 transition-all hover:bg-muted/60 active:scale-[0.98]"
>
<div className="flex h-8 w-8 items-center justify-center rounded-xl bg-background/80">
<Bug className="w-4.5 h-4.5 text-muted-foreground" />
<div className="flex h-7 w-7 items-center justify-center rounded-lg bg-background/80">
<Bug className="h-4 w-4 text-muted-foreground" />
</div>
<span className="text-base font-medium text-foreground">{t('actions.reportIssue')}</span>
<span className="text-sm font-medium text-foreground">{t('actions.reportIssue')}</span>
</a>
</div>
@@ -160,25 +160,25 @@ export default function SidebarFooter({
href={DISCORD_INVITE_URL}
target="_blank"
rel="noopener noreferrer"
className="flex h-12 w-full items-center gap-3.5 rounded-xl bg-muted/40 px-4 transition-all hover:bg-muted/60 active:scale-[0.98]"
className="flex h-10 w-full items-center gap-3 rounded-xl bg-muted/40 px-3.5 transition-all hover:bg-muted/60 active:scale-[0.98]"
>
<div className="flex h-8 w-8 items-center justify-center rounded-xl bg-background/80">
<DiscordIcon className="w-4.5 h-4.5 text-muted-foreground" />
<div className="flex h-7 w-7 items-center justify-center rounded-lg bg-background/80">
<DiscordIcon className="h-4 w-4 text-muted-foreground" />
</div>
<span className="text-base font-medium text-foreground">{t('actions.joinCommunity')}</span>
<span className="text-sm font-medium text-foreground">{t('actions.joinCommunity')}</span>
</a>
</div>
{/* Mobile settings */}
<div className="px-3 pb-3 pt-2 md:hidden">
<button
className="flex h-12 w-full items-center gap-3.5 rounded-xl bg-muted/40 px-4 transition-all hover:bg-muted/60 active:scale-[0.98]"
className="flex h-10 w-full items-center gap-3 rounded-xl bg-muted/40 px-3.5 transition-all hover:bg-muted/60 active:scale-[0.98]"
onClick={onShowSettings}
>
<div className="flex h-8 w-8 items-center justify-center rounded-xl bg-background/80">
<Settings className="w-4.5 h-4.5 text-muted-foreground" />
<div className="flex h-7 w-7 items-center justify-center rounded-lg bg-background/80">
<Settings className="h-4 w-4 text-muted-foreground" />
</div>
<span className="text-base font-medium text-foreground">{t('actions.settings')}</span>
<span className="text-sm font-medium text-foreground">{t('actions.settings')}</span>
</button>
</div>
</div>

View File

@@ -94,7 +94,7 @@
"git": "Git",
"apiTokens": "API & Tokens",
"tasks": "Tasks",
"browser": "Browser Use",
"browser": "Browser",
"notifications": "Notifications",
"plugins": "Plugins",
"about": "About"
@@ -451,6 +451,10 @@
"edit": "Edit server",
"delete": "Delete server"
},
"managed": {
"badge": "Managed",
"hint": "Managed by CloudCLI — control it from the feature's settings toggle."
},
"help": {
"title": "About Codex MCP",
"description": "Codex supports stdio-based MCP servers. You can add servers that extend Codex's capabilities with additional tools and resources."