@@ -5,6 +5,7 @@ import type { CliOptions, ConnectionInfo } from "@mongosh/arg-parser";
55import { generateConnectionInfoFromCliArgs } from "@mongosh/arg-parser" ;
66import { Keychain } from "./keychain.js" ;
77import type { Secret } from "./keychain.js" ;
8+ import levenshtein from "ts-levenshtein" ;
89
910// From: https://github.com/mongodb-js/mongosh/blob/main/packages/cli-repl/src/arg-parser.ts
1011const OPTIONS = {
@@ -91,6 +92,44 @@ const OPTIONS = {
9192 } ,
9293} as const ;
9394
95+ const ALL_CONFIG_KEYS = new Set (
96+ ( OPTIONS . string as readonly string [ ] )
97+ . concat ( OPTIONS . array )
98+ . concat ( OPTIONS . boolean )
99+ . concat ( Object . keys ( OPTIONS . alias ) )
100+ ) ;
101+
102+ export function validateConfigKey ( key : string ) : { valid : boolean ; suggestion ?: string } {
103+ if ( ALL_CONFIG_KEYS . has ( key ) ) {
104+ return { valid : true } ;
105+ }
106+
107+ let minLev = Number . MAX_VALUE ;
108+ let suggestion = "" ;
109+
110+ // find the closest match for a suggestion
111+ for ( const validKey of ALL_CONFIG_KEYS ) {
112+ // check if there is an exact case-insensitive match
113+ if ( validKey . toLowerCase ( ) === key . toLowerCase ( ) ) {
114+ return { valid : false , suggestion : validKey } ;
115+ }
116+
117+ // else, infer something using levenshtein so we suggest a valid key
118+ const lev = levenshtein . get ( key , validKey ) ;
119+ if ( lev < minLev ) {
120+ minLev = lev ;
121+ suggestion = validKey ;
122+ }
123+ }
124+
125+ if ( minLev <= 2 ) {
126+ // accept up to 2 typos
127+ return { valid : false , suggestion } ;
128+ }
129+
130+ return { valid : false } ;
131+ }
132+
94133function isConnectionSpecifier ( arg : string | undefined ) : boolean {
95134 return (
96135 arg !== undefined &&
@@ -267,7 +306,13 @@ function parseCliConfig(args: string[]): CliOptions {
267306 // so we don't have a logger. For stdio, the warning will be received as a string in
268307 // the client and IDEs like VSCode do show the message in the log window. For HTTP,
269308 // it will be in the stdout of the process.
270- warnAboutDeprecatedCliArgs ( { ...parsed , _ : positionalArguments } , console . warn ) ;
309+ warnAboutDeprecatedOrUnknownCliArgs (
310+ { ...parsed , _ : positionalArguments } ,
311+ {
312+ warn : ( msg ) => console . warn ( msg ) ,
313+ exit : ( status ) => process . exit ( status ) ,
314+ }
315+ ) ;
271316
272317 // if we have a positional argument that matches a connection string
273318 // store it as the connection specifier and remove it from the argument
@@ -280,26 +325,47 @@ function parseCliConfig(args: string[]): CliOptions {
280325 return parsed ;
281326}
282327
283- export function warnAboutDeprecatedCliArgs (
284- args : CliOptions &
285- UserConfig & {
286- _ ?: string [ ] ;
287- } ,
288- warn : ( msg : string ) => void
328+ export function warnAboutDeprecatedOrUnknownCliArgs (
329+ args : Record < string , unknown > ,
330+ { warn, exit } : { warn : ( msg : string ) => void ; exit : ( status : number ) => void | never }
289331) : void {
290332 let usedDeprecatedArgument = false ;
333+ let usedInvalidArgument = false ;
334+
335+ const knownArgs = args as unknown as UserConfig & CliOptions ;
291336 // the first position argument should be used
292337 // instead of --connectionString, as it's how the mongosh works.
293- if ( args . connectionString ) {
338+ if ( knownArgs . connectionString ) {
294339 usedDeprecatedArgument = true ;
295340 warn (
296341 "The --connectionString argument is deprecated. Prefer using the first positional argument for the connection string or the MDB_MCP_CONNECTION_STRING environment variable."
297342 ) ;
298343 }
299344
300- if ( usedDeprecatedArgument ) {
345+ for ( const providedKey of Object . keys ( args ) ) {
346+ if ( providedKey === "_" ) {
347+ // positional argument
348+ continue ;
349+ }
350+
351+ const { valid, suggestion } = validateConfigKey ( providedKey ) ;
352+ if ( ! valid ) {
353+ usedInvalidArgument = true ;
354+ if ( suggestion ) {
355+ warn ( `Invalid command line argument '${ providedKey } '. Did you mean '${ suggestion } '?` ) ;
356+ } else {
357+ warn ( `Invalid command line argument '${ providedKey } '.` ) ;
358+ }
359+ }
360+ }
361+
362+ if ( usedInvalidArgument || usedDeprecatedArgument ) {
301363 warn ( "Refer to https://www.mongodb.com/docs/mcp-server/get-started/ for setting up the MCP Server." ) ;
302364 }
365+
366+ if ( usedInvalidArgument ) {
367+ exit ( 1 ) ;
368+ }
303369}
304370
305371function commaSeparatedToArray < T extends string [ ] > ( str : string | string [ ] | undefined ) : T {
0 commit comments