)}
- {/* Step 3: Command Line - Show for manual installation or non-cursor clients */}
- {selectedClient &&
- selectedClient !== "mcp-url" &&
- (selectedClient !== "cursor" || cursorInstallTab === "manual") && (
-
- )}
-
- {/* 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) => (
+ -
+
+
+
+ {item.body}
+
+
+ {item.step === 1 ? (
+ isDetail ? (
+
+
+
+ {CLAUDE_DESKTOP_MCP_SNIPPET}
+
+
+
+
+ ) : (
+
+
+
+ {CLAUDE_DESKTOP_MCP_SNIPPET}
+
+
+
+
+ )
+ ) : null}
+
+ {item.imageSrc ? (
+
+ ) : null}
+
+
+ ))}
+
+
+
+ )
+}
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 (
-
- )
-}
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()}
+
+ ) : (
+ 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 (
-
-
-
-
-
-
+ ) : (
+
+
{
+ setSelectedClient(null)
+ setActiveStep(1)
+ }}
+ className="text-sm font-medium text-[#8B8B8B] transition-colors hover:text-[#FAFAFA]"
+ >
+ ← All clients
+
+
+
+
+
+
+ {clients[selectedKey]}
+
+
+ {detailSetup ? setupInstructionsSubtitle(detailSetup) : ""}
+
+
+
+
+
+ {detailSetup && mcpClientSetupShowsTabs(detailSetup) ? (
+
-
- {selectedClient ? (
-
-
-
- {clients[selectedClient as keyof typeof clients]}
-
-
- ) : (
-
- )}
-
-
- {Object.entries(clients)
- .slice(0, 7)
- .map(([key, clientName]) => (
-
-
-
- {clientName}
-
-
- ))}
-
-
- )}
-
-
- {Object.entries(clients)
- .slice(0, 7)
- .map(([key, clientName]) => (
setSetupTab("manual")}
+ role="tab"
type="button"
- onClick={() => {
- setSelectedClient(key)
- setActiveStep(2)
- }}
- className={`mcp-client-button-group py-[6px] pl-2 pr-3 rounded-full border transition-colors cursor-pointer duration-200 ${
- selectedClient === key
- ? "border-blue-500 bg-blue-500/10"
- : "border-[#242A33] bg-[#080B0F] hover:border-[#3273FC4D] hover:bg-[#08142D]"
- }`}
+ aria-selected={effectiveSetupTab === "manual"}
>
-
-
- {
- const target = e.target as HTMLImageElement
- target.style.display = "none"
- const parent = target.parentElement
- if (
- parent &&
- !parent.querySelector(".fallback-text")
- ) {
- const fallback = document.createElement("span")
- fallback.className =
- "fallback-text text-xs font-bold text-white"
- fallback.textContent = clientName
- .substring(0, 2)
- .toUpperCase()
- parent.appendChild(fallback)
- }
- }}
- src={
- key === "mcp-url"
- ? "/mcp-icon.svg"
- : `/mcp-supported-tools/${key === "claude-code" ? "claude" : key}.png`
- }
- width={20}
- />
-
-
- {clientName}
-
-
+ Manual instructions
- ))}
-
- {!selectedClient && (
-
- *You can connect to all of these, setup is different for each one
-
- )}
-
-
-
-
-
-
- 2
-
-
-
-
- Copy the installation command
-
- {selectedClient && (
-
- {selectedClient === "mcp-url" ? (
-
-
-
- setMcpUrlTab("oneClick")}
- type="button"
- >
- Quick Setup
-
- setMcpUrlTab("manual")}
- type="button"
- >
- Manual Config
-
-
-
-
- {mcpUrlTab === "oneClick" ? (
+
setSetupTab("oneClick")}
+ role="tab"
+ type="button"
+ aria-selected={effectiveSetupTab === "oneClick"}
+ >
+ One click setup
+
+
+ ) : 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.
{
navigator.clipboard.writeText(
- "https://api.supermemory.ai/mcp",
+ "https://mcp.supermemory.ai/mcp",
)
analytics.mcpInstallCmdCopied()
toast.success("Copied to clipboard!")
setActiveStep(3)
}}
>
-
+
- ) : (
+ )}
+ {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.
+
+
+
+
+ {isCommandCopied ? (
+ <>
+
+ Copied
+ >
+ ) : (
+ <>
+
+ Copy
+ >
+ )}
+
+
+
+ )}
+ >
+ ) : (
+ (() => {
+ const manual = getManualInstallEntry(selectedKey)
+ if (manual.kind === "chatgpt") {
+ return (
+
+
+ - Open ChatGPT in your browser.
+ -
+ Go to Settings → Apps → Advanced settings → enable
+ Developer mode.
+
+ -
+ Create an app and choose your MCP server URL when
+ asked.
+
+ -
+ Paste the URL below and complete OAuth in ChatGPT.
+
+
+
+
+
+ copyManualSnippet(CHATGPT_REMOTE_MCP_URL)
+ }
+ >
+
+
+
+
+ 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}
+
+
+
copyManualSnippet(snippet)}
+ >
+ {isManualCopied ? (
+ ✓
+ ) : (
+
+ )}
+
+
+ {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}
{
- const config = `{
- "supermemory-mcp": {
- "command": "npx",
- "args": ["-y", "mcp-remote", "https://api.supermemory.ai/mcp"],
- "env": {},
- "headers": {
- "Authorization": "Bearer your-api-key-here"
- }
- }
-}`
- navigator.clipboard.writeText(config)
- analytics.mcpInstallCmdCopied()
- toast.success("Copied to clipboard!")
- setIsCopied(true)
- setActiveStep(3)
- setTimeout(() => setIsCopied(false), 2000)
- }}
+ className="absolute top-2 right-2 flex size-8 cursor-pointer items-center justify-center rounded bg-[#0D121A] hover:bg-[#1a1a1a]"
+ onClick={() => copyManualSnippet(manual.snippet)}
>
- {isCopied ? (
- ✓
+ {isManualCopied ? (
+ ✓
) : (
)}
-
- The API key is included as a Bearer token in the
- Authorization header
-
- )}
-
- ) : (
-
-
-
-
- {isCopied ? (
- <>
-
- Copied
- >
- ) : (
- <>
-
- Copy
- >
- )}
-
-
-
+ )
+ })()
)}
- )}
-
-
+
-
-
-
- 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 (
-
-
+
+
← Back
-
-
- 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