feat(mcp): add export-memories tool for data portability#807
feat(mcp): add export-memories tool for data portability#807mvanhorn wants to merge 1 commit intosupermemoryai:mainfrom
Conversation
Add an export-memories MCP tool that dumps all documents with their extracted memories as JSON or JSONL. Uses the existing graph viewport endpoint to retrieve documents and memories without requiring new backend API endpoints. Supports per-project filtering via containerTag and two output formats (json for readability, jsonl for streaming/piping). Also adds an exportMemories() method to SupermemoryClient that fetches the full graph bounds and retrieves all documents within. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EntelligenceAI PR SummaryAdds an end-to-end export memories capability across the MCP client and server layers for backup and migration use cases.
Confidence Score: 1/5 - Blocking Issues
Files requiring special attention
|
There was a problem hiding this comment.
Walkthrough
This PR adds an export memories feature to the MCP integration. A new exportMemories method is introduced in the client to retrieve all documents using graph bounds and viewport queries. A corresponding export-memories MCP tool is registered on the server, supporting JSON and JSONL output formats with optional container scoping, intended for backup and migration use cases.
Changes
| File(s) | Summary |
|---|---|
apps/mcp/src/client.ts |
Added exportMemories async method to SupermemoryClient that fetches full coordinate bounds via getGraphBounds and retrieves all documents via getGraphViewport with a 10,000 document limit. |
apps/mcp/src/server.ts |
Registered a new export-memories MCP tool supporting json and jsonl output formats, optional containerTag scoping, and returning document/memory counts alongside serialized output with standardized error handling. |
🔗 Cross-Repository Impact Analysis
Enable automatic detection of breaking changes across your dependent repositories. → Set up now
Learn more about Cross-Repository Analysis
What It Does
- Automatically identifies repositories that depend on this code
- Analyzes potential breaking changes across your entire codebase
- Provides risk assessment before merging to prevent cross-repo issues
How to Enable
- Visit Settings → Code Management
- Configure repository dependencies
- Future PRs will automatically include cross-repo impact analysis!
Benefits
- 🛡️ Prevent breaking changes across repositories
- 🔍 Catch integration issues before they reach production
- 📊 Better visibility into your multi-repo architecture
| try { | ||
| // Get bounds first to know the full coordinate range | ||
| const bounds = await this.getGraphBounds(containerTags) | ||
| const { minX, maxX, minY, maxY } = bounds.bounds |
There was a problem hiding this comment.
Correctness: GraphBoundsResponse.bounds is typed as { minX, maxX, minY, maxY } | null, so destructuring bounds.bounds directly will throw a TypeError at runtime when there are no documents and the API returns null.
🤖 AI Agent Prompt for Cursor/Windsurf
📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue
In apps/mcp/src/client.ts, in the exportMemories method around line 396, `bounds.bounds` can be null (as declared in GraphBoundsResponse). Destructuring it directly will throw a TypeError when the API returns null bounds (e.g., when there are no documents). Add a null check before destructuring: if bounds.bounds is null/undefined, return early with { documents: [], totalCount: 0 }.
| ? [effectiveContainerTag] | ||
| : undefined | ||
|
|
||
| const result = await client.exportMemories(containerTags) |
There was a problem hiding this comment.
Correctness: The exportMemories method in apps/mcp/src/client.ts calls this.handleError(error) in its catch block but has no explicit return after it, meaning it can implicitly return undefined when an error occurs. Accessing result.documents on line 278 will throw TypeError: Cannot read properties of undefined if the underlying API call fails.
🤖 AI Agent Prompt for Cursor/Windsurf
📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue
In apps/mcp/src/server.ts around line 275, the call to `client.exportMemories(containerTags)` can return `undefined` because `apps/mcp/src/client.ts`'s `exportMemories` method swallows errors via `this.handleError(error)` without a guaranteed re-throw, resulting in an implicit `undefined` return. The subsequent access of `result.documents` (line 278) and `result.totalCount` (line 291) will throw a TypeError at runtime. Fix: either ensure `handleError` always throws, or add a null-check guard: `if (!result) throw new Error('Export failed'); ` after the await on line 275.
| // Get bounds first to know the full coordinate range | ||
| const bounds = await this.getGraphBounds(containerTags) | ||
| const { minX, maxX, minY, maxY } = bounds.bounds | ||
|
|
There was a problem hiding this comment.
Bug: The exportMemories function attempts to destructure bounds.bounds without checking if it's null, which can occur for empty accounts or projects, causing an error.
Severity: MEDIUM
Suggested Fix
Add a null check for bounds.bounds before destructuring. If bounds.bounds is null, the function should return an empty export, such as { documents: [], totalCount: 0 }, to gracefully handle empty accounts or projects.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: apps/mcp/src/client.ts#L397
Potential issue: In the `exportMemories` method, the code destructures `bounds.bounds`
without checking if it is `null`. The `getGraphBounds` method can return a response
where `bounds.bounds` is `null`, especially for empty accounts or projects. This will
cause a `TypeError: Cannot destructure property 'minX' of null`. Although a `try/catch`
block prevents a server crash, it leads to an unhelpful error message for the user
instead of providing a clean, empty export.
Did we get this right? 👍 / 👎 to inform future reviews.
Summary
Adds an
export-memoriesMCP tool that lets users export all their documents and extracted memories as structured JSON or JSONL.Why this matters
There is no way to export data from Supermemory. Users cannot back up their memories, migrate between accounts, or analyze their data offline. For a memory SaaS, data portability is table stakes - especially for enterprise users with sovereignty requirements.
The MCP server is the natural place for this since power users already interact via MCP, and it can be built entirely client-side using existing API endpoints.
Changes
2 files modified, 95 lines added:
apps/mcp/src/client.ts- NewexportMemories()method onSupermemoryClient:getGraphViewport()with a high limit{ documents, totalCount }apps/mcp/src/server.ts- Newexport-memoriestool registration:containerTagfor per-project exportformatparameter:json(single array, default) orjsonl(one doc per line)Usage:
No new dependencies. Uses existing graph viewport API endpoints.
Testing
Manual testing with MCP client. The
exportMemories()method chains two existing methods (getGraphBounds+getGraphViewport), both of which are already used by thememory-graphtool.This contribution was developed with AI assistance (Claude Code).
Video Demo