diff --git a/README.md b/README.md index b887870a..3a2d93d4 100644 --- a/README.md +++ b/README.md @@ -86,8 +86,7 @@ npm run build Prerequisites: -- Use VSCode Insiders (https://code.visualstudio.com/insiders/) -- Setup copilot in VSCode Insiders +- Node.js v20.x Step 1: Add the mcp server to VSCode configuration @@ -104,8 +103,8 @@ It should look like this "servers": { "mongodb-mcp-server": { "type": "stdio", - "command": "/Users//workplace/atlas-mcp-server/dist/index.js", - "args": [] + "command": "npx", + "args": ["-y", "@mongodb-js/mongodb-mcp-server"] } } } @@ -141,7 +140,8 @@ Paste the mcp server configuration into the file { "mcpServers": { "Demo": { - "command": "path/to/this/repo/atlas-mc-server/dist/index.js" + "command": "npx", + "args": ["-y", "@mongodb-js/mongodb-mcp-server"] } } } diff --git a/package-lock.json b/package-lock.json index db3e8841..d47036ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,15 @@ { "name": "@mongodb-js/mongodb-mcp-server", - "version": "0.0.0", + "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@mongodb-js/mongodb-mcp-server", - "version": "0.0.0", + "version": "0.0.1", "license": "Apache-2.0", "dependencies": { + "@modelcontextprotocol/sdk": "^1.8.0", "@mongodb-js/devtools-connect": "^3.7.2", "@mongosh/service-provider-node-driver": "^3.6.0", "bson": "^6.10.3", @@ -28,9 +29,7 @@ "@eslint/js": "^9.24.0", "@jest/globals": "^29.7.0", "@modelcontextprotocol/inspector": "^0.8.2", - "@modelcontextprotocol/sdk": "^1.8.0", "@redocly/cli": "^1.34.2", - "@types/express": "^5.0.1", "@types/jest": "^29.5.14", "@types/node": "^22.14.0", "@types/simple-oauth2": "^5.0.7", @@ -47,8 +46,7 @@ "ts-jest": "^29.3.1", "tsx": "^4.19.3", "typescript": "^5.8.2", - "typescript-eslint": "^8.29.1", - "yaml": "^2.7.1" + "typescript-eslint": "^8.29.1" }, "engines": { "node": ">=20.0.0" @@ -3046,7 +3044,6 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.9.0.tgz", "integrity": "sha512-Jq2EUCQpe0iyO5FGpzVYDNFR6oR53AIrwph9yWl7uSc7IWUMsrmpmSaTGra5hQNunXpM+9oit85p924jWuHzUA==", - "dev": true, "license": "MIT", "dependencies": { "content-type": "^1.0.5", @@ -3068,7 +3065,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=16.20.0" @@ -5840,27 +5836,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/estree": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", @@ -5868,31 +5843,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/express": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.1.tgz", - "integrity": "sha512-UZUw8vjpWFXuDnjFTh7/5c2TWDlQqeXHi6hcN7F2XSVT5P+WmUnnbFS3KA6Jnc6IsEqI2qCVu2bK0R0J4A8ZQQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^5.0.0", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.6.tgz", - "integrity": "sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -5903,13 +5853,6 @@ "@types/node": "*" } }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -5955,13 +5898,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/node": { "version": "22.14.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.0.tgz", @@ -5979,43 +5915,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/qs": { - "version": "6.9.18", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", - "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" - } - }, "node_modules/@types/simple-oauth2": { "version": "5.0.7", "resolved": "https://registry.npmjs.org/@types/simple-oauth2/-/simple-oauth2-5.0.7.tgz", @@ -6300,7 +6199,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "dev": true, "license": "MIT", "dependencies": { "mime-types": "^3.0.0", @@ -6765,7 +6663,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", - "dev": true, "license": "MIT", "dependencies": { "bytes": "^3.1.2", @@ -7396,7 +7293,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", - "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" @@ -7425,7 +7321,6 @@ "version": "0.7.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -7435,7 +7330,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.6.0" @@ -7464,7 +7358,6 @@ "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, "license": "MIT", "dependencies": { "object-assign": "^4", @@ -8487,7 +8380,6 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.6.tgz", "integrity": "sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==", - "dev": true, "license": "MIT", "dependencies": { "eventsource-parser": "^3.0.1" @@ -8500,7 +8392,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz", "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=18.0.0" @@ -8569,7 +8460,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", - "dev": true, "license": "MIT", "dependencies": { "accepts": "^2.0.0", @@ -8612,7 +8502,6 @@ "version": "7.5.0", "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 16" @@ -8837,7 +8726,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", - "dev": true, "license": "MIT", "dependencies": { "debug": "^4.4.0", @@ -8960,7 +8848,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -9393,7 +9280,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -9680,7 +9566,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "dev": true, "license": "MIT" }, "node_modules/is-stream": { @@ -10933,7 +10818,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -10949,7 +10833,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -11013,7 +10896,6 @@ "version": "1.54.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -11023,7 +10905,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "dev": true, "license": "MIT", "dependencies": { "mime-db": "^1.54.0" @@ -11465,7 +11346,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -11737,7 +11617,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11789,7 +11668,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "devOptional": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -12156,7 +12034,6 @@ "version": "8.2.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=16" @@ -12597,7 +12474,6 @@ "version": "6.14.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -12653,7 +12529,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", - "dev": true, "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -13036,7 +12911,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "dev": true, "license": "MIT", "dependencies": { "debug": "^4.4.0", @@ -13254,7 +13128,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", - "dev": true, "license": "MIT", "dependencies": { "debug": "^4.3.5", @@ -13353,7 +13226,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", - "dev": true, "license": "MIT", "dependencies": { "encodeurl": "^2.0.0", @@ -14499,7 +14371,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "dev": true, "license": "MIT", "dependencies": { "content-type": "^1.0.5", @@ -14912,7 +14783,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "devOptional": true, "license": "ISC" }, "node_modules/write-file-atomic": { @@ -14977,19 +14847,6 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "license": "ISC" }, - "node_modules/yaml": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", - "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/yaml-ast-parser": { "version": "0.0.43", "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", @@ -15072,7 +14929,6 @@ "version": "3.24.5", "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", - "dev": true, "license": "ISC", "peerDependencies": { "zod": "^3.24.1" diff --git a/package.json b/package.json index 3d334144..b9f4fccd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@mongodb-js/mongodb-mcp-server", "description": "MongoDB Model Context Protocol Server", - "version": "0.0.0", + "version": "0.0.1", "main": "dist/index.js", "author": "MongoDB ", "homepage": "https://github.com/mongodb-js/mongodb-mcp-server", @@ -35,9 +35,7 @@ "@eslint/js": "^9.24.0", "@jest/globals": "^29.7.0", "@modelcontextprotocol/inspector": "^0.8.2", - "@modelcontextprotocol/sdk": "^1.8.0", "@redocly/cli": "^1.34.2", - "@types/express": "^5.0.1", "@types/jest": "^29.5.14", "@types/node": "^22.14.0", "@types/simple-oauth2": "^5.0.7", @@ -54,12 +52,12 @@ "ts-jest": "^29.3.1", "tsx": "^4.19.3", "typescript": "^5.8.2", - "typescript-eslint": "^8.29.1", - "yaml": "^2.7.1" + "typescript-eslint": "^8.29.1" }, "dependencies": { "@mongodb-js/devtools-connect": "^3.7.2", "@mongosh/service-provider-node-driver": "^3.6.0", + "@modelcontextprotocol/sdk": "^1.8.0", "bson": "^6.10.3", "mongodb": "^6.15.0", "mongodb-log-writer": "^2.4.1", diff --git a/src/tools/mongodb/metadata/explain.ts b/src/tools/mongodb/metadata/explain.ts new file mode 100644 index 00000000..4a750a1f --- /dev/null +++ b/src/tools/mongodb/metadata/explain.ts @@ -0,0 +1,90 @@ +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs } from "../../tool.js"; +import { z } from "zod"; +import { ExplainVerbosity, Document } from "mongodb"; +import { AggregateArgs } from "../read/aggregate.js"; +import { FindArgs } from "../read/find.js"; +import { CountArgs } from "../read/count.js"; + +export class ExplainTool extends MongoDBToolBase { + protected name = "explain"; + protected description = + "Returns statistics describing the execution of the winning plan chosen by the query optimizer for the evaluated method"; + + protected argsShape = { + ...DbOperationArgs, + method: z + .array( + z.union([ + z.object({ + name: z.literal("aggregate"), + arguments: z.object(AggregateArgs), + }), + z.object({ + name: z.literal("find"), + arguments: z.object(FindArgs), + }), + z.object({ + name: z.literal("count"), + arguments: z.object(CountArgs), + }), + ]) + ) + .describe("The method and its arguments to run"), + }; + + protected operationType: DbOperationType = "metadata"; + + static readonly defaultVerbosity = ExplainVerbosity.queryPlanner; + + protected async execute({ + database, + collection, + method: methods, + }: ToolArgs): Promise { + const provider = await this.ensureConnected(); + const method = methods[0]; + + if (!method) { + throw new Error("No method provided"); + } + + let result: Document; + switch (method.name) { + case "aggregate": { + const { pipeline } = method.arguments; + result = await provider.aggregate(database, collection, pipeline).explain(ExplainTool.defaultVerbosity); + break; + } + case "find": { + const { filter, ...rest } = method.arguments; + result = await provider + .find(database, collection, filter as Document, { ...rest }) + .explain(ExplainTool.defaultVerbosity); + break; + } + case "count": { + const { query } = method.arguments; + // This helper doesn't have explain() command but does have the argument explain + result = (await provider.count(database, collection, query, { + explain: ExplainTool.defaultVerbosity, + })) as unknown as Document; + break; + } + } + + return { + content: [ + { + text: `Here is some information about the winning plan chosen by the query optimizer for running the given \`${method.name}\` operation in \`${database}.${collection}\`. This information can be used to understand how the query was executed and to optimize the query performance.`, + type: "text", + }, + { + text: JSON.stringify(result), + type: "text", + }, + ], + }; + } +} diff --git a/src/tools/mongodb/read/aggregate.ts b/src/tools/mongodb/read/aggregate.ts index 66bc1edb..abdbf70e 100644 --- a/src/tools/mongodb/read/aggregate.ts +++ b/src/tools/mongodb/read/aggregate.ts @@ -1,16 +1,19 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; +import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; import { ToolArgs } from "../../tool.js"; +export const AggregateArgs = { + pipeline: z.array(z.object({}).passthrough()).describe("An array of aggregation stages to execute"), + limit: z.number().optional().default(10).describe("The maximum number of documents to return"), +}; + export class AggregateTool extends MongoDBToolBase { protected name = "aggregate"; protected description = "Run an aggregation against a MongoDB collection"; protected argsShape = { - collection: z.string().describe("Collection name"), - database: z.string().describe("Database name"), - pipeline: z.array(z.object({}).passthrough()).describe("An array of aggregation stages to execute"), - limit: z.number().optional().default(10).describe("The maximum number of documents to return"), + ...DbOperationArgs, + ...AggregateArgs, }; protected operationType: DbOperationType = "read"; diff --git a/src/tools/mongodb/read/count.ts b/src/tools/mongodb/read/count.ts index 8c5f446d..63d052bb 100644 --- a/src/tools/mongodb/read/count.ts +++ b/src/tools/mongodb/read/count.ts @@ -3,18 +3,22 @@ import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbToo import { ToolArgs } from "../../tool.js"; import { z } from "zod"; +export const CountArgs = { + query: z + .object({}) + .passthrough() + .optional() + .describe( + "The query filter to count documents. Matches the syntax of the filter argument of db.collection.count()" + ), +}; + export class CountTool extends MongoDBToolBase { protected name = "count"; protected description = "Gets the number of documents in a MongoDB collection"; protected argsShape = { ...DbOperationArgs, - query: z - .object({}) - .passthrough() - .optional() - .describe( - "The query filter to count documents. Matches the syntax of the filter argument of db.collection.count()" - ), + ...CountArgs, }; protected operationType: DbOperationType = "metadata"; diff --git a/src/tools/mongodb/read/find.ts b/src/tools/mongodb/read/find.ts index 54edce8e..9893891a 100644 --- a/src/tools/mongodb/read/find.ts +++ b/src/tools/mongodb/read/find.ts @@ -1,32 +1,33 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; +import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; import { ToolArgs } from "../../tool.js"; import { SortDirection } from "mongodb"; +export const FindArgs = { + filter: z + .object({}) + .passthrough() + .optional() + .describe("The query filter, matching the syntax of the query argument of db.collection.find()"), + projection: z + .object({}) + .passthrough() + .optional() + .describe("The projection, matching the syntax of the projection argument of db.collection.find()"), + limit: z.number().optional().default(10).describe("The maximum number of documents to return"), + sort: z + .record(z.string(), z.custom()) + .optional() + .describe("A document, describing the sort order, matching the syntax of the sort argument of cursor.sort()"), +}; + export class FindTool extends MongoDBToolBase { protected name = "find"; protected description = "Run a find query against a MongoDB collection"; protected argsShape = { - collection: z.string().describe("Collection name"), - database: z.string().describe("Database name"), - filter: z - .object({}) - .passthrough() - .optional() - .describe("The query filter, matching the syntax of the query argument of db.collection.find()"), - projection: z - .object({}) - .passthrough() - .optional() - .describe("The projection, matching the syntax of the projection argument of db.collection.find()"), - limit: z.number().optional().default(10).describe("The maximum number of documents to return"), - sort: z - .record(z.string(), z.custom()) - .optional() - .describe( - "A document, describing the sort order, matching the syntax of the sort argument of cursor.sort()" - ), + ...DbOperationArgs, + ...FindArgs, }; protected operationType: DbOperationType = "read"; diff --git a/src/tools/mongodb/tools.ts b/src/tools/mongodb/tools.ts index 0f89335d..ac22e095 100644 --- a/src/tools/mongodb/tools.ts +++ b/src/tools/mongodb/tools.ts @@ -18,6 +18,7 @@ import { UpdateManyTool } from "./update/updateMany.js"; import { RenameCollectionTool } from "./update/renameCollection.js"; import { DropDatabaseTool } from "./delete/dropDatabase.js"; import { DropCollectionTool } from "./delete/dropCollection.js"; +import { ExplainTool } from "./metadata/explain.js"; export const MongoDbTools = [ ConnectTool, @@ -40,4 +41,5 @@ export const MongoDbTools = [ RenameCollectionTool, DropDatabaseTool, DropCollectionTool, + ExplainTool, ];