Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@
"types": "./dist/cjs/lib.d.ts",
"default": "./dist/cjs/lib.js"
}
},
"./tools": {
"import": {
"types": "./dist/esm/tools.d.ts",
"default": "./dist/esm/tools.js"
},
"require": {
"types": "./dist/cjs/tools.d.ts",
"default": "./dist/cjs/tools.js"
}
}
},
"main": "./dist/cjs/lib.js",
Expand Down
3 changes: 3 additions & 0 deletions src/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ export { Session, type SessionOptions } from "./common/session.js";
export { type UserConfig } from "./common/config.js";
export { LoggerBase, type LogPayload, type LoggerType, type LogLevel } from "./common/logger.js";
export { StreamableHttpRunner } from "./transports/streamableHttp.js";
export { StdioRunner } from "./transports/stdio.js";
export { TransportRunnerBase, type TransportRunnerConfig } from "./transports/base.js";
export {
ConnectionManager,
type AnyConnectionState,
Expand All @@ -21,3 +23,4 @@ export { ErrorCodes } from "./common/errors.js";
export { Telemetry } from "./telemetry/telemetry.js";
export { Keychain, registerGlobalSecretToRedact } from "./common/keychain.js";
export type { Secret } from "./common/keychain.js";
export { Elicitation } from "./elicitation.js";
23 changes: 17 additions & 6 deletions src/server.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import type { Session } from "./common/session.js";
import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
import { AtlasTools } from "./tools/atlas/tools.js";
import { AtlasLocalTools } from "./tools/atlasLocal/tools.js";
import { MongoDbTools } from "./tools/mongodb/tools.js";
import { Resources } from "./resources/resources.js";
import type { LogLevel } from "./common/logger.js";
import { LogId, McpLogger } from "./common/logger.js";
Expand All @@ -24,6 +21,7 @@ import { validateConnectionString } from "./helpers/connectionOptions.js";
import { packageInfo } from "./common/packageInfo.js";
import { type ConnectionErrorHandler } from "./common/connectionErrorHandler.js";
import type { Elicitation } from "./elicitation.js";
import { AllTools } from "./tools/index.js";

export interface ServerOptions {
session: Session;
Expand All @@ -32,7 +30,20 @@ export interface ServerOptions {
telemetry: Telemetry;
elicitation: Elicitation;
connectionErrorHandler: ConnectionErrorHandler;
toolConstructors?: (new (params: ToolConstructorParams) => ToolBase)[];
/** Custom tool constructors to register with the server.
* This will override any default tools. You can use both existing and custom tools by using the `mongodb-mcp-server/tools` export.
* ```ts
* import { AllTools, ToolBase } from "mongodb-mcp-server/tools";
* class CustomTool extends ToolBase {
* name = "custom_tool";
* ...
* }
* const server = new Server({
* tools: [...AllTools, CustomTool],
* });
* ```
*/
tools?: (new (params: ToolConstructorParams) => ToolBase)[];
}

export class Server {
Expand Down Expand Up @@ -61,7 +72,7 @@ export class Server {
telemetry,
connectionErrorHandler,
elicitation,
toolConstructors,
tools,
}: ServerOptions) {
this.startTime = Date.now();
this.session = session;
Expand All @@ -70,7 +81,7 @@ export class Server {
this.userConfig = userConfig;
this.elicitation = elicitation;
this.connectionErrorHandler = connectionErrorHandler;
this.toolConstructors = toolConstructors ?? [...AtlasTools, ...MongoDbTools, ...AtlasLocalTools];
this.toolConstructors = tools ?? AllTools;
}

async connect(transport: Transport): Promise<void> {
Expand Down
16 changes: 16 additions & 0 deletions src/tools/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { AtlasTools } from "./atlas/tools.js";
import { AtlasLocalTools } from "./atlasLocal/tools.js";
import { MongoDbTools } from "./mongodb/tools.js";

const AllTools = [...MongoDbTools, ...AtlasTools, ...AtlasLocalTools];

export { AllTools, MongoDbTools, AtlasTools, AtlasLocalTools };

export {
ToolBase,
type ToolConstructorParams,
type ToolCategory,
type OperationType,
type ToolArgs,
type ToolExecutionContext,
} from "./tool.js";
6 changes: 6 additions & 0 deletions src/transports/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type { AtlasLocalClientFactoryFn } from "../common/atlasLocal.js";
import { defaultCreateAtlasLocalClient } from "../common/atlasLocal.js";
import type { Client } from "@mongodb-js/atlas-local";
import { VectorSearchEmbeddingsManager } from "../common/search/vectorSearchEmbeddingsManager.js";
import type { ToolBase, ToolConstructorParams } from "../tools/tool.js";

export type TransportRunnerConfig = {
userConfig: UserConfig;
Expand All @@ -28,6 +29,7 @@ export type TransportRunnerConfig = {
createAtlasLocalClient?: AtlasLocalClientFactoryFn;
additionalLoggers?: LoggerBase[];
telemetryProperties?: Partial<CommonProperties>;
tools?: (new (params: ToolConstructorParams) => ToolBase)[];
};

export abstract class TransportRunnerBase {
Expand All @@ -38,6 +40,7 @@ export abstract class TransportRunnerBase {
private readonly connectionErrorHandler: ConnectionErrorHandler;
private readonly atlasLocalClient: Promise<Client | undefined>;
private readonly telemetryProperties: Partial<CommonProperties>;
private readonly tools?: (new (params: ToolConstructorParams) => ToolBase)[];

protected constructor({
userConfig,
Expand All @@ -46,12 +49,14 @@ export abstract class TransportRunnerBase {
createAtlasLocalClient = defaultCreateAtlasLocalClient,
additionalLoggers = [],
telemetryProperties = {},
tools,
}: TransportRunnerConfig) {
this.userConfig = userConfig;
this.createConnectionManager = createConnectionManager;
this.connectionErrorHandler = connectionErrorHandler;
this.atlasLocalClient = createAtlasLocalClient();
this.telemetryProperties = telemetryProperties;
this.tools = tools;
const loggers: LoggerBase[] = [...additionalLoggers];
if (this.userConfig.loggers.includes("stderr")) {
loggers.push(new ConsoleLogger(Keychain.root));
Expand Down Expand Up @@ -114,6 +119,7 @@ export abstract class TransportRunnerBase {
userConfig: this.userConfig,
connectionErrorHandler: this.connectionErrorHandler,
elicitation,
tools: this.tools,
});

// We need to create the MCP logger after the server is constructed
Expand Down
20 changes: 20 additions & 0 deletions tests/integration/build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
const esmPath = path.resolve(projectRoot, "dist/esm/lib.js");
const cjsPath = path.resolve(projectRoot, "dist/cjs/lib.js");

const esmToolsPath = path.resolve(projectRoot, "dist/esm/tools.js");
const cjsToolsPath = path.resolve(projectRoot, "dist/cjs/tools.js");

describe("Build Test", () => {
it("should successfully require CommonJS module", () => {
const require = createRequire(__filename);
Expand Down Expand Up @@ -49,7 +52,24 @@
"Session",
"StreamableHttpRunner",
"Telemetry",
"Elicitation",
])
);
});

it("should have matching exports between CommonJS and ESM tools modules", async () => {
// Import CommonJS module
const require = createRequire(__filename);
const cjsModule = require(cjsToolsPath) as Record<string, unknown>;

Check failure on line 63 in tests/integration/build.test.ts

View workflow job for this annotation

GitHub Actions / Run MongoDB tests (macos-latest)

tests/integration/build.test.ts > Build Test > should have matching exports between CommonJS and ESM tools modules

Error: Cannot find module '/Users/runner/work/mongodb-mcp-server/mongodb-mcp-server/dist/cjs/tools.js' Require stack: - /Users/runner/work/mongodb-mcp-server/mongodb-mcp-server/tests/integration/build.test.ts ❯ tests/integration/build.test.ts:63:27 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Serialized Error: { code: 'MODULE_NOT_FOUND', requireStack: [ '/Users/runner/work/mongodb-mcp-server/mongodb-mcp-server/tests/integration/build.test.ts' ] }

Check failure on line 63 in tests/integration/build.test.ts

View workflow job for this annotation

GitHub Actions / Run MongoDB tests (ubuntu-latest)

tests/integration/build.test.ts > Build Test > should have matching exports between CommonJS and ESM tools modules

Error: Cannot find module '/home/runner/work/mongodb-mcp-server/mongodb-mcp-server/dist/cjs/tools.js' Require stack: - /home/runner/work/mongodb-mcp-server/mongodb-mcp-server/tests/integration/build.test.ts ❯ tests/integration/build.test.ts:63:27 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Serialized Error: { code: 'MODULE_NOT_FOUND', requireStack: [ '/home/runner/work/mongodb-mcp-server/mongodb-mcp-server/tests/integration/build.test.ts' ] }

Check failure on line 63 in tests/integration/build.test.ts

View workflow job for this annotation

GitHub Actions / Run MongoDB tests (windows-latest)

tests/integration/build.test.ts > Build Test > should have matching exports between CommonJS and ESM tools modules

Error: Cannot find module 'D:\a\mongodb-mcp-server\mongodb-mcp-server\dist\cjs\tools.js' Require stack: - D:\a\mongodb-mcp-server\mongodb-mcp-server\tests\integration\build.test.ts ❯ tests/integration/build.test.ts:63:27 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Serialized Error: { code: 'MODULE_NOT_FOUND', requireStack: [ 'D:\a\mongodb-mcp-server\mongodb-mcp-server\tests\integration\build.test.ts' ] }

// Import ESM module
const esmModule = (await import(esmToolsPath)) as Record<string, unknown>;

// Compare exports
const cjsKeys = Object.keys(cjsModule).sort();
const esmKeys = Object.keys(esmModule).sort();

expect(cjsKeys).toEqual(esmKeys);
expect(cjsKeys).toEqual(expect.arrayContaining(["MongoDbTools", "AtlasTools", "AtlasLocalTools", "AllTools"]));
});
});
Loading
Loading