diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index d4603e0322..8a6d528b40 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -29,6 +29,7 @@ import { getUri } from "./getUri" import { AutoApprovalSettings, DEFAULT_AUTO_APPROVAL_SETTINGS } from "../../shared/AutoApprovalSettings" import { BrowserSettings, DEFAULT_BROWSER_SETTINGS } from "../../shared/BrowserSettings" import { ChatSettings, DEFAULT_CHAT_SETTINGS } from "../../shared/ChatSettings" +import { DIFF_VIEW_URI_SCHEME } from "../../integrations/editor/DiffViewProvider" /* https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts @@ -928,6 +929,37 @@ export class ClineProvider implements vscode.WebviewViewProvider { } break } + case "openMcpMarketplaceServerDetails": { + if (message.mcpId) { + // close existing + const tabs = vscode.window.tabGroups.all + .flatMap((tg) => tg.tabs) + .filter((tab) => tab.label && tab.label.includes("README") && tab.label.includes("Preview")) + for (const tab of tabs) { + await vscode.window.tabGroups.close(tab) + } + + const response = await fetch(`https://api.cline.bot/v1/mcp/marketplace/item?mcpId=${message.mcpId}`) + const details: McpDownloadResponse = await response.json() + + if (details.readmeContent) { + // Create URI with base64 encoded markdown content + const uri = vscode.Uri.parse( + `${DIFF_VIEW_URI_SCHEME}:${details.name} README?${Buffer.from(details.readmeContent).toString("base64")}`, + ) + + // Show only the preview + await vscode.commands.executeCommand("markdown.showPreview", uri, { + sideBySide: true, + preserveFocus: true, + }) + } + } + + this.postMessageToWebview({ type: "relinquishControl" }) + + break + } case "toggleMcpServer": { try { await this.mcpHub?.toggleServerDisabled(message.serverName!, message.disabled!) diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index b691315d45..5390ff0bdb 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -45,6 +45,7 @@ export interface WebviewMessage { | "subscribeEmail" | "fetchMcpMarketplace" | "downloadMcp" + | "openMcpMarketplaceServerDetails" // | "relaunchChromeDebugMode" text?: string disabled?: boolean diff --git a/webview-ui/src/components/mcp/marketplace/McpMarketplaceCard.tsx b/webview-ui/src/components/mcp/marketplace/McpMarketplaceCard.tsx index 2e6ec6a708..2c5fe11c34 100644 --- a/webview-ui/src/components/mcp/marketplace/McpMarketplaceCard.tsx +++ b/webview-ui/src/components/mcp/marketplace/McpMarketplaceCard.tsx @@ -12,6 +12,7 @@ interface McpMarketplaceCardProps { const McpMarketplaceCard = ({ item, installedServers }: McpMarketplaceCardProps) => { const isInstalled = installedServers.some((server) => server.name === item.mcpId) const [isDownloading, setIsDownloading] = useState(false) + const [isLoading, setIsLoading] = useState(false) useEffect(() => { const handleMessage = (event: MessageEvent) => { @@ -19,6 +20,9 @@ const McpMarketplaceCard = ({ item, installedServers }: McpMarketplaceCardProps) if (message.type === "mcpDownloadDetails") { setIsDownloading(false) } + if (message.type === "relinquishControl") { + setIsLoading(false) + } } window.addEventListener("message", handleMessage) @@ -43,10 +47,16 @@ const McpMarketplaceCard = ({ item, installedServers }: McpMarketplaceCardProps) className="mcp-card" onClick={() => { console.log("Card clicked:", item.mcpId) + setIsLoading(true) + vscode.postMessage({ + type: "openMcpMarketplaceServerDetails", + mcpId: item.mcpId, + }) }} style={{ borderBottom: "1px solid var(--vscode-textCodeBlock-background)", padding: "12px 16px", + cursor: isLoading ? "wait" : "pointer", }}> {/* Main container with logo and content */}