From 5afa9a56ad06b3f844d51ca75011e204860f23fb Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Mon, 15 Sep 2025 19:05:30 +0200 Subject: [PATCH 1/8] chore: update node engine in lock file --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 3bbff3b71..6a8cfe385 100644 --- a/package-lock.json +++ b/package-lock.json @@ -125,7 +125,7 @@ "xvfb-maybe": "^0.2.1" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >= 24.7.0", + "node": "^20.19.0 || ^22.12.0 || >= 23.0.0", "npm": ">=10.1.0", "vscode": "^1.101.1" } From 39e4e6f4e8da83d47a3a53afe18ab4c7261bbb00 Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Tue, 16 Sep 2025 12:39:18 +0200 Subject: [PATCH 2/8] chore: update mongodb-mcp-server --- package-lock.json | 86 ++++++++++++++++++++++------------------------- package.json | 2 +- 2 files changed, 41 insertions(+), 47 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6a8cfe385..1f6d3d20a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,7 +34,7 @@ "mongodb-connection-string-url": "^3.0.2", "mongodb-data-service": "^22.30.1", "mongodb-log-writer": "^2.4.1", - "mongodb-mcp-server": "^0.3.1-prerelease.1", + "mongodb-mcp-server": "^1.0.0-prerelease.1", "mongodb-query-parser": "^4.4.2", "mongodb-schema": "^12.6.2", "node-machine-id": "1.1.12", @@ -7719,15 +7719,6 @@ "node": ">=12" } }, - "node_modules/@mongodb-js/oidc-mock-provider/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/@mongodb-js/oidc-plugin": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@mongodb-js/oidc-plugin/-/oidc-plugin-2.0.3.tgz", @@ -20685,6 +20676,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/meow/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/merge-descriptors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", @@ -21151,6 +21152,16 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/mocha/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/mongodb": { "version": "6.19.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.19.0.tgz", @@ -21347,9 +21358,9 @@ } }, "node_modules/mongodb-mcp-server": { - "version": "0.3.1-prerelease.1", - "resolved": "https://registry.npmjs.org/mongodb-mcp-server/-/mongodb-mcp-server-0.3.1-prerelease.1.tgz", - "integrity": "sha512-FslY1fIgME1eaSA4umEUZUOkd2gcF+l4zTsr+RGwr1TEnGN/gF5lF5m8B0OwqjgKyxTIzBVB3+ZllZDsYBuWUA==", + "version": "1.0.0-prerelease.1", + "resolved": "https://registry.npmjs.org/mongodb-mcp-server/-/mongodb-mcp-server-1.0.0-prerelease.1.tgz", + "integrity": "sha512-fdpVBBgrozqZgDS6f+/2AgvbQqL9KCryi4DuS4sRLvyLf3rPZ/HLCpMAcOZqBQYOhi02UsNRHW99lpBZfa8Y/Q==", "license": "Apache-2.0", "dependencies": { "@modelcontextprotocol/sdk": "^1.17.4", @@ -21372,7 +21383,7 @@ "oauth4webapi": "^3.8.0", "openapi-fetch": "^0.14.0", "ts-levenshtein": "^1.0.7", - "yargs-parser": "^22.0.0", + "yargs-parser": "^21.1.1", "zod": "^3.25.76" }, "bin": { @@ -21477,15 +21488,6 @@ "node": ">=10" } }, - "node_modules/mongodb-mcp-server/node_modules/yargs-parser": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", - "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", - "license": "ISC", - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, "node_modules/mongodb-ns": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/mongodb-ns/-/mongodb-ns-2.4.2.tgz", @@ -22444,15 +22446,6 @@ "node": ">=12" } }, - "node_modules/mongodb-runner/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/mongodb-schema": { "version": "12.6.2", "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.6.2.tgz", @@ -22526,15 +22519,6 @@ "node": ">=12" } }, - "node_modules/mongodb-schema/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "optional": true, - "engines": { - "node": ">=12" - } - }, "node_modules/mrmime": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", @@ -29116,12 +29100,12 @@ } }, "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-unparser": { @@ -29148,6 +29132,16 @@ "node": ">=8" } }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", diff --git a/package.json b/package.json index 4f4593963..e99c7c696 100644 --- a/package.json +++ b/package.json @@ -1418,7 +1418,7 @@ "mongodb-connection-string-url": "^3.0.2", "mongodb-data-service": "^22.30.1", "mongodb-log-writer": "^2.4.1", - "mongodb-mcp-server": "^0.3.1-prerelease.1", + "mongodb-mcp-server": "^1.0.0-prerelease.1", "mongodb-query-parser": "^4.4.2", "mongodb-schema": "^12.6.2", "node-machine-id": "1.1.12", From 9db579d04ede7cafcae1c0e520fadcf887441f77 Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Tue, 16 Sep 2025 15:35:22 +0200 Subject: [PATCH 3/8] chore: extend mcp config with vscode configurations --- package-lock.json | 140 +++++++++++++++++- package.json | 3 +- src/mcp/mcpConnectionErrorHandler.ts | 5 +- src/mcp/mcpConnectionManager.ts | 2 +- src/mcp/mcpController.ts | 21 ++- .../mcp/mcpConnectionErrorHandler.test.ts | 4 +- .../suite/mcp/mcpConnectionManager.test.ts | 4 +- src/test/suite/mcp/mcpController.test.ts | 2 +- 8 files changed, 165 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1f6d3d20a..899e82022 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@babel/core": "^7.25.8", "@babel/parser": "^7.25.8", "@babel/traverse": "^7.25.7", + "@himanshusinghs/mongodb-mcp-server": "^1.0.0-prerelease.2", "@mongodb-js/compass-components": "^1.38.1", "@mongodb-js/connection-form": "^1.52.3", "@mongodb-js/connection-info": "^0.17.1", @@ -34,7 +35,7 @@ "mongodb-connection-string-url": "^3.0.2", "mongodb-data-service": "^22.30.1", "mongodb-log-writer": "^2.4.1", - "mongodb-mcp-server": "^1.0.0-prerelease.1", + "mongodb-mcp-server": "^1.0.0-prerelease.2", "mongodb-query-parser": "^4.4.2", "mongodb-schema": "^12.6.2", "node-machine-id": "1.1.12", @@ -5685,6 +5686,137 @@ "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", "license": "MIT" }, + "node_modules/@himanshusinghs/mongodb-mcp-server": { + "version": "1.0.0-prerelease.2", + "resolved": "https://registry.npmjs.org/@himanshusinghs/mongodb-mcp-server/-/mongodb-mcp-server-1.0.0-prerelease.2.tgz", + "integrity": "sha512-xpMuNhgdL6TKhYawKJfW3cUbXHBo7W1EarjpMUtTcUNaezyKi8CZs/tUrA8w6ghqTGJpINLTvPvRjISSIyWtEg==", + "license": "Apache-2.0", + "dependencies": { + "@modelcontextprotocol/sdk": "^1.17.4", + "@mongodb-js/device-id": "^0.3.1", + "@mongodb-js/devtools-connect": "^3.9.3", + "@mongodb-js/devtools-proxy-support": "^0.5.2", + "@mongosh/arg-parser": "^3.14.0", + "@mongosh/service-provider-node-driver": "~3.12.0", + "@vitest/eslint-plugin": "^1.3.4", + "bson": "^6.10.4", + "express": "^5.1.0", + "lru-cache": "^11.1.0", + "mongodb": "^6.19.0", + "mongodb-connection-string-url": "^3.0.2", + "mongodb-log-writer": "^2.4.1", + "mongodb-redact": "^1.2.0", + "mongodb-schema": "^12.6.2", + "node-fetch": "^3.3.2", + "node-machine-id": "1.1.12", + "oauth4webapi": "^3.8.0", + "openapi-fetch": "^0.14.0", + "ts-levenshtein": "^1.0.7", + "yargs-parser": "^21.1.1", + "zod": "^3.25.76" + }, + "bin": { + "mongodb-mcp-server": "dist/esm/index.js" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >= 23.0.0" + }, + "optionalDependencies": { + "kerberos": "^2.2.2" + } + }, + "node_modules/@himanshusinghs/mongodb-mcp-server/node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/@himanshusinghs/mongodb-mcp-server/node_modules/kerberos": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/kerberos/-/kerberos-2.2.2.tgz", + "integrity": "sha512-42O7+/1Zatsc3MkxaMPpXcIl/ukIrbQaGoArZEAr6GcEi2qhfprOBYOPhj+YvSMJkEkdpTjApUx+2DuWaKwRhg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "node-addon-api": "^6.1.0", + "prebuild-install": "^7.1.2" + }, + "engines": { + "node": ">=12.9.0" + } + }, + "node_modules/@himanshusinghs/mongodb-mcp-server/node_modules/lru-cache": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.1.tgz", + "integrity": "sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ==", + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@himanshusinghs/mongodb-mcp-server/node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT", + "optional": true + }, + "node_modules/@himanshusinghs/mongodb-mcp-server/node_modules/node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", + "license": "MIT", + "optional": true + }, + "node_modules/@himanshusinghs/mongodb-mcp-server/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/@himanshusinghs/mongodb-mcp-server/node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", @@ -21358,9 +21490,9 @@ } }, "node_modules/mongodb-mcp-server": { - "version": "1.0.0-prerelease.1", - "resolved": "https://registry.npmjs.org/mongodb-mcp-server/-/mongodb-mcp-server-1.0.0-prerelease.1.tgz", - "integrity": "sha512-fdpVBBgrozqZgDS6f+/2AgvbQqL9KCryi4DuS4sRLvyLf3rPZ/HLCpMAcOZqBQYOhi02UsNRHW99lpBZfa8Y/Q==", + "version": "1.0.0-prerelease.2", + "resolved": "https://registry.npmjs.org/mongodb-mcp-server/-/mongodb-mcp-server-1.0.0-prerelease.2.tgz", + "integrity": "sha512-kLIM0m6O1/k7IcrK870KHpOS6KrbCz+BnIx9fHEXnl6CakUPnrsFAMpZhSdsFe5qK3X8UtZX4V7bhuGMpMYEWQ==", "license": "Apache-2.0", "dependencies": { "@modelcontextprotocol/sdk": "^1.17.4", diff --git a/package.json b/package.json index e99c7c696..208c4c94a 100644 --- a/package.json +++ b/package.json @@ -1396,6 +1396,7 @@ "@babel/core": "^7.25.8", "@babel/parser": "^7.25.8", "@babel/traverse": "^7.25.7", + "@himanshusinghs/mongodb-mcp-server": "^1.0.0-prerelease.2", "@mongodb-js/compass-components": "^1.38.1", "@mongodb-js/connection-form": "^1.52.3", "@mongodb-js/connection-info": "^0.17.1", @@ -1418,7 +1419,7 @@ "mongodb-connection-string-url": "^3.0.2", "mongodb-data-service": "^22.30.1", "mongodb-log-writer": "^2.4.1", - "mongodb-mcp-server": "^1.0.0-prerelease.1", + "mongodb-mcp-server": "^1.0.0-prerelease.2", "mongodb-query-parser": "^4.4.2", "mongodb-schema": "^12.6.2", "node-machine-id": "1.1.12", diff --git a/src/mcp/mcpConnectionErrorHandler.ts b/src/mcp/mcpConnectionErrorHandler.ts index 0844f7a76..1fd6301fb 100644 --- a/src/mcp/mcpConnectionErrorHandler.ts +++ b/src/mcp/mcpConnectionErrorHandler.ts @@ -1,4 +1,7 @@ -import { ErrorCodes, type ConnectionErrorHandler } from 'mongodb-mcp-server'; +import { + ErrorCodes, + type ConnectionErrorHandler, +} from '@himanshusinghs/mongodb-mcp-server'; import type ConnectionController from '../connectionController'; export const createMCPConnectionErrorHandler = ( diff --git a/src/mcp/mcpConnectionManager.ts b/src/mcp/mcpConnectionManager.ts index 91e37afa2..1020e88b8 100644 --- a/src/mcp/mcpConnectionManager.ts +++ b/src/mcp/mcpConnectionManager.ts @@ -3,7 +3,7 @@ import { type AnyConnectionState, type ConnectionStateDisconnected, type LoggerBase, -} from 'mongodb-mcp-server'; +} from '@himanshusinghs/mongodb-mcp-server'; import { NodeDriverServiceProvider, type DevtoolsConnectOptions, diff --git a/src/mcp/mcpController.ts b/src/mcp/mcpController.ts index e060bcd7d..6161297d9 100644 --- a/src/mcp/mcpController.ts +++ b/src/mcp/mcpController.ts @@ -5,19 +5,20 @@ import type { LogPayload, UserConfig, ConnectionManagerFactoryFn, -} from 'mongodb-mcp-server'; +} from '@himanshusinghs/mongodb-mcp-server'; import { defaultUserConfig, LoggerBase, StreamableHttpRunner, Keychain, registerGlobalSecretToRedact, -} from 'mongodb-mcp-server'; +} from '@himanshusinghs/mongodb-mcp-server'; import type ConnectionController from '../connectionController'; import { createLogger } from '../logging'; import type { MCPConnectParams } from './mcpConnectionManager'; import { MCPConnectionManager } from './mcpConnectionManager'; import { createMCPConnectionErrorHandler } from './mcpConnectionErrorHandler'; +import { getMCPConfigFromVSCodeSettings } from './mcpConfig'; export type McpServerStartupConfig = 'enabled' | 'disabled'; @@ -64,6 +65,9 @@ export class MCPController { this.context = context; this.connectionController = connectionController; this.getTelemetryAnonymousId = getTelemetryAnonymousId; + } + + public async activate(): Promise { this.context.subscriptions.push( vscode.lm.registerMcpServerDefinitionProvider('mongodb', { onDidChangeMcpServerDefinitions: this.didChangeEmitter.event, @@ -75,9 +79,7 @@ export class MCPController { }, }), ); - } - public async activate(): Promise { this.connectionController.addEventListener( 'ACTIVE_CONNECTION_CHANGED', () => { @@ -102,14 +104,25 @@ export class MCPController { }; registerGlobalSecretToRedact(token, 'password'); + const vscodeConfiguredMCPConfig = getMCPConfigFromVSCodeSettings(); + const mcpConfig: UserConfig = { ...defaultUserConfig, + ...vscodeConfiguredMCPConfig, + transport: 'http', httpPort: 0, httpHeaders: headers, disabledTools: ['connect'], loggers: ['mcp'], }; + logger.info('Starting MCP server with config', { + ...mcpConfig, + httpHeaders: '', + apiClientId: '', + apiClientSecret: '', + }); + const createConnectionManager: ConnectionManagerFactoryFn = async ({ logger, }) => { diff --git a/src/test/suite/mcp/mcpConnectionErrorHandler.test.ts b/src/test/suite/mcp/mcpConnectionErrorHandler.test.ts index 95ff3ac57..c1db22f5c 100644 --- a/src/test/suite/mcp/mcpConnectionErrorHandler.test.ts +++ b/src/test/suite/mcp/mcpConnectionErrorHandler.test.ts @@ -9,8 +9,8 @@ import { StatusView } from '../../../views'; import type { ConnectionErrorHandled, ConnectionErrorHandlerContext, -} from 'mongodb-mcp-server'; -import { ErrorCodes } from 'mongodb-mcp-server'; +} from '@himanshusinghs/mongodb-mcp-server'; +import { ErrorCodes } from '@himanshusinghs/mongodb-mcp-server'; class MongoDBError extends Error { constructor( diff --git a/src/test/suite/mcp/mcpConnectionManager.test.ts b/src/test/suite/mcp/mcpConnectionManager.test.ts index e531eb2df..e753d7cc4 100644 --- a/src/test/suite/mcp/mcpConnectionManager.test.ts +++ b/src/test/suite/mcp/mcpConnectionManager.test.ts @@ -3,8 +3,8 @@ import { afterEach, beforeEach } from 'mocha'; import chai, { expect } from 'chai'; import chaiAsPromised from 'chai-as-promised'; import ConnectionString from 'mongodb-connection-string-url'; -import type { LoggerBase } from 'mongodb-mcp-server'; -import type { ConnectionStateErrored } from 'mongodb-mcp-server'; +import type { LoggerBase } from '@himanshusinghs/mongodb-mcp-server'; +import type { ConnectionStateErrored } from '@himanshusinghs/mongodb-mcp-server'; import type { DevtoolsConnectOptions } from '@mongosh/service-provider-node-driver'; import { NodeDriverServiceProvider } from '@mongosh/service-provider-node-driver'; import type { MCPConnectParams } from '../../../mcp/mcpConnectionManager'; diff --git a/src/test/suite/mcp/mcpController.test.ts b/src/test/suite/mcp/mcpController.test.ts index 98ca74a12..c1dc490ae 100644 --- a/src/test/suite/mcp/mcpController.test.ts +++ b/src/test/suite/mcp/mcpController.test.ts @@ -4,7 +4,7 @@ import { expect } from 'chai'; import { afterEach, beforeEach } from 'mocha'; import * as vscode from 'vscode'; import type { ExtensionContext } from 'vscode'; -import * as MCPServer from 'mongodb-mcp-server'; +import * as MCPServer from '@himanshusinghs/mongodb-mcp-server'; import { ExtensionContextStub } from '../stubs'; import type { MCPServerInfo } from '../../../mcp/mcpController'; import { MCPController } from '../../../mcp/mcpController'; From 8a363ca406a928a869561cbfa852d73afa3d4850 Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Tue, 16 Sep 2025 16:07:56 +0200 Subject: [PATCH 4/8] chore: merge the disabled tools properly --- package-lock.json | 8 ++-- package.json | 2 +- src/mcp/mcpConfig.ts | 70 ++++++++++++++++++++++++++++ src/mcp/mcpController.ts | 7 ++- src/test/suite/mcp/mcpConfig.test.ts | 51 ++++++++++++++++++++ 5 files changed, 131 insertions(+), 7 deletions(-) create mode 100644 src/mcp/mcpConfig.ts create mode 100644 src/test/suite/mcp/mcpConfig.test.ts diff --git a/package-lock.json b/package-lock.json index 899e82022..486a37879 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@babel/core": "^7.25.8", "@babel/parser": "^7.25.8", "@babel/traverse": "^7.25.7", - "@himanshusinghs/mongodb-mcp-server": "^1.0.0-prerelease.2", + "@himanshusinghs/mongodb-mcp-server": "^1.0.0-prerelease.4", "@mongodb-js/compass-components": "^1.38.1", "@mongodb-js/connection-form": "^1.52.3", "@mongodb-js/connection-info": "^0.17.1", @@ -5687,9 +5687,9 @@ "license": "MIT" }, "node_modules/@himanshusinghs/mongodb-mcp-server": { - "version": "1.0.0-prerelease.2", - "resolved": "https://registry.npmjs.org/@himanshusinghs/mongodb-mcp-server/-/mongodb-mcp-server-1.0.0-prerelease.2.tgz", - "integrity": "sha512-xpMuNhgdL6TKhYawKJfW3cUbXHBo7W1EarjpMUtTcUNaezyKi8CZs/tUrA8w6ghqTGJpINLTvPvRjISSIyWtEg==", + "version": "1.0.0-prerelease.4", + "resolved": "https://registry.npmjs.org/@himanshusinghs/mongodb-mcp-server/-/mongodb-mcp-server-1.0.0-prerelease.4.tgz", + "integrity": "sha512-WyM9SJXPJVC8FWDSMus8nAwRoUuouLRJsZJ9/H4gAGY2acBV9fnRdkG5RRyF5SZf/1SQPDfqSe1+d/uD+uE0uQ==", "license": "Apache-2.0", "dependencies": { "@modelcontextprotocol/sdk": "^1.17.4", diff --git a/package.json b/package.json index 208c4c94a..e243e5043 100644 --- a/package.json +++ b/package.json @@ -1396,7 +1396,7 @@ "@babel/core": "^7.25.8", "@babel/parser": "^7.25.8", "@babel/traverse": "^7.25.7", - "@himanshusinghs/mongodb-mcp-server": "^1.0.0-prerelease.2", + "@himanshusinghs/mongodb-mcp-server": "^1.0.0-prerelease.4", "@mongodb-js/compass-components": "^1.38.1", "@mongodb-js/connection-form": "^1.52.3", "@mongodb-js/connection-info": "^0.17.1", diff --git a/src/mcp/mcpConfig.ts b/src/mcp/mcpConfig.ts new file mode 100644 index 000000000..f9389edba --- /dev/null +++ b/src/mcp/mcpConfig.ts @@ -0,0 +1,70 @@ +import { + type UserConfig, + configurableProperties, + defaultUserConfig, +} from '@himanshusinghs/mongodb-mcp-server'; +import * as vscode from 'vscode'; +import { createLogger } from '../logging'; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { contributes } = require('../../package.json'); + +const logger = createLogger('mcp-config'); + +// eslint-disable-next-line complexity +function mcpConfigValues(property: string, configuredValue: unknown): unknown { + switch (property) { + case 'apiBaseUrl': + case 'apiClientId': + case 'apiClientSecret': + case 'exportsPath': + return String(configuredValue).trim() + ? configuredValue + : defaultUserConfig[property]; + case 'disabledTools': + return Array.isArray(configuredValue) + ? configuredValue + : defaultUserConfig.disabledTools; + case 'readOnly': + case 'indexCheck': + case 'exportTimeoutMs': + case 'exportCleanupIntervalMs': + default: + return configuredValue ?? defaultUserConfig[property]; + } +} + +export function getMCPConfigFromVSCodeSettings( + packageJsonConfiguredProperties: Record = contributes + ?.configuration?.properties ?? {}, + retrieveMCPConfiguration: () => vscode.WorkspaceConfiguration = (): vscode.WorkspaceConfiguration => + vscode.workspace.getConfiguration('mdb.mcp'), +): Partial { + // We're attempting to: + // 1. Use only the config values for MCP server exposed by VSCode config + // 2. Use only the config values that are relevant for MCP server (all mcp + // config exposed by VSCode does contain some irrelevant config as well, + // such as `server`) + const vscConfiguredProperties = Object.keys(packageJsonConfiguredProperties) + .filter((key) => key.startsWith('mdb.mcp')) + .map((key) => key.replace(/^mdb\.mcp\./, '')) + .filter((property) => configurableProperties.has(property)); + + logger.debug('Will retrieve MCP config for the following properties', { + vscConfiguredProperties, + }); + + const mcpConfiguration = retrieveMCPConfiguration(); + return Object.fromEntries( + vscConfiguredProperties.map((property) => { + const configuredValue = mcpConfiguration.get(property); + return [ + property, + // Most of the MCP config, if not all, consists of non-null configs and it is + // possible for a VSCode config to have a null value edited directly in the + // settings file which is why to safeguard against incorrect values we map + // them at-least to the expected defaults. + mcpConfigValues(property, configuredValue), + ]; + }), + ); +} diff --git a/src/mcp/mcpController.ts b/src/mcp/mcpController.ts index 6161297d9..7d8118a4e 100644 --- a/src/mcp/mcpController.ts +++ b/src/mcp/mcpController.ts @@ -112,8 +112,11 @@ export class MCPController { transport: 'http', httpPort: 0, httpHeaders: headers, - disabledTools: ['connect'], - loggers: ['mcp'], + disabledTools: [ + 'connect', + ...(vscodeConfiguredMCPConfig.disabledTools ?? []), + ], + loggers: ['mcp', ...(vscodeConfiguredMCPConfig.loggers ?? [])], }; logger.info('Starting MCP server with config', { diff --git a/src/test/suite/mcp/mcpConfig.test.ts b/src/test/suite/mcp/mcpConfig.test.ts new file mode 100644 index 000000000..e85307892 --- /dev/null +++ b/src/test/suite/mcp/mcpConfig.test.ts @@ -0,0 +1,51 @@ +import type * as vscode from 'vscode'; +import { expect } from 'chai'; +import { getMCPConfigFromVSCodeSettings } from '../../../mcp/mcpConfig'; + +const vscMCPConfig = { + 'mdb.mcp.apiBaseUrl': 'https://cloud.mongodb.com/', + 'mdb.mcp.apiClientId': '', + 'mdb.mcp.apiClientSecret': '', + 'mdb.mcp.disabledTools': ['connect'], + 'mdb.mcp.readOnly': false, + 'mdb.mcp.indexCheck': false, + 'mdb.mcp.server': 'ask', + 'mdb.mcp.exportsPath': '', // note that this is not modified + 'mdb.mcp.exportTimeoutMs': null, // note that this is set to null + 'mdb.mcp.exportCleanupIntervalMs': 0, // not that this is set to 0 +} as const; + +const getDefaultVSCodeConfigForMCP = (): vscode.WorkspaceConfiguration => + ({ + get(key: string) { + return vscMCPConfig[`mdb.mcp.${key}`]; + }, + has(key: string) { + return `mdb.mcp.${key}` in vscMCPConfig; + }, + }) as unknown as vscode.WorkspaceConfiguration; + +suite('MCPConfig test suite', () => { + test('normal calls with package.json properties should return expected MCP config from the configured VSCode config', () => { + const output = getMCPConfigFromVSCodeSettings( + undefined, + getDefaultVSCodeConfigForMCP, + ); + expect(Object.keys(output)).to.not.contain('server'); + expect(output.apiBaseUrl).to.equal('https://cloud.mongodb.com/'); + expect(output.apiClientId).to.be.undefined; + expect(output.apiClientSecret).to.be.undefined; + expect(output.disabledTools).to.deep.equal(['connect']); + expect(output.exportCleanupIntervalMs).to.equal(0); + expect(output.exportTimeoutMs).to.equal(300000); + expect(output.exportsPath?.endsWith('exports')).to.be.true; + expect(output.indexCheck).to.be.false; + expect(output.readOnly).to.be.false; + }); + + test('should return empty object if packageJsonConfiguredProperties resolves to empty object', () => { + expect( + getMCPConfigFromVSCodeSettings({}, getDefaultVSCodeConfigForMCP), + ).to.deep.equal({}); + }); +}); From 3adae736e11174344baac04f3922667b8a7bcfc2 Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Tue, 16 Sep 2025 16:33:19 +0200 Subject: [PATCH 5/8] chore: deduplicate the list items --- src/mcp/mcpController.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/mcp/mcpController.ts b/src/mcp/mcpController.ts index 7d8118a4e..720e633c2 100644 --- a/src/mcp/mcpController.ts +++ b/src/mcp/mcpController.ts @@ -112,11 +112,15 @@ export class MCPController { transport: 'http', httpPort: 0, httpHeaders: headers, - disabledTools: [ - 'connect', - ...(vscodeConfiguredMCPConfig.disabledTools ?? []), - ], - loggers: ['mcp', ...(vscodeConfiguredMCPConfig.loggers ?? [])], + disabledTools: Array.from( + new Set([ + 'connect', + ...(vscodeConfiguredMCPConfig.disabledTools ?? []), + ]), + ), + loggers: Array.from( + new Set(['mcp', ...(vscodeConfiguredMCPConfig.loggers ?? [])]), + ), }; logger.info('Starting MCP server with config', { From ec6dff2e78898970c044f26c83b3f8c8a9cdd396 Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Tue, 16 Sep 2025 16:53:31 +0200 Subject: [PATCH 6/8] chore: replace with mongodb-mcp-server@1.0.0 --- package-lock.json | 140 +----------------- package.json | 3 +- src/mcp/mcpConfig.ts | 2 +- src/mcp/mcpConnectionErrorHandler.ts | 5 +- src/mcp/mcpConnectionManager.ts | 2 +- src/mcp/mcpController.ts | 4 +- .../mcp/mcpConnectionErrorHandler.test.ts | 4 +- .../suite/mcp/mcpConnectionManager.test.ts | 4 +- src/test/suite/mcp/mcpController.test.ts | 2 +- 9 files changed, 15 insertions(+), 151 deletions(-) diff --git a/package-lock.json b/package-lock.json index 486a37879..34caaf974 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,6 @@ "@babel/core": "^7.25.8", "@babel/parser": "^7.25.8", "@babel/traverse": "^7.25.7", - "@himanshusinghs/mongodb-mcp-server": "^1.0.0-prerelease.4", "@mongodb-js/compass-components": "^1.38.1", "@mongodb-js/connection-form": "^1.52.3", "@mongodb-js/connection-info": "^0.17.1", @@ -35,7 +34,7 @@ "mongodb-connection-string-url": "^3.0.2", "mongodb-data-service": "^22.30.1", "mongodb-log-writer": "^2.4.1", - "mongodb-mcp-server": "^1.0.0-prerelease.2", + "mongodb-mcp-server": "^1.0.0", "mongodb-query-parser": "^4.4.2", "mongodb-schema": "^12.6.2", "node-machine-id": "1.1.12", @@ -5686,137 +5685,6 @@ "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", "license": "MIT" }, - "node_modules/@himanshusinghs/mongodb-mcp-server": { - "version": "1.0.0-prerelease.4", - "resolved": "https://registry.npmjs.org/@himanshusinghs/mongodb-mcp-server/-/mongodb-mcp-server-1.0.0-prerelease.4.tgz", - "integrity": "sha512-WyM9SJXPJVC8FWDSMus8nAwRoUuouLRJsZJ9/H4gAGY2acBV9fnRdkG5RRyF5SZf/1SQPDfqSe1+d/uD+uE0uQ==", - "license": "Apache-2.0", - "dependencies": { - "@modelcontextprotocol/sdk": "^1.17.4", - "@mongodb-js/device-id": "^0.3.1", - "@mongodb-js/devtools-connect": "^3.9.3", - "@mongodb-js/devtools-proxy-support": "^0.5.2", - "@mongosh/arg-parser": "^3.14.0", - "@mongosh/service-provider-node-driver": "~3.12.0", - "@vitest/eslint-plugin": "^1.3.4", - "bson": "^6.10.4", - "express": "^5.1.0", - "lru-cache": "^11.1.0", - "mongodb": "^6.19.0", - "mongodb-connection-string-url": "^3.0.2", - "mongodb-log-writer": "^2.4.1", - "mongodb-redact": "^1.2.0", - "mongodb-schema": "^12.6.2", - "node-fetch": "^3.3.2", - "node-machine-id": "1.1.12", - "oauth4webapi": "^3.8.0", - "openapi-fetch": "^0.14.0", - "ts-levenshtein": "^1.0.7", - "yargs-parser": "^21.1.1", - "zod": "^3.25.76" - }, - "bin": { - "mongodb-mcp-server": "dist/esm/index.js" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >= 23.0.0" - }, - "optionalDependencies": { - "kerberos": "^2.2.2" - } - }, - "node_modules/@himanshusinghs/mongodb-mcp-server/node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/@himanshusinghs/mongodb-mcp-server/node_modules/kerberos": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/kerberos/-/kerberos-2.2.2.tgz", - "integrity": "sha512-42O7+/1Zatsc3MkxaMPpXcIl/ukIrbQaGoArZEAr6GcEi2qhfprOBYOPhj+YvSMJkEkdpTjApUx+2DuWaKwRhg==", - "hasInstallScript": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "node-addon-api": "^6.1.0", - "prebuild-install": "^7.1.2" - }, - "engines": { - "node": ">=12.9.0" - } - }, - "node_modules/@himanshusinghs/mongodb-mcp-server/node_modules/lru-cache": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.1.tgz", - "integrity": "sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ==", - "license": "ISC", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@himanshusinghs/mongodb-mcp-server/node_modules/napi-build-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", - "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", - "license": "MIT", - "optional": true - }, - "node_modules/@himanshusinghs/mongodb-mcp-server/node_modules/node-addon-api": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", - "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", - "license": "MIT", - "optional": true - }, - "node_modules/@himanshusinghs/mongodb-mcp-server/node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "license": "MIT", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, - "node_modules/@himanshusinghs/mongodb-mcp-server/node_modules/prebuild-install": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", - "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", - "license": "MIT", - "optional": true, - "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^2.0.0", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@humanwhocodes/config-array": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", @@ -21490,9 +21358,9 @@ } }, "node_modules/mongodb-mcp-server": { - "version": "1.0.0-prerelease.2", - "resolved": "https://registry.npmjs.org/mongodb-mcp-server/-/mongodb-mcp-server-1.0.0-prerelease.2.tgz", - "integrity": "sha512-kLIM0m6O1/k7IcrK870KHpOS6KrbCz+BnIx9fHEXnl6CakUPnrsFAMpZhSdsFe5qK3X8UtZX4V7bhuGMpMYEWQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mongodb-mcp-server/-/mongodb-mcp-server-1.0.0.tgz", + "integrity": "sha512-0pPyYQd2ciwotlMPzvRUwx8suIY2HvVsUOyeR2NN9Zk3kM84hcVR1h2MBOMgMdESfte4jkpXeohtLatlTVd/Gg==", "license": "Apache-2.0", "dependencies": { "@modelcontextprotocol/sdk": "^1.17.4", diff --git a/package.json b/package.json index e243e5043..f9a7c2308 100644 --- a/package.json +++ b/package.json @@ -1396,7 +1396,6 @@ "@babel/core": "^7.25.8", "@babel/parser": "^7.25.8", "@babel/traverse": "^7.25.7", - "@himanshusinghs/mongodb-mcp-server": "^1.0.0-prerelease.4", "@mongodb-js/compass-components": "^1.38.1", "@mongodb-js/connection-form": "^1.52.3", "@mongodb-js/connection-info": "^0.17.1", @@ -1419,7 +1418,7 @@ "mongodb-connection-string-url": "^3.0.2", "mongodb-data-service": "^22.30.1", "mongodb-log-writer": "^2.4.1", - "mongodb-mcp-server": "^1.0.0-prerelease.2", + "mongodb-mcp-server": "^1.0.0", "mongodb-query-parser": "^4.4.2", "mongodb-schema": "^12.6.2", "node-machine-id": "1.1.12", diff --git a/src/mcp/mcpConfig.ts b/src/mcp/mcpConfig.ts index f9389edba..174e2fca9 100644 --- a/src/mcp/mcpConfig.ts +++ b/src/mcp/mcpConfig.ts @@ -2,7 +2,7 @@ import { type UserConfig, configurableProperties, defaultUserConfig, -} from '@himanshusinghs/mongodb-mcp-server'; +} from 'mongodb-mcp-server'; import * as vscode from 'vscode'; import { createLogger } from '../logging'; // eslint-disable-next-line @typescript-eslint/no-var-requires diff --git a/src/mcp/mcpConnectionErrorHandler.ts b/src/mcp/mcpConnectionErrorHandler.ts index 1fd6301fb..0844f7a76 100644 --- a/src/mcp/mcpConnectionErrorHandler.ts +++ b/src/mcp/mcpConnectionErrorHandler.ts @@ -1,7 +1,4 @@ -import { - ErrorCodes, - type ConnectionErrorHandler, -} from '@himanshusinghs/mongodb-mcp-server'; +import { ErrorCodes, type ConnectionErrorHandler } from 'mongodb-mcp-server'; import type ConnectionController from '../connectionController'; export const createMCPConnectionErrorHandler = ( diff --git a/src/mcp/mcpConnectionManager.ts b/src/mcp/mcpConnectionManager.ts index 1020e88b8..91e37afa2 100644 --- a/src/mcp/mcpConnectionManager.ts +++ b/src/mcp/mcpConnectionManager.ts @@ -3,7 +3,7 @@ import { type AnyConnectionState, type ConnectionStateDisconnected, type LoggerBase, -} from '@himanshusinghs/mongodb-mcp-server'; +} from 'mongodb-mcp-server'; import { NodeDriverServiceProvider, type DevtoolsConnectOptions, diff --git a/src/mcp/mcpController.ts b/src/mcp/mcpController.ts index 720e633c2..da1105e9f 100644 --- a/src/mcp/mcpController.ts +++ b/src/mcp/mcpController.ts @@ -5,14 +5,14 @@ import type { LogPayload, UserConfig, ConnectionManagerFactoryFn, -} from '@himanshusinghs/mongodb-mcp-server'; +} from 'mongodb-mcp-server'; import { defaultUserConfig, LoggerBase, StreamableHttpRunner, Keychain, registerGlobalSecretToRedact, -} from '@himanshusinghs/mongodb-mcp-server'; +} from 'mongodb-mcp-server'; import type ConnectionController from '../connectionController'; import { createLogger } from '../logging'; import type { MCPConnectParams } from './mcpConnectionManager'; diff --git a/src/test/suite/mcp/mcpConnectionErrorHandler.test.ts b/src/test/suite/mcp/mcpConnectionErrorHandler.test.ts index c1db22f5c..95ff3ac57 100644 --- a/src/test/suite/mcp/mcpConnectionErrorHandler.test.ts +++ b/src/test/suite/mcp/mcpConnectionErrorHandler.test.ts @@ -9,8 +9,8 @@ import { StatusView } from '../../../views'; import type { ConnectionErrorHandled, ConnectionErrorHandlerContext, -} from '@himanshusinghs/mongodb-mcp-server'; -import { ErrorCodes } from '@himanshusinghs/mongodb-mcp-server'; +} from 'mongodb-mcp-server'; +import { ErrorCodes } from 'mongodb-mcp-server'; class MongoDBError extends Error { constructor( diff --git a/src/test/suite/mcp/mcpConnectionManager.test.ts b/src/test/suite/mcp/mcpConnectionManager.test.ts index e753d7cc4..e531eb2df 100644 --- a/src/test/suite/mcp/mcpConnectionManager.test.ts +++ b/src/test/suite/mcp/mcpConnectionManager.test.ts @@ -3,8 +3,8 @@ import { afterEach, beforeEach } from 'mocha'; import chai, { expect } from 'chai'; import chaiAsPromised from 'chai-as-promised'; import ConnectionString from 'mongodb-connection-string-url'; -import type { LoggerBase } from '@himanshusinghs/mongodb-mcp-server'; -import type { ConnectionStateErrored } from '@himanshusinghs/mongodb-mcp-server'; +import type { LoggerBase } from 'mongodb-mcp-server'; +import type { ConnectionStateErrored } from 'mongodb-mcp-server'; import type { DevtoolsConnectOptions } from '@mongosh/service-provider-node-driver'; import { NodeDriverServiceProvider } from '@mongosh/service-provider-node-driver'; import type { MCPConnectParams } from '../../../mcp/mcpConnectionManager'; diff --git a/src/test/suite/mcp/mcpController.test.ts b/src/test/suite/mcp/mcpController.test.ts index c1dc490ae..98ca74a12 100644 --- a/src/test/suite/mcp/mcpController.test.ts +++ b/src/test/suite/mcp/mcpController.test.ts @@ -4,7 +4,7 @@ import { expect } from 'chai'; import { afterEach, beforeEach } from 'mocha'; import * as vscode from 'vscode'; import type { ExtensionContext } from 'vscode'; -import * as MCPServer from '@himanshusinghs/mongodb-mcp-server'; +import * as MCPServer from 'mongodb-mcp-server'; import { ExtensionContextStub } from '../stubs'; import type { MCPServerInfo } from '../../../mcp/mcpController'; import { MCPController } from '../../../mcp/mcpController'; From 817cde28d726a26847c7660520bbdbac50301ddd Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Tue, 16 Sep 2025 17:14:47 +0200 Subject: [PATCH 7/8] chore: trim string values before using them --- src/mcp/mcpConfig.ts | 48 ++++++------ src/test/suite/mcp/mcpConfig.test.ts | 113 ++++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 27 deletions(-) diff --git a/src/mcp/mcpConfig.ts b/src/mcp/mcpConfig.ts index 174e2fca9..3de49bd72 100644 --- a/src/mcp/mcpConfig.ts +++ b/src/mcp/mcpConfig.ts @@ -10,29 +10,6 @@ const { contributes } = require('../../package.json'); const logger = createLogger('mcp-config'); -// eslint-disable-next-line complexity -function mcpConfigValues(property: string, configuredValue: unknown): unknown { - switch (property) { - case 'apiBaseUrl': - case 'apiClientId': - case 'apiClientSecret': - case 'exportsPath': - return String(configuredValue).trim() - ? configuredValue - : defaultUserConfig[property]; - case 'disabledTools': - return Array.isArray(configuredValue) - ? configuredValue - : defaultUserConfig.disabledTools; - case 'readOnly': - case 'indexCheck': - case 'exportTimeoutMs': - case 'exportCleanupIntervalMs': - default: - return configuredValue ?? defaultUserConfig[property]; - } -} - export function getMCPConfigFromVSCodeSettings( packageJsonConfiguredProperties: Record = contributes ?.configuration?.properties ?? {}, @@ -68,3 +45,28 @@ export function getMCPConfigFromVSCodeSettings( }), ); } + +// eslint-disable-next-line complexity +function mcpConfigValues(property: string, configuredValue: unknown): unknown { + switch (property) { + case 'apiBaseUrl': + case 'apiClientId': + case 'apiClientSecret': + case 'exportsPath': { + const trimmedValue = String(configuredValue).trim(); + return typeof configuredValue === 'string' && !!trimmedValue + ? trimmedValue + : defaultUserConfig[property]; + } + case 'disabledTools': + return Array.isArray(configuredValue) + ? configuredValue + : defaultUserConfig.disabledTools; + case 'readOnly': + case 'indexCheck': + case 'exportTimeoutMs': + case 'exportCleanupIntervalMs': + default: + return configuredValue ?? defaultUserConfig[property]; + } +} diff --git a/src/test/suite/mcp/mcpConfig.test.ts b/src/test/suite/mcp/mcpConfig.test.ts index e85307892..5b83d36f4 100644 --- a/src/test/suite/mcp/mcpConfig.test.ts +++ b/src/test/suite/mcp/mcpConfig.test.ts @@ -7,8 +7,8 @@ const vscMCPConfig = { 'mdb.mcp.apiClientId': '', 'mdb.mcp.apiClientSecret': '', 'mdb.mcp.disabledTools': ['connect'], - 'mdb.mcp.readOnly': false, - 'mdb.mcp.indexCheck': false, + 'mdb.mcp.readOnly': true, // note that we changed it to true + 'mdb.mcp.indexCheck': null, // note that this is null 'mdb.mcp.server': 'ask', 'mdb.mcp.exportsPath': '', // note that this is not modified 'mdb.mcp.exportTimeoutMs': null, // note that this is set to null @@ -25,7 +25,7 @@ const getDefaultVSCodeConfigForMCP = (): vscode.WorkspaceConfiguration => }, }) as unknown as vscode.WorkspaceConfiguration; -suite('MCPConfig test suite', () => { +suite.only('MCPConfig test suite', () => { test('normal calls with package.json properties should return expected MCP config from the configured VSCode config', () => { const output = getMCPConfigFromVSCodeSettings( undefined, @@ -40,7 +40,7 @@ suite('MCPConfig test suite', () => { expect(output.exportTimeoutMs).to.equal(300000); expect(output.exportsPath?.endsWith('exports')).to.be.true; expect(output.indexCheck).to.be.false; - expect(output.readOnly).to.be.false; + expect(output.readOnly).to.be.true; }); test('should return empty object if packageJsonConfiguredProperties resolves to empty object', () => { @@ -48,4 +48,109 @@ suite('MCPConfig test suite', () => { getMCPConfigFromVSCodeSettings({}, getDefaultVSCodeConfigForMCP), ).to.deep.equal({}); }); + + suite('mcpConfigValues edge cases', () => { + test('should handle non-string values for string properties', () => { + const mockConfig = { + 'mdb.mcp.apiBaseUrl': 42, + 'mdb.mcp.apiClientId': true, + 'mdb.mcp.apiClientSecret': {}, + 'mdb.mcp.exportsPath': [], + }; + + const getMockConfig = (): vscode.WorkspaceConfiguration => + ({ + get(key: string) { + return mockConfig[`mdb.mcp.${key}`]; + }, + has(key: string) { + return `mdb.mcp.${key}` in mockConfig; + }, + }) as unknown as vscode.WorkspaceConfiguration; + + const output = getMCPConfigFromVSCodeSettings(undefined, getMockConfig); + + // All should fall back to defaults since they're not valid strings + expect(output.apiBaseUrl).to.equal('https://cloud.mongodb.com/'); + expect(output.apiClientId).to.be.undefined; + expect(output.apiClientSecret).to.be.undefined; + expect(output.exportsPath?.endsWith('exports')).to.be.true; + }); + + test('should handle whitespace-only string values', () => { + const mockConfig = { + 'mdb.mcp.apiBaseUrl': ' ', + 'mdb.mcp.apiClientId': '\t\t', + 'mdb.mcp.apiClientSecret': '\n\n', + 'mdb.mcp.exportsPath': '', + }; + + const getMockConfig = (): vscode.WorkspaceConfiguration => + ({ + get(key: string) { + return mockConfig[`mdb.mcp.${key}`]; + }, + has(key: string) { + return `mdb.mcp.${key}` in mockConfig; + }, + }) as unknown as vscode.WorkspaceConfiguration; + + const output = getMCPConfigFromVSCodeSettings(undefined, getMockConfig); + + // All should fall back to defaults since trimmed values are empty + expect(output.apiBaseUrl).to.equal('https://cloud.mongodb.com/'); + expect(output.apiClientId).to.be.undefined; + expect(output.apiClientSecret).to.be.undefined; + expect(output.exportsPath?.endsWith('exports')).to.be.true; + }); + + test('should properly trim and return valid string values', () => { + const mockConfig = { + 'mdb.mcp.apiBaseUrl': ' https://custom.mongodb.com ', + 'mdb.mcp.apiClientId': '\tcustom-client-id\t', + 'mdb.mcp.apiClientSecret': '\ncustom-secret\n', + 'mdb.mcp.exportsPath': ' /custom/path ', + }; + + const getMockConfig = (): vscode.WorkspaceConfiguration => + ({ + get(key: string) { + return mockConfig[`mdb.mcp.${key}`]; + }, + has(key: string) { + return `mdb.mcp.${key}` in mockConfig; + }, + }) as unknown as vscode.WorkspaceConfiguration; + + const output = getMCPConfigFromVSCodeSettings(undefined, getMockConfig); + + // Should return the trimmed original values + expect(output.apiBaseUrl).to.equal('https://custom.mongodb.com'); + expect(output.apiClientId).to.equal('custom-client-id'); + expect(output.apiClientSecret).to.equal('custom-secret'); + expect(output.exportsPath).to.equal('/custom/path'); + }); + + test('should handle non-array values for disabledTools', () => { + const mockConfig = { + 'mdb.mcp.disabledTools': 'not-an-array', + }; + + const getMockConfig = (): vscode.WorkspaceConfiguration => + ({ + get(key: string) { + return mockConfig[`mdb.mcp.${key}`]; + }, + has(key: string) { + return `mdb.mcp.${key}` in mockConfig; + }, + }) as unknown as vscode.WorkspaceConfiguration; + + const output = getMCPConfigFromVSCodeSettings(undefined, getMockConfig); + + // Should fall back to default disabledTools array + expect(output.disabledTools).to.be.an('array'); + expect(output.disabledTools).to.deep.equal([]); + }); + }); }); From 7e8750346af1e5db7c655b024cd3ff5f73406eb8 Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Tue, 16 Sep 2025 17:18:25 +0200 Subject: [PATCH 8/8] chore: no exclusive tests --- src/test/suite/mcp/mcpConfig.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/suite/mcp/mcpConfig.test.ts b/src/test/suite/mcp/mcpConfig.test.ts index 5b83d36f4..72e15a8c5 100644 --- a/src/test/suite/mcp/mcpConfig.test.ts +++ b/src/test/suite/mcp/mcpConfig.test.ts @@ -25,7 +25,7 @@ const getDefaultVSCodeConfigForMCP = (): vscode.WorkspaceConfiguration => }, }) as unknown as vscode.WorkspaceConfiguration; -suite.only('MCPConfig test suite', () => { +suite('MCPConfig test suite', () => { test('normal calls with package.json properties should return expected MCP config from the configured VSCode config', () => { const output = getMCPConfigFromVSCodeSettings( undefined,