diff --git a/apps/docs/supermemory-mcp/mcp.mdx b/apps/docs/supermemory-mcp/mcp.mdx index c7f5f6dc..2835f497 100644 --- a/apps/docs/supermemory-mcp/mcp.mdx +++ b/apps/docs/supermemory-mcp/mcp.mdx @@ -48,7 +48,8 @@ Your assistant chooses these tools automatically. Use this table when you need t | --- | --- | --- | --- | | `search_memory` | Semantic recall from one space | `query` (required), `containerTag` | Matching memories | | `get_profile` | Stable and recent profile context for one space | `containerTag` | Profile facts | -| `add_memory` | Save information or forget outdated information | `content` (required), `action` (`save` or `forget`), `containerTag` | Save or forget confirmation | +| `add_memory` | Save information | `content` (required), `namespace` | Save confirmation | +| `forget_memory` | Forget outdated information | `content` (required), `namespace` | Forget confirmation | | `list_documents` | Browse stored source documents and their summaries | `page`, `limit`, `containerTag` | Document IDs, titles, types, status, dates, and summaries | | `get_document` | Read the available content of one document | `documentId` (required) | Document metadata, summary, and available content | | `list_memories` | Browse recent extracted memory entries and their source document IDs | `page`, `limit`, `containerTag` | Memory IDs, text, versions, and source document IDs | @@ -70,7 +71,7 @@ Use the retrieval tools for different questions: ### Save or forget -`add_memory` saves the supplied `content` by default. Set `action` to `forget` when a fact is outdated or should be removed. There is no separate forget tool. +`add_memory` saves the supplied `content`. Use `forget_memory` when a fact is outdated or should be removed. Both tools use the active space unless you pass `namespace`. The deprecated `containerTag` input and `add_memory` with `action: "forget"` remain supported for existing clients. Because the legacy action can remove information, `add_memory` retains its destructive safety annotation. If the content is already final, the assistant should use `add_memory`. If you want to review, edit, or choose a space before saving, it should open the `guided-save` widget instead. diff --git a/apps/mcp/README.md b/apps/mcp/README.md index 9608db6e..26476920 100644 --- a/apps/mcp/README.md +++ b/apps/mcp/README.md @@ -55,7 +55,8 @@ The client discovers the OAuth authorization server through | `list_memories` | List extracted memory entries and their source document IDs | | `list_spaces` | List spaces visible to the authenticated account | | `who_am_i` | Return identity, access, and active-space context | -| `add_memory` | Save or forget a memory | +| `add_memory` | Save a memory (legacy `action: "forget"` remains supported) | +| `forget_memory` | Forget a memory matching the supplied content | ### MCP App launchers diff --git a/apps/mcp/e2e/discovery.test.ts b/apps/mcp/e2e/discovery.test.ts index c252105a..2260fc7d 100644 --- a/apps/mcp/e2e/discovery.test.ts +++ b/apps/mcp/e2e/discovery.test.ts @@ -10,6 +10,7 @@ import { const EXPECTED_TOOLS = [ "add_memory", "fetch-graph-data", + "forget_memory", "getDocument", "get_document", "get_profile", diff --git a/apps/mcp/src/server/tools/add-memory.ts b/apps/mcp/src/server/tools/add-memory.ts index 104dd87b..97bdd6da 100644 --- a/apps/mcp/src/server/tools/add-memory.ts +++ b/apps/mcp/src/server/tools/add-memory.ts @@ -6,6 +6,7 @@ import { withLegacyNamespace, } from "./compat" import { MEMORY_TOOL_ANNOTATIONS } from "./annotations" +import { forgetMemory } from "./forget-memory" import { addMemoryOutputSchema, type AddMemoryOutput } from "./output-schemas" import { textContent, type ToolDeps } from "./types" @@ -14,8 +15,14 @@ export function register(deps: ToolDeps) { content: z .string() .max(200000, "Content exceeds maximum length") - .describe("The memory content to save or forget"), - action: z.enum(["save", "forget"]).optional().default("save"), + .describe("The memory content to save"), + action: z + .enum(["save", "forget"]) + .optional() + .default("save") + .describe( + "Deprecated compatibility input. Use forget_memory to forget content; omit action to save.", + ), namespace: optionalNamespaceSchema, ...legacyNamespaceInput, }) @@ -24,30 +31,17 @@ export function register(deps: ToolDeps) { "add_memory", { description: - "Add (save) or forget a memory in the user's ACTIVE space. Defaults to 'save'. The target space is the one the user selected via select-space; pass namespace only to override it. Use 'forget' when information is outdated or the user asks to remove it.", + "Save a memory in the user's ACTIVE space. The target space is the one the user selected via select-space; pass namespace only to override it. To remove outdated information, use the separately exposed forget_memory tool. Legacy action='forget' remains supported for existing clients.", inputSchema, outputSchema: addMemoryOutputSchema, annotations: MEMORY_TOOL_ANNOTATIONS, }, async (args) => { + if (args.action === "forget") return forgetMemory(deps, args) try { const namespace = await deps.resolveNamespace(namespaceArg(args)) const client = deps.getClient(namespace) - if (args.action === "forget") { - const result = await client.forgetMemory(args.content) - const structuredContent: AddMemoryOutput = withLegacyNamespace({ - action: "forget", - success: result.success, - namespace: result.namespace, - message: result.message, - }) - return { - content: [textContent(result.message)], - structuredContent, - } - } - const result = await client.createMemory(args.content) const message = `Memory saved (ID: ${result.id}, space: ${result.namespace})` const structuredContent: AddMemoryOutput = withLegacyNamespace({ diff --git a/apps/mcp/src/server/tools/forget-memory.ts b/apps/mcp/src/server/tools/forget-memory.ts new file mode 100644 index 00000000..1369fbde --- /dev/null +++ b/apps/mcp/src/server/tools/forget-memory.ts @@ -0,0 +1,52 @@ +import { z } from "zod" +import { optionalNamespaceSchema } from "../namespace" +import { MEMORY_TOOL_ANNOTATIONS } from "./annotations" +import { + legacyNamespaceInput, + namespaceArg, + withLegacyNamespace, +} from "./compat" +import { forgetMemoryOutputSchema } from "./output-schemas" +import { textContent, type ToolDeps } from "./types" + +export async function forgetMemory( + deps: ToolDeps, + args: { content: string; namespace?: string; containerTag?: string }, +) { + try { + const namespace = await deps.resolveNamespace(namespaceArg(args)) + const result = await deps.getClient(namespace).forgetMemory(args.content) + return { + content: [textContent(result.message)], + structuredContent: withLegacyNamespace({ + action: "forget" as const, + success: result.success, + namespace: result.namespace, + message: result.message, + }), + } + } catch (error) { + return deps.errorResult(error) + } +} + +export function register(deps: ToolDeps) { + deps.server.registerTool( + "forget_memory", + { + description: + "Forget a memory matching the supplied content in the user's ACTIVE space. Use when information is outdated or the user asks to remove it. The target space is the one selected via select-space; pass namespace only to override it.", + inputSchema: z.object({ + content: z + .string() + .max(200000, "Content exceeds maximum length") + .describe("The memory content to forget"), + namespace: optionalNamespaceSchema, + ...legacyNamespaceInput, + }), + outputSchema: forgetMemoryOutputSchema, + annotations: MEMORY_TOOL_ANNOTATIONS, + }, + async (args) => forgetMemory(deps, args), + ) +} diff --git a/apps/mcp/src/server/tools/index.ts b/apps/mcp/src/server/tools/index.ts index 26eb454c..15d786ff 100644 --- a/apps/mcp/src/server/tools/index.ts +++ b/apps/mcp/src/server/tools/index.ts @@ -1,5 +1,6 @@ import * as addMemory from "./add-memory" import * as fetchGraphData from "./fetch-graph-data" +import * as forgetMemory from "./forget-memory" import * as getDocument from "./get-document" import * as getProfile from "./get-profile" import * as guidedSave from "./guided-save" @@ -68,6 +69,7 @@ export function registerAllTools(toolDeps: ToolDeps) { memoryGraph.register(deps) fetchGraphData.register(deps) addMemory.register(deps) + forgetMemory.register(deps) guidedSave.register(deps) saveMemory.register(deps) uploadFile.register(deps) diff --git a/apps/mcp/src/server/tools/output-schemas.ts b/apps/mcp/src/server/tools/output-schemas.ts index 72a9065d..0fe1e96e 100644 --- a/apps/mcp/src/server/tools/output-schemas.ts +++ b/apps/mcp/src/server/tools/output-schemas.ts @@ -29,6 +29,10 @@ export const addMemoryOutputSchema = z.object({ export type AddMemoryOutput = z.infer +export const forgetMemoryOutputSchema = addMemoryOutputSchema.extend({ + action: z.literal("forget"), +}) + export const getDocumentOutputSchema = z.object({ namespace: z.string(), ...legacyNamespaceOutput,