query
Query MongoDB collections using filters, projections, and sorting. Output results in JSON or CSV format for easy analysis. Supports read-only operations for secure data access.
Instructions
Execute a read-only query on a collection using MongoDB query syntax.
Supports both JSON and CSV output formats:
Use outputFormat="json" for standard JSON (default)
Use outputFormat="csv" for comma-separated values export
Best Practices:
Use projections to fetch only needed fields
Add limits for large collections
Use sort for consistent ordering
Example - Standard Query: use_mcp_tool with server_name: "mongodb", tool_name: "query", arguments: { "collection": "users", "filter": { "age": { "$gte": 21 } }, "projection": { "name": 1, "email": 1 }, "sort": { "name": 1 }, "limit": 100 }
Example - CSV Export: use_mcp_tool with server_name: "mongodb", tool_name: "query", arguments: { "collection": "users", "filter": { "active": true }, "outputFormat": "csv", "formatOptions": { "includeHeaders": true, "delimiter": "," } }
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| collection | Yes | Collection name | |
| database | No | Database name (optional if default database is configured) | |
| filter | Yes | MongoDB query filter using standard MongoDB operators ($eq, $gt, $in, etc.) | |
| formatOptions | No | Format-specific options | |
| limit | No | Maximum number of documents to return (optional) | |
| outputFormat | No | Output format for results (json or csv) | |
| projection | No | MongoDB projection to specify fields to return (optional) | |
| sort | No | MongoDB sort specification (optional) |
Implementation Reference
- src/index.ts:1087-1152 (handler)Handler for the 'query' tool: executes MongoDB find operation with filter, optional projection, sort, limit. Supports JSON (default) and CSV output formats. Appends visualization hints for JSON results.case 'query': { const { database, collection, filter, projection, sort, limit, outputFormat = 'json', formatOptions = {} } = request.params.arguments as { database?: string; collection: string; filter: object; projection?: object; sort?: Sort; limit?: number; outputFormat?: 'json' | 'csv'; formatOptions?: any; }; const dbName = database || this.defaultDatabase; if (!dbName) { throw new McpError( ErrorCode.InvalidRequest, 'Database name is required when no default database is configured' ); } const db = client.db(dbName); let query = db.collection(collection).find(filter); if (projection) { query = query.project(projection); } if (sort) { query = query.sort(sort); } if (limit) { query = query.limit(limit); } const results = await query.toArray(); // Handle different output formats if (outputFormat.toLowerCase() === 'csv') { return { content: [ { type: 'text', text: this.documentsToCsv(results, formatOptions), }, ], }; } else { // Default JSON format const vizHint = this.generateVisualizationHint(results); return { content: [ { type: 'text', text: JSON.stringify(results, null, 2) + (vizHint ? `\n\nVisualization Hint:\n${vizHint}` : ''), }, ], }; } }
- src/index.ts:408-458 (schema)Input schema definition for the 'query' tool, specifying parameters like database, collection, filter (required), projection, sort, limit, outputFormat, and formatOptions.inputSchema: { type: 'object', properties: { database: { type: 'string', description: 'Database name (optional if default database is configured)', }, collection: { type: 'string', description: 'Collection name', }, filter: { type: 'object', description: 'MongoDB query filter using standard MongoDB operators ($eq, $gt, $in, etc.)', }, projection: { type: 'object', description: 'MongoDB projection to specify fields to return (optional)', }, sort: { type: 'object', description: 'MongoDB sort specification (optional)', }, limit: { type: 'number', description: 'Maximum number of documents to return (optional)', minimum: 1, maximum: 1000, }, outputFormat: { type: 'string', description: 'Output format for results (json or csv)', enum: ['json', 'csv'], }, formatOptions: { type: 'object', description: 'Format-specific options', properties: { delimiter: { type: 'string', description: 'CSV delimiter character (default: comma)', }, includeHeaders: { type: 'boolean', description: 'Whether to include header row in CSV (default: true)', }, }, }, }, required: ['collection', 'filter'], },
- src/index.ts:370-458 (registration)Registration of the 'query' tool in the list_tools response, including name, detailed description with examples, and input schema.{ name: 'query', description: `Execute a read-only query on a collection using MongoDB query syntax. Supports both JSON and CSV output formats: - Use outputFormat="json" for standard JSON (default) - Use outputFormat="csv" for comma-separated values export Best Practices: - Use projections to fetch only needed fields - Add limits for large collections - Use sort for consistent ordering Example - Standard Query: use_mcp_tool with server_name: "mongodb", tool_name: "query", arguments: { "collection": "users", "filter": { "age": { "$gte": 21 } }, "projection": { "name": 1, "email": 1 }, "sort": { "name": 1 }, "limit": 100 } Example - CSV Export: use_mcp_tool with server_name: "mongodb", tool_name: "query", arguments: { "collection": "users", "filter": { "active": true }, "outputFormat": "csv", "formatOptions": { "includeHeaders": true, "delimiter": "," } }`, inputSchema: { type: 'object', properties: { database: { type: 'string', description: 'Database name (optional if default database is configured)', }, collection: { type: 'string', description: 'Collection name', }, filter: { type: 'object', description: 'MongoDB query filter using standard MongoDB operators ($eq, $gt, $in, etc.)', }, projection: { type: 'object', description: 'MongoDB projection to specify fields to return (optional)', }, sort: { type: 'object', description: 'MongoDB sort specification (optional)', }, limit: { type: 'number', description: 'Maximum number of documents to return (optional)', minimum: 1, maximum: 1000, }, outputFormat: { type: 'string', description: 'Output format for results (json or csv)', enum: ['json', 'csv'], }, formatOptions: { type: 'object', description: 'Format-specific options', properties: { delimiter: { type: 'string', description: 'CSV delimiter character (default: comma)', }, includeHeaders: { type: 'boolean', description: 'Whether to include header row in CSV (default: true)', }, }, }, }, required: ['collection', 'filter'], },
- src/index.ts:194-246 (helper)Helper function to generate visualization suggestions based on query results characteristics (time series, numeric, categorical, geospatial). Appended to JSON query results.private generateVisualizationHint(data: any[]): string { if (!Array.isArray(data) || data.length === 0) return ''; // Check if the data looks like time series const hasDateFields = Object.keys(data[0]).some(key => data[0][key] instanceof Date || (typeof data[0][key] === 'string' && !isNaN(Date.parse(data[0][key]))) ); // Check if the data has numeric fields const numericFields = Object.keys(data[0]).filter(key => typeof data[0][key] === 'number' ); // Check if the data has categorical fields const categoricalFields = Object.keys(data[0]).filter(key => typeof data[0][key] === 'string' && data.every(item => typeof item[key] === 'string') ); // Check if the data has geospatial fields const hasGeoData = Object.keys(data[0]).some(key => { const value = data[0][key]; return value && typeof value === 'object' && (('type' in value && value.type === 'Point' && 'coordinates' in value) || (Array.isArray(value) && value.length === 2 && typeof value[0] === 'number' && typeof value[1] === 'number')); }); let hints = []; if (hasDateFields && numericFields.length > 0) { hints.push('Time Series Visualization:\n- Consider line charts for temporal trends\n- Time-based heat maps for density patterns\n- Area charts for cumulative values over time'); } if (categoricalFields.length > 0 && numericFields.length > 0) { hints.push('Categorical Analysis:\n- Bar charts for comparing categories\n- Box plots for distribution analysis\n- Heat maps for category correlations\n- Treemaps for hierarchical data'); } if (numericFields.length >= 2) { hints.push('Numerical Analysis:\n- Scatter plots for correlation analysis\n- Bubble charts if three numeric dimensions\n- Correlation matrices for multiple variables\n- Histograms for distribution analysis'); } if (hasGeoData) { hints.push('Geospatial Visualization:\n- Map overlays for location data\n- Choropleth maps for regional analysis\n- Heat maps for density visualization\n- Cluster maps for point concentration'); } if (data.length > 1000) { hints.push('Large Dataset Considerations:\n- Consider sampling for initial visualization\n- Use aggregation for summary views\n- Implement pagination or infinite scroll\n- Consider server-side rendering'); } return hints.join('\n\n'); }
- src/index.ts:254-289 (helper)Helper function to convert query results to CSV format, used when outputFormat='csv'. Handles headers, delimiters, escaping, and nested JSON.private documentsToCsv(docs: any[], options: { includeHeaders?: boolean; delimiter?: string; } = {}): string { if (!Array.isArray(docs) || docs.length === 0) return ''; const delimiter = options.delimiter || ','; const includeHeaders = options.includeHeaders !== false; // Extract all possible field names from all documents (handles varying schemas) const fieldsSet = new Set<string>(); docs.forEach(doc => { Object.keys(doc).forEach(key => fieldsSet.add(key)); }); const fields = Array.from(fieldsSet); let result = ''; // Add headers if (includeHeaders) { result += fields.map(field => this.escapeCsvField(field, delimiter)).join(delimiter) + '\n'; } // Add data rows docs.forEach(doc => { const row = fields.map(field => { const value = doc[field]; if (value === undefined || value === null) return ''; if (typeof value === 'object') return this.escapeCsvField(JSON.stringify(value), delimiter); return this.escapeCsvField(String(value), delimiter); }); result += row.join(delimiter) + '\n'; }); return result; }