From 1a38e2a081aa943787f73d15d3abbc78dc9f5c39 Mon Sep 17 00:00:00 2001
From: Dustin Healy <54083382+dustinhealy@users.noreply.github.com>
Date: Mon, 1 Dec 2025 07:08:28 -0800
Subject: [PATCH] =?UTF-8?q?=F0=9F=97=A3=20feat:=20MCP=20Status=20Accessibi?=
=?UTF-8?q?lity=20Improvements=20(#10738)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat: make MultiSelect highlight same opacity as other focus highlights in app
* feat: add better screenreader announcements for mcp server and variable states
* feat: memoize fullTitle calculation
---
.../components/MCP/CustomUserVarsSection.tsx | 27 ++++++++-------
client/src/components/MCP/MCPConfigDialog.tsx | 34 +++++++++++++++++--
client/src/locales/en/translation.json | 1 +
.../client/src/components/MultiSelect.tsx | 2 +-
4 files changed, 49 insertions(+), 15 deletions(-)
diff --git a/client/src/components/MCP/CustomUserVarsSection.tsx b/client/src/components/MCP/CustomUserVarsSection.tsx
index 35e613dd42..987613e24c 100644
--- a/client/src/components/MCP/CustomUserVarsSection.tsx
+++ b/client/src/components/MCP/CustomUserVarsSection.tsx
@@ -27,6 +27,7 @@ interface AuthFieldProps {
function AuthField({ name, config, hasValue, control, errors }: AuthFieldProps) {
const localize = useLocalize();
+ const statusText = hasValue ? localize('com_ui_set') : localize('com_ui_unset');
const sanitizer = useMemo(() => {
const instance = DOMPurify();
@@ -60,19 +61,21 @@ function AuthField({ name, config, hasValue, control, errors }: AuthFieldProps)
- {hasValue ? (
-
-
-
{localize('com_ui_set')}
-
- ) : (
-
-
-
{localize('com_ui_unset')}
-
- )}
+
+ {hasValue ? (
+
+
+
{localize('com_ui_set')}
+
+ ) : (
+
+
+
{localize('com_ui_unset')}
+
+ )}
+
{
+ if (!serverStatus) {
+ return localize('com_ui_mcp_dialog_title', {
+ serverName,
+ status: '',
+ });
+ }
+
+ const { connectionState, requiresOAuth } = serverStatus;
+ let statusText = '';
+
+ if (connectionState === 'connecting') {
+ statusText = localize('com_ui_connecting');
+ } else if (connectionState === 'error') {
+ statusText = localize('com_ui_error');
+ } else if (connectionState === 'connected') {
+ statusText = localize('com_ui_active');
+ } else if (connectionState === 'disconnected') {
+ statusText = requiresOAuth ? localize('com_ui_oauth') : localize('com_ui_offline');
+ }
+
+ return localize('com_ui_mcp_dialog_title', {
+ serverName,
+ status: statusText,
+ });
+ }, [serverStatus, serverName, localize]);
+
// Helper function to render status badge based on connection state
const renderStatusBadge = () => {
if (!serverStatus) {
@@ -102,7 +129,10 @@ export default function MCPConfigDialog({
return (
-
+
diff --git a/client/src/locales/en/translation.json b/client/src/locales/en/translation.json
index 6930ecfef4..4e5221f47c 100644
--- a/client/src/locales/en/translation.json
+++ b/client/src/locales/en/translation.json
@@ -789,6 +789,7 @@
"com_ui_complete_setup": "Complete Setup",
"com_ui_concise": "Concise",
"com_ui_configure_mcp_variables_for": "Configure Variables for {{0}}",
+ "com_ui_mcp_dialog_title": "Configure Variables for {{serverName}}. Server Status: {{status}}",
"com_ui_confirm": "Confirm",
"com_ui_confirm_action": "Confirm Action",
"com_ui_confirm_admin_use_change": "Changing this setting will block access for admins, including yourself. Are you sure you want to proceed?",
diff --git a/packages/client/src/components/MultiSelect.tsx b/packages/client/src/components/MultiSelect.tsx
index a793e1c550..8fa60137ea 100644
--- a/packages/client/src/components/MultiSelect.tsx
+++ b/packages/client/src/components/MultiSelect.tsx
@@ -82,7 +82,7 @@ export default function MultiSelect({
className={cn(
'flex items-center justify-between gap-2 rounded-xl px-3 py-2 text-sm',
'bg-surface-tertiary text-text-primary shadow-sm hover:cursor-pointer hover:bg-surface-hover',
- 'outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75',
+ 'outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white',
selectClassName,
selectedValues.length > 0 && selectItemsClassName != null && selectItemsClassName,
)}