Skip to content

Commit 32df857

Browse files
committed
feat(mcp): Priority 1 improvements auto-approve, unit tests, result display
- Auto-approve toggle: per-server setting in MCP config to skip manual tool approval for trusted servers, with green 'Auto' toggle in settings and 'Auto-approving...' spinner in chat UI - MCP service unit tests: 32 comprehensive tests covering getInstance, isValidToolName, toolsWithoutExecute, processToolCall, processToolInvocations (8 cases), _validateServerConfig (8 cases), _registerTools (3 cases) - Tool result display: collapsible long JSON with 200px max-height, 'Show more/less' toggle, line count indicator, copy-to-clipboard button, and theme-aware fade gradient overlay All 484 tests pass (24 files).
1 parent 44d430a commit 32df857

6 files changed

Lines changed: 927 additions & 95 deletions

File tree

app/components/@settings/tabs/mcp/McpServerList.tsx

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import type { MCPServer } from '~/lib/services/mcpService';
22
import McpStatusBadge from '~/components/@settings/tabs/mcp/McpStatusBadge';
33
import McpServerListItem from '~/components/@settings/tabs/mcp/McpServerListItem';
4+
import { classNames } from '~/utils/classNames';
45

56
type McpServerListProps = {
67
serverEntries: [string, MCPServer][];
78
expandedServer: string | null;
89
checkingServers: boolean;
910
onlyShowAvailableServers?: boolean;
1011
toggleServerExpanded: (serverName: string) => void;
12+
autoApproveServers?: string[];
13+
onToggleAutoApprove?: (serverName: string) => void;
1114
};
1215

1316
export default function McpServerList({
@@ -16,6 +19,8 @@ export default function McpServerList({
1619
checkingServers,
1720
onlyShowAvailableServers = false,
1821
toggleServerExpanded,
22+
autoApproveServers = [],
23+
onToggleAutoApprove,
1924
}: McpServerListProps) {
2025
if (serverEntries.length === 0) {
2126
return <p className="text-sm text-bolt-elements-textSecondary">No MCP servers configured</p>;
@@ -31,6 +36,7 @@ export default function McpServerList({
3136
const isAvailable = mcpServer.status === 'available';
3237
const isExpanded = expandedServer === serverName;
3338
const serverTools = isAvailable ? Object.entries(mcpServer.tools) : [];
39+
const isAutoApproved = autoApproveServers.includes(serverName);
3440

3541
return (
3642
<div key={serverName} className="flex flex-col p-2 rounded-md bg-bolt-elements-background-depth-1">
@@ -58,7 +64,26 @@ export default function McpServerList({
5864
</div>
5965
</div>
6066

61-
<div className="ml-2 flex-shrink-0">
67+
<div className="ml-2 flex-shrink-0 flex items-center gap-2">
68+
{isAvailable && onToggleAutoApprove && (
69+
<button
70+
onClick={() => onToggleAutoApprove(serverName)}
71+
className={classNames(
72+
'flex items-center gap-1 px-2 py-0.5 rounded text-xs transition-colors',
73+
isAutoApproved
74+
? 'bg-green-500/15 text-green-400 hover:bg-green-500/25'
75+
: 'bg-bolt-elements-background-depth-2 text-bolt-elements-textTertiary hover:text-bolt-elements-textSecondary',
76+
)}
77+
title={
78+
isAutoApproved
79+
? 'Auto-approve enabled — tools run without confirmation'
80+
: 'Click to enable auto-approve for this server'
81+
}
82+
>
83+
<div className={`${isAutoApproved ? 'i-ph:check-circle-fill' : 'i-ph:circle'} w-3 h-3`} />
84+
Auto
85+
</button>
86+
)}
6287
{checkingServers ? (
6388
<McpStatusBadge status="checking" />
6489
) : (

app/components/@settings/tabs/mcp/McpTab.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export default function McpTab() {
3333
const [isSaving, setIsSaving] = useState(false);
3434
const [mcpConfigText, setMCPConfigText] = useState('');
3535
const [maxLLMSteps, setMaxLLMSteps] = useState(1);
36+
const [autoApproveServers, setAutoApproveServers] = useState<string[]>([]);
3637
const [error, setError] = useState<string | null>(null);
3738
const [isCheckingServers, setIsCheckingServers] = useState(false);
3839
const [expandedServer, setExpandedServer] = useState<string | null>(null);
@@ -49,6 +50,7 @@ export default function McpTab() {
4950
useEffect(() => {
5051
setMCPConfigText(JSON.stringify(settings.mcpConfig, null, 2));
5152
setMaxLLMSteps(settings.maxLLMSteps);
53+
setAutoApproveServers(settings.autoApproveServers || []);
5254
setError(null);
5355
}, [settings]);
5456

@@ -77,6 +79,7 @@ export default function McpTab() {
7779
await updateMCPSettings({
7880
mcpConfig: parsedConfig,
7981
maxLLMSteps,
82+
autoApproveServers,
8083
});
8184
toast.success('MCP configuration saved');
8285

@@ -115,6 +118,12 @@ export default function McpTab() {
115118
setExpandedServer(expandedServer === serverName ? null : serverName);
116119
};
117120

121+
const toggleAutoApprove = (serverName: string) => {
122+
setAutoApproveServers((prev) =>
123+
prev.includes(serverName) ? prev.filter((s) => s !== serverName) : [...prev, serverName],
124+
);
125+
};
126+
118127
const serverEntries = useMemo(() => Object.entries(serverTools), [serverTools]);
119128

120129
return (
@@ -147,6 +156,8 @@ export default function McpTab() {
147156
expandedServer={expandedServer}
148157
serverEntries={serverEntries}
149158
toggleServerExpanded={toggleServerExpanded}
159+
autoApproveServers={autoApproveServers}
160+
onToggleAutoApprove={toggleAutoApprove}
150161
/>
151162
</section>
152163

0 commit comments

Comments
 (0)