Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ drizzle.config.ts

# Dependencies
node_modules
bun.lock
.pnp
.pnp.js

Expand Down Expand Up @@ -44,4 +43,3 @@ yarn-error.log*
.venv
.arch
__pycache__

93 changes: 67 additions & 26 deletions apps/mcp/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,21 @@ import Supermemory from "supermemory"
const MAX_CHARS = 200000 // ~50k tokens (character-based limit)
const DEFAULT_PROJECT_ID = "sm_project_default"

export interface Memory {
id: string
memory: string
similarity: number
title?: string
content?: string
}
export type Memory =
| {
id: string
memory: string
similarity: number
title?: string
content?: string
}
| {
id: string
chunk: string
similarity: number
title?: string
content?: string
}

export interface SearchResult {
results: Memory[]
Expand Down Expand Up @@ -85,6 +93,10 @@ export interface GraphBoundsResponse {
} | null
}

export function getMemoryText(m: Memory): string {
return "memory" in m ? m.memory : m.chunk
}

function limitByChars(text: string, maxChars = MAX_CHARS): string {
return text.length > maxChars ? `${text.slice(0, maxChars)}...` : text
}
Expand All @@ -93,6 +105,7 @@ function limitByChars(text: string, maxChars = MAX_CHARS): string {
interface SDKResult {
id: string
memory?: string
chunk?: string
content?: string
similarity: number
title?: string
Expand Down Expand Up @@ -157,11 +170,23 @@ export class SupermemoryClient {
}
}

// Delete the most similar match
const memoryToDelete = searchResult.results[0]
await this.client.documents.delete(memoryToDelete.id)
// Only actual memories (not chunks) can be forgotten
const memoryToDelete = searchResult.results.find((r) => "memory" in r)
if (!memoryToDelete) {
return {
success: false,
message:
"No matching memory found to forget (only document chunks matched).",
containerTag: this.containerTag,
}
}
await this.client.memories.forget({
id: memoryToDelete.id,
containerTag: this.containerTag,
})

const memoryText = memoryToDelete.memory || memoryToDelete.content || ""
const memoryText =
getMemoryText(memoryToDelete) || memoryToDelete.content || ""
return {
success: true,
message: `Forgot: "${limitByChars(memoryText, 100)}"`,
Expand All @@ -182,14 +207,22 @@ export class SupermemoryClient {
searchMode: "hybrid",
})

// Normalize and limit response size
const results: Memory[] = (result.results as SDKResult[]).map((r) => ({
id: r.id,
memory: limitByChars(r.content || r.memory || r.context || ""),
similarity: r.similarity,
title: r.title,
content: r.content,
}))
// Normalize and limit response size — preserve memory vs chunk distinction
const results: Memory[] = (result.results as SDKResult[]).map((r) => {
const text = limitByChars(
r.content || r.memory || r.chunk || r.context || "",
)
const base = {
id: r.id,
similarity: r.similarity,
title: r.title,
content: r.content,
}
if (r.chunk && !r.memory) {
return { ...base, chunk: text }
}
return { ...base, memory: text }
})

return {
results,
Expand Down Expand Up @@ -218,13 +251,21 @@ export class SupermemoryClient {

if (result.searchResults) {
response.searchResults = {
results: (result.searchResults.results as SDKResult[]).map((r) => ({
id: r.id,
memory: limitByChars(r.content || r.memory || r.context || ""),
similarity: r.similarity,
title: r.title,
content: r.content,
})),
results: (result.searchResults.results as SDKResult[]).map((r) => {
const text = limitByChars(
r.content || r.memory || r.chunk || r.context || "",
)
const base = {
id: r.id,
similarity: r.similarity,
title: r.title,
content: r.content,
}
if (r.chunk && !r.memory) {
return { ...base, chunk: text }
}
return { ...base, memory: text }
}),
total: result.searchResults.total,
timing: result.searchResults.timing,
}
Expand Down
7 changes: 3 additions & 4 deletions apps/mcp/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ import {
registerAppResource,
RESOURCE_MIME_TYPE,
} from "@modelcontextprotocol/ext-apps/server"
import { SupermemoryClient } from "./client"
import { SupermemoryClient, getMemoryText } from "./client"
import { initPosthog, posthog } from "./posthog"
import { z } from "zod"
// @ts-expect-error - wrangler handles HTML imports as text modules via rules config
import mcpAppHtml from "../dist/mcp-app.html"

type Env = {
Expand Down Expand Up @@ -670,7 +669,7 @@ export class SupermemoryMCP extends McpAgent<Env, unknown, Props> {
`\n### Memory ${i + 1} (${Math.round(memory.similarity * 100)}% match)`,
)
if (memory.title) parts.push(`**${memory.title}**`)
parts.push(memory.memory)
parts.push(getMemoryText(memory))
}
}

Expand Down Expand Up @@ -736,7 +735,7 @@ export class SupermemoryMCP extends McpAgent<Env, unknown, Props> {
`\n### Memory ${i + 1} (${Math.round(memory.similarity * 100)}% match)`,
)
if (memory.title) parts.push(`**${memory.title}**`)
parts.push(memory.memory)
parts.push(getMemoryText(memory))
}

return { content: [{ type: "text" as const, text: parts.join("\n") }] }
Expand Down
Loading
Loading