Skip to content

feat(mcp): add export-memories tool for data portability#807

Open
mvanhorn wants to merge 1 commit intosupermemoryai:mainfrom
mvanhorn:osc/feat-mcp-export-memories
Open

feat(mcp): add export-memories tool for data portability#807
mvanhorn wants to merge 1 commit intosupermemoryai:mainfrom
mvanhorn:osc/feat-mcp-export-memories

Conversation

@mvanhorn
Copy link

@mvanhorn mvanhorn commented Mar 25, 2026

Summary

Adds an export-memories MCP 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 - New exportMemories() method on SupermemoryClient:

  • Fetches graph bounds to get the full coordinate range
  • Retrieves all documents + memories via getGraphViewport() with a high limit
  • Returns { documents, totalCount }

apps/mcp/src/server.ts - New export-memories tool registration:

  • Accepts optional containerTag for per-project export
  • Accepts format parameter: json (single array, default) or jsonl (one doc per line)
  • Returns document count, memory count, and the full data

Usage:

export-memories                           # Export all memories as JSON
export-memories containerTag="my-project" # Export one project
export-memories format="jsonl"            # JSONL for streaming

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 the memory-graph tool.

This contribution was developed with AI assistance (Claude Code).

Video Demo

Demo

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>
@graphite-app graphite-app bot requested a review from Dhravya March 25, 2026 23:28
@entelligence-ai-pr-reviews
Copy link

entelligence-ai-pr-reviews bot commented Mar 25, 2026

EntelligenceAI PR Summary

Adds an end-to-end export memories capability across the MCP client and server layers for backup and migration use cases.

  • apps/mcp/src/client.ts: New exportMemories method chains getGraphBounds and getGraphViewport (limit: 10,000) to retrieve all documents and their total count
  • apps/mcp/src/server.ts: New export-memories tool accepts format (json/jsonl) and optional containerTag parameters, serializes results, and returns a summary with document and memory counts
  • Error handling is standardized on the server-side tool registration

Confidence Score: 1/5 - Blocking Issues

  • A score 8.5 bug in client.ts indicates a direct TypeError at runtime when destructuring bounds.bounds — this is a crash-level defect that will break functionality for users.
  • A score 7.5 bug in server.ts reveals missing return-after-error-handling, meaning the code silently continues execution after an error path, potentially causing incorrect behavior or data corruption.
  • Both issues are logic/correctness bugs with high runtime impact, not cosmetic concerns — they must be fixed before merging.
  • With two high-severity bugs across two reviewed files and a heuristic ceiling of 2, the PR is not safe to merge in its current state.
Files requiring special attention
  • apps/mcp/src/client.ts
  • apps/mcp/src/server.ts

Copy link

@entelligence-ai-pr-reviews entelligence-ai-pr-reviews bot left a comment

Choose a reason for hiding this comment

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

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

  1. Visit Settings → Code Management
  2. Configure repository dependencies
  3. 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

Choose a reason for hiding this comment

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

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)

Choose a reason for hiding this comment

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

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

Copy link

Choose a reason for hiding this comment

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

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.

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.

1 participant