8000 feat: add data access tools by nirinchev · Pull Request #14 · mongodb-js/mongodb-mcp-server · GitHub
[go: up one dir, main page]

Skip to content

feat: add data access tools #14

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

Merged
merged 6 commits into from
Apr 9, 2025
Merged

feat: add data access tools #14

merged 6 commits into from
Apr 9, 2025

Conversation

nirinchev
Copy link
Collaborator
@nirinchev nirinchev commented Apr 8, 2025

Adds the following data-access tools:

  • connect
  • list-databases
  • list-collections
  • collection-schema
  • collection-indexes
  • collection-storage-size
  • db-stats
  • find
  • aggregate
  • count
  • create-index
  • insert-one
  • insert-many
  • delete-one
  • delete-many
  • drop-collection
  • drop-database
  • update-one
  • update-many
  • rename-collection

Follow-ups:

  • update-one/many doesn't support aggregation update

@nirinchev nirinchev requested review from Copilot and gagik April 8, 2025 17:36
@@ -14,6 +14,7 @@
"publishConfig": {
"access": "public"
},
"type": "module",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to add this since I was seeing complaints that node was first trying to parse it as cjs, but was seeing an esm. I don't have a strong opinion on whether we should go with one or the other.

Comment on lines -4 to +8
const packageMetadata = fs.readFileSync(path.resolve("./package.json"), "utf8");
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const packageMetadata = fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8");
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may have regressed at some point, but path.resolve("./package.json") is looking at dist/config.js rather than in the parent directory. For some reason, Claude is not happy about relative paths, so "../package.json" didn't work either, so I needed the __dirname shenanigans above, since esm doesn't have __dirname built in.

Copy link
Contributor
@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • package.json: Language not supported
Comments suppressed due to low confidence (1)

src/tools/mongodb/createIndex.ts:28

  • Ensure that the 'indexes' array is not empty before accessing indexes[0]; consider adding a check or handling the scenario where no index is created.
text: `Created the index `${indexes[0]}``,


protected constructor(protected state: State) {}

public register(server: McpServer): void {
const callback = async (args: z.objectOutputType<Args, ZodTypeAny>): Promise<CallToolResult> => {
const callback = async (args: z.objectOutputType<Args, ZodNever>): Promise<CallToolResult> => {
Copy link
Preview
Copilot AI Apr 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using z.ZodNever in the callback signature (and in ToolArgs) might unintentionally restrict valid input data if argsShape is expected to allow non-empty objects. Please verify that this change aligns with the intended usage of the tool arguments.

Suggested change
const callback = async (args: z.objectOutputType<Args, ZodNever>): Promise<CallToolResult> => {
const callback = async (args: ToolArgs<Args>): Promise<CallToolResult> => {

Copilot uses AI. Check for mistakes.


private async connect(connectionString: string): Promise<void> {
const provider = await NodeDriverServiceProvider.connect(connectionString, {
productDocsLink: "https://docs.mongodb.com/todo-mcp",
Copy link
Preview
Copilot AI Apr 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The productDocsLink value appears to be a placeholder. It is recommended to update this URL to point to the correct documentation for MongoDB MCP.

Suggested change
productDocsLink: "https://docs.mongodb.com/todo-mcp",
productDocsLink: "https://docs.mongodb.com/manual/reference/mongodb-mcp/",

Copilot uses AI. Check for mistakes.

Comment on lines 9 to 14
export abstract class ToolBase<Args extends ZodRawShape> {
protected abstract name: string;

protected abstract description: string;

protected abstract argsShape: Args;
Copy link
Collaborator
@gagik gagik Apr 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export abstract class ToolBase<Args extends ZodRawShape> {
protected abstract name: string;
protected abstract description: string;
protected abstract argsShape: Args;
export abstract class ToolBase {
protected abstract name: string;
protected abstract description: string;
protected abstract argsShape: ZodRawShape;
protected abstract execute(args: ToolArgs<typeof this.argsShape>): Promise<CallToolResult>;

I went on a rabbithole trying to get rid of some redundancy here. Unfortunately I don't think the Args generic is doing anything for us.

I would instead get rid of it and use typeof this.argsShape. This is still not really going to be a strict type as is. For example in find.ts in both cases you can define execute to use ToolArgs<ZodRawShape> and it'd still pass fine so unfortunately TypeScript isn't that strict/smart anyhow.

Same for MongoDBToolBase.

Then we can simply define argsShape inside the class as is without replicating it

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I couldn't get typescript to behave exactly how I wanted it to, but figured it's better this way than rewriting the entire server in a proper language 🥲 Anyway, agree with your assessment and have removed the args generic.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I was also hoping there's a better way but couldn't come up with an alternative either 🥲

Copy link
Collaborator
@gagik gagik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@nirinchev nirinchev merged commit a2237d2 into main Apr 9, 2025
1 check passed
@nirinchev nirinchev deleted the ni/data-access branch April 9, 2025 08:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0