Skip to content

feat(mcp): add listMemories tool for enumerating stored memories#1183

Open
abhay-codes07 wants to merge 1 commit into
supermemoryai:mainfrom
abhay-codes07:feat/mcp-list-memories-tool
Open

feat(mcp): add listMemories tool for enumerating stored memories#1183
abhay-codes07 wants to merge 1 commit into
supermemoryai:mainfrom
abhay-codes07:feat/mcp-list-memories-tool

Conversation

@abhay-codes07

@abhay-codes07 abhay-codes07 commented Jul 2, 2026

Copy link
Copy Markdown

What

Fixes #1030

Adds a listMemories tool to the MCP server so agents can enumerate what is stored — audit before a save/forget, bulk cleanup of stale memories, or a plain "show me everything you remember" — none of which recall's top-K search can do reliably.

How this differs from #1044

The earlier attempt was closed because it called the documents list API with includeContent: true, so a single ~48k-char document blew Claude's output limits even at limit: 5. This implementation takes the direction suggested in that review:

  • No document content, ever. It reuses the existing getDocuments client method (same one memory-graph uses), which returns documents with their extracted memoryEntries — the short memory facts — plus title/type/date for context. No includeContent anywhere.
  • Bounded output. limit is capped at 50 documents per page (default 10), each memory fact is whitespace-flattened and truncated at 500 chars, and forgotten (isForgotten) and superseded (isLatest: false) entries are filtered out.
  • Pagination that matches the API. Page/limit like the underlying documents endpoint, with an explicit "More available — call listMemories with page: N" hint so agents can walk the full set.

Sample output:

3 memories across 2 documents (page 1 of 4, 37 documents total), newest first.

"Preferences" (text, 2026-06-12)
- User prefers dark mode
- User works in TypeScript

"Meeting notes" (text, 2026-06-10)
- Standup moved to 9:30am

The tool description steers agents to keep using recall for topic search and listMemories only for enumeration/audit, and the containerTag scoping follows the same hasRootContainerTag pattern as the other tools (root-scoped connections can't override it).

Changes

  • src/server.ts — register listMemories + handler, mirroring the existing tool patterns (zod schema, error shape)
  • src/format.tsformatMemoriesList(), a pure formatter over the existing DocumentsApiResponse type
  • src/format.test.ts — 8 unit tests: empty store vs out-of-range page, grouping, forgotten/superseded filtering, untitled docs, docs still extracting, multi-line flattening + truncation, next-page hint
  • e2e/list-memories.test.ts — key-gated spec following the suite's conventions (unique markers, polling for eventual consistency, teardown forget): discovery, save→list round-trip, pagination, limit validation
  • vitest.config.ts — also pick up src/**/*.test.ts
  • README.md — document the tool and the new e2e file

Testing

  • vitest run src/format.test.ts — 8/8 pass
  • vite build + wrangler deploy --dry-run — worker bundles cleanly with the new tool
  • biome check — clean on all touched files
  • e2e spec skips without SUPERMEMORY_API_KEY (same as the rest of the suite), so CI stays safe without secrets; happy to run it against staging if someone can trigger it with a key
  • Note: the three e2e/oauth.test.ts no-secret failures I see locally reproduce on main too (the production authorize endpoint now returns 200 instead of a 302 to /login) — unrelated to this change

cc @ved015 — this picks up where #1044 left off, with the output-size concern from your review addressed at the data-shape level.


Session Details

  • Session: View Session
  • Requested by: Unknown
  • Address comments on this PR. Add (aside) to your comment to have me ignore it.

The MCP server had no way to enumerate what is stored - only top-K
recall results, or save/forget one at a time. This blocked audit and
cleanup workflows (list everything on file, prune stale memories).

Add a listMemories tool that pages through documents via the existing
getDocuments client method and returns only the extracted memory facts,
grouped by source document, newest first. Document content is never
included and each fact is capped at 500 chars, keeping responses well
within client output limits (the concern that stalled the previous
attempt in supermemoryai#1044). Forgotten and superseded memory entries are
filtered out.

Pagination is page/limit based (limit capped at 50 documents) to match
the underlying documents API, with a next-page hint in the output.

Testing: unit tests for the formatter (vitest config now also picks up
src/**/*.test.ts), a key-gated e2e spec following the existing suite
conventions, and README docs for the new tool.

Fixes supermemoryai#1030
Copilot AI review requested due to automatic review settings July 2, 2026 01:24

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@vorflux vorflux Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Reviewed — found 1 issue(s). I reviewed the new MCP listMemories formatter/tool implementation and related docs/tests for correctness, output-safety, and client-facing behavior.

Findings

apps/mcp/src/format.ts

  1. The formatter caps each memory string but not the total number of rendered memory entries, so one response can still grow without a practical bound.

Verdict

⚠️ Changes requested. Please add an overall output cap and/or cap memories per page/document so listMemories cannot exceed MCP/client output limits or force large Worker string allocations.


Review with Vorflux

Comment thread apps/mcp/src/format.ts
}

memoryCount += activeEntries.length
const lines = activeEntries.map((entry) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formatMemoriesList truncates each individual entry.memory, but this loop still renders every active memoryEntries item for every document on the page. Since the limit only caps documents, a single document with hundreds or thousands of memories, or a full page of documents with many memories each, can produce unbounded MCP output and large Worker string allocations. Please add an overall response character cap and/or a per-document/page memory cap with a clear truncation message, such as asking the caller to request a narrower scope or later page.

@vorflux

vorflux Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Testing

The testing subagent exercised the new MCP listMemories tool against the PR Worker, ran the targeted formatter tests, performed MCP smoke checks, and compared the MCP type-check result against main. The targeted new e2e test is currently failing because it asserts that raw saved document content appears in listMemories, while the tool returns extracted memory facts only.

Commands run:

bun install
cd apps/mcp && bun run dev:app
bunx vitest run e2e/list-memories.test.ts
bunx vitest run src/format.test.ts
# Sanitized MCP smoke scripts calling listTools() and listMemories
NODE_OPTIONS=--max-old-space-size=8192 bunx tsc --noEmit -p apps/mcp/tsconfig.json
# Compared MCP type-check failures against refs/remotes/origin/main

Result:

Targeted MCP e2e: FAILED
- listMemories appears in tool discovery: passed
- save -> list round trip returned UUID marker within ~90s: failed
- pagination with page: 1, limit: 1: passed
- invalid limit: 500 rejected as tool error: passed

Failure:
listMemories never returned marker ...

Diagnosis:
Direct API query to POST /v3/documents/documents found the newly saved marker document on page 1, but that document had memoryEntries: []. Since listMemories returns extracted memory facts only and does not dump raw document content, expecting the raw UUID marker in the output is unstable/incorrect unless extraction produces a fact containing that exact marker.

Formatter unit audit: PASSED
bunx vitest run src/format.test.ts
8 tests passed.

MCP smoke checks: PASSED after one transient upstream retry
listTools() confirmed listMemories is discoverable on the local PR Worker.
listMemories page=1 limit=20 retry returned:
2 memories across 20 documents (page 1 of 266, 5307 documents total), newest first.

Type check: FAILED, but pre-existing
NODE_OPTIONS=--max-old-space-size=8192 bunx tsc --noEmit -p apps/mcp/tsconfig.json fails on this PR, and the same MCP type-check failures reproduce on refs/remotes/origin/main.

Text logs from the run:

/tmp/list-memories-e2e.log
/tmp/format-test.log
/tmp/mcp-tsc.log
/tmp/mcp-tsc-main.log
/tmp/list-memories-smoke.log
/tmp/list-memories-smoke20-retry.log

Verdict

⚠️ Issues found. The new tool is discoverable and basic listing works, but the newly added e2e/list-memories.test.ts currently fails and should be fixed before merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Add 'listMemories' tool to MCP server for enumerating user memories

2 participants