From 92812138b0640a5f4d486826816214913a8d7560 Mon Sep 17 00:00:00 2001 From: Mahesh Sanikommmu Date: Thu, 19 Mar 2026 22:42:07 -0700 Subject: [PATCH] update mcp installation flow with instruction --- apps/web/components/mcp-modal/index.tsx | 2 +- .../components/mcp-modal/mcp-detail-view.tsx | 860 +++++++++++------- 2 files changed, 540 insertions(+), 322 deletions(-) diff --git a/apps/web/components/mcp-modal/index.tsx b/apps/web/components/mcp-modal/index.tsx index dbc7391f..7406c437 100644 --- a/apps/web/components/mcp-modal/index.tsx +++ b/apps/web/components/mcp-modal/index.tsx @@ -22,7 +22,7 @@ export function MCPModal({ !open && onClose()}> = { + ides: { + label: "IDEs", + description: "Cursor, VS Code, and other code editors", + clients: ["cursor", "vscode"], + }, + "desktop-mcp": { + label: "Desktop MCP Apps", + description: "Claude Desktop, Cline, and similar apps", + clients: ["claude", "cline", "roo-cline", "witsy", "enconvo"], + }, + "cli-agents": { + label: "CLI Agents", + description: "Claude Code, Gemini CLI, and terminal tools", + clients: ["claude-code", "gemini-cli"], + }, + manual: { + label: "Manual / MCP URL", + description: "Any MCP-compatible client or custom setup", + clients: ["mcp-url"], + }, +} + +const CLIENTS: Record< + ClientId, + { name: string; iconKey: string; installMode: InstallMode } +> = { + cursor: { name: "Cursor", iconKey: "cursor", installMode: "one-click" }, + vscode: { name: "VSCode", iconKey: "vscode", installMode: "command" }, + claude: { name: "Claude Desktop", iconKey: "claude", installMode: "command" }, + cline: { name: "Cline", iconKey: "cline", installMode: "command" }, + "roo-cline": { + name: "Roo Cline", + iconKey: "roo-cline", + installMode: "command", + }, + witsy: { name: "Witsy", iconKey: "witsy", installMode: "command" }, + enconvo: { name: "Enconvo", iconKey: "enconvo", installMode: "command" }, + "claude-code": { + name: "Claude Code", + iconKey: "claude", + installMode: "command", + }, + "gemini-cli": { + name: "Gemini CLI", + iconKey: "gemini-cli", + installMode: "command", + }, + "mcp-url": { name: "MCP URL", iconKey: "mcp-url", installMode: "manual" }, +} + +function getClientIconSrc(clientId: ClientId): string { + if (clientId === "mcp-url") return "/mcp-icon.svg" + return `/mcp-supported-tools/${clientId === "claude-code" ? "claude" : clientId}.png` +} interface MCPStepsProps { variant?: "full" | "embedded" } +const stepGradient = { + background: + "linear-gradient(94deg, #369BFD 4.8%, #36FDFD 77.04%, #36FDB5 143.99%)", + backgroundClip: "text", + WebkitBackgroundClip: "text", + WebkitTextFillColor: "transparent", +} as const + +function StepCircle({ + step, + isActive, + onClick, + disabled, +}: { + step: number + isActive: boolean + onClick?: () => void + disabled?: boolean +}) { + return ( + + ) +} + +function ClientChip({ + clientId, + isSelected, + onSelect, +}: { + clientId: ClientId + isSelected: boolean + onSelect: () => void +}) { + const client = CLIENTS[clientId] + return ( + + ) +} + export function MCPSteps({ variant = "full" }: MCPStepsProps) { + const [selectedCategory, setSelectedCategory] = useQueryState( + "mcpCategory", + parseAsString, + ) const [selectedClient, setSelectedClient] = useQueryState( "mcpClient", parseAsString, ) const [selectedProject] = useState("sm_project_default") + const [cursorInstallTab, setCursorInstallTab] = useQueryState( + "cursorTab", + parseAsStringLiteral(["oneClick", "manual"] as const).withDefault( + "oneClick", + ), + ) const [mcpUrlTab, setMcpUrlTab] = useQueryState( "mcpTab", parseAsStringLiteral(["oneClick", "manual"] as const).withDefault( @@ -62,14 +240,17 @@ export function MCPSteps({ variant = "full" }: MCPStepsProps) { analytics.mcpViewOpened() }, []) - function generateInstallCommand() { - if (!selectedClient) return "" - - let command = `npx -y install-mcp@latest https://mcp.supermemory.ai/mcp --client ${selectedClient} --oauth=yes` + const resolvedCategory = selectedCategory as CategoryId | null + const resolvedClient = selectedClient as ClientId | null + const categoryClients = resolvedCategory + ? (CATEGORIES[resolvedCategory]?.clients ?? []) + : [] + const generateInstallCommand = () => { + if (!resolvedClient) return "" + let command = `npx -y install-mcp@latest ${MCP_SERVER_URL} --client ${resolvedClient} --oauth=yes` const projectIdForCommand = selectedProject.replace(/^sm_project_/, "") command += ` --project ${projectIdForCommand}` - return command } @@ -78,11 +259,54 @@ export function MCPSteps({ variant = "full" }: MCPStepsProps) { navigator.clipboard.writeText(command) analytics.mcpInstallCmdCopied() setIsCopied(true) + setActiveStep(4) + setTimeout(() => setIsCopied(false), 2000) + } + + const handleCategorySelect = (cat: CategoryId) => { + setSelectedCategory(cat) + const firstClient = CATEGORIES[cat].clients[0] + setSelectedClient(firstClient ?? null) + setActiveStep(2) + } + + const handleClientSelect = (client: ClientId) => { + setSelectedClient(client) setActiveStep(3) + } + + const handleBackToCategory = () => { + setSelectedCategory(null) + setSelectedClient(null) + setActiveStep(1) + } + + const handleBackToClient = () => { + setSelectedClient(null) + setActiveStep(2) + } + + const handleCopyAndAdvance = (value: string) => { + navigator.clipboard.writeText(value) + analytics.mcpInstallCmdCopied() + toast.success("Copied to clipboard!") + setIsCopied(true) + setActiveStep(4) setTimeout(() => setIsCopied(false), 2000) } const isEmbedded = variant === "embedded" + const showStep3 = resolvedClient && activeStep >= 3 + const showStep4 = activeStep >= 4 + + const step3Title = + resolvedClient === "cursor" && cursorInstallTab === "oneClick" + ? "Install supermemory in Cursor" + : resolvedClient === "mcp-url" + ? mcpUrlTab === "oneClick" + ? "Add MCP URL to your client" + : "Paste config into your MCP settings" + : "Copy and run the installation command" return (
+ + {/* Step 1: Choose setup type */}
- +
-
+ +
+ {( + Object.entries(CATEGORIES) as [ + CategoryId, + (typeof CATEGORIES)[CategoryId], + ][] + ).map(([catId, cat]) => ( + + ))} - {selectedClient && ( - - )}
-
+
+ + {/* Step 2: Choose your app */} +
+ +
+ + Choose your app + + {resolvedCategory && ( +
+ {categoryClients.map((clientId) => ( + handleClientSelect(clientId)} + /> ))} -
- {!selectedClient && ( -

- *You can connect to all of these, setup is different for each one -

+
)}
-
+ {/* Step 3: Install or add supermemory */} +
- 2 + 3

- Copy the installation command + {step3Title}

- {selectedClient && ( + {showStep3 && resolvedClient && (
- {selectedClient === "mcp-url" ? ( + {resolvedClient === "mcp-url" ? (
- {mcpUrlTab === "oneClick" ? (

- Use this URL to quickly configure supermemory in your AI - assistant + Paste this URL into your MCP client to add supermemory

@@ -430,7 +552,7 @@ export function MCPSteps({ variant = "full" }: MCPStepsProps) { {`{ "supermemory-mcp": { "command": "npx", - "args": ["-y", "mcp-remote", "https://api.supermemory.ai/mcp"], + "args": ["-y", "mcp-remote", "${MCP_API_URL}"], "env": {}, "headers": { "Authorization": "Bearer your-api-key-here" @@ -441,24 +563,20 @@ export function MCPSteps({ variant = "full" }: MCPStepsProps) {

- The API key is included as a Bearer token in the + Include your API key as a Bearer token in the Authorization header

)}
+ ) : resolvedClient === "cursor" ? ( +
+
+
+ + +
+
+ {cursorInstallTab === "oneClick" ? ( + + ) : ( +
+

+ Copy the command and run it in your terminal +

+
+ + +
+
+ )} +
) : (
+

+ Copy the command and run it in your terminal +

-
+ {/* Step 4: Restart and test */} +
- 3 + 4

- Run command in your terminal + Restart and test

- {activeStep === 3 && ( -

- - Waiting for installation -

+ {showStep4 && ( +
+

+ Restart your AI client, then ask: "What do you remember + about this project?" or type{" "} + + /context + {" "} + to verify supermemory is connected. +

+
+ + Waiting for connection +
+
)}