export
Export MongoDB query or aggregation results to EJSON format for data transfer or analysis, handling large datasets beyond standard response limits.
Instructions
Export a query or aggregation results in the specified EJSON format.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| database | Yes | Database name | |
| collection | Yes | Collection name | |
| exportTitle | Yes | A short description to uniquely identify the export. | |
| exportTarget | Yes | The export target along with its arguments. | |
| jsonExportFormat | No | The format to be used when exporting collection data as EJSON with default being relaxed. relaxed: A string format that emphasizes readability and interoperability at the expense of type preservation. That is, conversion from relaxed format to BSON can lose type information. canonical: A string format that emphasizes type preservation at the expense of readability and interoperability. That is, conversion from canonical to BSON will generally preserve type information except in certain specific cases. | relaxed |
Implementation Reference
- src/tools/mongodb/read/export.ts:11-131 (handler)The ExportTool class implements the "export" tool. It defines the tool name, description, input schema (argsShape), and the execute method that creates a MongoDB cursor (find or aggregate) and uses exportsManager to export results as JSON, returning resource links.export class ExportTool extends MongoDBToolBase { public name = "export"; protected description = "Export a query or aggregation results in the specified EJSON format."; protected argsShape = { ...DbOperationArgs, exportTitle: z.string().describe("A short description to uniquely identify the export."), exportTarget: z .array( z.discriminatedUnion("name", [ z.object({ name: z .literal("find") .describe("The literal name 'find' to represent a find cursor as target."), arguments: z .object({ ...FindArgs, limit: FindArgs.limit.removeDefault(), }) .describe("The arguments for 'find' operation."), }), z.object({ name: z .literal("aggregate") .describe("The literal name 'aggregate' to represent an aggregation cursor as target."), arguments: z .object(getAggregateArgs(this.isFeatureEnabled("search"))) .describe("The arguments for 'aggregate' operation."), }), ]) ) .describe("The export target along with its arguments."), jsonExportFormat: jsonExportFormat .default("relaxed") .describe( [ "The format to be used when exporting collection data as EJSON with default being relaxed.", "relaxed: A string format that emphasizes readability and interoperability at the expense of type preservation. That is, conversion from relaxed format to BSON can lose type information.", "canonical: A string format that emphasizes type preservation at the expense of readability and interoperability. That is, conversion from canonical to BSON will generally preserve type information except in certain specific cases.", ].join("\n") ), }; static operationType: OperationType = "read"; protected async execute({ database, collection, jsonExportFormat, exportTitle, exportTarget: target, }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> { const provider = await this.ensureConnected(); const exportTarget = target[0]; if (!exportTarget) { throw new Error("Export target not provided. Expected one of the following: `aggregate`, `find`"); } let cursor: FindCursor | AggregationCursor; if (exportTarget.name === "find") { const { filter, projection, sort, limit } = exportTarget.arguments; cursor = provider.find(database, collection, filter ?? {}, { projection, sort, limit, promoteValues: false, bsonRegExp: true, }); } else { const { pipeline } = exportTarget.arguments; cursor = provider.aggregate(database, collection, pipeline, { promoteValues: false, bsonRegExp: true, allowDiskUse: true, }); } const exportName = `${new ObjectId().toString()}.json`; const { exportURI, exportPath } = await this.session.exportsManager.createJSONExport({ input: cursor, exportName, exportTitle: exportTitle || `Export for namespace ${database}.${collection} requested on ${new Date().toLocaleString()}`, jsonExportFormat, }); const toolCallContent: CallToolResult["content"] = [ // Not all the clients as of this commit understands how to // parse a resource_link so we provide a text result for them to // understand what to do with the result. { type: "text", text: `Data for namespace ${database}.${collection} is being exported and will be made available under resource URI - "${exportURI}".`, }, { type: "resource_link", name: exportName, uri: exportURI, description: "Resource URI for fetching exported data once it is ready.", mimeType: "application/json", }, ]; // This special case is to make it easier to work with exported data for // clients that still cannot reference resources (Cursor). // More information here: https://jira.mongodb.org/browse/MCP-104 if (this.isServerRunningLocally()) { toolCallContent.push({ type: "text", text: `Optionally, when the export is finished, the exported data can also be accessed under path - "${exportPath}"`, }); } return { content: toolCallContent, }; } private isServerRunningLocally(): boolean { return this.config.transport === "stdio" || ["127.0.0.1", "localhost"].includes(this.config.httpHost); } }
- Input schema definition (argsShape) for the export tool, including database/collection, exportTitle, exportTarget (find or aggregate args), and jsonExportFormat.protected argsShape = { ...DbOperationArgs, exportTitle: z.string().describe("A short description to uniquely identify the export."), exportTarget: z .array( z.discriminatedUnion("name", [ z.object({ name: z .literal("find") .describe("The literal name 'find' to represent a find cursor as target."), arguments: z .object({ ...FindArgs, limit: FindArgs.limit.removeDefault(), }) .describe("The arguments for 'find' operation."), }), z.object({ name: z .literal("aggregate") .describe("The literal name 'aggregate' to represent an aggregation cursor as target."), arguments: z .object(getAggregateArgs(this.isFeatureEnabled("search"))) .describe("The arguments for 'aggregate' operation."), }), ]) ) .describe("The export target along with its arguments."), jsonExportFormat: jsonExportFormat .default("relaxed") .describe( [ "The format to be used when exporting collection data as EJSON with default being relaxed.", "relaxed: A string format that emphasizes readability and interoperability at the expense of type preservation. That is, conversion from relaxed format to BSON can lose type information.", "canonical: A string format that emphasizes type preservation at the expense of readability and interoperability. That is, conversion from canonical to BSON will generally preserve type information except in certain specific cases.", ].join("\n") ), };
- src/tools/mongodb/tools.ts:21-21 (registration)Re-export of the ExportTool class for inclusion in the MongoDB tools module.export { ExportTool } from "./read/export.js";
- src/tools/index.ts:3-11 (registration)Import of MongoDB tools (including export) and inclusion in AllTools array, which is used by the server to register all tools dynamically via ToolBase.register().import * as MongoDbTools from "./mongodb/tools.js"; import type { ToolClass } from "./tool.js"; // Export the collection of tools for easier reference export const AllTools: ToolClass[] = Object.values({ ...MongoDbTools, ...AtlasTools, ...AtlasLocalTools, });
- src/common/exportsManager.ts:157-196 (helper)ExportsManager.createJSONExport method called by the export tool handler to asynchronously generate the JSON export file from the MongoDB cursor and provide URI/path for access.public async createJSONExport({ input, exportName, exportTitle, jsonExportFormat, }: { input: FindCursor | AggregationCursor; exportName: string; exportTitle: string; jsonExportFormat: JSONExportFormat; }): Promise<AvailableExport> { try { this.assertIsNotShuttingDown(); const exportNameWithExtension = decodeAndNormalize(ensureExtension(exportName, "json")); if (this.storedExports[exportNameWithExtension]) { return Promise.reject( new Error("Export with same name is either already available or being generated.") ); } const exportURI = `exported-data://${encodeURIComponent(exportNameWithExtension)}`; const exportFilePath = path.join(this.exportsDirectoryPath, exportNameWithExtension); const inProgressExport: InProgressExport = (this.storedExports[exportNameWithExtension] = { exportName: exportNameWithExtension, exportTitle, exportPath: exportFilePath, exportURI: exportURI, exportStatus: "in-progress", }); void this.startExport({ input, jsonExportFormat, inProgressExport }); return Promise.resolve(inProgressExport); } catch (error) { this.logger.error({ id: LogId.exportCreationError, context: "Error when registering JSON export request", message: error instanceof Error ? error.message : String(error), }); throw error; } }