fix(settings): inline MCP delete errors and stabilize save-close timer

Replace blocking alert() calls in MCP delete handlers with non-blocking deleteError state updates and setSaveStatus('error') on failure.

Thread deleteError through Settings -> Agents settings views and render inline error feedback in Claude/Codex MCP sections near delete actions.

Prevent orphaned save-close timers by clearing and nulling closeTimerRef before scheduling a new timeout, and by nulling the ref during unmount cleanup.
This commit is contained in:
Haileyesus
2026-02-24 14:05:30 +03:00
parent f59f40d0f9
commit e20ee2828d
6 changed files with 36 additions and 3 deletions

View File

@@ -24,6 +24,7 @@ export default function AgentsSettingsTab({
mcpTestResults,
mcpServerTools,
mcpToolsLoading,
deleteError,
onOpenMcpForm,
onDeleteMcpServer,
onTestMcpServer,
@@ -86,6 +87,7 @@ export default function AgentsSettingsTab({
mcpTestResults={mcpTestResults}
mcpServerTools={mcpServerTools}
mcpToolsLoading={mcpToolsLoading}
deleteError={deleteError}
onOpenMcpForm={onOpenMcpForm}
onDeleteMcpServer={onDeleteMcpServer}
onTestMcpServer={onTestMcpServer}

View File

@@ -19,6 +19,7 @@ export default function AgentCategoryContentSection({
mcpTestResults,
mcpServerTools,
mcpToolsLoading,
deleteError,
onOpenMcpForm,
onDeleteMcpServer,
onTestMcpServer,
@@ -95,6 +96,7 @@ export default function AgentCategoryContentSection({
testResults={mcpTestResults}
serverTools={mcpServerTools}
toolsLoading={mcpToolsLoading}
deleteError={deleteError}
/>
)}
@@ -115,6 +117,7 @@ export default function AgentCategoryContentSection({
onAdd={() => onOpenCodexMcpForm()}
onEdit={(server) => onOpenCodexMcpForm(server)}
onDelete={(serverId) => onDeleteCodexMcpServer(serverId)}
deleteError={deleteError}
/>
)}
</div>

View File

@@ -31,6 +31,7 @@ type ClaudeMcpServersProps = {
testResults: Record<string, McpTestResult>;
serverTools: Record<string, McpToolsResult>;
toolsLoading: Record<string, boolean>;
deleteError?: string | null;
};
function ClaudeMcpServers({
@@ -40,6 +41,7 @@ function ClaudeMcpServers({
onDelete,
testResults,
serverTools,
deleteError,
}: Omit<ClaudeMcpServersProps, 'agent' | 'onTest' | 'onDiscoverTools' | 'toolsLoading'>) {
const { t } = useTranslation('settings');
@@ -57,6 +59,11 @@ function ClaudeMcpServers({
{t('mcpServers.addButton')}
</Button>
</div>
{deleteError && (
<div className="rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700 dark:border-red-800/60 dark:bg-red-900/20 dark:text-red-200">
{deleteError}
</div>
)}
<div className="space-y-2">
{servers.map((server) => {
@@ -254,9 +261,10 @@ type CodexMcpServersProps = {
onAdd: () => void;
onEdit: (server: McpServer) => void;
onDelete: (serverId: string) => void;
deleteError?: string | null;
};
function CodexMcpServers({ servers, onAdd, onEdit, onDelete }: Omit<CodexMcpServersProps, 'agent'>) {
function CodexMcpServers({ servers, onAdd, onEdit, onDelete, deleteError }: Omit<CodexMcpServersProps, 'agent'>) {
const { t } = useTranslation('settings');
return (
@@ -273,6 +281,11 @@ function CodexMcpServers({ servers, onAdd, onEdit, onDelete }: Omit<CodexMcpServ
{t('mcpServers.addButton')}
</Button>
</div>
{deleteError && (
<div className="rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700 dark:border-red-800/60 dark:bg-red-900/20 dark:text-red-200">
{deleteError}
</div>
)}
<div className="space-y-2">
{servers.map((server) => (

View File

@@ -36,6 +36,7 @@ export type AgentsSettingsTabProps = {
mcpTestResults: Record<string, McpTestResult>;
mcpServerTools: Record<string, McpToolsResult>;
mcpToolsLoading: Record<string, boolean>;
deleteError: string | null;
onOpenMcpForm: (server?: McpServer) => void;
onDeleteMcpServer: (serverId: string, scope?: string) => void;
onTestMcpServer: (serverId: string, scope?: string) => void;
@@ -71,6 +72,7 @@ export type AgentCategoryContentSectionProps = {
mcpTestResults: Record<string, McpTestResult>;
mcpServerTools: Record<string, McpToolsResult>;
mcpToolsLoading: Record<string, boolean>;
deleteError: string | null;
onOpenMcpForm: (server?: McpServer) => void;
onDeleteMcpServer: (serverId: string, scope?: string) => void;
onTestMcpServer: (serverId: string, scope?: string) => void;