Skip to main content
Glama
home.tsx10.8 kB
import { Supermemory } from "supermemory" import { nanoid } from "nanoid" import { data, type AppLoadContext } from "react-router" import { commitSession, getSession } from "~/session-cookies.server" import { Welcome } from "../welcome/welcome" import type { Route } from "./+types/home" export function meta() { return [ { title: "Supermemory MCP" }, { name: "description", content: "Universal Memory MCP" }, // og image { name: "og:image", content: "/og-image.png" }, { name: "twitter:card", content: "summary_large_image" }, // twitter large image { name: "twitter:image", content: "/og-image.png" }, // apple touch icons { tagName: "link", rel: "apple-touch-icon", sizes: "57x57", href: "/icons/apple-icon-57x57.png", }, { tagName: "link", rel: "apple-touch-icon", sizes: "60x60", href: "/icons/apple-icon-60x60.png", }, { tagName: "link", rel: "apple-touch-icon", sizes: "72x72", href: "/icons/apple-icon-72x72.png", }, { tagName: "link", rel: "apple-touch-icon", sizes: "76x76", href: "/icons/apple-icon-76x76.png", }, { tagName: "link", rel: "apple-touch-icon", sizes: "114x114", href: "/icons/apple-icon-114x114.png", }, { tagName: "link", rel: "apple-touch-icon", sizes: "120x120", href: "/icons/apple-icon-120x120.png", }, { tagName: "link", rel: "apple-touch-icon", sizes: "144x144", href: "/icons/apple-icon-144x144.png", }, { tagName: "link", rel: "apple-touch-icon", sizes: "152x152", href: "/icons/apple-icon-152x152.png", }, { tagName: "link", rel: "apple-touch-icon", sizes: "180x180", href: "/icons/apple-icon-180x180.png", }, // favicons { tagName: "link", rel: "icon", type: "image/png", sizes: "192x192", href: "/icons/android-icon-192x192.png", }, { tagName: "link", rel: "icon", type: "image/png", sizes: "32x32", href: "/icons/favicon-32x32.png", }, { tagName: "link", rel: "icon", type: "image/png", sizes: "96x96", href: "/icons/favicon-96x96.png", }, { tagName: "link", rel: "icon", type: "image/png", sizes: "16x16", href: "/icons/favicon-16x16.png", }, // manifest and theme { tagName: "link", rel: "manifest", href: "/icons/manifest.json" }, { name: "msapplication-TileColor", content: "#ffffff" }, { name: "msapplication-TileImage", content: "/icons/ms-icon-144x144.png", }, { name: "theme-color", content: "#ffffff" }, ] } export async function loader({ request, context }: Route.LoaderArgs) { const cookies = request.headers.get("Cookie") const session = await getSession(cookies) const supermemory = new Supermemory({ apiKey: context.cloudflare.env.SUPERMEMORY_API_KEY, }) if (session.has("userId")) { const userId = session.get("userId")! const memories = ( await supermemory.memories.list({ limit: "2000", containerTags: [userId] }) ).memories console.log("memories", memories) return data({ message: "Welcome back!", userId, memories, }) } session.set("userId", nanoid()) const userId = session.get("userId")! return data( { message: "Welcome to Supermemory MCP!", userId, memories: [], }, { headers: { "Set-Cookie": await commitSession(session, { expires: new Date("9999-12-31"), }), }, }, ) } export async function action({ request, context, }: { request: Request context: AppLoadContext }) { const formData = await request.formData() const userId = formData.get("userId") as string const actionType = formData.get("action") as string if (!userId) { return data({ error: "User ID is required" }, { status: 400 }) } console.log(context.cloudflare.env.SUPERMEMORY_API_KEY) const supermemory = new Supermemory({ apiKey: context.cloudflare.env.SUPERMEMORY_API_KEY, }) try { // Handle different action types switch (actionType) { case "fetch": // Just return the memories return data({ success: true, memories: ( await supermemory.memories.list({ limit: "2000", containerTags: [userId] }) ).memories, }) // case "add": // const content = formData.get("content") as string; // if (content) { // await supermemory.memory.create({ // content // }); // } // return data({ success: true, memories: (await supermemory.memory.list({ // limit: "2000", // })).memories }); case "delete": { const memoryId = formData.get("memoryId") as string if (!memoryId) { return data( { error: "Memory ID is required" }, { status: 400 }, ) } // Delete from Supermemory API try { console.log( "deleting", await supermemory.memories.get(memoryId), ) await supermemory.memories.delete(memoryId) // Update user data return data({ success: true, message: "Memory deleted successfully", memories: ( await supermemory.memories.list({ limit: "2000", containerTags: [userId] }) ).memories, }) } catch (error: unknown) { console.error("Error deleting memory:", error) return data( { error: `Error deleting memory: ${ error instanceof Error ? error.message : String(error) }`, }, { status: 500 }, ) } } case "update": { const memoryId = formData.get("memoryId") as string const content = formData.get("content") as string if (!memoryId) { return data( { error: "Memory ID is required" }, { status: 400 }, ) } // Update from Supermemory API try { console.log( "updating", await supermemory.memories.get(memoryId), ) await supermemory.memories.update(memoryId, { content }) // Update user data return data({ success: true, message: "Memory updated successfully", memories: ( await supermemory.memories.list({ limit: "2000", containerTags: [userId], }) ).memories, }) } catch (error: unknown) { console.error("Error updating memory:", error) return data( { error: `Error updating memory: ${ error instanceof Error ? error.message : String(error) }`, }, { status: 500 }, ) } } case "restore": { const cookies = request.headers.get("Cookie") const session = await getSession(cookies) // Set the userId in the session session.set("userId", userId) // Get memories for the restored userId const memories = ( await supermemory.memories.list({ limit: "2000", containerTags: [userId] }) ).memories return data( { success: true, message: "Session restored successfully", userId, memories, }, { headers: { "Set-Cookie": await commitSession(session, { expires: new Date("9999-12-31"), }), }, }, ) } default: return data({ error: "Invalid action type" }, { status: 400 }) } } catch (error) { console.error("Error processing memory action:", error) return data( { error: "Failed to process memory action" }, { status: 500 }, ) } } export default function Home({ loaderData }: Route.ComponentProps) { return ( <Welcome message={loaderData.message} userId={loaderData.userId} initialMemories={loaderData.memories} /> ) }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/supermemoryai/supermemory-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server