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

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>
This commit is contained in:
Matt Van Horn 2026-03-25 16:27:58 -07:00
parent fe5d16509a
commit c3b16f871d
No known key found for this signature in database
2 changed files with 95 additions and 0 deletions

View file

@ -384,6 +384,33 @@ export class SupermemoryClient {
}
}
// Export all memories via the graph viewport endpoint.
// Returns documents with their extracted memories for backup/migration.
async exportMemories(containerTags?: string[]): Promise<{
documents: GraphApiDocument[]
totalCount: number
}> {
try {
// Get bounds first to know the full coordinate range
const bounds = await this.getGraphBounds(containerTags)
const { minX, maxX, minY, maxY } = bounds.bounds
// Fetch all documents within the full bounds, high limit
const viewport = await this.getGraphViewport(
{ minX, maxX, minY, maxY },
containerTags,
10000,
)
return {
documents: viewport.documents,
totalCount: viewport.totalCount,
}
} catch (error) {
this.handleError(error)
}
}
private handleError(error: unknown): never {
// Handle network/fetch errors
if (error instanceof TypeError) {

View file

@ -242,6 +242,74 @@ export class SupermemoryMCP extends McpAgent<Env, unknown, Props> {
},
)
// Register export-memories tool
const exportSchema = z.object({
...(hasRootContainerTag ? {} : containerTagField),
format: z
.enum(["json", "jsonl"])
.optional()
.default("json")
.describe("Output format: json (single array) or jsonl (one document per line)"),
})
type ExportArgs = z.infer<typeof exportSchema>
this.server.registerTool(
"export-memories",
{
description:
"Export all memories as structured data for backup or migration. Returns documents with their extracted memories.",
inputSchema: exportSchema,
},
// @ts-expect-error - zod type inference issue with MCP SDK
async (args: ExportArgs) => {
try {
const effectiveContainerTag =
(args as { containerTag?: string }).containerTag ||
this.props?.containerTag
const client = this.getClient(effectiveContainerTag)
const containerTags = effectiveContainerTag
? [effectiveContainerTag]
: undefined
const result = await client.exportMemories(containerTags)
const isJsonl = args.format === "jsonl"
const output = isJsonl
? result.documents.map((d) => JSON.stringify(d)).join("\n")
: JSON.stringify(result.documents, null, 2)
const memoryCount = result.documents.reduce(
(sum, d) => sum + d.memories.length,
0,
)
return {
content: [
{
type: "text" as const,
text: `Exported ${result.documents.length} documents with ${memoryCount} memories (${result.totalCount} total).${effectiveContainerTag ? ` Project: ${effectiveContainerTag}` : ""}\n\n${output}`,
},
],
}
} catch (error) {
const message =
error instanceof Error
? error.message
: "An unexpected error occurred"
return {
content: [
{
type: "text" as const,
text: `Error exporting memories: ${message}`,
},
],
isError: true,
}
}
},
)
// Register whoAmI tool
this.server.registerTool(
"whoAmI",