refactor: remove MCP permission settings and streamline SDK options for autonomous mode

- Removed MCP permission settings from the application, including related functions and UI components.
- Updated SDK options to always bypass permissions and allow unrestricted tool access in autonomous mode.
- Adjusted related components and services to reflect the removal of MCP permission configurations, ensuring a cleaner and more efficient codebase.
This commit is contained in:
webdevcody
2026-01-03 23:00:20 -05:00
parent 019d6dd7bd
commit e32a82cca5
17 changed files with 36 additions and 361 deletions

View File

@@ -252,10 +252,14 @@ export function getModelForUseCase(
/** /**
* Base options that apply to all SDK calls * Base options that apply to all SDK calls
*
* AUTONOMOUS MODE: Always bypass permissions and allow dangerous operations
* for fully autonomous operation without user prompts.
*/ */
function getBaseOptions(): Partial<Options> { function getBaseOptions(): Partial<Options> {
return { return {
permissionMode: 'acceptEdits', permissionMode: 'bypassPermissions',
allowDangerouslySkipPermissions: true,
}; };
} }
@@ -276,31 +280,27 @@ interface McpPermissionOptions {
* Centralizes the logic for determining permission modes and tool restrictions * Centralizes the logic for determining permission modes and tool restrictions
* when MCP servers are configured. * when MCP servers are configured.
* *
* AUTONOMOUS MODE: Always bypass permissions for fully autonomous operation.
* Always allow unrestricted tools when MCP servers are configured.
*
* @param config - The SDK options config * @param config - The SDK options config
* @returns Object with MCP permission settings to spread into final options * @returns Object with MCP permission settings to spread into final options
*/ */
function buildMcpOptions(config: CreateSdkOptionsConfig): McpPermissionOptions { function buildMcpOptions(config: CreateSdkOptionsConfig): McpPermissionOptions {
const hasMcpServers = config.mcpServers && Object.keys(config.mcpServers).length > 0; const hasMcpServers = config.mcpServers && Object.keys(config.mcpServers).length > 0;
// Default to true for autonomous workflow. Security is enforced when adding servers
// via the security warning dialog that explains the risks.
const mcpAutoApprove = config.mcpAutoApproveTools ?? true;
const mcpUnrestricted = config.mcpUnrestrictedTools ?? true;
// Determine if we should bypass permissions based on settings // AUTONOMOUS MODE: Always bypass permissions and allow unrestricted tools
const shouldBypassPermissions = hasMcpServers && mcpAutoApprove; // Only restrict tools when no MCP servers are configured
// Determine if we should restrict tools (only when no MCP or unrestricted is disabled) const shouldRestrictTools = !hasMcpServers;
const shouldRestrictTools = !hasMcpServers || !mcpUnrestricted;
return { return {
shouldRestrictTools, shouldRestrictTools,
// Only include bypass options when MCP is configured and auto-approve is enabled // AUTONOMOUS MODE: Always include bypass options (though base options already set this)
bypassOptions: shouldBypassPermissions bypassOptions: {
? { permissionMode: 'bypassPermissions' as const,
permissionMode: 'bypassPermissions' as const, // Required flag when using bypassPermissions mode
// Required flag when using bypassPermissions mode allowDangerouslySkipPermissions: true,
allowDangerouslySkipPermissions: true, },
}
: {},
// Include MCP servers if configured // Include MCP servers if configured
mcpServerOptions: config.mcpServers ? { mcpServers: config.mcpServers } : {}, mcpServerOptions: config.mcpServers ? { mcpServers: config.mcpServers } : {},
}; };
@@ -392,12 +392,6 @@ export interface CreateSdkOptionsConfig {
/** MCP servers to make available to the agent */ /** MCP servers to make available to the agent */
mcpServers?: Record<string, McpServerConfig>; mcpServers?: Record<string, McpServerConfig>;
/** Auto-approve MCP tool calls without permission prompts */
mcpAutoApproveTools?: boolean;
/** Allow unrestricted tools when MCP servers are enabled */
mcpUnrestrictedTools?: boolean;
} }
// Re-export MCP types from @automaker/types for convenience // Re-export MCP types from @automaker/types for convenience
@@ -426,10 +420,7 @@ export function createSpecGenerationOptions(config: CreateSdkOptionsConfig): Opt
return { return {
...getBaseOptions(), ...getBaseOptions(),
// Override permissionMode - spec generation only needs read-only tools // AUTONOMOUS MODE: Base options already set bypassPermissions and allowDangerouslySkipPermissions
// Using "acceptEdits" can cause Claude to write files to unexpected locations
// See: https://github.com/AutoMaker-Org/automaker/issues/149
permissionMode: 'default',
model: getModelForUseCase('spec', config.model), model: getModelForUseCase('spec', config.model),
maxTurns: MAX_TURNS.maximum, maxTurns: MAX_TURNS.maximum,
cwd: config.cwd, cwd: config.cwd,
@@ -458,8 +449,7 @@ export function createFeatureGenerationOptions(config: CreateSdkOptionsConfig):
return { return {
...getBaseOptions(), ...getBaseOptions(),
// Override permissionMode - feature generation only needs read-only tools // AUTONOMOUS MODE: Base options already set bypassPermissions and allowDangerouslySkipPermissions
permissionMode: 'default',
model: getModelForUseCase('features', config.model), model: getModelForUseCase('features', config.model),
maxTurns: MAX_TURNS.quick, maxTurns: MAX_TURNS.quick,
cwd: config.cwd, cwd: config.cwd,

View File

@@ -191,41 +191,6 @@ export async function getMCPServersFromSettings(
} }
} }
/**
* Get MCP permission settings from global settings.
*
* @param settingsService - Optional settings service instance
* @param logPrefix - Prefix for log messages (e.g., '[AgentService]')
* @returns Promise resolving to MCP permission settings
*/
export async function getMCPPermissionSettings(
settingsService?: SettingsService | null,
logPrefix = '[SettingsHelper]'
): Promise<{ mcpAutoApproveTools: boolean; mcpUnrestrictedTools: boolean }> {
// Default to true for autonomous workflow. Security is enforced when adding servers
// via the security warning dialog that explains the risks.
const defaults = { mcpAutoApproveTools: true, mcpUnrestrictedTools: true };
if (!settingsService) {
return defaults;
}
try {
const globalSettings = await settingsService.getGlobalSettings();
const result = {
mcpAutoApproveTools: globalSettings.mcpAutoApproveTools ?? true,
mcpUnrestrictedTools: globalSettings.mcpUnrestrictedTools ?? true,
};
logger.info(
`${logPrefix} MCP permission settings: autoApprove=${result.mcpAutoApproveTools}, unrestricted=${result.mcpUnrestrictedTools}`
);
return result;
} catch (error) {
logger.error(`${logPrefix} Failed to load MCP permission settings:`, error);
return defaults;
}
}
/** /**
* Convert a settings MCPServerConfig to SDK McpServerConfig format. * Convert a settings MCPServerConfig to SDK McpServerConfig format.
* Validates required fields and throws informative errors if missing. * Validates required fields and throws informative errors if missing.

View File

@@ -63,20 +63,13 @@ export class ClaudeProvider extends BaseProvider {
} = options; } = options;
// Build Claude SDK options // Build Claude SDK options
// MCP permission logic - determines how to handle tool permissions when MCP servers are configured. // AUTONOMOUS MODE: Always bypass permissions for fully autonomous operation
// This logic mirrors buildMcpOptions() in sdk-options.ts but is applied here since
// the provider is the final point where SDK options are constructed.
const hasMcpServers = options.mcpServers && Object.keys(options.mcpServers).length > 0; const hasMcpServers = options.mcpServers && Object.keys(options.mcpServers).length > 0;
// Default to true for autonomous workflow. Security is enforced when adding servers
// via the security warning dialog that explains the risks.
const mcpAutoApprove = options.mcpAutoApproveTools ?? true;
const mcpUnrestricted = options.mcpUnrestrictedTools ?? true;
const defaultTools = ['Read', 'Write', 'Edit', 'Glob', 'Grep', 'Bash', 'WebSearch', 'WebFetch']; const defaultTools = ['Read', 'Write', 'Edit', 'Glob', 'Grep', 'Bash', 'WebSearch', 'WebFetch'];
// Determine permission mode based on settings // AUTONOMOUS MODE: Always bypass permissions and allow unrestricted tools
const shouldBypassPermissions = hasMcpServers && mcpAutoApprove; // Only restrict tools when no MCP servers are configured
// Determine if we should restrict tools (only when no MCP or unrestricted is disabled) const shouldRestrictTools = !hasMcpServers;
const shouldRestrictTools = !hasMcpServers || !mcpUnrestricted;
const sdkOptions: Options = { const sdkOptions: Options = {
model, model,
@@ -88,10 +81,9 @@ export class ClaudeProvider extends BaseProvider {
// Only restrict tools if explicitly set OR (no MCP / unrestricted disabled) // Only restrict tools if explicitly set OR (no MCP / unrestricted disabled)
...(allowedTools && shouldRestrictTools && { allowedTools }), ...(allowedTools && shouldRestrictTools && { allowedTools }),
...(!allowedTools && shouldRestrictTools && { allowedTools: defaultTools }), ...(!allowedTools && shouldRestrictTools && { allowedTools: defaultTools }),
// When MCP servers are configured and auto-approve is enabled, use bypassPermissions // AUTONOMOUS MODE: Always bypass permissions and allow dangerous operations
permissionMode: shouldBypassPermissions ? 'bypassPermissions' : 'default', permissionMode: 'bypassPermissions',
// Required when using bypassPermissions mode allowDangerouslySkipPermissions: true,
...(shouldBypassPermissions && { allowDangerouslySkipPermissions: true }),
abortController, abortController,
// Resume existing SDK session if we have a session ID // Resume existing SDK session if we have a session ID
...(sdkSessionId && conversationHistory && conversationHistory.length > 0 ...(sdkSessionId && conversationHistory && conversationHistory.length > 0

View File

@@ -164,7 +164,9 @@ export function createEnhanceHandler(
systemPrompt, systemPrompt,
maxTurns: 1, maxTurns: 1,
allowedTools: [], allowedTools: [],
permissionMode: 'acceptEdits', // AUTONOMOUS MODE: Always bypass permissions
permissionMode: 'bypassPermissions',
allowDangerouslySkipPermissions: true,
}, },
}); });

View File

@@ -96,7 +96,9 @@ export function createGenerateTitleHandler(): (req: Request, res: Response) => P
systemPrompt: SYSTEM_PROMPT, systemPrompt: SYSTEM_PROMPT,
maxTurns: 1, maxTurns: 1,
allowedTools: [], allowedTools: [],
permissionMode: 'acceptEdits', // AUTONOMOUS MODE: Always bypass permissions
permissionMode: 'bypassPermissions',
allowDangerouslySkipPermissions: true,
}, },
}); });

View File

@@ -23,7 +23,6 @@ import {
getEnableSandboxModeSetting, getEnableSandboxModeSetting,
filterClaudeMdFromContext, filterClaudeMdFromContext,
getMCPServersFromSettings, getMCPServersFromSettings,
getMCPPermissionSettings,
getPromptCustomization, getPromptCustomization,
} from '../lib/settings-helpers.js'; } from '../lib/settings-helpers.js';
@@ -235,9 +234,6 @@ export class AgentService {
// Load MCP servers from settings (global setting only) // Load MCP servers from settings (global setting only)
const mcpServers = await getMCPServersFromSettings(this.settingsService, '[AgentService]'); const mcpServers = await getMCPServersFromSettings(this.settingsService, '[AgentService]');
// Load MCP permission settings (global setting only)
const mcpPermissions = await getMCPPermissionSettings(this.settingsService, '[AgentService]');
// Load project context files (CLAUDE.md, CODE_QUALITY.md, etc.) // Load project context files (CLAUDE.md, CODE_QUALITY.md, etc.)
const contextResult = await loadContextFiles({ const contextResult = await loadContextFiles({
projectPath: effectiveWorkDir, projectPath: effectiveWorkDir,
@@ -264,8 +260,6 @@ export class AgentService {
autoLoadClaudeMd, autoLoadClaudeMd,
enableSandboxMode, enableSandboxMode,
mcpServers: Object.keys(mcpServers).length > 0 ? mcpServers : undefined, mcpServers: Object.keys(mcpServers).length > 0 ? mcpServers : undefined,
mcpAutoApproveTools: mcpPermissions.mcpAutoApproveTools,
mcpUnrestrictedTools: mcpPermissions.mcpUnrestrictedTools,
}); });
// Extract model, maxTurns, and allowedTools from SDK options // Extract model, maxTurns, and allowedTools from SDK options
@@ -290,8 +284,6 @@ export class AgentService {
sandbox: sdkOptions.sandbox, // Pass sandbox configuration sandbox: sdkOptions.sandbox, // Pass sandbox configuration
sdkSessionId: session.sdkSessionId, // Pass SDK session ID for resuming sdkSessionId: session.sdkSessionId, // Pass SDK session ID for resuming
mcpServers: Object.keys(mcpServers).length > 0 ? mcpServers : undefined, // Pass MCP servers configuration mcpServers: Object.keys(mcpServers).length > 0 ? mcpServers : undefined, // Pass MCP servers configuration
mcpAutoApproveTools: mcpPermissions.mcpAutoApproveTools, // Pass MCP auto-approve setting
mcpUnrestrictedTools: mcpPermissions.mcpUnrestrictedTools, // Pass MCP unrestricted tools setting
}; };
// Build prompt content with images // Build prompt content with images

View File

@@ -38,7 +38,6 @@ import {
getEnableSandboxModeSetting, getEnableSandboxModeSetting,
filterClaudeMdFromContext, filterClaudeMdFromContext,
getMCPServersFromSettings, getMCPServersFromSettings,
getMCPPermissionSettings,
getPromptCustomization, getPromptCustomization,
} from '../lib/settings-helpers.js'; } from '../lib/settings-helpers.js';
@@ -2003,9 +2002,6 @@ This mock response was generated because AUTOMAKER_MOCK_AGENT=true was set.
// Load MCP servers from settings (global setting only) // Load MCP servers from settings (global setting only)
const mcpServers = await getMCPServersFromSettings(this.settingsService, '[AutoMode]'); const mcpServers = await getMCPServersFromSettings(this.settingsService, '[AutoMode]');
// Load MCP permission settings (global setting only)
const mcpPermissions = await getMCPPermissionSettings(this.settingsService, '[AutoMode]');
// Build SDK options using centralized configuration for feature implementation // Build SDK options using centralized configuration for feature implementation
const sdkOptions = createAutoModeOptions({ const sdkOptions = createAutoModeOptions({
cwd: workDir, cwd: workDir,
@@ -2014,8 +2010,6 @@ This mock response was generated because AUTOMAKER_MOCK_AGENT=true was set.
autoLoadClaudeMd, autoLoadClaudeMd,
enableSandboxMode, enableSandboxMode,
mcpServers: Object.keys(mcpServers).length > 0 ? mcpServers : undefined, mcpServers: Object.keys(mcpServers).length > 0 ? mcpServers : undefined,
mcpAutoApproveTools: mcpPermissions.mcpAutoApproveTools,
mcpUnrestrictedTools: mcpPermissions.mcpUnrestrictedTools,
}); });
// Extract model, maxTurns, and allowedTools from SDK options // Extract model, maxTurns, and allowedTools from SDK options
@@ -2058,8 +2052,6 @@ This mock response was generated because AUTOMAKER_MOCK_AGENT=true was set.
settingSources: sdkOptions.settingSources, settingSources: sdkOptions.settingSources,
sandbox: sdkOptions.sandbox, // Pass sandbox configuration sandbox: sdkOptions.sandbox, // Pass sandbox configuration
mcpServers: Object.keys(mcpServers).length > 0 ? mcpServers : undefined, // Pass MCP servers configuration mcpServers: Object.keys(mcpServers).length > 0 ? mcpServers : undefined, // Pass MCP servers configuration
mcpAutoApproveTools: mcpPermissions.mcpAutoApproveTools, // Pass MCP auto-approve setting
mcpUnrestrictedTools: mcpPermissions.mcpUnrestrictedTools, // Pass MCP unrestricted tools setting
}; };
// Execute via provider // Execute via provider
@@ -2291,8 +2283,6 @@ After generating the revised spec, output:
allowedTools: allowedTools, allowedTools: allowedTools,
abortController, abortController,
mcpServers: Object.keys(mcpServers).length > 0 ? mcpServers : undefined, mcpServers: Object.keys(mcpServers).length > 0 ? mcpServers : undefined,
mcpAutoApproveTools: mcpPermissions.mcpAutoApproveTools,
mcpUnrestrictedTools: mcpPermissions.mcpUnrestrictedTools,
}); });
let revisionText = ''; let revisionText = '';
@@ -2431,8 +2421,6 @@ After generating the revised spec, output:
allowedTools: allowedTools, allowedTools: allowedTools,
abortController, abortController,
mcpServers: Object.keys(mcpServers).length > 0 ? mcpServers : undefined, mcpServers: Object.keys(mcpServers).length > 0 ? mcpServers : undefined,
mcpAutoApproveTools: mcpPermissions.mcpAutoApproveTools,
mcpUnrestrictedTools: mcpPermissions.mcpUnrestrictedTools,
}); });
let taskOutput = ''; let taskOutput = '';
@@ -2523,8 +2511,6 @@ Implement all the changes described in the plan above.`;
allowedTools: allowedTools, allowedTools: allowedTools,
abortController, abortController,
mcpServers: Object.keys(mcpServers).length > 0 ? mcpServers : undefined, mcpServers: Object.keys(mcpServers).length > 0 ? mcpServers : undefined,
mcpAutoApproveTools: mcpPermissions.mcpAutoApproveTools,
mcpUnrestrictedTools: mcpPermissions.mcpUnrestrictedTools,
}); });
for await (const msg of continuationStream) { for await (const msg of continuationStream) {

View File

@@ -1,5 +1,5 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'; import { describe, it, expect, vi, beforeEach } from 'vitest';
import { getMCPServersFromSettings, getMCPPermissionSettings } from '@/lib/settings-helpers.js'; import { getMCPServersFromSettings } from '@/lib/settings-helpers.js';
import type { SettingsService } from '@/services/settings-service.js'; import type { SettingsService } from '@/services/settings-service.js';
// Mock the logger // Mock the logger
@@ -286,93 +286,4 @@ describe('settings-helpers.ts', () => {
}); });
}); });
}); });
describe('getMCPPermissionSettings', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('should return defaults when settingsService is null', async () => {
const result = await getMCPPermissionSettings(null);
expect(result).toEqual({
mcpAutoApproveTools: true,
mcpUnrestrictedTools: true,
});
});
it('should return defaults when settingsService is undefined', async () => {
const result = await getMCPPermissionSettings(undefined);
expect(result).toEqual({
mcpAutoApproveTools: true,
mcpUnrestrictedTools: true,
});
});
it('should return settings from service', async () => {
const mockSettingsService = {
getGlobalSettings: vi.fn().mockResolvedValue({
mcpAutoApproveTools: false,
mcpUnrestrictedTools: false,
}),
} as unknown as SettingsService;
const result = await getMCPPermissionSettings(mockSettingsService);
expect(result).toEqual({
mcpAutoApproveTools: false,
mcpUnrestrictedTools: false,
});
});
it('should default to true when settings are undefined', async () => {
const mockSettingsService = {
getGlobalSettings: vi.fn().mockResolvedValue({}),
} as unknown as SettingsService;
const result = await getMCPPermissionSettings(mockSettingsService);
expect(result).toEqual({
mcpAutoApproveTools: true,
mcpUnrestrictedTools: true,
});
});
it('should handle mixed settings', async () => {
const mockSettingsService = {
getGlobalSettings: vi.fn().mockResolvedValue({
mcpAutoApproveTools: true,
mcpUnrestrictedTools: false,
}),
} as unknown as SettingsService;
const result = await getMCPPermissionSettings(mockSettingsService);
expect(result).toEqual({
mcpAutoApproveTools: true,
mcpUnrestrictedTools: false,
});
});
it('should return defaults and log error on exception', async () => {
const mockSettingsService = {
getGlobalSettings: vi.fn().mockRejectedValue(new Error('Settings error')),
} as unknown as SettingsService;
const result = await getMCPPermissionSettings(mockSettingsService, '[Test]');
expect(result).toEqual({
mcpAutoApproveTools: true,
mcpUnrestrictedTools: true,
});
// Logger will be called with error, but we don't need to assert it
});
it('should use custom log prefix', async () => {
const mockSettingsService = {
getGlobalSettings: vi.fn().mockResolvedValue({
mcpAutoApproveTools: true,
mcpUnrestrictedTools: true,
}),
} as unknown as SettingsService;
await getMCPPermissionSettings(mockSettingsService, '[CustomPrefix]');
// Logger will be called with custom prefix, but we don't need to assert it
});
});
}); });

View File

@@ -1,4 +1,3 @@
export { MCPServerHeader } from './mcp-server-header'; export { MCPServerHeader } from './mcp-server-header';
export { MCPPermissionSettings } from './mcp-permission-settings';
export { MCPToolsWarning } from './mcp-tools-warning'; export { MCPToolsWarning } from './mcp-tools-warning';
export { MCPServerCard } from './mcp-server-card'; export { MCPServerCard } from './mcp-server-card';

View File

@@ -1,96 +0,0 @@
import { ShieldAlert } from 'lucide-react';
import { Label } from '@/components/ui/label';
import { Switch } from '@/components/ui/switch';
import { syncSettingsToServer } from '@/hooks/use-settings-migration';
import { cn } from '@/lib/utils';
interface MCPPermissionSettingsProps {
mcpAutoApproveTools: boolean;
mcpUnrestrictedTools: boolean;
onAutoApproveChange: (checked: boolean) => void;
onUnrestrictedChange: (checked: boolean) => void;
}
export function MCPPermissionSettings({
mcpAutoApproveTools,
mcpUnrestrictedTools,
onAutoApproveChange,
onUnrestrictedChange,
}: MCPPermissionSettingsProps) {
const hasAnyEnabled = mcpAutoApproveTools || mcpUnrestrictedTools;
return (
<div className="px-6 py-4 border-b border-border/50 bg-muted/20">
<div className="space-y-4">
<div className="flex items-start gap-3">
<Switch
id="mcp-auto-approve"
checked={mcpAutoApproveTools}
onCheckedChange={async (checked) => {
onAutoApproveChange(checked);
await syncSettingsToServer();
}}
data-testid="mcp-auto-approve-toggle"
className="mt-0.5"
/>
<div className="space-y-1 flex-1">
<Label htmlFor="mcp-auto-approve" className="text-sm font-medium cursor-pointer">
Auto-approve MCP tool calls
</Label>
<p className="text-xs text-muted-foreground">
When enabled, the AI agent can use MCP tools without permission prompts.
</p>
{mcpAutoApproveTools && (
<p className="text-xs text-amber-600 flex items-center gap-1 mt-1">
<ShieldAlert className="h-3 w-3" />
Bypasses normal permission checks
</p>
)}
</div>
</div>
<div className="flex items-start gap-3">
<Switch
id="mcp-unrestricted"
checked={mcpUnrestrictedTools}
onCheckedChange={async (checked) => {
onUnrestrictedChange(checked);
await syncSettingsToServer();
}}
data-testid="mcp-unrestricted-toggle"
className="mt-0.5"
/>
<div className="space-y-1 flex-1">
<Label htmlFor="mcp-unrestricted" className="text-sm font-medium cursor-pointer">
Unrestricted tool access
</Label>
<p className="text-xs text-muted-foreground">
When enabled, the AI agent can use any tool, not just the default set.
</p>
{mcpUnrestrictedTools && (
<p className="text-xs text-amber-600 flex items-center gap-1 mt-1">
<ShieldAlert className="h-3 w-3" />
Agent has full tool access including file writes and bash
</p>
)}
</div>
</div>
{hasAnyEnabled && (
<div
className={cn(
'rounded-md border border-amber-500/30 bg-amber-500/10 p-3 mt-2',
'text-xs text-amber-700 dark:text-amber-400'
)}
>
<p className="font-medium mb-1">Security Note</p>
<p>
These settings reduce security restrictions for MCP tool usage. Only enable if you
trust all configured MCP servers.
</p>
</div>
)}
</div>
</div>
);
}

View File

@@ -21,16 +21,7 @@ interface PendingServerData {
} }
export function useMCPServers() { export function useMCPServers() {
const { const { mcpServers, addMCPServer, updateMCPServer, removeMCPServer } = useAppStore();
mcpServers,
addMCPServer,
updateMCPServer,
removeMCPServer,
mcpAutoApproveTools,
mcpUnrestrictedTools,
setMcpAutoApproveTools,
setMcpUnrestrictedTools,
} = useAppStore();
// State // State
const [isAddDialogOpen, setIsAddDialogOpen] = useState(false); const [isAddDialogOpen, setIsAddDialogOpen] = useState(false);
@@ -938,10 +929,6 @@ export function useMCPServers() {
return { return {
// Store state // Store state
mcpServers, mcpServers,
mcpAutoApproveTools,
mcpUnrestrictedTools,
setMcpAutoApproveTools,
setMcpUnrestrictedTools,
// Dialog state // Dialog state
isAddDialogOpen, isAddDialogOpen,

View File

@@ -1,12 +1,7 @@
import { Plug } from 'lucide-react'; import { Plug } from 'lucide-react';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { useMCPServers } from './hooks'; import { useMCPServers } from './hooks';
import { import { MCPServerHeader, MCPToolsWarning, MCPServerCard } from './components';
MCPServerHeader,
MCPPermissionSettings,
MCPToolsWarning,
MCPServerCard,
} from './components';
import { import {
AddEditServerDialog, AddEditServerDialog,
DeleteServerDialog, DeleteServerDialog,
@@ -20,10 +15,6 @@ export function MCPServersSection() {
const { const {
// Store state // Store state
mcpServers, mcpServers,
mcpAutoApproveTools,
mcpUnrestrictedTools,
setMcpAutoApproveTools,
setMcpUnrestrictedTools,
// Dialog state // Dialog state
isAddDialogOpen, isAddDialogOpen,
@@ -98,15 +89,6 @@ export function MCPServersSection() {
onAdd={handleOpenAddDialog} onAdd={handleOpenAddDialog}
/> />
{mcpServers.length > 0 && (
<MCPPermissionSettings
mcpAutoApproveTools={mcpAutoApproveTools}
mcpUnrestrictedTools={mcpUnrestrictedTools}
onAutoApproveChange={setMcpAutoApproveTools}
onUnrestrictedChange={setMcpUnrestrictedTools}
/>
)}
{showToolsWarning && <MCPToolsWarning totalTools={totalToolsCount} />} {showToolsWarning && <MCPToolsWarning totalTools={totalToolsCount} />}
<div className="p-6"> <div className="p-6">

View File

@@ -230,8 +230,6 @@ export async function syncSettingsToServer(): Promise<boolean> {
keyboardShortcuts: state.keyboardShortcuts, keyboardShortcuts: state.keyboardShortcuts,
aiProfiles: state.aiProfiles, aiProfiles: state.aiProfiles,
mcpServers: state.mcpServers, mcpServers: state.mcpServers,
mcpAutoApproveTools: state.mcpAutoApproveTools,
mcpUnrestrictedTools: state.mcpUnrestrictedTools,
promptCustomization: state.promptCustomization, promptCustomization: state.promptCustomization,
projects: state.projects, projects: state.projects,
trashedProjects: state.trashedProjects, trashedProjects: state.trashedProjects,
@@ -336,12 +334,10 @@ export async function loadMCPServersFromServer(): Promise<boolean> {
} }
const mcpServers = result.settings.mcpServers || []; const mcpServers = result.settings.mcpServers || [];
const mcpAutoApproveTools = result.settings.mcpAutoApproveTools ?? true;
const mcpUnrestrictedTools = result.settings.mcpUnrestrictedTools ?? true;
// Clear existing and add all from server // Clear existing and add all from server
// We need to update the store directly since we can't use hooks here // We need to update the store directly since we can't use hooks here
useAppStore.setState({ mcpServers, mcpAutoApproveTools, mcpUnrestrictedTools }); useAppStore.setState({ mcpServers });
console.log(`[Settings Load] Loaded ${mcpServers.length} MCP servers from server`); console.log(`[Settings Load] Loaded ${mcpServers.length} MCP servers from server`);
return true; return true;

View File

@@ -1438,8 +1438,6 @@ export class HttpApiClient implements ElectronAPI {
headers?: Record<string, string>; headers?: Record<string, string>;
enabled?: boolean; enabled?: boolean;
}>; }>;
mcpAutoApproveTools?: boolean;
mcpUnrestrictedTools?: boolean;
}; };
error?: string; error?: string;
}> => this.get('/api/settings/global'), }> => this.get('/api/settings/global'),

View File

@@ -491,8 +491,6 @@ export interface AppState {
// MCP Servers // MCP Servers
mcpServers: MCPServerConfig[]; // List of configured MCP servers for agent use mcpServers: MCPServerConfig[]; // List of configured MCP servers for agent use
mcpAutoApproveTools: boolean; // Auto-approve MCP tool calls without permission prompts
mcpUnrestrictedTools: boolean; // Allow unrestricted tools when MCP servers are enabled
// Prompt Customization // Prompt Customization
promptCustomization: PromptCustomization; // Custom prompts for Auto Mode, Agent, Backlog Plan, Enhancement promptCustomization: PromptCustomization; // Custom prompts for Auto Mode, Agent, Backlog Plan, Enhancement
@@ -777,8 +775,6 @@ export interface AppActions {
setAutoLoadClaudeMd: (enabled: boolean) => Promise<void>; setAutoLoadClaudeMd: (enabled: boolean) => Promise<void>;
setEnableSandboxMode: (enabled: boolean) => Promise<void>; setEnableSandboxMode: (enabled: boolean) => Promise<void>;
setSkipSandboxWarning: (skip: boolean) => Promise<void>; setSkipSandboxWarning: (skip: boolean) => Promise<void>;
setMcpAutoApproveTools: (enabled: boolean) => Promise<void>;
setMcpUnrestrictedTools: (enabled: boolean) => Promise<void>;
// Prompt Customization actions // Prompt Customization actions
setPromptCustomization: (customization: PromptCustomization) => Promise<void>; setPromptCustomization: (customization: PromptCustomization) => Promise<void>;
@@ -980,8 +976,6 @@ const initialState: AppState = {
enableSandboxMode: false, // Default to disabled (can be enabled for additional security) enableSandboxMode: false, // Default to disabled (can be enabled for additional security)
skipSandboxWarning: false, // Default to disabled (show sandbox warning dialog) skipSandboxWarning: false, // Default to disabled (show sandbox warning dialog)
mcpServers: [], // No MCP servers configured by default mcpServers: [], // No MCP servers configured by default
mcpAutoApproveTools: true, // Default to enabled - bypass permission prompts for MCP tools
mcpUnrestrictedTools: true, // Default to enabled - don't filter allowedTools when MCP enabled
promptCustomization: {}, // Empty by default - all prompts use built-in defaults promptCustomization: {}, // Empty by default - all prompts use built-in defaults
aiProfiles: DEFAULT_AI_PROFILES, aiProfiles: DEFAULT_AI_PROFILES,
projectAnalysis: null, projectAnalysis: null,
@@ -1632,19 +1626,6 @@ export const useAppStore = create<AppState & AppActions>()(
const { syncSettingsToServer } = await import('@/hooks/use-settings-migration'); const { syncSettingsToServer } = await import('@/hooks/use-settings-migration');
await syncSettingsToServer(); await syncSettingsToServer();
}, },
setMcpAutoApproveTools: async (enabled) => {
set({ mcpAutoApproveTools: enabled });
// Sync to server settings file
const { syncSettingsToServer } = await import('@/hooks/use-settings-migration');
await syncSettingsToServer();
},
setMcpUnrestrictedTools: async (enabled) => {
set({ mcpUnrestrictedTools: enabled });
// Sync to server settings file
const { syncSettingsToServer } = await import('@/hooks/use-settings-migration');
await syncSettingsToServer();
},
// Prompt Customization actions // Prompt Customization actions
setPromptCustomization: async (customization) => { setPromptCustomization: async (customization) => {
set({ promptCustomization: customization }); set({ promptCustomization: customization });
@@ -2933,8 +2914,6 @@ export const useAppStore = create<AppState & AppActions>()(
skipSandboxWarning: state.skipSandboxWarning, skipSandboxWarning: state.skipSandboxWarning,
// MCP settings // MCP settings
mcpServers: state.mcpServers, mcpServers: state.mcpServers,
mcpAutoApproveTools: state.mcpAutoApproveTools,
mcpUnrestrictedTools: state.mcpUnrestrictedTools,
// Prompt customization // Prompt customization
promptCustomization: state.promptCustomization, promptCustomization: state.promptCustomization,
// Profiles and sessions // Profiles and sessions

View File

@@ -71,8 +71,6 @@ export interface ExecuteOptions {
maxTurns?: number; maxTurns?: number;
allowedTools?: string[]; allowedTools?: string[];
mcpServers?: Record<string, McpServerConfig>; mcpServers?: Record<string, McpServerConfig>;
mcpAutoApproveTools?: boolean; // Auto-approve MCP tool calls without permission prompts
mcpUnrestrictedTools?: boolean; // Allow unrestricted tools when MCP servers are enabled
abortController?: AbortController; abortController?: AbortController;
conversationHistory?: ConversationMessage[]; // Previous messages for context conversationHistory?: ConversationMessage[]; // Previous messages for context
sdkSessionId?: string; // Claude SDK session ID for resuming conversations sdkSessionId?: string; // Claude SDK session ID for resuming conversations

View File

@@ -359,10 +359,6 @@ export interface GlobalSettings {
// MCP Server Configuration // MCP Server Configuration
/** List of configured MCP servers for agent use */ /** List of configured MCP servers for agent use */
mcpServers: MCPServerConfig[]; mcpServers: MCPServerConfig[];
/** Auto-approve MCP tool calls without permission prompts (uses bypassPermissions mode) */
mcpAutoApproveTools?: boolean;
/** Allow unrestricted tools when MCP servers are enabled (don't filter allowedTools) */
mcpUnrestrictedTools?: boolean;
// Prompt Customization // Prompt Customization
/** Custom prompts for Auto Mode, Agent Runner, Backlog Planning, and Enhancements */ /** Custom prompts for Auto Mode, Agent Runner, Backlog Planning, and Enhancements */
@@ -535,10 +531,6 @@ export const DEFAULT_GLOBAL_SETTINGS: GlobalSettings = {
enableSandboxMode: false, enableSandboxMode: false,
skipSandboxWarning: false, skipSandboxWarning: false,
mcpServers: [], mcpServers: [],
// Default to true for autonomous workflow. Security is enforced when adding servers
// via the security warning dialog that explains the risks.
mcpAutoApproveTools: true,
mcpUnrestrictedTools: true,
}; };
/** Default credentials (empty strings - user must provide API keys) */ /** Default credentials (empty strings - user must provide API keys) */