Skip to content

Commit d27b199

Browse files
Vl4diC0de0xToshii
andauthored
Mcp rich display setting (RooCodeInc#4029)
* + Adding a global setting for mcp rich display in features settings, storing it in global storage, and using it as the starting value for each new session to still allow local toggle of mcp rich display on the tab, but let users keep the base stored default * + adding changest * + fxing linting post conflict merge * fix --------- Co-authored-by: 0xtoshii <[email protected]>
1 parent 7ba4c9e commit d27b199

File tree

12 files changed

+67
-26
lines changed

12 files changed

+67
-26
lines changed

.changeset/wild-cycles-cough.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"claude-dev": minor
3+
---
4+
5+
Adding MCP Rich Display settings in cline's settings page, to enable users to change it in a persistent manner

proto/state.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ message UpdateSettingsRequest {
9595
optional int64 shell_integration_timeout = 8;
9696
optional bool terminal_reuse_enabled = 9;
9797
optional bool mcp_responses_collapsed = 10;
98+
optional bool mcp_rich_display_enabled = 11;
9899
}
99100

100101
// Complete API Configuration message

src/core/controller/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,7 @@ export class Controller {
948948
chatSettings,
949949
userInfo,
950950
mcpMarketplaceEnabled,
951+
mcpRichDisplayEnabled,
951952
telemetrySetting,
952953
planActSeparateModelsSetting,
953954
enableCheckpointsSetting,
@@ -989,6 +990,7 @@ export class Controller {
989990
chatSettings,
990991
userInfo,
991992
mcpMarketplaceEnabled,
993+
mcpRichDisplayEnabled,
992994
telemetrySetting,
993995
planActSeparateModelsSetting,
994996
enableCheckpointsSetting: enableCheckpointsSetting ?? true,

src/core/controller/state/updateSettings.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ export async function updateSettings(controller: Controller, request: UpdateSett
5050
await controller.context.globalState.update("mcpResponsesCollapsed", request.mcpResponsesCollapsed)
5151
}
5252

53+
// Update MCP responses collapsed setting
54+
if (request.mcpRichDisplayEnabled !== undefined) {
55+
await controller.context.globalState.update("mcpRichDisplayEnabled", request.mcpRichDisplayEnabled)
56+
}
57+
5358
// Update chat settings
5459
if (request.chatSettings) {
5560
const chatSettings = convertProtoChatSettingsToChatSettings(request.chatSettings)

src/core/storage/state-keys.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ export type GlobalStateKey =
6969
| "terminalReuseEnabled"
7070
| "defaultTerminalProfile"
7171
| "isNewUser"
72+
| "mcpRichDisplayEnabled"
7273

7374
export type LocalStateKey =
7475
| "localClineRulesToggles"

src/core/storage/state.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
234234
shellIntegrationTimeout,
235235
enableCheckpointsSettingRaw,
236236
mcpMarketplaceEnabledRaw,
237+
mcpRichDisplayEnabled,
237238
mcpResponsesCollapsedRaw,
238239
globalWorkflowToggles,
239240
terminalReuseEnabled,
@@ -298,6 +299,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
298299
getGlobalState(context, "shellIntegrationTimeout") as Promise<number | undefined>,
299300
getGlobalState(context, "enableCheckpointsSetting") as Promise<boolean | undefined>,
300301
getGlobalState(context, "mcpMarketplaceEnabled") as Promise<boolean | undefined>,
302+
getGlobalState(context, "mcpRichDisplayEnabled") as Promise<boolean | undefined>,
301303
getGlobalState(context, "mcpResponsesCollapsed") as Promise<boolean | undefined>,
302304
getGlobalState(context, "globalWorkflowToggles") as Promise<ClineRulesToggles | undefined>,
303305
getGlobalState(context, "terminalReuseEnabled") as Promise<boolean | undefined>,
@@ -492,6 +494,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
492494
previousModeAwsBedrockCustomSelected,
493495
previousModeAwsBedrockCustomModelBaseId,
494496
mcpMarketplaceEnabled: mcpMarketplaceEnabled,
497+
mcpRichDisplayEnabled: mcpRichDisplayEnabled ?? true,
495498
mcpResponsesCollapsed: mcpResponsesCollapsed,
496499
telemetrySetting: telemetrySetting || "unset",
497500
planActSeparateModelsSetting,

src/shared/ExtensionMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export interface ExtensionState {
8282
clineMessages: ClineMessage[]
8383
currentTaskItem?: HistoryItem
8484
mcpMarketplaceEnabled?: boolean
85+
mcpRichDisplayEnabled: boolean
8586
planActSeparateModelsSetting: boolean
8687
enableCheckpointsSetting?: boolean
8788
platform: Platform

src/shared/WebviewMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export interface WebviewMessage {
4545
mcpMarketplaceEnabled?: boolean
4646
mcpResponsesCollapsed?: boolean
4747
telemetrySetting?: TelemetrySetting
48+
mcpRichDisplayEnabled?: boolean
4849
mentionsRequestId?: string
4950
query?: string
5051
// For toggleFavoriteModel

webview-ui/src/components/mcp/chat-display/McpResponseDisplay.tsx

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -117,36 +117,19 @@ interface UrlMatch {
117117
}
118118

119119
const McpResponseDisplay: React.FC<McpResponseDisplayProps> = ({ responseText }) => {
120-
const { mcpResponsesCollapsed } = useExtensionState() // Get setting from context
120+
const { mcpResponsesCollapsed, mcpRichDisplayEnabled } = useExtensionState() // Get setting from context
121121
const [isExpanded, setIsExpanded] = useState(!mcpResponsesCollapsed) // Initialize with context setting
122122
const [isLoading, setIsLoading] = useState(false) // Initial loading state for rich content
123123
const [displayMode, setDisplayMode] = useState<"rich" | "plain">(() => {
124-
// Get saved preference from localStorage, default to 'rich'
125-
const savedMode = localStorage.getItem("mcpDisplayMode")
126-
return savedMode === "plain" ? "plain" : "rich"
124+
// Initialize directly from the global setting.
125+
return mcpRichDisplayEnabled ? "rich" : "plain"
127126
})
128127
const [urlMatches, setUrlMatches] = useState<UrlMatch[]>([])
129128
const [error, setError] = useState<string | null>(null)
130-
// Add a counter state for forcing re-renders to make toggling run smoother
131-
const [forceUpdateCounter, setForceUpdateCounter] = useState(0)
132129

133130
const toggleDisplayMode = useCallback(() => {
134-
const newMode = displayMode === "rich" ? "plain" : "rich"
135-
// Force an immediate re-render
136-
setForceUpdateCounter((prev) => prev + 1)
137-
// Update display mode and save preference
138-
setDisplayMode(newMode)
139-
localStorage.setItem("mcpDisplayMode", newMode)
140-
// If switching to plain mode, cancel any ongoing processing
141-
if (newMode === "plain") {
142-
console.log("Switching to plain mode - cancelling URL processing")
143-
setUrlMatches([]) // Clear any existing matches when switching to plain mode
144-
} else {
145-
// If switching to rich mode, the useEffect will re-run and fetch data
146-
console.log("Switching to rich mode - will start URL processing")
147-
setUrlMatches([])
148-
}
149-
}, [displayMode])
131+
setDisplayMode((prevMode) => (prevMode === "rich" ? "plain" : "rich"))
132+
}, [])
150133

151134
const toggleExpand = useCallback(() => {
152135
setIsExpanded((prev) => !prev)
@@ -155,14 +138,16 @@ const McpResponseDisplay: React.FC<McpResponseDisplayProps> = ({ responseText })
155138
// Effect to update isExpanded if mcpResponsesCollapsed changes from context
156139
useEffect(() => {
157140
setIsExpanded(!mcpResponsesCollapsed)
158-
}, [])
141+
}, [mcpResponsesCollapsed])
159142

160143
// Find all URLs in the text and determine if they're images
161144
useEffect(() => {
162145
// Skip all processing if in plain mode
163146
if (!isExpanded || displayMode === "plain") {
164147
setIsLoading(false)
165-
setUrlMatches([]) // Clear any existing matches when in plain mode
148+
if (urlMatches.length > 0) {
149+
setUrlMatches([]) // Clear any existing matches when in plain mode
150+
}
166151
return
167152
}
168153

@@ -280,7 +265,7 @@ const McpResponseDisplay: React.FC<McpResponseDisplayProps> = ({ responseText })
280265
processingCanceled = true
281266
console.log("Cleaning up URL processing")
282267
}
283-
}, [responseText, displayMode, forceUpdateCounter, isExpanded])
268+
}, [responseText, displayMode, isExpanded])
284269

285270
// Function to render content based on display mode
286271
const renderContent = () => {

webview-ui/src/components/settings/FeatureSettingsSection.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ const FeatureSettingsSection = () => {
99
setEnableCheckpointsSetting,
1010
mcpMarketplaceEnabled,
1111
setMcpMarketplaceEnabled,
12+
mcpRichDisplayEnabled,
13+
setMcpRichDisplayEnabled,
1214
mcpResponsesCollapsed,
1315
setMcpResponsesCollapsed,
1416
chatSettings,
@@ -44,6 +46,19 @@ const FeatureSettingsSection = () => {
4446
Enables the MCP Marketplace tab for discovering and installing MCP servers.
4547
</p>
4648
</div>
49+
<div style={{ marginTop: 10 }}>
50+
<VSCodeCheckbox
51+
checked={mcpRichDisplayEnabled}
52+
onChange={(e: any) => {
53+
const checked = e.target.checked === true
54+
setMcpRichDisplayEnabled(checked)
55+
}}>
56+
Enable Rich MCP Display
57+
</VSCodeCheckbox>
58+
<p className="text-xs text-[var(--vscode-descriptionForeground)]">
59+
Enables rich formatting for MCP responses. When disabled, responses will be shown in plain text.
60+
</p>
61+
</div>
4762
<div style={{ marginTop: 10 }}>
4863
<VSCodeCheckbox
4964
checked={mcpResponsesCollapsed}

0 commit comments

Comments
 (0)