diff --git a/apps/docs/docs.json b/apps/docs/docs.json index ea21db4d..8a32c873 100644 --- a/apps/docs/docs.json +++ b/apps/docs/docs.json @@ -135,7 +135,15 @@ { "anchor": "Supermemory MCP", "icon": "terminal", - "pages": ["supermemory-mcp/mcp", "supermemory-mcp/setup"] + "pages": [ + "supermemory-mcp/mcp", + "supermemory-mcp/setup", + { + "group": "Setups", + "icon": "layers", + "pages": ["supermemory-mcp/claude-desktop"] + } + ] } ], "tab": "Developer Platform" diff --git a/apps/docs/images/supermemory-mcp/claude-desktop/step-1.png b/apps/docs/images/supermemory-mcp/claude-desktop/step-1.png new file mode 100644 index 00000000..242cef7f Binary files /dev/null and b/apps/docs/images/supermemory-mcp/claude-desktop/step-1.png differ diff --git a/apps/docs/images/supermemory-mcp/claude-desktop/step-2.png b/apps/docs/images/supermemory-mcp/claude-desktop/step-2.png new file mode 100644 index 00000000..f6a30341 Binary files /dev/null and b/apps/docs/images/supermemory-mcp/claude-desktop/step-2.png differ diff --git a/apps/docs/images/supermemory-mcp/claude-desktop/step-3.png b/apps/docs/images/supermemory-mcp/claude-desktop/step-3.png new file mode 100644 index 00000000..9467a059 Binary files /dev/null and b/apps/docs/images/supermemory-mcp/claude-desktop/step-3.png differ diff --git a/apps/docs/images/supermemory-mcp/claude-desktop/step-4.png b/apps/docs/images/supermemory-mcp/claude-desktop/step-4.png new file mode 100644 index 00000000..70799e83 Binary files /dev/null and b/apps/docs/images/supermemory-mcp/claude-desktop/step-4.png differ diff --git a/apps/docs/supermemory-mcp/claude-desktop.mdx b/apps/docs/supermemory-mcp/claude-desktop.mdx new file mode 100644 index 00000000..837945a8 --- /dev/null +++ b/apps/docs/supermemory-mcp/claude-desktop.mdx @@ -0,0 +1,65 @@ +--- +title: "Claude Desktop" +description: "Manual setup for supermemory MCP in Claude Desktop with step-by-step screenshots" +icon: "monitor" +sidebarTitle: "Claude Desktop" +--- + +This guide walks through the **manual** install for [Claude Desktop](https://claude.ai/download): edit `claude_desktop_config.json`, add the supermemory server, then finish in **Connectors**. For a one-line CLI install instead, see [Setup and Usage](/supermemory-mcp/setup). + + + Config file location: **macOS** `~/Library/Application Support/Claude/claude_desktop_config.json` · **Windows** `%APPDATA%\Claude\claude_desktop_config.json` + + +## Step 1 — Copy the configuration + +Copy the supermemory block below. You will paste it inside `mcpServers` in a later step. + +```json +{ + "mcpServers": { + "supermemory": { + "command": "npx", + "args": [ + "-y", + "mcp-remote@latest", + "https://mcp.supermemory.ai/mcp" + ] + } + } +} +``` + +This is the same configuration shown in the supermemory dashboard when you choose **Claude Desktop** for MCP setup. + +## Step 2 — Open Developer settings and Edit Config + +In Claude Desktop, open **Settings → Developer**, then click **Edit Config**. + +![Claude Desktop settings: Developer in the sidebar and Edit Config highlighted](/images/supermemory-mcp/claude-desktop/step-1.png) + +## Step 3 — Open claude_desktop_config.json + +When `claude_desktop_config.json` opens in your editor, keep it ready for the next step. + +![File list with claude_desktop_config.json selected](/images/supermemory-mcp/claude-desktop/step-2.png) + +## Step 4 — Paste under mcpServers and save + +Paste what you copied under `mcpServers` (merge with existing servers if the file already has some), then save. + +![JSON editor showing supermemory mcpServers configuration](/images/supermemory-mcp/claude-desktop/step-3.png) + +## Step 5 — Restart and configure in Connectors + +Restart Claude Desktop. Open **Settings → Connectors**, find **supermemory**, and click **Configure**. + +![Claude Desktop Connectors settings with supermemory and Configure highlighted](/images/supermemory-mcp/claude-desktop/step-4.png) + +## Step 6 — Done + +supermemory is installed in your Claude Desktop and ready to use. + +--- + +**See also:** [Overview](/supermemory-mcp/mcp) · [Setup and Usage](/supermemory-mcp/setup) diff --git a/apps/docs/supermemory-mcp/setup.mdx b/apps/docs/supermemory-mcp/setup.mdx index 92180467..cf66e3a8 100644 --- a/apps/docs/supermemory-mcp/setup.mdx +++ b/apps/docs/supermemory-mcp/setup.mdx @@ -70,17 +70,7 @@ This keeps memories organized by project, useful when working on multiple codeba ### Claude Desktop -Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows): - -```json -{ - "mcpServers": { - "supermemory": { - "url": "https://mcp.supermemory.ai/mcp" - } - } -} -``` +For a screenshot-backed walkthrough (Developer → Edit Config, `claude_desktop_config.json`, Connectors), see **[Claude Desktop](/supermemory-mcp/claude-desktop)**. The recommended one-line install at the top of this page also supports Claude. ### Cursor diff --git a/apps/web/components/connect-ai-modal.tsx b/apps/web/components/connect-ai-modal.tsx index f0806e5e..70487cd6 100644 --- a/apps/web/components/connect-ai-modal.tsx +++ b/apps/web/components/connect-ai-modal.tsx @@ -30,11 +30,27 @@ import { useEffect, useState } from "react" import { toast } from "sonner" import { z } from "zod/v4" import { analytics } from "@/lib/analytics" +import { + defaultMcpSetupTab, + getMcpClientSetup, + mcpClientSetupShowsTabs, + mcpClientShowsOneClick, + resolveMcpSetupTabForClient, +} from "@/lib/mcp-client-setup" +import { ClaudeDesktopManualTimeline } from "@/components/mcp-modal/claude-desktop-manual-timeline" +import { + buildMcpUrlRemoteJson, + CHATGPT_REMOTE_MCP_URL, + CLAUDE_DESKTOP_MCP_SNIPPET, + getManualInstallEntry, +} from "@/lib/mcp-manual-instructions" import { cn } from "@lib/utils" import type { Project } from "@lib/types" import { motion, AnimatePresence } from "motion/react" const clients = { + chatgpt: "ChatGPT", + codex: "Codex", cursor: "Cursor", claude: "Claude Desktop", vscode: "VSCode", @@ -42,9 +58,6 @@ const clients = { "gemini-cli": "Gemini CLI", "claude-code": "Claude Code", "mcp-url": "MCP URL", - "roo-cline": "Roo Cline", - witsy: "Witsy", - enconvo: "Enconvo", } as const const mcpMigrationSchema = z.object({ @@ -125,11 +138,8 @@ export function ConnectAIModal({ const setIsOpen = onOpenChange || setInternalIsOpen const [isMigrateDialogOpen, setIsMigrateDialogOpen] = useState(false) const [selectedProject, setSelectedProject] = useState("none") - const [cursorInstallTab, setCursorInstallTab] = useState< - "oneClick" | "manual" - >("oneClick") - const [mcpUrlTab, setMcpUrlTab] = useState<"oneClick" | "manual">( - openInitialTab || "oneClick", + const [setupTab, setSetupTab] = useState<"oneClick" | "manual">( + openInitialTab ?? "manual", ) const [manualApiKey, setManualApiKey] = useState(null) const [isCopied, setIsCopied] = useState(false) @@ -252,21 +262,38 @@ export function ConnectAIModal({ }, }) - // biome-ignore lint/correctness/useExhaustiveDependencies(createMcpApiKeyMutation.mutate): we need to mutate the mutation useEffect(() => { if (openInitialClient) { setSelectedClient(openInitialClient as keyof typeof clients) - if (openInitialTab) { - setMcpUrlTab(openInitialTab) - if (org?.id) { - createMcpApiKeyMutation.mutate() - } - } + setSetupTab( + resolveMcpSetupTabForClient(openInitialClient, openInitialTab), + ) } - }, [openInitialClient, openInitialTab, org?.id]) + }, [openInitialClient, openInitialTab]) + + useEffect(() => { + if (!selectedClient) return + const s = getMcpClientSetup(selectedClient) + if (!s.oneClick && setupTab === "oneClick") setSetupTab("manual") + if (!s.manual && setupTab === "manual") setSetupTab("oneClick") + }, [selectedClient, setupTab]) + + useEffect(() => { + if (selectedClient !== "mcp-url" || setupTab !== "manual" || !org?.id) + return + if (manualApiKey || createMcpApiKeyMutation.isPending) return + createMcpApiKeyMutation.mutate() + }, [ + selectedClient, + setupTab, + org?.id, + manualApiKey, + createMcpApiKeyMutation.isPending, + createMcpApiKeyMutation.mutate, + ]) function generateInstallCommand() { - if (!selectedClient) return "" + if (!selectedClient || selectedClient === "chatgpt") return "" let command = `npx -y install-mcp@latest https://mcp.supermemory.ai/mcp --client ${selectedClient} --oauth=yes` @@ -290,6 +317,24 @@ export function ConnectAIModal({ toast.success("Copied to clipboard!") } + const copyManualSnippet = (text: string) => { + navigator.clipboard.writeText(text) + analytics.mcpInstallCmdCopied() + toast.success("Copied to clipboard!") + setIsCopied(true) + setTimeout(() => setIsCopied(false), 2000) + } + + const clientSetup = selectedClient ? getMcpClientSetup(selectedClient) : null + const effectiveSetupTab: "manual" | "oneClick" = + clientSetup == null + ? "manual" + : !clientSetup.manual + ? "oneClick" + : !clientSetup.oneClick + ? "manual" + : setupTab + return ( {children} @@ -313,414 +358,406 @@ export function ConnectAIModal({
- {Object.entries(clients) - .slice(0, 7) - .map(([key, clientName]) => ( - - ))} + + {clientName} + +
+ + ))} - {/* Step 2: One-click Install for Cursor, Project Selection for others, or MCP URL */} {selectedClient && (
-
-
-
- 2 -
-

- {selectedClient === "cursor" - ? "Install Supermemory MCP" - : selectedClient === "mcp-url" - ? "MCP Server Configuration" - : "Select Target Project (Optional)"} -

-
- -
- {selectedClient && selectedClient !== "mcp-url" && ( - { - setSelectedClient("mcp-url") - setMcpUrlTab("manual") - if ( - !manualApiKey && - !createMcpApiKeyMutation.isPending - ) { - createMcpApiKeyMutation.mutate() - } - }} - /> - )} - -
- {/* Tabs */} -
-
- - -
-
-
+
+
+ 2
- - {selectedClient === "cursor" ? ( -
- {/* Tab Content */} - {cursorInstallTab === "oneClick" ? ( -
-
-
-

- Click the button below to automatically install and - configure Supermemory in Cursor -

-
- { - analytics.mcpInstallCmdCopied() - toast.success("Opening Cursor installer...") - }} - > - Add Supermemory MCP server to Cursor - -
+ {((clientSetup && mcpClientSetupShowsTabs(clientSetup)) || + selectedClient !== "mcp-url") && ( +
+ {clientSetup && mcpClientSetupShowsTabs(clientSetup) ? ( +
+ +
- ) : ( -
-

- Choose a project and follow the installation steps below -

-
- -
+ ) : null} + {selectedClient !== "mcp-url" && ( +
+ { + setSelectedClient("mcp-url") + setSetupTab("manual") + if ( + !manualApiKey && + !createMcpApiKeyMutation.isPending + ) { + createMcpApiKeyMutation.mutate() + } + }} + />
)}
- ) : selectedClient === "mcp-url" ? ( -
- {mcpUrlTab === "oneClick" ? ( -
-

- Use this URL to quickly configure supermemory in your AI - assistant -

-
- - -
-
- ) : ( -
-

- Add this configuration to your MCP settings file with - authentication -

- {createMcpApiKeyMutation.isPending ? ( -
- + )} +
+ {clientSetup && + mcpClientShowsOneClick(clientSetup, effectiveSetupTab) ? ( + <> + {selectedClient === "cursor" && ( +
+
+

+ Open Cursor and add supermemory in one step, or + switch to Manual instructions to edit{" "} + mcp.json yourself. +

+ { + analytics.mcpInstallCmdCopied() + toast.success("Opening Cursor installer...") + }} + > + Add Supermemory MCP server to Cursor +
- ) : ( - <> -
-
-															
-																{`{
-  "supermemory-mcp": {
-    "command": "npx",
-    "args": ["-y", "mcp-remote", "https://mcp.supermemory.ai/mcp"],
-    "env": {},
-    "headers": {
-      "Authorization": "Bearer ${manualApiKey || "your-api-key-here"}"
-    }
-  }
-}`}
-															
-														
-
+ )} + {selectedClient === "mcp-url" && ( +
+

+ Paste this URL into clients that support remote MCP + over HTTPS (OAuth). +

+
+ + +
+
+ )} + {selectedClient !== "cursor" && + selectedClient !== "mcp-url" && ( +
+

+ Optional: scope installs to a project. Then copy and + run the command in your terminal. +

+
+ +
+
+ +

- The API key is included as a Bearer token in the - Authorization header + Requires Node/npx. OAuth runs when the CLI prompts + you.

- +
)} -
- )} -
- ) : ( -
- + +
+ - {project.name} - - ))} - - -
- )} + Developer mode docs (OpenAI) + +
+ ) + } + if (manual.kind === "claude-desktop-timeline") { + return ( + + copyManualSnippet(CLAUDE_DESKTOP_MCP_SNIPPET) + } + snippetCopied={isCopied} + variant="modal" + /> + ) + } + if (manual.kind === "generic-remote") { + const remoteSnippet = buildMcpUrlRemoteJson( + manualApiKey || "your-api-key-here", + ) + return ( +
+

+ Paste into your MCP config. We create an API key for + you when you open this tab; copy the block after it + appears. +

+ {createMcpApiKeyMutation.isPending ? ( +
+ +
+ ) : ( + <> +
+
+																	
+																		{remoteSnippet}
+																	
+																
+ +
+

+ Bearer token uses your supermemory API key. +

+ + )} +
+ ) + } + return ( +
+

+ {manual.paths} +

+

+ Merge the snippet with your existing config. Restart + the client and sign in with OAuth when prompted. +

+
+
+														
+															{manual.snippet}
+														
+													
+ +
+
+ ) + })() + )} +
)} - {/* Step 3: Command Line - Show for manual installation or non-cursor clients */} - {selectedClient && - selectedClient !== "mcp-url" && - (selectedClient !== "cursor" || cursorInstallTab === "manual") && ( -
-
-
- 3 -
-

- {selectedClient === "cursor" && - cursorInstallTab === "manual" - ? "Manual Installation Command" - : "Installation Command"} -

-
- -
- - -
- -

- {selectedClient === "cursor" && cursorInstallTab === "manual" - ? "Copy and run this command in your terminal for manual installation (or switch to the one-click option above)" - : "Copy and run this command in your terminal to install the MCP server"} -

-
- )} - - {/* Blurred Command Placeholder - Only show when no client selected */} {!selectedClient && (
-
- 3 +
+ 2
-

Installation Command

-
-
+
+

- Select a client above to see the installation command + Select a client for setup instructions

)} @@ -740,7 +777,7 @@ export function ConnectAIModal({
diff --git a/apps/web/components/mcp-modal/claude-desktop-manual-timeline.tsx b/apps/web/components/mcp-modal/claude-desktop-manual-timeline.tsx new file mode 100644 index 00000000..df031f93 --- /dev/null +++ b/apps/web/components/mcp-modal/claude-desktop-manual-timeline.tsx @@ -0,0 +1,214 @@ +"use client" + +import { CheckIcon, CopyIcon } from "lucide-react" +import Image from "next/image" +import { Button } from "@ui/components/button" +import { CLAUDE_DESKTOP_MCP_SNIPPET } from "@/lib/mcp-manual-instructions" +import { cn } from "@lib/utils" +import { dmMonoClassName } from "@/lib/fonts" + +const GUIDE_IMAGES = { + step2: "/mcp-supported-tools/guides/claude-desktop/step-1.png", + step3: "/mcp-supported-tools/guides/claude-desktop/step-2.png", + step4: "/mcp-supported-tools/guides/claude-desktop/step-3.png", + step5: "/mcp-supported-tools/guides/claude-desktop/step-4.png", +} as const + +const STEPS: { + step: number + body: string + imageSrc?: string + imageAlt?: string +}[] = [ + { + step: 1, + body: "Copy the supermemory block below. You will paste it inside mcpServers in a later step.", + }, + { + step: 2, + body: "In Claude Desktop, open Settings → Developer, then click Edit Config.", + imageSrc: GUIDE_IMAGES.step2, + imageAlt: + "Claude Desktop settings: Developer in the sidebar and Edit Config highlighted", + }, + { + step: 3, + body: "When claude_desktop_config.json opens in your editor, keep it ready for the next step.", + imageSrc: GUIDE_IMAGES.step3, + imageAlt: "File list with claude_desktop_config.json selected", + }, + { + step: 4, + body: "Paste what you copied under mcpServers (merge with existing servers if the file already has some), then save.", + imageSrc: GUIDE_IMAGES.step4, + imageAlt: "JSON editor showing supermemory mcpServers configuration", + }, + { + step: 5, + body: "Restart Claude Desktop. Open Settings → Connectors, find supermemory, and click Configure.", + imageSrc: GUIDE_IMAGES.step5, + imageAlt: + "Claude Desktop Connectors settings with supermemory and Configure highlighted", + }, + { + step: 6, + body: "supermemory is installed in your Claude Desktop and ready to use.", + }, +] + +type ClaudeDesktopManualTimelineProps = { + variant: "detail" | "modal" + onCopySnippet: () => void + snippetCopied: boolean +} + +export function ClaudeDesktopManualTimeline({ + variant, + onCopySnippet, + snippetCopied, +}: ClaudeDesktopManualTimelineProps) { + const isDetail = variant === "detail" + + const textMuted = isDetail ? "text-[#B0B0B0]" : "text-muted-foreground" + const border = isDetail ? "border-[#3D434D]" : "border-border" + const spine = isDetail ? "bg-[#7C8C9E]" : "bg-muted-foreground/40" + const circleBorder = isDetail + ? "border-[#9CA8B8]" + : "border-muted-foreground/50" + const circleBg = isDetail ? "bg-[#080B0F]" : "bg-background" + const codeBg = isDetail ? "bg-[#050608]" : "bg-muted" + const imgBorder = isDetail ? "border-[#3D434D]" : "border-border" + const screenshotBed = isDetail ? "bg-[#2A2D35]" : "bg-muted" + + return ( +
+
+
+ +
    + {STEPS.map((item) => ( +
  1. +
    +
    + {item.step} +
    +
    +
    +

    + {item.body} +

    + + {item.step === 1 ? ( + isDetail ? ( +
    +
    +												
    +													{CLAUDE_DESKTOP_MCP_SNIPPET}
    +												
    +											
    + +
    + ) : ( +
    +
    +												
    +													{CLAUDE_DESKTOP_MCP_SNIPPET}
    +												
    +											
    + +
    + ) + ) : null} + + {item.imageSrc ? ( +
    +
    + {item.imageAlt +
    +
    + ) : null} +
    +
  2. + ))} +
+
+
+ ) +} diff --git a/apps/web/components/mcp-modal/index.tsx b/apps/web/components/mcp-modal/index.tsx deleted file mode 100644 index dbc7391f..00000000 --- a/apps/web/components/mcp-modal/index.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { dmSans125ClassName, dmSansClassName } from "@/lib/fonts" -import { Dialog, DialogContent, DialogFooter } from "@repo/ui/components/dialog" -import { cn } from "@lib/utils" -import * as DialogPrimitive from "@radix-ui/react-dialog" -import { XIcon } from "lucide-react" -import { Button } from "@ui/components/button" -import { MCPSteps } from "./mcp-detail-view" -import { SpaceSelector } from "../space-selector" -import { useProject } from "@/stores" -import { useProjectMutations } from "@/hooks/use-project-mutations" - -export function MCPModal({ - isOpen, - onClose, -}: { - isOpen: boolean - onClose: () => void -}) { - const { selectedProject } = useProject() - const { switchProject } = useProjectMutations() - return ( - !open && onClose()}> - -
-
-

- Connect your AI to Supermemory -

-

- Let your AI create and use your memories via MCP. -

-
-
- - - Close - -
-
-
- -
- -
- - switchProject(projects[0] ?? selectedProject) - } - variant="insideOut" - /> - -
- -
-
-
- ) -} diff --git a/apps/web/components/mcp-modal/mcp-detail-view.tsx b/apps/web/components/mcp-modal/mcp-detail-view.tsx index 8f10585b..96d809d1 100644 --- a/apps/web/components/mcp-modal/mcp-detail-view.tsx +++ b/apps/web/components/mcp-modal/mcp-detail-view.tsx @@ -8,22 +8,32 @@ import { parseAsInteger, } from "nuqs" import { Button } from "@ui/components/button" -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@ui/components/select" -import { CircleCheckIcon, CopyIcon, Check } from "lucide-react" +import { CopyIcon, Check, ChevronRight } from "lucide-react" import Image from "next/image" import { toast } from "sonner" import { analytics } from "@/lib/analytics" import { cn } from "@lib/utils" import { dmMonoClassName, dmSansClassName } from "@/lib/fonts" import { SyncLogoIcon } from "@ui/assets/icons" +import { + defaultMcpSetupTab, + getMcpClientSetup, + mcpClientSetupShowsTabs, + mcpClientShowsManual, + mcpClientShowsOneClick, + setupInstructionsSubtitle, +} from "@/lib/mcp-client-setup" +import { + buildMcpUrlRemoteJson, + CHATGPT_REMOTE_MCP_URL, + CLAUDE_DESKTOP_MCP_SNIPPET, + getManualInstallEntry, +} from "@/lib/mcp-manual-instructions" +import { ClaudeDesktopManualTimeline } from "@/components/mcp-modal/claude-desktop-manual-timeline" const clients = { + chatgpt: "ChatGPT", + codex: "Codex", cursor: "Cursor", claude: "Claude Desktop", vscode: "VSCode", @@ -31,11 +41,88 @@ const clients = { "gemini-cli": "Gemini CLI", "claude-code": "Claude Code", "mcp-url": "MCP URL", - "roo-cline": "Roo Cline", - witsy: "Witsy", - enconvo: "Enconvo", } as const +type ClientKey = keyof typeof clients + +const MCP_CATEGORIES: { + label: string + items: { key: ClientKey; title: string; subtitle: string }[] +}[] = [ + { + label: "OpenAI", + items: [ + { + key: "chatgpt", + title: "ChatGPT", + subtitle: "Developer mode · Apps", + }, + { key: "codex", title: "Codex", subtitle: "CLI" }, + ], + }, + { + label: "Claude", + items: [ + { key: "claude", title: "Claude Desktop", subtitle: "Desktop app" }, + { key: "claude-code", title: "Claude Code", subtitle: "CLI" }, + ], + }, + { + label: "IDEs", + items: [ + { key: "cursor", title: "Cursor", subtitle: "AI IDE" }, + { key: "vscode", title: "VS Code", subtitle: "IDE" }, + { key: "cline", title: "Cline", subtitle: "VS Code extension" }, + { key: "gemini-cli", title: "Gemini CLI", subtitle: "Terminal" }, + ], + }, + { + label: "MCP", + items: [{ key: "mcp-url", title: "MCP URL", subtitle: "Custom clients" }], + }, +] + +function clientIconSrc(key: ClientKey) { + if (key === "mcp-url") return "/mcp-icon.svg" + const file = key === "claude-code" ? "claude" : key + return `/mcp-supported-tools/${file}.png` +} + +function ClientToolIcon({ + clientKey, + title, +}: { + clientKey: ClientKey + title: string +}) { + const [failed, setFailed] = useState(false) + const src = clientIconSrc(clientKey) + + return ( +
+ {failed ? ( + + {title.slice(0, 2).toUpperCase()} + + ) : ( + {title} setFailed(true)} + /> + )} +
+ ) +} + interface MCPStepsProps { variant?: "full" | "embedded" } @@ -46,13 +133,12 @@ export function MCPSteps({ variant = "full" }: MCPStepsProps) { parseAsString, ) const [selectedProject] = useState("sm_project_default") - const [mcpUrlTab, setMcpUrlTab] = useQueryState( + const [setupTab, setSetupTab] = useQueryState( "mcpTab", - parseAsStringLiteral(["oneClick", "manual"] as const).withDefault( - "oneClick", - ), + parseAsStringLiteral(["oneClick", "manual"] as const).withDefault("manual"), ) - const [isCopied, setIsCopied] = useState(false) + const [isCommandCopied, setIsCommandCopied] = useState(false) + const [isManualCopied, setIsManualCopied] = useState(false) const [activeStep, setActiveStep] = useQueryState( "mcpStep", parseAsInteger.withDefault(1), @@ -62,8 +148,19 @@ export function MCPSteps({ variant = "full" }: MCPStepsProps) { analytics.mcpViewOpened() }, []) + useEffect(() => { + if (!selectedClient) return + const s = getMcpClientSetup(selectedClient) + if (!s.oneClick && setupTab === "oneClick") setSetupTab("manual") + if (!s.manual && setupTab === "manual") setSetupTab("oneClick") + }, [selectedClient, setupTab, setSetupTab]) + + function getCursorDeeplink() { + return "cursor://anysphere.cursor-deeplink/mcp/install?name=supermemory&config=eyJ1cmwiOiJodHRwczovL2FwaS5zdXBlcm1lbW9yeS5haS9tY3AifQ%3D%3D" + } + function generateInstallCommand() { - if (!selectedClient) return "" + if (!selectedClient || selectedClient === "chatgpt") return "" let command = `npx -y install-mcp@latest https://mcp.supermemory.ai/mcp --client ${selectedClient} --oauth=yes` @@ -77,513 +174,474 @@ export function MCPSteps({ variant = "full" }: MCPStepsProps) { const command = generateInstallCommand() navigator.clipboard.writeText(command) analytics.mcpInstallCmdCopied() - setIsCopied(true) + setIsCommandCopied(true) setActiveStep(3) - setTimeout(() => setIsCopied(false), 2000) + setTimeout(() => setIsCommandCopied(false), 2000) + } + + const copyManualSnippet = (text: string) => { + navigator.clipboard.writeText(text) + analytics.mcpInstallCmdCopied() + toast.success("Copied to clipboard!") + setIsManualCopied(true) + setActiveStep(3) + setTimeout(() => setIsManualCopied(false), 2000) } const isEmbedded = variant === "embedded" + const isValidClient = Boolean(selectedClient && selectedClient in clients) + const selectedKey = isValidClient ? (selectedClient as ClientKey) : null + + const detailSetup = + selectedKey != null ? getMcpClientSetup(selectedKey) : null + const effectiveSetupTab: "manual" | "oneClick" = + detailSetup == null + ? "manual" + : !detailSetup.manual + ? "oneClick" + : !detailSetup.oneClick + ? "manual" + : setupTab + + const gradientStep3 = + activeStep === 3 + ? { + background: + "linear-gradient(94deg, #369BFD 4.8%, #36FDFD 77.04%, #36FDB5 143.99%)", + backgroundClip: "text", + WebkitBackgroundClip: "text", + WebkitTextFillColor: "transparent", + } + : undefined return (
-
-
- -
-
- - {selectedClient && ( - - )} -
-
- {Object.entries(clients) - .slice(0, 7) - .map(([key, clientName]) => ( - ))} -
- {!selectedClient && ( -

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

- )} -
-
- -
-
- - 2 - -
-
-

- Copy the installation command -

- {selectedClient && ( -
- {selectedClient === "mcp-url" ? ( -
-
-
- - -
-
- - {mcpUrlTab === "oneClick" ? ( + +
+ ) : null} +
+ {detailSetup && + mcpClientShowsOneClick(detailSetup, effectiveSetupTab) ? ( + <> + {selectedClient === "mcp-url" && (
-

- Use this URL to quickly configure supermemory in your AI - assistant +

+ Paste this URL into any MCP client that supports remote + servers over HTTPS.

- ) : ( + )} + {selectedClient === "cursor" && ( +
+

+ Open the link below to add supermemory in Cursor, or use + Manual instructions to edit{" "} + + ~/.cursor/mcp.json + + . +

+ +
+ )} + {selectedClient !== "mcp-url" && + selectedClient !== "cursor" && ( +
+

+ Run this command in your terminal. It installs the MCP + for {clients[selectedKey]} and starts OAuth when + needed. +

+
+ + +
+
+ )} + + ) : ( + (() => { + const manual = getManualInstallEntry(selectedKey) + if (manual.kind === "chatgpt") { + return ( +
+
    +
  1. Open ChatGPT in your browser.
  2. +
  3. + Go to Settings → Apps → Advanced settings → enable + Developer mode. +
  4. +
  5. + Create an app and choose your MCP server URL when + asked. +
  6. +
  7. + Paste the URL below and complete OAuth in ChatGPT. +
  8. +
+
+ + +
+ + Developer mode docs (OpenAI) + +
+ ) + } + if (manual.kind === "claude-desktop-timeline") { + return ( + + copyManualSnippet(CLAUDE_DESKTOP_MCP_SNIPPET) + } + snippetCopied={isManualCopied} + variant="detail" + /> + ) + } + if (manual.kind === "generic-remote") { + const snippet = buildMcpUrlRemoteJson("your-api-key-here") + return ( +
+

+ Add this to your client's MCP config. Replace the + placeholder with an API key from supermemory settings + (Integrations). +

+
+
+														
+															{snippet}
+														
+													
+ +
+ {detailSetup?.oneClick ? ( +

+ Use Bearer auth in headers, or switch to One click + setup and paste the HTTPS URL if your client + supports OAuth only. +

+ ) : null} +
+ ) + } + return (
-

- Add this configuration to your MCP settings file with - authentication +

{manual.paths}

+

+ Merge the snippet with your existing file (create it if + needed). Restart the client and complete OAuth when + prompted.

-
-													
-														{`{
-  "supermemory-mcp": {
-    "command": "npx",
-    "args": ["-y", "mcp-remote", "https://api.supermemory.ai/mcp"],
-    "env": {},
-    "headers": {
-      "Authorization": "Bearer your-api-key-here"
-    }
-  }
-}`}
+												
+													
+														{manual.snippet}
 													
 												
-

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

- )} -
- ) : ( -
-
- - -
-
+ ) + })() )}
- )} -
-
+
-
-
- - 3 - -
-
-

- Run command in your terminal -

- {activeStep === 3 && ( -

+

- - Waiting for installation -

- )} + {detailSetup != null && + mcpClientShowsManual(detailSetup, effectiveSetupTab) + ? selectedClient === "chatgpt" + ? "Finish in ChatGPT" + : selectedClient === "claude" + ? "Finish in Claude Desktop" + : "Save and restart" + : selectedClient === "cursor" + ? "Finish in Cursor" + : "Run in terminal"} +

+ {activeStep === 3 && ( +

+ + {detailSetup != null && + mcpClientShowsManual(detailSetup, effectiveSetupTab) + ? selectedClient === "chatgpt" + ? "Complete app setup in ChatGPT, then enable it for your chat." + : selectedClient === "claude" + ? "After Connectors, complete any prompts so supermemory is enabled for chat." + : "Save your config, restart the client, and sign in if prompted." + : selectedClient === "cursor" + ? "Complete the install in Cursor and sign in with OAuth if asked." + : "Waiting for installation"} +

+ )} +
-
+ )}
) } @@ -594,57 +652,29 @@ interface MCPDetailViewProps { export function MCPDetailView({ onBack }: MCPDetailViewProps) { return ( -
-
+
+
-
-

- Connect your AI to supermemory MCP +
+

+ Connect Supermemory MCP to your AI Tools

- -
-
- -

- MCP connects your AI apps to create and use memories directly -

-
-
- -

- Auto-fetch the right context from anything you've saved -

-
-
- -

- One-time setup,
seamless integration across your workflow -

-
-
+

+ Connect Cursor, Claude, VS Code, and more via MCP. +

diff --git a/apps/web/lib/mcp-client-setup.ts b/apps/web/lib/mcp-client-setup.ts new file mode 100644 index 00000000..c983971c --- /dev/null +++ b/apps/web/lib/mcp-client-setup.ts @@ -0,0 +1,68 @@ +export type McpSetupAvailability = { + manual: boolean + oneClick: boolean +} + +const DEFAULT_SETUP: McpSetupAvailability = { + manual: true, + oneClick: true, +} + +/** + * Which setup surfaces each MCP client supports. Clients not listed use both + * manual instructions and one-click (CLI / deeplink / URL copy). + */ +export const MCP_CLIENT_SETUP: Record = { + chatgpt: { manual: true, oneClick: false }, + cline: { manual: false, oneClick: true }, +} + +export function getMcpClientSetup(clientKey: string): McpSetupAvailability { + return MCP_CLIENT_SETUP[clientKey] ?? DEFAULT_SETUP +} + +export function mcpClientSetupShowsTabs(setup: McpSetupAvailability): boolean { + return setup.manual && setup.oneClick +} + +export function defaultMcpSetupTab( + setup: McpSetupAvailability, +): "manual" | "oneClick" { + if (setup.manual && setup.oneClick) return "manual" + if (setup.manual) return "manual" + return "oneClick" +} + +export function resolveMcpSetupTabForClient( + clientKey: string, + preferred: "manual" | "oneClick" | null | undefined, +): "manual" | "oneClick" { + const s = getMcpClientSetup(clientKey) + if (!s.manual) return "oneClick" + if (!s.oneClick) return "manual" + return preferred ?? "manual" +} + +export function mcpClientShowsOneClick( + setup: McpSetupAvailability, + tab: "manual" | "oneClick", +): boolean { + return setup.oneClick && (!setup.manual || tab === "oneClick") +} + +export function mcpClientShowsManual( + setup: McpSetupAvailability, + tab: "manual" | "oneClick", +): boolean { + return setup.manual && (!setup.oneClick || tab === "manual") +} + +export function setupInstructionsSubtitle(setup: McpSetupAvailability): string { + if (mcpClientSetupShowsTabs(setup)) { + return "Choose manual instructions or one click setup (CLI, deeplink, or paste URL)." + } + if (setup.manual) { + return "Follow the steps below to finish setup." + } + return "Use the command or link below, then complete OAuth if prompted." +} diff --git a/apps/web/lib/mcp-manual-instructions.ts b/apps/web/lib/mcp-manual-instructions.ts new file mode 100644 index 00000000..fef869e8 --- /dev/null +++ b/apps/web/lib/mcp-manual-instructions.ts @@ -0,0 +1,113 @@ +export const CHATGPT_REMOTE_MCP_URL = "https://mcp.supermemory.ai/mcp" + +export const SUPERMEMORY_MCP_OAUTH_JSON = `{ + "mcpServers": { + "supermemory": { + "url": "${CHATGPT_REMOTE_MCP_URL}" + } + } +}` + +export function buildMcpUrlRemoteJson(apiKeyPlaceholder: string) { + return `{ + "supermemory-mcp": { + "command": "npx", + "args": ["-y", "mcp-remote", "https://mcp.supermemory.ai/mcp"], + "env": {}, + "headers": { + "Authorization": "Bearer ${apiKeyPlaceholder}" + } + } +}` +} + +export const CODEX_MCP_TOML = `[mcp_servers.supermemory] +command = "npx" +args = ["-y", "mcp-remote@latest", "https://mcp.supermemory.ai/mcp"] +` + +/** Full file merge target: Claude Desktop `claude_desktop_config.json` → `mcpServers`. */ +export const CLAUDE_DESKTOP_MCP_SNIPPET = `{ + "mcpServers": { + "supermemory": { + "command": "npx", + "args": [ + "-y", + "mcp-remote@latest", + "https://mcp.supermemory.ai/mcp" + ] + } + } +}` + +export type ManualInstallEntry = + | { kind: "file"; paths: string; snippet: string; format: "json" | "toml" } + | { kind: "chatgpt" } + | { kind: "generic-remote" } + | { kind: "claude-desktop-timeline" } + +export function getManualInstallEntry(clientKey: string): ManualInstallEntry { + switch (clientKey) { + case "chatgpt": + return { kind: "chatgpt" } + case "mcp-url": + return { kind: "generic-remote" } + case "codex": + return { + kind: "file", + paths: + "Codex: ~/.codex/config.toml (or $CODEX_HOME/config.toml). Merge the block into your existing [mcp_servers] section.", + snippet: CODEX_MCP_TOML, + format: "toml", + } + case "cursor": + return { + kind: "file", + paths: + "Cursor: ~/.cursor/mcp.json globally, or .cursor/mcp.json in your project.", + snippet: SUPERMEMORY_MCP_OAUTH_JSON, + format: "json", + } + case "vscode": + return { + kind: "file", + paths: + "VS Code: macOS ~/Library/Application Support/Code/User/mcp.json · Windows %APPDATA%\\Code\\User\\mcp.json · Linux ~/.config/Code/User/mcp.json.", + snippet: SUPERMEMORY_MCP_OAUTH_JSON, + format: "json", + } + case "cline": + return { + kind: "file", + paths: + "Cline: VS Code user folder → globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json.", + snippet: SUPERMEMORY_MCP_OAUTH_JSON, + format: "json", + } + case "claude": + return { kind: "claude-desktop-timeline" } + case "claude-code": + return { + kind: "file", + paths: + "Claude Code: ~/.claude.json (user) or .mcp.json in the project root.", + snippet: SUPERMEMORY_MCP_OAUTH_JSON, + format: "json", + } + case "gemini-cli": + return { + kind: "file", + paths: + "Gemini CLI: ~/.gemini/settings.json (or project .gemini/settings.json).", + snippet: SUPERMEMORY_MCP_OAUTH_JSON, + format: "json", + } + default: + return { + kind: "file", + paths: "Open your client's MCP settings file (see its documentation).", + snippet: SUPERMEMORY_MCP_OAUTH_JSON, + format: "json", + } + } +} diff --git a/apps/web/public/mcp-supported-tools/chatgpt.png b/apps/web/public/mcp-supported-tools/chatgpt.png new file mode 100644 index 00000000..c784cfb6 Binary files /dev/null and b/apps/web/public/mcp-supported-tools/chatgpt.png differ diff --git a/apps/web/public/mcp-supported-tools/codex.png b/apps/web/public/mcp-supported-tools/codex.png new file mode 100644 index 00000000..11155e4d Binary files /dev/null and b/apps/web/public/mcp-supported-tools/codex.png differ diff --git a/apps/web/public/mcp-supported-tools/guides/claude-desktop/step-1.png b/apps/web/public/mcp-supported-tools/guides/claude-desktop/step-1.png new file mode 100644 index 00000000..242cef7f Binary files /dev/null and b/apps/web/public/mcp-supported-tools/guides/claude-desktop/step-1.png differ diff --git a/apps/web/public/mcp-supported-tools/guides/claude-desktop/step-2.png b/apps/web/public/mcp-supported-tools/guides/claude-desktop/step-2.png new file mode 100644 index 00000000..f6a30341 Binary files /dev/null and b/apps/web/public/mcp-supported-tools/guides/claude-desktop/step-2.png differ diff --git a/apps/web/public/mcp-supported-tools/guides/claude-desktop/step-3.png b/apps/web/public/mcp-supported-tools/guides/claude-desktop/step-3.png new file mode 100644 index 00000000..9467a059 Binary files /dev/null and b/apps/web/public/mcp-supported-tools/guides/claude-desktop/step-3.png differ diff --git a/apps/web/public/mcp-supported-tools/guides/claude-desktop/step-4.png b/apps/web/public/mcp-supported-tools/guides/claude-desktop/step-4.png new file mode 100644 index 00000000..70799e83 Binary files /dev/null and b/apps/web/public/mcp-supported-tools/guides/claude-desktop/step-4.png differ