Skip to main content
Glama

MongoDB MCP Server

Official
by mongodb-js
elicitation.test.ts14.2 kB
/* eslint-disable @typescript-eslint/no-unsafe-assignment */ import { describe, it, expect, afterEach } from "vitest"; import { type UserConfig } from "../../src/common/config.js"; import { defaultTestConfig } from "./helpers.js"; import { Elicitation } from "../../src/elicitation.js"; import { createMockElicitInput } from "../utils/elicitationMocks.js"; import { describeWithMongoDB } from "./tools/mongodb/mongodbHelpers.js"; function createTestConfig(config: Partial<UserConfig> = {}): UserConfig { return { ...defaultTestConfig, // Add fake API credentials so Atlas tools get registered apiClientId: "test-client-id", apiClientSecret: "test-client-secret", ...config, }; } describe("Elicitation Integration Tests", () => { const mockElicitInput = createMockElicitInput(); afterEach(() => { mockElicitInput.clear(); }); describeWithMongoDB( "with elicitation support", (integration) => { describe("tools requiring confirmation by default", () => { it("should request confirmation for drop-database tool and proceed when confirmed", async () => { mockElicitInput.confirmYes(); const result = await integration.mcpClient().callTool({ name: "drop-database", arguments: { database: "test-db" }, }); expect(mockElicitInput.mock).toHaveBeenCalledTimes(1); expect(mockElicitInput.mock).toHaveBeenCalledWith({ message: expect.stringContaining("You are about to drop the `test-db` database"), requestedSchema: Elicitation.CONFIRMATION_SCHEMA, }); // Should attempt to execute (will fail due to no connection, but confirms flow worked) expect(result.isError).toBe(true); expect(result.content).toEqual( expect.arrayContaining([ expect.objectContaining({ type: "text", text: expect.stringContaining("You need to connect to a MongoDB instance"), }), ]) ); }); it("should not proceed when user declines confirmation", async () => { mockElicitInput.confirmNo(); const result = await integration.mcpClient().callTool({ name: "drop-database", arguments: { database: "test-db" }, }); expect(mockElicitInput.mock).toHaveBeenCalledTimes(1); expect(result.isError).toBeFalsy(); expect(result.content).toEqual([ { type: "text", text: "User did not confirm the execution of the `drop-database` tool so the operation was not performed.", }, ]); }); it("should request confirmation for drop-collection tool", async () => { mockElicitInput.confirmYes(); await integration.mcpClient().callTool({ name: "drop-collection", arguments: { database: "test-db", collection: "test-collection" }, }); expect(mockElicitInput.mock).toHaveBeenCalledTimes(1); expect(mockElicitInput.mock).toHaveBeenCalledWith({ message: expect.stringContaining("You are about to drop the `test-collection` collection"), requestedSchema: expect.objectContaining(Elicitation.CONFIRMATION_SCHEMA), }); }); it("should request confirmation for delete-many tool", async () => { mockElicitInput.confirmYes(); await integration.mcpClient().callTool({ name: "delete-many", arguments: { database: "test-db", collection: "test-collection", filter: { status: "inactive" }, }, }); expect(mockElicitInput.mock).toHaveBeenCalledTimes(1); expect(mockElicitInput.mock).toHaveBeenCalledWith({ message: expect.stringContaining("You are about to delete documents"), requestedSchema: expect.objectContaining(Elicitation.CONFIRMATION_SCHEMA), }); }); it("should request confirmation for create-db-user tool", async () => { mockElicitInput.confirmYes(); await integration.mcpClient().callTool({ name: "atlas-create-db-user", arguments: { projectId: "507f1f77bcf86cd799439011", // Valid 24-char hex string username: "test-user", roles: [{ roleName: "read", databaseName: "test-db" }], }, }); expect(mockElicitInput.mock).toHaveBeenCalledTimes(1); expect(mockElicitInput.mock).toHaveBeenCalledWith({ message: expect.stringContaining("You are about to create a database user"), requestedSchema: expect.objectContaining(Elicitation.CONFIRMATION_SCHEMA), }); }); it("should request confirmation for create-access-list tool", async () => { mockElicitInput.confirmYes(); await integration.mcpClient().callTool({ name: "atlas-create-access-list", arguments: { projectId: "507f1f77bcf86cd799439011", // Valid 24-char hex string ipAddresses: ["192.168.1.1"], }, }); expect(mockElicitInput.mock).toHaveBeenCalledTimes(1); expect(mockElicitInput.mock).toHaveBeenCalledWith({ message: expect.stringContaining( "You are about to add the following entries to the access list" ), requestedSchema: expect.objectContaining(Elicitation.CONFIRMATION_SCHEMA), }); }); }); describe("tools not requiring confirmation by default", () => { it("should not request confirmation for read operations", async () => { const result = await integration.mcpClient().callTool({ name: "list-databases", arguments: {}, }); expect(mockElicitInput.mock).not.toHaveBeenCalled(); // Should fail with connection error since we're not connected expect(result.isError).toBe(true); }); it("should not request confirmation for find operations", async () => { const result = await integration.mcpClient().callTool({ name: "find", arguments: { database: "test-db", collection: "test-collection", }, }); expect(mockElicitInput.mock).not.toHaveBeenCalled(); // Should fail with connection error since we're not connected expect(result.isError).toBe(true); }); }); }, { getUserConfig: () => createTestConfig(), getMockElicitationInput: () => mockElicitInput, } ); describeWithMongoDB( "without elicitation support", (integration) => { it("should proceed without confirmation for default confirmation-required tools when client lacks elicitation support", async () => { const result = await integration.mcpClient().callTool({ name: "drop-database", arguments: { database: "test-db" }, }); // Note: No mock assertions needed since elicitation is disabled // Should fail with connection error since we're not connected, but confirms flow bypassed confirmation expect(result.isError).toBe(true); expect(result.content).toEqual( expect.arrayContaining([ expect.objectContaining({ type: "text", text: expect.stringContaining("You need to connect to a MongoDB instance"), }), ]) ); }); }, { getUserConfig: () => createTestConfig(), getClientCapabilities: () => ({}), } ); describeWithMongoDB( "custom confirmation configuration", (integration) => { it("should confirm with a generic message with custom configurations for other tools", async () => { mockElicitInput.confirmYes(); await integration.mcpClient().callTool({ name: "list-databases", arguments: {}, }); expect(mockElicitInput.mock).toHaveBeenCalledTimes(1); expect(mockElicitInput.mock).toHaveBeenCalledWith({ message: expect.stringMatching( /You are about to execute the `list-databases` tool which requires additional confirmation. Would you like to proceed\?/ ), requestedSchema: expect.objectContaining(Elicitation.CONFIRMATION_SCHEMA), }); }); it("should not request confirmation when tool is removed from default confirmationRequiredTools", async () => { const result = await integration.mcpClient().callTool({ name: "drop-database", arguments: { database: "test-db" }, }); expect(mockElicitInput.mock).not.toHaveBeenCalled(); // Should fail with connection error since we're not connected expect(result.isError).toBe(true); }); }, { getUserConfig: () => createTestConfig({ confirmationRequiredTools: ["list-databases"] }), getMockElicitationInput: () => mockElicitInput, } ); describeWithMongoDB( "confirmation message content validation", (integration) => { it("should include specific details in create-db-user confirmation", async () => { mockElicitInput.confirmYes(); await integration.mcpClient().callTool({ name: "atlas-create-db-user", arguments: { projectId: "507f1f77bcf86cd799439011", // Valid 24-char hex string username: "myuser", password: "mypassword", roles: [ { roleName: "readWrite", databaseName: "mydb" }, { roleName: "read", databaseName: "logs", collectionName: "events" }, ], clusters: ["cluster1", "cluster2"], }, }); expect(mockElicitInput.mock).toHaveBeenCalledWith({ message: expect.stringMatching(/project.*507f1f77bcf86cd799439011/), requestedSchema: expect.objectContaining(Elicitation.CONFIRMATION_SCHEMA), }); }); it("should include filter details in delete-many confirmation", async () => { mockElicitInput.confirmYes(); await integration.mcpClient().callTool({ name: "delete-many", arguments: { database: "mydb", collection: "users", filter: { status: "inactive", lastLogin: { $lt: "2023-01-01" } }, }, }); expect(mockElicitInput.mock).toHaveBeenCalledWith({ message: expect.stringMatching(/mydb.*database/), requestedSchema: expect.objectContaining(Elicitation.CONFIRMATION_SCHEMA), }); }); }, { getUserConfig: () => createTestConfig(), getMockElicitationInput: () => mockElicitInput, } ); describeWithMongoDB( "error handling in confirmation flow", (integration) => { it("should handle confirmation errors gracefully", async () => { mockElicitInput.rejectWith(new Error("Confirmation service unavailable")); const result = await integration.mcpClient().callTool({ name: "drop-database", arguments: { database: "test-db" }, }); expect(mockElicitInput.mock).toHaveBeenCalledTimes(1); expect(result.isError).toBe(true); expect(result.content).toEqual( expect.arrayContaining([ expect.objectContaining({ type: "text", text: expect.stringContaining("Error running drop-database"), }), ]) ); }); }, { getUserConfig: () => createTestConfig(), getMockElicitationInput: () => mockElicitInput, } ); });

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