-
Notifications
You must be signed in to change notification settings - Fork 170
chore: adopt strict validation for all command line arguments MCP-298 #777
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adopts strict validation for command-line arguments by relying entirely on Zod schemas instead of hardcoded OPTIONS configurations, eliminating redundancy and enabling type-safe argument parsing for both internal and mongosh-related arguments.
Key changes include:
- Removal of manual
OPTIONSarray and theargsParserOptions.tsfile - Integration with
@mongosh/arg-parserfor unified CLI argument parsing - Support for complex types like objects via CLI (e.g.,
--httpHeaders='{"test":"1"}'or--httpHeaders.test='1') - Better alignment with mongosh's connection string handling (e.g.,
sslarguments map totlsequivalents) - Improved error handling that returns structured validation results instead of directly calling
process.exit()
Reviewed changes
Copilot reviewed 16 out of 19 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
tsconfig.cjs.json |
Updated module system from commonjs to node16 |
tests/utils/index.ts |
Added createEnvironment helper for managing test environment variables |
tests/unit/common/config.test.ts |
Refactored tests to use new createUserConfig API returning structured results instead of throwing errors |
tests/e2e/e2eUtils.ts |
Added CLI runner utility for e2e tests |
tests/e2e/cli.test.ts |
Converted warning/error tests from unit to e2e tests |
src/index.ts |
Updated to handle structured validation results from createUserConfig |
src/common/config/userConfig.ts |
Introduced UserConfigSchemaWithCliOptions merging internal and mongosh schemas |
src/common/config/createUserConfig.ts |
Replaced manual argument parsing with parseArgsWithCliOptions from mongosh |
src/common/config/configUtils.ts |
Removed isConnectionSpecifier function, now handled by mongosh |
src/common/config/argsParserOptions.ts |
Deleted file - manual OPTIONS array no longer needed |
server.json |
Updated format fields to correct types (boolean/number instead of string) and added missing configuration options |
scripts/generateArguments.ts |
Updated to derive argument types from Zod schemas instead of OPTIONS |
scripts/apply.ts |
Migrated from yargs-parser to @mongosh/arg-parser |
package.json |
Removed yargs-parser dependency |
eslint-rules/enforce-zod-v4.js |
Added createUserConfig.ts to allowed files for zod/v4 imports |
README.md |
Updated configuration table with new/corrected options |
| .DS_Store | ||
|
|
||
| # Development tool files | ||
| .yalc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like yalc so would be great if this is gitgnored
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
| }); | ||
| }); | ||
|
|
||
| describe("Warning and Error messages", () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved to e2e tests instead
| - Refer to https://www.mongodb.com/docs/mcp-server/get-started/ for setting up the MCP Server. | ||
| `; | ||
| onError(errorMessage); | ||
| return closeProcess(1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed this callback-based logic to instead be returning information to be used at a higher level
| { | ||
| cli: ["--sslCertificateSelector", "pem=pom"], | ||
| expected: { sslCertificateSelector: "pem=pom" }, | ||
| expected: { tlsCertificateSelector: "pem=pom" }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is what the actually happens in mongosh since ssl arguments are deprecated
| "description": "Idle timeout for a client to disconnect (only applies to http transport).", | ||
| "isRequired": false, | ||
| "format": "string", | ||
| "format": "number", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like there were some issues with the server.json generation before 🤷
src/common/config/userConfig.ts
Outdated
| export const UserConfigSchemaWithCliOptions = z4.object({ | ||
| ...UserConfigSchema.shape, | ||
| ...CliOptionsSchema.shape, | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to at-least deprecate nodb here otherwise that will hinder the rightful parsing of a connection specifier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gagik did you find a way to deprecate this? I notice that we now have a warning message but the argument still end up deflecting the positional connection string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deprecation to me means the behavior continues to work. We warn them to remove this so we can eventually throw an error. Otherwise we're breaking behavior
himanshusinghs
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are amazing changes @gagik. I left one additional note for tsconfig consideration.
scripts/generateArguments.ts
Outdated
| import { join, dirname } from "path"; | ||
| import { fileURLToPath } from "url"; | ||
| import { UserConfigSchema, configRegistry } from "../src/common/config/userConfig.js"; | ||
| import { UserConfigSchemaWithCliOptions, configRegistry } from "../src/common/config/userConfig.js"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're using the UserConfig schema together with CliOptions schema, yet, in the final server.json I don't see the entries from CliOptions schema? We should expect those right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmmmm..... I guess in server.json we should; should we have any fields in the README?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's follow-up on this. otherwise we're going to dump a bunch of unrelated fields into it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea - I am also unsure if they deserve a place in server.json and README but worth noting that somehow with this script they don't end up there. Happy to address this as a follow up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is existing behavior and I think the code is self-explanatory, let's follow up on this later
Pull Request Test Coverage Report for Build 19928292758Warning: This coverage report may be inaccurate.This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.
Details
💛 - Coveralls |
Co-authored-by: Himanshu Singh <himanshu.singhs@outlook.in>
a5438af to
b009bb3
Compare
| } | ||
|
|
||
| if (parsed.nodb) { | ||
| return { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This ended up being more manual because of some mongosh type integrity stuff. We will need to follow-up to make this and more arguments use a subset of functionality
b009bb3 to
9263486
Compare
himanshusinghs
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noice 🚀
fad86b9 to
52b5c39
Compare
cveticm
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ LGTM and thanks for the descriptive summary, gave great context on the issue!
This will not work until mongodb-js/mongosh#2589 is released but making it available for early reviews.
This gets rid of our hardcoded dependency on
OPTIONSfor both internal and mongosh-related argument parsing and instead relies completely on our (and mongosh's) Zod schema.This provides the following advantages:
OPTIONSarray when adding new config fields which is easy to forget. This actually revealed that we had forgotten to add i.e.vectorSearchDimensionsto this array before because of the redundancy involved.--object.field=3which would otherwise have require us to manually specify different scenarios in theOPTIONSarray.As a consequence of some of these advantages, this PR also...:
httpHeadersusing the CLI (or env), either as--httpHeaders='{ "test": "1" }'or--httpHeaders.test='1'!ssl-related fields actually get replaced withtlsequivalents; and some fields are also unsupported. We would correctly throw an error in this case (which we weren't doing before).Some considerations: