Skip to main content
Glama

MongoDB MCP Server

Official
by mongodb-js
getPerformanceAdvisor.ts7.23 kB
import { z } from "zod"; import { AtlasToolBase } from "../atlasTool.js"; import type { CallToolResult, ServerNotification, ServerRequest } from "@modelcontextprotocol/sdk/types.js"; import type { OperationType, ToolArgs } from "../../tool.js"; import { formatUntrustedData } from "../../tool.js"; import { getSuggestedIndexes, getDropIndexSuggestions, getSchemaAdvice, getSlowQueries, DEFAULT_SLOW_QUERY_LOGS_LIMIT, SUGGESTED_INDEXES_COPY, SLOW_QUERY_LOGS_COPY, } from "../../../common/atlas/performanceAdvisorUtils.js"; import { AtlasArgs } from "../../args.js"; import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js"; import type { PerfAdvisorToolMetadata } from "../../../telemetry/types.js"; const PerformanceAdvisorOperationType = z.enum([ "suggestedIndexes", "dropIndexSuggestions", "slowQueryLogs", "schemaSuggestions", ]); export class GetPerformanceAdvisorTool extends AtlasToolBase { public name = "atlas-get-performance-advisor"; protected description = `Get MongoDB Atlas performance advisor recommendations, which includes the operations: suggested indexes, drop index suggestions, schema suggestions, and a sample of the most recent (max ${DEFAULT_SLOW_QUERY_LOGS_LIMIT}) slow query logs`; public operationType: OperationType = "read"; protected argsShape = { projectId: AtlasArgs.projectId().describe( "Atlas project ID to get performance advisor recommendations. The project ID is a hexadecimal identifier of 24 characters. If the user has only specified the name, use the `atlas-list-projects` tool to retrieve the user's projects with their ids." ), clusterName: AtlasArgs.clusterName().describe("Atlas cluster name to get performance advisor recommendations"), operations: z .array(PerformanceAdvisorOperationType) .default(PerformanceAdvisorOperationType.options) .describe("Operations to get performance advisor recommendations"), since: z .string() .datetime() .describe( "Date to get slow query logs since. Must be a string in ISO 8601 format. Only relevant for the slowQueryLogs operation." ) .optional(), namespaces: z .array(z.string()) .describe("Namespaces to get slow query logs. Only relevant for the slowQueryLogs operation.") .optional(), }; protected async execute({ projectId, clusterName, operations, since, namespaces, }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> { try { const [suggestedIndexesResult, dropIndexSuggestionsResult, slowQueryLogsResult, schemaSuggestionsResult] = await Promise.allSettled([ operations.includes("suggestedIndexes") ? getSuggestedIndexes(this.session.apiClient, projectId, clusterName) : Promise.resolve(undefined), operations.includes("dropIndexSuggestions") ? getDropIndexSuggestions(this.session.apiClient, projectId, clusterName) : Promise.resolve(undefined), operations.includes("slowQueryLogs") ? getSlowQueries( this.session.apiClient, projectId, clusterName, since ? new Date(since) : undefined, namespaces ) : Promise.resolve(undefined), operations.includes("schemaSuggestions") ? getSchemaAdvice(this.session.apiClient, projectId, clusterName) : Promise.resolve(undefined), ]); const hasSuggestedIndexes = suggestedIndexesResult.status === "fulfilled" && suggestedIndexesResult.value?.suggestedIndexes && suggestedIndexesResult.value.suggestedIndexes.length > 0; const hasDropIndexSuggestions = dropIndexSuggestionsResult.status === "fulfilled" && dropIndexSuggestionsResult.value?.hiddenIndexes && dropIndexSuggestionsResult.value?.redundantIndexes && dropIndexSuggestionsResult.value?.unusedIndexes && (dropIndexSuggestionsResult.value.hiddenIndexes.length > 0 || dropIndexSuggestionsResult.value.redundantIndexes.length > 0 || dropIndexSuggestionsResult.value.unusedIndexes.length > 0); const hasSlowQueryLogs = slowQueryLogsResult.status === "fulfilled" && slowQueryLogsResult.value?.slowQueryLogs && slowQueryLogsResult.value.slowQueryLogs.length > 0; const hasSchemaSuggestions = schemaSuggestionsResult.status === "fulfilled" && schemaSuggestionsResult.value?.recommendations && schemaSuggestionsResult.value.recommendations.length > 0; // Inserts the performance advisor data with the relevant section header if it exists const performanceAdvisorData = [ `## Suggested Indexes\n${ hasSuggestedIndexes ? `${SUGGESTED_INDEXES_COPY}\n${JSON.stringify(suggestedIndexesResult.value?.suggestedIndexes)}` : "No suggested indexes found." }`, `## Drop Index Suggestions\n${hasDropIndexSuggestions ? JSON.stringify(dropIndexSuggestionsResult.value) : "No drop index suggestions found."}`, `## Slow Query Logs\n${hasSlowQueryLogs ? `${SLOW_QUERY_LOGS_COPY}\n${JSON.stringify(slowQueryLogsResult.value?.slowQueryLogs)}` : "No slow query logs found."}`, `## Schema Suggestions\n${hasSchemaSuggestions ? JSON.stringify(schemaSuggestionsResult.value?.recommendations) : "No schema suggestions found."}`, ]; if (performanceAdvisorData.length === 0) { return { content: [{ type: "text", text: "No performance advisor recommendations found." }], }; } return { content: formatUntrustedData("Performance advisor data", performanceAdvisorData.join("\n\n")), }; } catch (error) { return { content: [ { type: "text", text: `Error retrieving performance advisor data: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } } protected override resolveTelemetryMetadata( result: CallToolResult, args: ToolArgs<typeof this.argsShape>, extra: RequestHandlerExtra<ServerRequest, ServerNotification> ): PerfAdvisorToolMetadata { return { ...super.resolveTelemetryMetadata(result, args, extra), operations: args.operations, }; } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mongodb-js/mongodb-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server