From fe9994f68a15e9b7425e0e3d33f1110deab0a26b Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Tue, 8 Apr 2025 13:59:06 +0200 Subject: [PATCH 1/4] Refactor the tool registration --- .vscode/launch.json | 17 ++ dist/client.js | 1 + dist/client.js.map | 1 + dist/config.js | 1 + dist/config.js.map | 1 + dist/index.js | 1 + dist/index.js.map | 1 + dist/logger.js | 5 + dist/logger.js.map | 1 + dist/server.js | 222 +---------------------- dist/server.js.map | 1 + dist/state.js | 1 + dist/state.js.map | 1 + dist/tools/atlas/atlasTool.js | 8 + dist/tools/atlas/atlasTool.js.map | 1 + dist/tools/atlas/auth.js | 79 +++++++++ dist/tools/atlas/auth.js.map | 1 + dist/tools/atlas/index.js | 14 ++ dist/tools/atlas/index.js.map | 1 + dist/tools/atlas/listClusters.js | 67 +++++++ dist/tools/atlas/listClusters.js.map | 1 + dist/tools/atlas/listProjects.js | 37 ++++ dist/tools/atlas/listProjects.js.map | 1 + dist/tools/mongodb/index.js | 2 + dist/tools/mongodb/index.js.map | 1 + dist/tools/tool.js | 47 +++++ dist/tools/tool.js.map | 1 + src/logger.ts | 4 + src/server.ts | 251 ++------------------------- src/tools/atlas/atlasTool.ts | 9 + src/tools/atlas/auth.ts | 86 +++++++++ src/tools/atlas/index.ts | 19 ++ src/tools/atlas/listClusters.ts | 86 +++++++++ src/tools/atlas/listProjects.ts | 39 +++++ src/tools/mongodb/index.ts | 4 + src/tools/tool.ts | 60 +++++++ tsconfig.json | 3 +- 37 files changed, 621 insertions(+), 455 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 dist/client.js.map create mode 100644 dist/config.js.map create mode 100644 dist/index.js.map create mode 100644 dist/logger.js create mode 100644 dist/logger.js.map create mode 100644 dist/server.js.map create mode 100644 dist/state.js.map create mode 100644 dist/tools/atlas/atlasTool.js create mode 100644 dist/tools/atlas/atlasTool.js.map create mode 100644 dist/tools/atlas/auth.js create mode 100644 dist/tools/atlas/auth.js.map create mode 100644 dist/tools/atlas/index.js create mode 100644 dist/tools/atlas/index.js.map create mode 100644 dist/tools/atlas/listClusters.js create mode 100644 dist/tools/atlas/listClusters.js.map create mode 100644 dist/tools/atlas/listProjects.js create mode 100644 dist/tools/atlas/listProjects.js.map create mode 100644 dist/tools/mongodb/index.js create mode 100644 dist/tools/mongodb/index.js.map create mode 100644 dist/tools/tool.js create mode 100644 dist/tools/tool.js.map create mode 100644 src/logger.ts create mode 100644 src/tools/atlas/atlasTool.ts create mode 100644 src/tools/atlas/auth.ts create mode 100644 src/tools/atlas/index.ts create mode 100644 src/tools/atlas/listClusters.ts create mode 100644 src/tools/atlas/listProjects.ts create mode 100644 src/tools/mongodb/index.ts create mode 100644 src/tools/tool.ts diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..a55e49ac --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "skipFiles": ["/**"], + "program": "${workspaceFolder}/dist/index.js", + "preLaunchTask": "tsc: build - tsconfig.json", + "outFiles": ["${workspaceFolder}/dist/**/*.js"] + } + ] +} diff --git a/dist/client.js b/dist/client.js index 6b589aa6..6bff7a39 100644 --- a/dist/client.js +++ b/dist/client.js @@ -223,3 +223,4 @@ export class ApiClient { return await this.do(`/clusters`); } } +//# sourceMappingURL=client.js.map \ No newline at end of file diff --git a/dist/client.js.map b/dist/client.js.map new file mode 100644 index 00000000..58e80b1b --- /dev/null +++ b/dist/client.js.map @@ -0,0 +1 @@ +{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/config.js b/dist/config.js index b3dcc181..7fb421be 100644 --- a/dist/config.js +++ b/dist/config.js @@ -7,3 +7,4 @@ export const config = { projectID: process.env.PROJECT_ID, }; export default config; +//# sourceMappingURL=config.js.map \ No newline at end of file diff --git a/dist/config.js.map b/dist/config.js.map new file mode 100644 index 00000000..e3dd8d58 --- /dev/null +++ b/dist/config.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,CAAC,MAAM,MAAM,GAAG;IAClB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO;IACvC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,4BAA4B;IACpE,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,sBAAsB;IACzD,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC;IACjE,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU;CACpC,CAAC;AAEF,eAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 868a3c8d..9d711694 100755 --- a/dist/index.js +++ b/dist/index.js @@ -10,3 +10,4 @@ runServer().catch((error) => { console.error(`Fatal error running server:`, error); process.exit(1); }); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/index.js.map b/dist/index.js.map new file mode 100644 index 00000000..fef0a94b --- /dev/null +++ b/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,KAAK,UAAU,SAAS;IACpB,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;IAE5B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACxB,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;IACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/logger.js b/dist/logger.js new file mode 100644 index 00000000..87d11479 --- /dev/null +++ b/dist/logger.js @@ -0,0 +1,5 @@ +// TODO: use a proper logger here +export function log(level, message) { + console.error(`[${level.toUpperCase()}] ${message}`); +} +//# sourceMappingURL=logger.js.map \ No newline at end of file diff --git a/dist/logger.js.map b/dist/logger.js.map new file mode 100644 index 00000000..154034d6 --- /dev/null +++ b/dist/logger.js.map @@ -0,0 +1 @@ +{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,MAAM,UAAU,GAAG,CAAC,KAAa,EAAE,OAAe;IAC9C,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,WAAW,EAAE,KAAK,OAAO,EAAE,CAAC,CAAC;AACzD,CAAC"} \ No newline at end of file diff --git a/dist/server.js b/dist/server.js index 8963ca2a..cdde83f2 100644 --- a/dist/server.js +++ b/dist/server.js @@ -1,19 +1,16 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z } from "zod"; import { ApiClient } from "./client.js"; import { saveState, loadState } from "./state.js"; -import { config } from "./config.js"; -function log(level, message) { - console.error(`[${level.toUpperCase()}] ${message}`); -} +import { registerAtlasTools } from "./tools/atlas/index.js"; +import { registerMongoDBTools } from "./tools/mongodb/index.js"; export class Server { constructor() { this.state = undefined; this.apiClient = undefined; - this.initiated = false; + this.initialized = false; } async init() { - if (this.initiated) { + if (this.initialized) { return; } this.state = await loadState(); @@ -29,203 +26,15 @@ export class Server { saveState(this.state); }, }); - this.initiated = true; - } - async ensureAuthenticated() { - switch (this.state.auth.status) { - case "not_auth": - return false; - case "requested": - try { - if (!this.state.auth.code) { - return false; - } - await this.apiClient.retrieveToken(this.state.auth.code.device_code); - return !!this.state.auth.token; - } - catch (error) { - return false; - } - case "issued": - if (!this.state.auth.token) { - return false; - } - return await this.apiClient.validateToken(); - default: - throw new Error("Unknown authentication status"); - } - } - async authTool() { - const auth = await this.ensureAuthenticated(); - if (auth) { - log("INFO", "Already authenticated!"); - return { - content: [{ type: "text", text: "You are already authenticated!" }], - }; - } - try { - const code = await this.apiClient.authenticate(); - this.state.auth.status = "requested"; - this.state.auth.code = code; - this.state.auth.token = undefined; - await saveState(this.state); - return { - content: [ - { - type: "text", - text: `Please authenticate by visiting ${code.verification_uri} and entering the code ${code.user_code}`, - }, - ], - }; - } - catch (error) { - if (error instanceof Error) { - log("error", `Authentication error: ${error}`); - return { - content: [{ type: "text", text: `Authentication failed: ${error.message}` }], - }; - } - else { - log("error", `Unknown authentication error: ${error}`); - return { - content: [{ type: "text", text: "Authentication failed due to an unknown error." }], - }; - } - } - } - async listClustersTool(projectId) { - try { - // Ensure user is authenticated or throw an error - const auth = await this.ensureAuthenticated(); - if (!auth) { - return { - content: [{ type: "text", text: "You need to be authenticated first" }], - }; - } - let clusters = undefined; - let introText = "Here are your MongoDB Atlas clusters:"; - const selectedProjectId = projectId || config.projectID; - if (!selectedProjectId) { - return { - content: [{ type: "text", text: "No project ID provided. Please specify a project ID." }], - }; - } - const project = await this.apiClient.getProject(selectedProjectId); - const data = await this.apiClient.listProjectClusters(project.id); - clusters = data.results || []; - try { - introText = `Here are the clusters in project "${project.name}" (${project.id}):`; - } - catch (e) { - log("error", `Error fetching project details: ${e}`); - } - if (clusters.length === 0) { - return { - content: [ - { - type: "text", - text: "No clusters found. You may need to create a cluster in your MongoDB Atlas account.", - }, - ], - }; - } - const formattedClusters = formatClustersTable(clusters); - return { - content: [ - { type: "text", text: introText }, - { type: "text", text: formattedClusters }, - ], - }; - } - catch (error) { - log("error", `Error listing clusters: ${error}`); - // If the error is authentication related, suggest using auth tool - if (error instanceof Error && error.message.includes("Not authenticated")) { - return { - content: [ - { type: "text", text: "You need to authenticate before listing clusters." }, - { type: "text", text: "Please use the 'auth' tool to log in to your MongoDB Atlas account." }, - ], - }; - } - return { - content: [ - { - type: "text", - text: `Error listing clusters: ${error instanceof Error ? error.message : String(error)}`, - }, - ], - }; - } - } - async listProjectsTool() { - try { - // Ensure user is authenticated or throw an error - const auth = await this.ensureAuthenticated(); - if (!auth) { - return { - content: [{ type: "text", text: "You need to be authenticated first" }], - }; - } - const projectsData = await this.apiClient.listProjects(); - const projects = projectsData.results || []; - if (!projects || projects.length === 0) { - return { - content: [{ type: "text", text: "No projects found in your MongoDB Atlas account." }], - }; - } - // Format projects as a table - const header = `Project Name | Project ID | Created At -----------------|----------------|----------------`; - const rows = projects - .map((project) => { - const createdAt = project.created ? new Date(project.created.$date).toLocaleString() : "N/A"; - return `${project.name} | ${project.id} | ${createdAt}`; - }) - .join("\n"); - const formattedProjects = `${header}\n${rows}`; - return { - content: [ - { type: "text", text: "Here are your MongoDB Atlas projects:" }, - { type: "text", text: formattedProjects }, - ], - }; - } - catch (error) { - log("error", `Error listing projects: ${error}`); - // If the error is authentication related, suggest using auth tool - if (error instanceof Error && error.message.includes("Not authenticated")) { - return { - content: [ - { type: "text", text: "You need to authenticate before listing projects." }, - { type: "text", text: "Please use the 'auth' tool to log in to your MongoDB Atlas account." }, - ], - }; - } - return { - content: [ - { - type: "text", - text: `Error listing projects: ${error instanceof Error ? error.message : String(error)}`, - }, - ], - }; - } + this.initialized = true; } mcpServer() { const server = new McpServer({ name: "MongoDB Atlas", version: process.env.VERSION || "1.0.0", }); - server.tool("auth", "Authenticate to Atlas", async ({}) => this.authTool()); - let projectIdFilter = z.string().describe("Optional Atlas project ID to filter clusters"); - if (config.projectID) { - projectIdFilter = projectIdFilter.optional(); - } - server.tool("list-clusters", "Lists MongoDB Atlas clusters", { - projectId: projectIdFilter, - }, async ({ projectId }) => this.listClustersTool(projectId)); - server.tool("list-projects", "Lists MongoDB Atlas projects", async () => this.listProjectsTool()); + registerAtlasTools(server, this.state, this.apiClient); + registerMongoDBTools(server, this.state); return server; } async connect(transport) { @@ -234,19 +43,4 @@ export class Server { await server.connect(transport); } } -function formatClustersTable(clusters) { - if (clusters.length === 0) { - return "No clusters found."; - } - const header = `Cluster Name | State | MongoDB Version | Region | Connection String -----------------|----------------|----------------|----------------|----------------|----------------`; - const rows = clusters - .map((cluster) => { - const region = cluster.providerSettings?.regionName || "N/A"; - const connectionString = cluster.connectionStrings?.standard || "N/A"; - const mongoDBVersion = cluster.mongoDBVersion || "N/A"; - return `${cluster.name} | ${cluster.stateName} | ${mongoDBVersion} | ${region} | ${connectionString}`; - }) - .join("\n"); - return `${header}\n${rows}`; -} +//# sourceMappingURL=server.js.map \ No newline at end of file diff --git a/dist/server.js.map b/dist/server.js.map new file mode 100644 index 00000000..1ca064e6 --- /dev/null +++ b/dist/server.js.map @@ -0,0 +1 @@ +{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAS,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE,MAAM,OAAO,MAAM;IAAnB;QACI,UAAK,GAAsB,SAAS,CAAC;QACrC,cAAS,GAA0B,SAAS,CAAC;QAC7C,gBAAW,GAAY,KAAK,CAAC;IA0CjC,CAAC;IAxCW,KAAK,CAAC,IAAI;QACd,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,OAAO;QACX,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;QAE/B,IAAI,CAAC,SAAS,GAAG,IAAI,SAAS,CAAC;YAC3B,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK;YAC7B,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;gBACjB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;oBACd,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;gBAChD,CAAC;gBACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;gBACjC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;gBAC9B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC;gBAClC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC;SACJ,CAAC,CAAC;QAEH,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC5B,CAAC;IAEO,SAAS;QACb,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;YACzB,IAAI,EAAE,eAAe;YACrB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO;SAC1C,CAAC,CAAC;QAEH,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,KAAM,EAAE,IAAI,CAAC,SAAU,CAAC,CAAC;QACzD,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,KAAM,CAAC,CAAC;QAE1C,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,SAAoB;QAC9B,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAEhC,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;CACJ"} \ No newline at end of file diff --git a/dist/state.js b/dist/state.js index 440cb98f..40c95478 100644 --- a/dist/state.js +++ b/dist/state.js @@ -31,3 +31,4 @@ export async function loadState() { }); }); } +//# sourceMappingURL=state.js.map \ No newline at end of file diff --git a/dist/state.js.map b/dist/state.js.map new file mode 100644 index 00000000..22cd93c8 --- /dev/null +++ b/dist/state.js.map @@ -0,0 +1 @@ +{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,MAAM,MAAM,aAAa,CAAC;AAWjC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAY;IACxC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG;YAC/D,IAAI,GAAG,EAAE,CAAC;gBACN,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,CAAC;YAED,OAAO,OAAO,EAAE,CAAC;QACrB,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC3B,OAAO,IAAI,OAAO,CAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;YACjD,IAAI,GAAG,EAAE,CAAC;gBACN,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACxB,4CAA4C;oBAC5C,MAAM,YAAY,GAAU;wBACxB,IAAI,EAAE;4BACF,MAAM,EAAE,UAAU;yBACrB;qBACJ,CAAC;oBACF,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC;gBACjC,CAAC;qBAAM,CAAC;oBACJ,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;gBACvB,CAAC;YACL,CAAC;YACD,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAU,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC"} \ No newline at end of file diff --git a/dist/tools/atlas/atlasTool.js b/dist/tools/atlas/atlasTool.js new file mode 100644 index 00000000..fa7a043b --- /dev/null +++ b/dist/tools/atlas/atlasTool.js @@ -0,0 +1,8 @@ +import { ToolBase } from "../tool.js"; +export class AtlasToolBase extends ToolBase { + constructor(apiClient) { + super(); + this.apiClient = apiClient; + } +} +//# sourceMappingURL=atlasTool.js.map \ No newline at end of file diff --git a/dist/tools/atlas/atlasTool.js.map b/dist/tools/atlas/atlasTool.js.map new file mode 100644 index 00000000..7e24b9bd --- /dev/null +++ b/dist/tools/atlas/atlasTool.js.map @@ -0,0 +1 @@ +{"version":3,"file":"atlasTool.js","sourceRoot":"","sources":["../../../src/tools/atlas/atlasTool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,MAAM,OAAgB,aAAwC,SAAQ,QAAc;IAChF,YAAsB,SAAoB;QACtC,KAAK,EAAE,CAAC;QADU,cAAS,GAAT,SAAS,CAAW;IAE1C,CAAC;CACJ"} \ No newline at end of file diff --git a/dist/tools/atlas/auth.js b/dist/tools/atlas/auth.js new file mode 100644 index 00000000..089eabc8 --- /dev/null +++ b/dist/tools/atlas/auth.js @@ -0,0 +1,79 @@ +import { log } from "../../logger.js"; +import { saveState } from "../../state.js"; +import { AtlasToolBase } from "./atlasTool.js"; +export async function ensureAuthenticated(state, apiClient) { + if (!(await isAuthenticated(state, apiClient))) { + throw new Error("Not authenticated"); + } +} +export async function isAuthenticated(state, apiClient) { + switch (state.auth.status) { + case "not_auth": + return false; + case "requested": + try { + if (!state.auth.code) { + return false; + } + await apiClient.retrieveToken(state.auth.code.device_code); + return !!state.auth.token; + } + catch (error) { + return false; + } + case "issued": + if (!state.auth.token) { + return false; + } + return await apiClient.validateToken(); + default: + throw new Error("Unknown authentication status"); + } +} +export class AuthTool extends AtlasToolBase { + constructor() { + super(...arguments); + this.name = "auth"; + this.description = "Authenticate to MongoDB Atlas"; + this.argsShape = {}; + } + async isAuthenticated() { + return isAuthenticated(this.state, this.apiClient); + } + async execute() { + if (await this.isAuthenticated()) { + log("INFO", "Already authenticated!"); + return { + content: [{ type: "text", text: "You are already authenticated!" }], + }; + } + try { + const code = await this.apiClient.authenticate(); + this.state.auth.status = "requested"; + this.state.auth.code = code; + this.state.auth.token = undefined; + await saveState(this.state); + return { + content: [ + { + type: "text", + text: `Please authenticate by visiting ${code.verification_uri} and entering the code ${code.user_code}`, + }, + ], + }; + } + catch (error) { + if (error instanceof Error) { + log("error", `Authentication error: ${error}`); + return { + content: [{ type: "text", text: `Authentication failed: ${error.message}` }], + }; + } + log("error", `Unknown authentication error: ${error}`); + return { + content: [{ type: "text", text: "Authentication failed due to an unknown error." }], + }; + } + } +} +//# sourceMappingURL=auth.js.map \ No newline at end of file diff --git a/dist/tools/atlas/auth.js.map b/dist/tools/atlas/auth.js.map new file mode 100644 index 00000000..9788b8b1 --- /dev/null +++ b/dist/tools/atlas/auth.js.map @@ -0,0 +1 @@ +{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/tools/atlas/auth.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/tools/atlas/index.js b/dist/tools/atlas/index.js new file mode 100644 index 00000000..47ab2911 --- /dev/null +++ b/dist/tools/atlas/index.js @@ -0,0 +1,14 @@ +import { AuthTool } from "./auth.js"; +import { ListClustersTool } from "./listClusters.js"; +import { ListProjectsTool } from "./listProjects.js"; +export function registerAtlasTools(server, state, apiClient) { + const tools = [ + new AuthTool(apiClient), + new ListClustersTool(apiClient), + new ListProjectsTool(apiClient), + ]; + for (const tool of tools) { + tool.register(server, state); + } +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/tools/atlas/index.js.map b/dist/tools/atlas/index.js.map new file mode 100644 index 00000000..c0243269 --- /dev/null +++ b/dist/tools/atlas/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/atlas/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,KAAY,EAAE,SAAoB;IACpF,MAAM,KAAK,GAAoB;QAC3B,IAAI,QAAQ,CAAC,SAAS,CAAC;QACvB,IAAI,gBAAgB,CAAC,SAAS,CAAC;QAC/B,IAAI,gBAAgB,CAAC,SAAS,CAAC;KAClC,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/dist/tools/atlas/listClusters.js b/dist/tools/atlas/listClusters.js new file mode 100644 index 00000000..f995e42b --- /dev/null +++ b/dist/tools/atlas/listClusters.js @@ -0,0 +1,67 @@ +import { z } from "zod"; +import { config } from "../../config.js"; +import { ensureAuthenticated } from "./auth.js"; +import { AtlasToolBase } from "./atlasTool.js"; +export class ListClustersTool extends AtlasToolBase { + constructor(apiClient) { + super(apiClient); + this.name = "listClusters"; + this.description = "List MongoDB Atlas clusters"; + let projectIdFilter = z.string().describe("Optional Atlas project ID to filter clusters"); + if (config.projectID) { + projectIdFilter = projectIdFilter.optional(); + } + this.argsShape = { + projectId: projectIdFilter, + }; + } + async execute({ projectId }) { + await ensureAuthenticated(this.state, this.apiClient); + let clusters = undefined; + let introText = "Here are your MongoDB Atlas clusters:"; + const selectedProjectId = projectId || config.projectID; + if (!selectedProjectId) { + return { + content: [{ type: "text", text: "No project ID provided. Please specify a project ID." }], + }; + } + const project = await this.apiClient.getProject(selectedProjectId); + const data = await this.apiClient.listProjectClusters(project.id); + clusters = data.results || []; + introText = `Here are the clusters in project "${project.name}" (${project.id}):`; + if (clusters.length === 0) { + return { + content: [ + { + type: "text", + text: "No clusters found. You may need to create a cluster in your MongoDB Atlas account.", + }, + ], + }; + } + const formattedClusters = this.formatClustersTable(clusters); + return { + content: [ + { type: "text", text: introText }, + { type: "text", text: formattedClusters }, + ], + }; + } + formatClustersTable(clusters) { + if (clusters.length === 0) { + return "No clusters found."; + } + const header = `Cluster Name | State | MongoDB Version | Region | Connection String + ----------------|----------------|----------------|----------------|----------------|----------------`; + const rows = clusters + .map((cluster) => { + const region = cluster.providerSettings?.regionName || "N/A"; + const connectionString = cluster.connectionStrings?.standard || "N/A"; + const mongoDBVersion = cluster.mongoDBVersion || "N/A"; + return `${cluster.name} | ${cluster.stateName} | ${mongoDBVersion} | ${region} | ${connectionString}`; + }) + .join("\n"); + return `${header}\n${rows}`; + } +} +//# sourceMappingURL=listClusters.js.map \ No newline at end of file diff --git a/dist/tools/atlas/listClusters.js.map b/dist/tools/atlas/listClusters.js.map new file mode 100644 index 00000000..cb34481a --- /dev/null +++ b/dist/tools/atlas/listClusters.js.map @@ -0,0 +1 @@ +{"version":3,"file":"listClusters.js","sourceRoot":"","sources":["../../../src/tools/atlas/listClusters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAa,MAAM,KAAK,CAAC;AAEnC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,OAAO,gBAAiB,SAAQ,aAEpC;IAKE,YAAY,SAAoB;QAC5B,KAAK,CAAC,SAAS,CAAC,CAAC;QALX,SAAI,GAAG,cAAc,CAAC;QACtB,gBAAW,GAAG,6BAA6B,CAAC;QAMlD,IAAI,eAAe,GAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC,CAAC;QAE/F,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACnB,eAAe,GAAG,eAAe,CAAC,QAAQ,EAAE,CAAC;QACjD,CAAC;QAED,IAAI,CAAC,SAAS,GAAG;YACb,SAAS,EAAE,eAAe;SAC7B,CAAC;IACN,CAAC;IAES,KAAK,CAAC,OAAO,CAAC,EAAE,SAAS,EAAyB;QACxD,MAAM,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAEtD,IAAI,QAAQ,GAA+B,SAAS,CAAC;QACrD,IAAI,SAAS,GAAG,uCAAuC,CAAC;QAExD,MAAM,iBAAiB,GAAG,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC;QACxD,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACrB,OAAO;gBACH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,sDAAsD,EAAE,CAAC;aAC5F,CAAC;QACN,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;QAEnE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAClE,QAAQ,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;QAE9B,SAAS,GAAG,qCAAqC,OAAO,CAAC,IAAI,MAAM,OAAO,CAAC,EAAE,IAAI,CAAC;QAElF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO;gBACH,OAAO,EAAE;oBACL;wBACI,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,oFAAoF;qBAC7F;iBACJ;aACJ,CAAC;QACN,CAAC;QAED,MAAM,iBAAiB,GAAG,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAE7D,OAAO;YACH,OAAO,EAAE;gBACL,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE;gBACjC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE;aAC5C;SACJ,CAAC;IACN,CAAC;IAEO,mBAAmB,CAAC,QAAwB;QAChD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,oBAAoB,CAAC;QAChC,CAAC;QACD,MAAM,MAAM,GAAG;0GACmF,CAAC;QACnG,MAAM,IAAI,GAAG,QAAQ;aAChB,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;YACb,MAAM,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,UAAU,IAAI,KAAK,CAAC;YAC7D,MAAM,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,EAAE,QAAQ,IAAI,KAAK,CAAC;YACtE,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,KAAK,CAAC;YACvD,OAAO,GAAG,OAAO,CAAC,IAAI,MAAM,OAAO,CAAC,SAAS,MAAM,cAAc,MAAM,MAAM,MAAM,gBAAgB,EAAE,CAAC;QAC1G,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;QAChB,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE,CAAC;IAChC,CAAC;CACJ"} \ No newline at end of file diff --git a/dist/tools/atlas/listProjects.js b/dist/tools/atlas/listProjects.js new file mode 100644 index 00000000..6a5ecf91 --- /dev/null +++ b/dist/tools/atlas/listProjects.js @@ -0,0 +1,37 @@ +import { ensureAuthenticated } from "./auth.js"; +import { AtlasToolBase } from "./atlasTool.js"; +export class ListProjectsTool extends AtlasToolBase { + constructor() { + super(...arguments); + this.name = "listProjects"; + this.description = "List MongoDB Atlas projects"; + this.argsShape = {}; + } + async execute() { + await ensureAuthenticated(this.state, this.apiClient); + const projectsData = await this.apiClient.listProjects(); + const projects = projectsData.results || []; + if (projects.length === 0) { + return { + content: [{ type: "text", text: "No projects found in your MongoDB Atlas account." }], + }; + } + // Format projects as a table + const header = `Project Name | Project ID | Created At +----------------|----------------|----------------`; + const rows = projects + .map((project) => { + const createdAt = project.created ? new Date(project.created.$date).toLocaleString() : "N/A"; + return `${project.name} | ${project.id} | ${createdAt}`; + }) + .join("\n"); + const formattedProjects = `${header}\n${rows}`; + return { + content: [ + { type: "text", text: "Here are your MongoDB Atlas projects:" }, + { type: "text", text: formattedProjects }, + ], + }; + } +} +//# sourceMappingURL=listProjects.js.map \ No newline at end of file diff --git a/dist/tools/atlas/listProjects.js.map b/dist/tools/atlas/listProjects.js.map new file mode 100644 index 00000000..7f545603 --- /dev/null +++ b/dist/tools/atlas/listProjects.js.map @@ -0,0 +1 @@ +{"version":3,"file":"listProjects.js","sourceRoot":"","sources":["../../../src/tools/atlas/listProjects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,OAAO,gBAAiB,SAAQ,aAAiB;IAAvD;;QACc,SAAI,GAAG,cAAc,CAAC;QACtB,gBAAW,GAAG,6BAA6B,CAAC;QAC5C,cAAS,GAAG,EAAE,CAAC;IA+B7B,CAAC;IA7Ba,KAAK,CAAC,OAAO;QACnB,MAAM,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAEtD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,SAAU,CAAC,YAAY,EAAE,CAAC;QAC1D,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,IAAI,EAAE,CAAC;QAE5C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO;gBACH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kDAAkD,EAAE,CAAC;aACxF,CAAC;QACN,CAAC;QAED,6BAA6B;QAC7B,MAAM,MAAM,GAAG;mDAC4B,CAAC;QAC5C,MAAM,IAAI,GAAG,QAAQ;aAChB,GAAG,CAAC,CAAC,OAAY,EAAE,EAAE;YAClB,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;YAC7F,OAAO,GAAG,OAAO,CAAC,IAAI,MAAM,OAAO,CAAC,EAAE,MAAM,SAAS,EAAE,CAAC;QAC5D,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;QAChB,MAAM,iBAAiB,GAAG,GAAG,MAAM,KAAK,IAAI,EAAE,CAAC;QAC/C,OAAO;YACH,OAAO,EAAE;gBACL,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,uCAAuC,EAAE;gBAC/D,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE;aAC5C;SACJ,CAAC;IACN,CAAC;CACJ"} \ No newline at end of file diff --git a/dist/tools/mongodb/index.js b/dist/tools/mongodb/index.js new file mode 100644 index 00000000..62877634 --- /dev/null +++ b/dist/tools/mongodb/index.js @@ -0,0 +1,2 @@ +export function registerMongoDBTools(server, state) { } +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/tools/mongodb/index.js.map b/dist/tools/mongodb/index.js.map new file mode 100644 index 00000000..1eb74df5 --- /dev/null +++ b/dist/tools/mongodb/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/mongodb/index.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,KAAY,IAAG,CAAC"} \ No newline at end of file diff --git a/dist/tools/tool.js b/dist/tools/tool.js new file mode 100644 index 00000000..33278ee0 --- /dev/null +++ b/dist/tools/tool.js @@ -0,0 +1,47 @@ +import { log } from "../logger.js"; +export class ToolBase { + constructor() { + this.state = undefined; // We should never use this before it's set + } + register(server, state) { + this.state = state; + const callback = async (args) => { + try { + // TODO: add telemetry here + return await this.execute(args); + } + catch (error) { + log("error", `Error executing ${this.name}: ${error}`); + // If the error is authentication related, suggest using auth tool + if (error instanceof Error && error.message.includes("Not authenticated")) { + return { + content: [ + { type: "text", text: "You need to authenticate before accessing Atlas data." }, + { + type: "text", + text: "Please use the 'auth' tool to log in to your MongoDB Atlas account.", + }, + ], + }; + } + return { + content: [ + { + type: "text", + text: `Error running ${this.name}: ${error instanceof Error ? error.message : String(error)}`, + }, + ], + isError: true, + }; + } + }; + if (this.argsShape) { + // Not sure why typescript doesn't like the type signature of callback. + server.tool(this.name, this.description, this.argsShape, callback); + } + else { + server.tool(this.name, this.description, callback); + } + } +} +//# sourceMappingURL=tool.js.map \ No newline at end of file diff --git a/dist/tools/tool.js.map b/dist/tools/tool.js.map new file mode 100644 index 00000000..1af80acd --- /dev/null +++ b/dist/tools/tool.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/tools/tool.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAInC,MAAM,OAAgB,QAAQ;IAA9B;QACc,UAAK,GAAU,SAAU,CAAC,CAAC,2CAA2C;IAoDpF,CAAC;IA3CU,QAAQ,CAAC,MAAiB,EAAE,KAAY;QAC3C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QAEnB,MAAM,QAAQ,GAAG,KAAK,EAAE,IAA0C,EAA2B,EAAE;YAC3F,IAAI,CAAC;gBACD,2BAA2B;gBAE3B,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACpC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,GAAG,CAAC,OAAO,EAAE,mBAAmB,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC;gBAEvD,kEAAkE;gBAClE,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;oBACxE,OAAO;wBACH,OAAO,EAAE;4BACL,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,uDAAuD,EAAE;4BAC/E;gCACI,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,qEAAqE;6BAC9E;yBACJ;qBACJ,CAAC;gBACN,CAAC;gBAED,OAAO;oBACH,OAAO,EAAE;wBACL;4BACI,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,iBAAiB,IAAI,CAAC,IAAI,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;yBAChG;qBACJ;oBACD,OAAO,EAAE,IAAI;iBAChB,CAAC;YACN,CAAC;QACL,CAAC,CAAC;QAEF,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,uEAAuE;YACvE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,EAAE,QAAe,CAAC,CAAC;QAC9E,CAAC;aAAM,CAAC;YACJ,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,QAAe,CAAC,CAAC;QAC9D,CAAC;IACL,CAAC;CACJ"} \ No newline at end of file diff --git a/src/logger.ts b/src/logger.ts new file mode 100644 index 00000000..4e7f6f08 --- /dev/null +++ b/src/logger.ts @@ -0,0 +1,4 @@ +// TODO: use a proper logger here +export function log(level: string, message: string) { + console.error(`[${level.toUpperCase()}] ${message}`); +} diff --git a/src/server.ts b/src/server.ts index d7dcd65a..3cdb8bf4 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,21 +1,17 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { z } from "zod"; -import { ApiClient, AtlasCluster, AtlasResponse } from "./client.js"; +import { ApiClient } from "./client.js"; import { State, saveState, loadState } from "./state.js"; -import { config } from "./config.js"; - -function log(level: string, message: string) { - console.error(`[${level.toUpperCase()}] ${message}`); -} +import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js"; +import { registerAtlasTools } from "./tools/atlas/index.js"; +import { registerMongoDBTools } from "./tools/mongodb/index.js"; export class Server { state: State | undefined = undefined; apiClient: ApiClient | undefined = undefined; - initiated: boolean = false; + initialized: boolean = false; private async init() { - if (this.initiated) { + if (this.initialized) { return; } this.state = await loadState(); @@ -33,202 +29,7 @@ export class Server { }, }); - this.initiated = true; - } - - private async ensureAuthenticated() { - switch (this.state!.auth.status) { - case "not_auth": - return false; - case "requested": - try { - if (!this.state!.auth.code) { - return false; - } - await this.apiClient!.retrieveToken(this.state!.auth.code.device_code); - return !!this.state!.auth.token; - } catch (error) { - return false; - } - case "issued": - if (!this.state!.auth.token) { - return false; - } - return await this.apiClient!.validateToken(); - default: - throw new Error("Unknown authentication status"); - } - } - - private async authTool(): Promise { - const auth = await this.ensureAuthenticated(); - if (auth) { - log("INFO", "Already authenticated!"); - return { - content: [{ type: "text", text: "You are already authenticated!" }], - }; - } - - try { - const code = await this.apiClient!.authenticate(); - - this.state!.auth.status = "requested"; - this.state!.auth.code = code; - this.state!.auth.token = undefined; - - await saveState(this.state!); - - return { - content: [ - { - type: "text", - text: `Please authenticate by visiting ${code.verification_uri} and entering the code ${code.user_code}`, - }, - ], - }; - } catch (error: unknown) { - if (error instanceof Error) { - log("error", `Authentication error: ${error}`); - return { - content: [{ type: "text", text: `Authentication failed: ${error.message}` }], - }; - } else { - log("error", `Unknown authentication error: ${error}`); - return { - content: [{ type: "text", text: "Authentication failed due to an unknown error." }], - }; - } - } - } - private async listClustersTool(projectId?: string): Promise { - try { - // Ensure user is authenticated or throw an error - const auth = await this.ensureAuthenticated(); - if (!auth) { - return { - content: [{ type: "text", text: "You need to be authenticated first" }], - }; - } - - let clusters: AtlasCluster[] | undefined = undefined; - let introText = "Here are your MongoDB Atlas clusters:"; - - const selectedProjectId = projectId || config.projectID; - if (!selectedProjectId) { - return { - content: [{ type: "text", text: "No project ID provided. Please specify a project ID." }], - }; - } - const project = await this.apiClient!.getProject(selectedProjectId); - - const data = await this.apiClient!.listProjectClusters(project.id); - clusters = data.results || []; - - try { - introText = `Here are the clusters in project "${project.name}" (${project.id}):`; - } catch (e) { - log("error", `Error fetching project details: ${e}`); - } - - if (clusters.length === 0) { - return { - content: [ - { - type: "text", - text: "No clusters found. You may need to create a cluster in your MongoDB Atlas account.", - }, - ], - }; - } - - const formattedClusters = formatClustersTable(clusters); - - return { - content: [ - { type: "text", text: introText }, - { type: "text", text: formattedClusters }, - ], - }; - } catch (error) { - log("error", `Error listing clusters: ${error}`); - - // If the error is authentication related, suggest using auth tool - if (error instanceof Error && error.message.includes("Not authenticated")) { - return { - content: [ - { type: "text", text: "You need to authenticate before listing clusters." }, - { type: "text", text: "Please use the 'auth' tool to log in to your MongoDB Atlas account." }, - ], - }; - } - - return { - content: [ - { - type: "text", - text: `Error listing clusters: ${error instanceof Error ? error.message : String(error)}`, - }, - ], - }; - } - } - private async listProjectsTool(): Promise { - try { - // Ensure user is authenticated or throw an error - const auth = await this.ensureAuthenticated(); - if (!auth) { - return { - content: [{ type: "text", text: "You need to be authenticated first" }], - }; - } - - const projectsData = await this.apiClient!.listProjects(); - const projects = projectsData.results || []; - - if (!projects || projects.length === 0) { - return { - content: [{ type: "text", text: "No projects found in your MongoDB Atlas account." }], - }; - } - - // Format projects as a table - const header = `Project Name | Project ID | Created At -----------------|----------------|----------------`; - const rows = projects - .map((project: any) => { - const createdAt = project.created ? new Date(project.created.$date).toLocaleString() : "N/A"; - return `${project.name} | ${project.id} | ${createdAt}`; - }) - .join("\n"); - const formattedProjects = `${header}\n${rows}`; - return { - content: [ - { type: "text", text: "Here are your MongoDB Atlas projects:" }, - { type: "text", text: formattedProjects }, - ], - }; - } catch (error) { - log("error", `Error listing projects: ${error}`); - - // If the error is authentication related, suggest using auth tool - if (error instanceof Error && error.message.includes("Not authenticated")) { - return { - content: [ - { type: "text", text: "You need to authenticate before listing projects." }, - { type: "text", text: "Please use the 'auth' tool to log in to your MongoDB Atlas account." }, - ], - }; - } - - return { - content: [ - { - type: "text", - text: `Error listing projects: ${error instanceof Error ? error.message : String(error)}`, - }, - ], - }; - } + this.initialized = true; } private mcpServer(): McpServer { @@ -237,46 +38,16 @@ export class Server { version: process.env.VERSION || "1.0.0", }); - server.tool("auth", "Authenticate to Atlas", async ({}) => this.authTool()); - - let projectIdFilter: any = z.string().describe("Optional Atlas project ID to filter clusters"); - if (config.projectID) { - projectIdFilter = projectIdFilter.optional(); - } - - server.tool( - "list-clusters", - "Lists MongoDB Atlas clusters", - { - projectId: projectIdFilter, - }, - async ({ projectId }: { projectId?: string }) => this.listClustersTool(projectId) - ); - server.tool("list-projects", "Lists MongoDB Atlas projects", async () => this.listProjectsTool()); + registerAtlasTools(server, this.state!, this.apiClient!); + registerMongoDBTools(server, this.state!); return server; } - async connect(transport: any) { + async connect(transport: Transport) { await this.init(); const server = this.mcpServer(); - await server.connect(transport); - } -} -function formatClustersTable(clusters: AtlasCluster[]): string { - if (clusters.length === 0) { - return "No clusters found."; + await server.connect(transport); } - const header = `Cluster Name | State | MongoDB Version | Region | Connection String -----------------|----------------|----------------|----------------|----------------|----------------`; - const rows = clusters - .map((cluster) => { - const region = cluster.providerSettings?.regionName || "N/A"; - const connectionString = cluster.connectionStrings?.standard || "N/A"; - const mongoDBVersion = cluster.mongoDBVersion || "N/A"; - return `${cluster.name} | ${cluster.stateName} | ${mongoDBVersion} | ${region} | ${connectionString}`; - }) - .join("\n"); - return `${header}\n${rows}`; } diff --git a/src/tools/atlas/atlasTool.ts b/src/tools/atlas/atlasTool.ts new file mode 100644 index 00000000..c9fee302 --- /dev/null +++ b/src/tools/atlas/atlasTool.ts @@ -0,0 +1,9 @@ +import { ZodRawShape } from "zod"; +import { ToolBase } from "../tool.js"; +import { ApiClient } from "../../client.js"; + +export abstract class AtlasToolBase extends ToolBase { + constructor(protected apiClient: ApiClient) { + super(); + } +} diff --git a/src/tools/atlas/auth.ts b/src/tools/atlas/auth.ts new file mode 100644 index 00000000..240f07ea --- /dev/null +++ b/src/tools/atlas/auth.ts @@ -0,0 +1,86 @@ +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { ApiClient } from "../../client.js"; +import { log } from "../../logger.js"; +import { saveState } from "../../state.js"; +import { State } from "../../state.js"; +import { AtlasToolBase } from "./atlasTool.js"; + +export async function ensureAuthenticated(state: State, apiClient: ApiClient): Promise { + if (!(await isAuthenticated(state, apiClient))) { + throw new Error("Not authenticated"); + } +} + +export async function isAuthenticated(state: State, apiClient: ApiClient): Promise { + switch (state.auth.status) { + case "not_auth": + return false; + case "requested": + try { + if (!state.auth.code) { + return false; + } + await apiClient.retrieveToken(state.auth.code.device_code); + return !!state.auth.token; + } catch (error) { + return false; + } + case "issued": + if (!state.auth.token) { + return false; + } + return await apiClient.validateToken(); + default: + throw new Error("Unknown authentication status"); + } +} + +export class AuthTool extends AtlasToolBase<{}> { + protected name = "auth"; + protected description = "Authenticate to MongoDB Atlas"; + protected argsShape = {}; + + private async isAuthenticated(): Promise { + return isAuthenticated(this.state!, this.apiClient); + } + + async execute(): Promise { + if (await this.isAuthenticated()) { + log("INFO", "Already authenticated!"); + return { + content: [{ type: "text", text: "You are already authenticated!" }], + }; + } + + try { + const code = await this.apiClient.authenticate(); + + this.state!.auth.status = "requested"; + this.state!.auth.code = code; + this.state!.auth.token = undefined; + + await saveState(this.state!); + + return { + content: [ + { + type: "text", + text: `Please authenticate by visiting ${code.verification_uri} and entering the code ${code.user_code}`, + }, + ], + }; + } catch (error: unknown) { + if (error instanceof Error) { + log("error", `Authentication error: ${error}`); + return { + content: [{ type: "text", text: `Authentication failed: ${error.message}` }], + }; + } + + log("error", `Unknown authentication error: ${error}`); + return { + content: [{ type: "text", text: "Authentication failed due to an unknown error." }], + }; + } + } +} diff --git a/src/tools/atlas/index.ts b/src/tools/atlas/index.ts new file mode 100644 index 00000000..791b4a82 --- /dev/null +++ b/src/tools/atlas/index.ts @@ -0,0 +1,19 @@ +import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { State } from "../../state.js"; +import { ApiClient } from "../../client.js"; +import { ToolBase } from "../tool.js"; +import { AuthTool } from "./auth.js"; +import { ListClustersTool } from "./listClusters.js"; +import { ListProjectsTool } from "./listProjects.js"; + +export function registerAtlasTools(server: McpServer, state: State, apiClient: ApiClient) { + const tools: ToolBase[] = [ + new AuthTool(apiClient), + new ListClustersTool(apiClient), + new ListProjectsTool(apiClient), + ]; + + for (const tool of tools) { + tool.register(server, state); + } +} diff --git a/src/tools/atlas/listClusters.ts b/src/tools/atlas/listClusters.ts new file mode 100644 index 00000000..ef740978 --- /dev/null +++ b/src/tools/atlas/listClusters.ts @@ -0,0 +1,86 @@ +import { z, ZodString } from "zod"; +import { ApiClient, AtlasCluster } from "../../client.js"; +import { config } from "../../config.js"; +import { ensureAuthenticated } from "./auth.js"; +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { AtlasToolBase } from "./atlasTool.js"; + +export class ListClustersTool extends AtlasToolBase<{ + projectId: ZodString; +}> { + protected name = "listClusters"; + protected description = "List MongoDB Atlas clusters"; + protected argsShape; + + constructor(apiClient: ApiClient) { + super(apiClient); + + let projectIdFilter: any = z.string().describe("Optional Atlas project ID to filter clusters"); + + if (config.projectID) { + projectIdFilter = projectIdFilter.optional(); + } + + this.argsShape = { + projectId: projectIdFilter, + }; + } + + protected async execute({ projectId }: { projectId: string }): Promise { + await ensureAuthenticated(this.state, this.apiClient); + + let clusters: AtlasCluster[] | undefined = undefined; + let introText = "Here are your MongoDB Atlas clusters:"; + + const selectedProjectId = projectId || config.projectID; + if (!selectedProjectId) { + return { + content: [{ type: "text", text: "No project ID provided. Please specify a project ID." }], + }; + } + + const project = await this.apiClient.getProject(selectedProjectId); + + const data = await this.apiClient.listProjectClusters(project.id); + clusters = data.results || []; + + introText = `Here are the clusters in project "${project.name}" (${project.id}):`; + + if (clusters.length === 0) { + return { + content: [ + { + type: "text", + text: "No clusters found. You may need to create a cluster in your MongoDB Atlas account.", + }, + ], + }; + } + + const formattedClusters = this.formatClustersTable(clusters); + + return { + content: [ + { type: "text", text: introText }, + { type: "text", text: formattedClusters }, + ], + }; + } + + private formatClustersTable(clusters: AtlasCluster[]): string { + if (clusters.length === 0) { + return "No clusters found."; + } + const header = `Cluster Name | State | MongoDB Version | Region | Connection String + ----------------|----------------|----------------|----------------|----------------|----------------`; + const rows = clusters + .map((cluster) => { + const region = cluster.providerSettings?.regionName || "N/A"; + const connectionString = cluster.connectionStrings?.standard || "N/A"; + const mongoDBVersion = cluster.mongoDBVersion || "N/A"; + return `${cluster.name} | ${cluster.stateName} | ${mongoDBVersion} | ${region} | ${connectionString}`; + }) + .join("\n"); + return `${header}\n${rows}`; + } +} diff --git a/src/tools/atlas/listProjects.ts b/src/tools/atlas/listProjects.ts new file mode 100644 index 00000000..d74e2d8d --- /dev/null +++ b/src/tools/atlas/listProjects.ts @@ -0,0 +1,39 @@ +import { ensureAuthenticated } from "./auth.js"; +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { AtlasToolBase } from "./atlasTool.js"; + +export class ListProjectsTool extends AtlasToolBase<{}> { + protected name = "listProjects"; + protected description = "List MongoDB Atlas projects"; + protected argsShape = {}; + + protected async execute(): Promise { + await ensureAuthenticated(this.state, this.apiClient); + + const projectsData = await this.apiClient!.listProjects(); + const projects = projectsData.results || []; + + if (projects.length === 0) { + return { + content: [{ type: "text", text: "No projects found in your MongoDB Atlas account." }], + }; + } + + // Format projects as a table + const header = `Project Name | Project ID | Created At +----------------|----------------|----------------`; + const rows = projects + .map((project: any) => { + const createdAt = project.created ? new Date(project.created.$date).toLocaleString() : "N/A"; + return `${project.name} | ${project.id} | ${createdAt}`; + }) + .join("\n"); + const formattedProjects = `${header}\n${rows}`; + return { + content: [ + { type: "text", text: "Here are your MongoDB Atlas projects:" }, + { type: "text", text: formattedProjects }, + ], + }; + } +} diff --git a/src/tools/mongodb/index.ts b/src/tools/mongodb/index.ts new file mode 100644 index 00000000..ae58e18b --- /dev/null +++ b/src/tools/mongodb/index.ts @@ -0,0 +1,4 @@ +import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { State } from "../../state.js"; + +export function registerMongoDBTools(server: McpServer, state: State) {} diff --git a/src/tools/tool.ts b/src/tools/tool.ts new file mode 100644 index 00000000..b3d2ecc3 --- /dev/null +++ b/src/tools/tool.ts @@ -0,0 +1,60 @@ +import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { z, ZodRawShape, ZodTypeAny } from "zod"; +import { log } from "../logger.js"; +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { State } from "../state.js"; + +export abstract class ToolBase { + protected state: State = undefined!; // We should never use this before it's set + protected abstract name: string; + + protected abstract description: string; + + protected abstract argsShape: Args; + + protected abstract execute(args: z.objectOutputType): Promise; + + public register(server: McpServer, state: State): void { + this.state = state; + + const callback = async (args: z.objectOutputType): Promise => { + try { + // TODO: add telemetry here + + return await this.execute(args); + } catch (error) { + log("error", `Error executing ${this.name}: ${error}`); + + // If the error is authentication related, suggest using auth tool + if (error instanceof Error && error.message.includes("Not authenticated")) { + return { + content: [ + { type: "text", text: "You need to authenticate before accessing Atlas data." }, + { + type: "text", + text: "Please use the 'auth' tool to log in to your MongoDB Atlas account.", + }, + ], + }; + } + + return { + content: [ + { + type: "text", + text: `Error running ${this.name}: ${error instanceof Error ? error.message : String(error)}`, + }, + ], + isError: true, + }; + } + }; + + if (this.argsShape) { + // Not sure why typescript doesn't like the type signature of callback. + server.tool(this.name, this.description, this.argsShape, callback as any); + } else { + server.tool(this.name, this.description, callback as any); + } + } +} diff --git a/tsconfig.json b/tsconfig.json index 432f7b6b..c41240df 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,8 @@ "outDir": "./dist", "strict": true, "esModuleInterop": true, - "types": ["node"] + "types": ["node"], + "sourceMap": true }, "include": ["src/**/*.ts"] } From 14144913734095a30b5a263575ea93e6c79c3a54 Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Tue, 8 Apr 2025 14:27:44 +0200 Subject: [PATCH 2/4] fix lint errors --- dist/tools/atlas/atlasTool.js.map | 2 +- dist/tools/atlas/auth.js | 2 +- dist/tools/atlas/auth.js.map | 2 +- dist/tools/atlas/index.js.map | 2 +- dist/tools/atlas/listClusters.js | 4 +++- dist/tools/atlas/listClusters.js.map | 2 +- dist/tools/atlas/listProjects.js.map | 2 +- dist/tools/mongodb/index.js | 1 + dist/tools/mongodb/index.js.map | 2 +- dist/tools/tool.js | 2 ++ dist/tools/tool.js.map | 2 +- eslint.config.js | 3 ++- src/tools/atlas/atlasTool.ts | 2 +- src/tools/atlas/auth.ts | 4 ++-- src/tools/atlas/index.ts | 3 ++- src/tools/atlas/listClusters.ts | 8 +++++--- src/tools/atlas/listProjects.ts | 4 ++-- src/tools/mongodb/index.ts | 1 + src/tools/tool.ts | 2 ++ 19 files changed, 31 insertions(+), 19 deletions(-) diff --git a/dist/tools/atlas/atlasTool.js.map b/dist/tools/atlas/atlasTool.js.map index 7e24b9bd..f0da29f4 100644 --- a/dist/tools/atlas/atlasTool.js.map +++ b/dist/tools/atlas/atlasTool.js.map @@ -1 +1 @@ -{"version":3,"file":"atlasTool.js","sourceRoot":"","sources":["../../../src/tools/atlas/atlasTool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,MAAM,OAAgB,aAAwC,SAAQ,QAAc;IAChF,YAAsB,SAAoB;QACtC,KAAK,EAAE,CAAC;QADU,cAAS,GAAT,SAAS,CAAW;IAE1C,CAAC;CACJ"} \ No newline at end of file +{"version":3,"file":"atlasTool.js","sourceRoot":"","sources":["../../../src/tools/atlas/atlasTool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,MAAM,OAAgB,aAAsD,SAAQ,QAAc;IAC9F,YAAsB,SAAoB;QACtC,KAAK,EAAE,CAAC;QADU,cAAS,GAAT,SAAS,CAAW;IAE1C,CAAC;CACJ"} \ No newline at end of file diff --git a/dist/tools/atlas/auth.js b/dist/tools/atlas/auth.js index 089eabc8..7de01981 100644 --- a/dist/tools/atlas/auth.js +++ b/dist/tools/atlas/auth.js @@ -18,7 +18,7 @@ export async function isAuthenticated(state, apiClient) { await apiClient.retrieveToken(state.auth.code.device_code); return !!state.auth.token; } - catch (error) { + catch { return false; } case "issued": diff --git a/dist/tools/atlas/auth.js.map b/dist/tools/atlas/auth.js.map index 9788b8b1..2068eaad 100644 --- a/dist/tools/atlas/auth.js.map +++ b/dist/tools/atlas/auth.js.map @@ -1 +1 @@ -{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/tools/atlas/auth.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/tools/atlas/auth.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/tools/atlas/index.js.map b/dist/tools/atlas/index.js.map index c0243269..adef7f29 100644 --- a/dist/tools/atlas/index.js.map +++ b/dist/tools/atlas/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/atlas/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,KAAY,EAAE,SAAoB;IACpF,MAAM,KAAK,GAAoB;QAC3B,IAAI,QAAQ,CAAC,SAAS,CAAC;QACvB,IAAI,gBAAgB,CAAC,SAAS,CAAC;QAC/B,IAAI,gBAAgB,CAAC,SAAS,CAAC;KAClC,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;AACL,CAAC"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/atlas/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGrD,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,KAAY,EAAE,SAAoB;IACpF,MAAM,KAAK,GAA4B;QACnC,IAAI,QAAQ,CAAC,SAAS,CAAC;QACvB,IAAI,gBAAgB,CAAC,SAAS,CAAC;QAC/B,IAAI,gBAAgB,CAAC,SAAS,CAAC;KAClC,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/dist/tools/atlas/listClusters.js b/dist/tools/atlas/listClusters.js index f995e42b..c6f1ac37 100644 --- a/dist/tools/atlas/listClusters.js +++ b/dist/tools/atlas/listClusters.js @@ -7,7 +7,9 @@ export class ListClustersTool extends AtlasToolBase { super(apiClient); this.name = "listClusters"; this.description = "List MongoDB Atlas clusters"; - let projectIdFilter = z.string().describe("Optional Atlas project ID to filter clusters"); + let projectIdFilter = z + .string() + .describe("Optional Atlas project ID to filter clusters"); if (config.projectID) { projectIdFilter = projectIdFilter.optional(); } diff --git a/dist/tools/atlas/listClusters.js.map b/dist/tools/atlas/listClusters.js.map index cb34481a..51965c6a 100644 --- a/dist/tools/atlas/listClusters.js.map +++ b/dist/tools/atlas/listClusters.js.map @@ -1 +1 @@ -{"version":3,"file":"listClusters.js","sourceRoot":"","sources":["../../../src/tools/atlas/listClusters.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"listClusters.js","sourceRoot":"","sources":["../../../src/tools/atlas/listClusters.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/tools/atlas/listProjects.js.map b/dist/tools/atlas/listProjects.js.map index 7f545603..0f78775d 100644 --- a/dist/tools/atlas/listProjects.js.map +++ b/dist/tools/atlas/listProjects.js.map @@ -1 +1 @@ -{"version":3,"file":"listProjects.js","sourceRoot":"","sources":["../../../src/tools/atlas/listProjects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,OAAO,gBAAiB,SAAQ,aAAiB;IAAvD;;QACc,SAAI,GAAG,cAAc,CAAC;QACtB,gBAAW,GAAG,6BAA6B,CAAC;QAC5C,cAAS,GAAG,EAAE,CAAC;IA+B7B,CAAC;IA7Ba,KAAK,CAAC,OAAO;QACnB,MAAM,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAEtD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,SAAU,CAAC,YAAY,EAAE,CAAC;QAC1D,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,IAAI,EAAE,CAAC;QAE5C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO;gBACH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kDAAkD,EAAE,CAAC;aACxF,CAAC;QACN,CAAC;QAED,6BAA6B;QAC7B,MAAM,MAAM,GAAG;mDAC4B,CAAC;QAC5C,MAAM,IAAI,GAAG,QAAQ;aAChB,GAAG,CAAC,CAAC,OAAY,EAAE,EAAE;YAClB,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;YAC7F,OAAO,GAAG,OAAO,CAAC,IAAI,MAAM,OAAO,CAAC,EAAE,MAAM,SAAS,EAAE,CAAC;QAC5D,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;QAChB,MAAM,iBAAiB,GAAG,GAAG,MAAM,KAAK,IAAI,EAAE,CAAC;QAC/C,OAAO;YACH,OAAO,EAAE;gBACL,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,uCAAuC,EAAE;gBAC/D,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE;aAC5C;SACJ,CAAC;IACN,CAAC;CACJ"} \ No newline at end of file +{"version":3,"file":"listProjects.js","sourceRoot":"","sources":["../../../src/tools/atlas/listProjects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,OAAO,gBAAiB,SAAQ,aAAa;IAAnD;;QACc,SAAI,GAAG,cAAc,CAAC;QACtB,gBAAW,GAAG,6BAA6B,CAAC;QAC5C,cAAS,GAAG,EAAE,CAAC;IA+B7B,CAAC;IA7Ba,KAAK,CAAC,OAAO;QACnB,MAAM,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAEtD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,SAAU,CAAC,YAAY,EAAE,CAAC;QAC1D,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,IAAI,EAAE,CAAC;QAE5C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO;gBACH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kDAAkD,EAAE,CAAC;aACxF,CAAC;QACN,CAAC;QAED,6BAA6B;QAC7B,MAAM,MAAM,GAAG;mDAC4B,CAAC;QAC5C,MAAM,IAAI,GAAG,QAAQ;aAChB,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;YACb,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;YAC7F,OAAO,GAAG,OAAO,CAAC,IAAI,MAAM,OAAO,CAAC,EAAE,MAAM,SAAS,EAAE,CAAC;QAC5D,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;QAChB,MAAM,iBAAiB,GAAG,GAAG,MAAM,KAAK,IAAI,EAAE,CAAC;QAC/C,OAAO;YACH,OAAO,EAAE;gBACL,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,uCAAuC,EAAE;gBAC/D,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE;aAC5C;SACJ,CAAC;IACN,CAAC;CACJ"} \ No newline at end of file diff --git a/dist/tools/mongodb/index.js b/dist/tools/mongodb/index.js index 62877634..16af8455 100644 --- a/dist/tools/mongodb/index.js +++ b/dist/tools/mongodb/index.js @@ -1,2 +1,3 @@ +// eslint-disable-next-line @typescript-eslint/no-unused-vars export function registerMongoDBTools(server, state) { } //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/tools/mongodb/index.js.map b/dist/tools/mongodb/index.js.map index 1eb74df5..abc9f807 100644 --- a/dist/tools/mongodb/index.js.map +++ b/dist/tools/mongodb/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/mongodb/index.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,KAAY,IAAG,CAAC"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/mongodb/index.ts"],"names":[],"mappings":"AAGA,6DAA6D;AAC7D,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,KAAY,IAAG,CAAC"} \ No newline at end of file diff --git a/dist/tools/tool.js b/dist/tools/tool.js index 33278ee0..4f34b781 100644 --- a/dist/tools/tool.js +++ b/dist/tools/tool.js @@ -37,9 +37,11 @@ export class ToolBase { }; if (this.argsShape) { // Not sure why typescript doesn't like the type signature of callback. + // eslint-disable-next-line @typescript-eslint/no-explicit-any server.tool(this.name, this.description, this.argsShape, callback); } else { + // eslint-disable-next-line @typescript-eslint/no-explicit-any server.tool(this.name, this.description, callback); } } diff --git a/dist/tools/tool.js.map b/dist/tools/tool.js.map index 1af80acd..8258c42a 100644 --- a/dist/tools/tool.js.map +++ b/dist/tools/tool.js.map @@ -1 +1 @@ -{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/tools/tool.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAInC,MAAM,OAAgB,QAAQ;IAA9B;QACc,UAAK,GAAU,SAAU,CAAC,CAAC,2CAA2C;IAoDpF,CAAC;IA3CU,QAAQ,CAAC,MAAiB,EAAE,KAAY;QAC3C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QAEnB,MAAM,QAAQ,GAAG,KAAK,EAAE,IAA0C,EAA2B,EAAE;YAC3F,IAAI,CAAC;gBACD,2BAA2B;gBAE3B,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACpC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,GAAG,CAAC,OAAO,EAAE,mBAAmB,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC;gBAEvD,kEAAkE;gBAClE,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;oBACxE,OAAO;wBACH,OAAO,EAAE;4BACL,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,uDAAuD,EAAE;4BAC/E;gCACI,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,qEAAqE;6BAC9E;yBACJ;qBACJ,CAAC;gBACN,CAAC;gBAED,OAAO;oBACH,OAAO,EAAE;wBACL;4BACI,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,iBAAiB,IAAI,CAAC,IAAI,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;yBAChG;qBACJ;oBACD,OAAO,EAAE,IAAI;iBAChB,CAAC;YACN,CAAC;QACL,CAAC,CAAC;QAEF,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,uEAAuE;YACvE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,EAAE,QAAe,CAAC,CAAC;QAC9E,CAAC;aAAM,CAAC;YACJ,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,QAAe,CAAC,CAAC;QAC9D,CAAC;IACL,CAAC;CACJ"} \ No newline at end of file +{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/tools/tool.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAInC,MAAM,OAAgB,QAAQ;IAA9B;QACc,UAAK,GAAU,SAAU,CAAC,CAAC,2CAA2C;IAsDpF,CAAC;IA7CU,QAAQ,CAAC,MAAiB,EAAE,KAAY;QAC3C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QAEnB,MAAM,QAAQ,GAAG,KAAK,EAAE,IAA0C,EAA2B,EAAE;YAC3F,IAAI,CAAC;gBACD,2BAA2B;gBAE3B,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACpC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,GAAG,CAAC,OAAO,EAAE,mBAAmB,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC;gBAEvD,kEAAkE;gBAClE,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;oBACxE,OAAO;wBACH,OAAO,EAAE;4BACL,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,uDAAuD,EAAE;4BAC/E;gCACI,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,qEAAqE;6BAC9E;yBACJ;qBACJ,CAAC;gBACN,CAAC;gBAED,OAAO;oBACH,OAAO,EAAE;wBACL;4BACI,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,iBAAiB,IAAI,CAAC,IAAI,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;yBAChG;qBACJ;oBACD,OAAO,EAAE,IAAI;iBAChB,CAAC;YACN,CAAC;QACL,CAAC,CAAC;QAEF,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,uEAAuE;YACvE,8DAA8D;YAC9D,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,EAAE,QAAe,CAAC,CAAC;QAC9E,CAAC;aAAM,CAAC;YACJ,8DAA8D;YAC9D,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,QAAe,CAAC,CAAC;QAC9D,CAAC;IACL,CAAC;CACJ"} \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js index 279b709f..e93a22bf 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,4 +1,4 @@ -import { defineConfig } from "eslint/config"; +import { defineConfig, globalIgnores } from "eslint/config"; import js from "@eslint/js"; import globals from "globals"; import tseslint from "typescript-eslint"; @@ -9,4 +9,5 @@ export default defineConfig([ { files: ["src/**/*.ts"], languageOptions: { globals: globals.node } }, tseslint.configs.recommended, eslintConfigPrettier, + globalIgnores(["node_modules", "dist"]), ]); diff --git a/src/tools/atlas/atlasTool.ts b/src/tools/atlas/atlasTool.ts index c9fee302..f0547a54 100644 --- a/src/tools/atlas/atlasTool.ts +++ b/src/tools/atlas/atlasTool.ts @@ -2,7 +2,7 @@ import { ZodRawShape } from "zod"; import { ToolBase } from "../tool.js"; import { ApiClient } from "../../client.js"; -export abstract class AtlasToolBase extends ToolBase { +export abstract class AtlasToolBase extends ToolBase { constructor(protected apiClient: ApiClient) { super(); } diff --git a/src/tools/atlas/auth.ts b/src/tools/atlas/auth.ts index 240f07ea..d8db34f9 100644 --- a/src/tools/atlas/auth.ts +++ b/src/tools/atlas/auth.ts @@ -22,7 +22,7 @@ export async function isAuthenticated(state: State, apiClient: ApiClient): Promi } await apiClient.retrieveToken(state.auth.code.device_code); return !!state.auth.token; - } catch (error) { + } catch { return false; } case "issued": @@ -35,7 +35,7 @@ export async function isAuthenticated(state: State, apiClient: ApiClient): Promi } } -export class AuthTool extends AtlasToolBase<{}> { +export class AuthTool extends AtlasToolBase { protected name = "auth"; protected description = "Authenticate to MongoDB Atlas"; protected argsShape = {}; diff --git a/src/tools/atlas/index.ts b/src/tools/atlas/index.ts index 791b4a82..598c17af 100644 --- a/src/tools/atlas/index.ts +++ b/src/tools/atlas/index.ts @@ -5,9 +5,10 @@ import { ToolBase } from "../tool.js"; import { AuthTool } from "./auth.js"; import { ListClustersTool } from "./listClusters.js"; import { ListProjectsTool } from "./listProjects.js"; +import { ZodRawShape } from "zod"; export function registerAtlasTools(server: McpServer, state: State, apiClient: ApiClient) { - const tools: ToolBase[] = [ + const tools: ToolBase[] = [ new AuthTool(apiClient), new ListClustersTool(apiClient), new ListProjectsTool(apiClient), diff --git a/src/tools/atlas/listClusters.ts b/src/tools/atlas/listClusters.ts index ef740978..916c12ef 100644 --- a/src/tools/atlas/listClusters.ts +++ b/src/tools/atlas/listClusters.ts @@ -1,4 +1,4 @@ -import { z, ZodString } from "zod"; +import { z, ZodOptional, ZodString } from "zod"; import { ApiClient, AtlasCluster } from "../../client.js"; import { config } from "../../config.js"; import { ensureAuthenticated } from "./auth.js"; @@ -6,7 +6,7 @@ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { AtlasToolBase } from "./atlasTool.js"; export class ListClustersTool extends AtlasToolBase<{ - projectId: ZodString; + projectId: ZodString | ZodOptional; }> { protected name = "listClusters"; protected description = "List MongoDB Atlas clusters"; @@ -15,7 +15,9 @@ export class ListClustersTool extends AtlasToolBase<{ constructor(apiClient: ApiClient) { super(apiClient); - let projectIdFilter: any = z.string().describe("Optional Atlas project ID to filter clusters"); + let projectIdFilter: ZodString | ZodOptional = z + .string() + .describe("Optional Atlas project ID to filter clusters"); if (config.projectID) { projectIdFilter = projectIdFilter.optional(); diff --git a/src/tools/atlas/listProjects.ts b/src/tools/atlas/listProjects.ts index d74e2d8d..e3f4af04 100644 --- a/src/tools/atlas/listProjects.ts +++ b/src/tools/atlas/listProjects.ts @@ -2,7 +2,7 @@ import { ensureAuthenticated } from "./auth.js"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { AtlasToolBase } from "./atlasTool.js"; -export class ListProjectsTool extends AtlasToolBase<{}> { +export class ListProjectsTool extends AtlasToolBase { protected name = "listProjects"; protected description = "List MongoDB Atlas projects"; protected argsShape = {}; @@ -23,7 +23,7 @@ export class ListProjectsTool extends AtlasToolBase<{}> { const header = `Project Name | Project ID | Created At ----------------|----------------|----------------`; const rows = projects - .map((project: any) => { + .map((project) => { const createdAt = project.created ? new Date(project.created.$date).toLocaleString() : "N/A"; return `${project.name} | ${project.id} | ${createdAt}`; }) diff --git a/src/tools/mongodb/index.ts b/src/tools/mongodb/index.ts index ae58e18b..5b6d1360 100644 --- a/src/tools/mongodb/index.ts +++ b/src/tools/mongodb/index.ts @@ -1,4 +1,5 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { State } from "../../state.js"; +// eslint-disable-next-line @typescript-eslint/no-unused-vars export function registerMongoDBTools(server: McpServer, state: State) {} diff --git a/src/tools/tool.ts b/src/tools/tool.ts index b3d2ecc3..db084d31 100644 --- a/src/tools/tool.ts +++ b/src/tools/tool.ts @@ -52,8 +52,10 @@ export abstract class ToolBase { if (this.argsShape) { // Not sure why typescript doesn't like the type signature of callback. + // eslint-disable-next-line @typescript-eslint/no-explicit-any server.tool(this.name, this.description, this.argsShape, callback as any); } else { + // eslint-disable-next-line @typescript-eslint/no-explicit-any server.tool(this.name, this.description, callback as any); } } From e2103231349a0945022f1943797566cb8a365cdb Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Tue, 8 Apr 2025 16:00:46 +0200 Subject: [PATCH 3/4] Remove /dist --- dist/client.js | 226 ------------------------- dist/client.js.map | 1 - dist/config.js | 14 -- dist/config.js.map | 1 - dist/index.js | 13 -- dist/index.js.map | 1 - dist/logger.js | 5 - dist/logger.js.map | 1 - dist/server.js | 47 ----- dist/server.js.map | 1 - dist/state.js | 34 ---- dist/state.js.map | 1 - dist/tools/atlas/atlasTool.js | 8 - dist/tools/atlas/atlasTool.js.map | 1 - dist/tools/atlas/auth.js | 79 --------- dist/tools/atlas/auth.js.map | 1 - dist/tools/atlas/index.js | 14 -- dist/tools/atlas/index.js.map | 1 - dist/tools/atlas/listClusters.js | 69 -------- dist/tools/atlas/listClusters.js.map | 1 - dist/tools/atlas/listProjects.js | 37 ---- dist/tools/atlas/listProjects.js.map | 1 - dist/tools/mongodb/index.js | 3 - dist/tools/mongodb/index.js.map | 1 - dist/tools/tool.js | 49 ------ dist/tools/tool.js.map | 1 - src/server.ts | 2 +- src/tools/atlas/{index.ts => tools.ts} | 6 +- 28 files changed, 4 insertions(+), 615 deletions(-) delete mode 100644 dist/client.js delete mode 100644 dist/client.js.map delete mode 100644 dist/config.js delete mode 100644 dist/config.js.map delete mode 100755 dist/index.js delete mode 100644 dist/index.js.map delete mode 100644 dist/logger.js delete mode 100644 dist/logger.js.map delete mode 100644 dist/server.js delete mode 100644 dist/server.js.map delete mode 100644 dist/state.js delete mode 100644 dist/state.js.map delete mode 100644 dist/tools/atlas/atlasTool.js delete mode 100644 dist/tools/atlas/atlasTool.js.map delete mode 100644 dist/tools/atlas/auth.js delete mode 100644 dist/tools/atlas/auth.js.map delete mode 100644 dist/tools/atlas/index.js delete mode 100644 dist/tools/atlas/index.js.map delete mode 100644 dist/tools/atlas/listClusters.js delete mode 100644 dist/tools/atlas/listClusters.js.map delete mode 100644 dist/tools/atlas/listProjects.js delete mode 100644 dist/tools/atlas/listProjects.js.map delete mode 100644 dist/tools/mongodb/index.js delete mode 100644 dist/tools/mongodb/index.js.map delete mode 100644 dist/tools/tool.js delete mode 100644 dist/tools/tool.js.map rename src/tools/atlas/{index.ts => tools.ts} (100%) diff --git a/dist/client.js b/dist/client.js deleted file mode 100644 index cc602ee7..00000000 --- a/dist/client.js +++ /dev/null @@ -1,226 +0,0 @@ -import config from "./config.js"; -export class ApiClientError extends Error { - constructor(message, response = undefined) { - super(message); - this.name = "ApiClientError"; - this.response = response; - } -} -export class ApiClient { - constructor(options) { - const { token, saveToken } = options; - this.token = token; - this.saveToken = saveToken; - } - defaultOptions() { - const authHeaders = !this.token?.access_token - ? null - : { - Authorization: `Bearer ${this.token.access_token}`, - }; - return { - method: "GET", - credentials: !this.token?.access_token ? undefined : "include", - headers: { - "Content-Type": "application/json", - Accept: "application/vnd.atlas.2025-04-07+json", - "User-Agent": config.userAgent, - ...authHeaders, - }, - }; - } - async storeToken(token) { - this.token = token; - if (this.saveToken) { - await this.saveToken(token); - } - return token; - } - async do(endpoint, options) { - if (!this.token || !this.token.access_token) { - throw new Error("Not authenticated. Please run the auth tool first."); - } - const url = new URL(`api/atlas/v2${endpoint}`, `${config.apiBaseURL}`); - if (!this.checkTokenExpiry()) { - await this.refreshToken(); - } - const defaultOpt = this.defaultOptions(); - const opt = { - ...defaultOpt, - ...options, - headers: { - ...defaultOpt.headers, - ...options?.headers, - }, - }; - const response = await fetch(url, opt); - if (!response.ok) { - throw new ApiClientError(`Error calling Atlas API: ${response.statusText}`, response); - } - return (await response.json()); - } - async authenticate() { - const endpoint = "api/private/unauth/account/device/authorize"; - const authUrl = new URL(endpoint, config.apiBaseURL); - const response = await fetch(authUrl, { - method: "POST", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - Accept: "application/json", - }, - body: new URLSearchParams({ - client_id: config.clientID, - scope: "openid profile offline_access", - grant_type: "urn:ietf:params:oauth:grant-type:device_code", - }).toString(), - }); - if (!response.ok) { - throw new ApiClientError(`Failed to initiate authentication: ${response.statusText}`, response); - } - return (await response.json()); - } - async retrieveToken(device_code) { - const endpoint = "api/private/unauth/account/device/token"; - const url = new URL(endpoint, config.apiBaseURL); - const response = await fetch(url, { - method: "POST", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - }, - body: new URLSearchParams({ - client_id: config.clientID, - device_code: device_code, - grant_type: "urn:ietf:params:oauth:grant-type:device_code", - }).toString(), - }); - if (response.ok) { - const tokenData = await response.json(); - const buf = Buffer.from(tokenData.access_token.split(".")[1], "base64").toString(); - const jwt = JSON.parse(buf); - const expiry = new Date(jwt.exp * 1000); - return await this.storeToken({ ...tokenData, expiry }); - } - try { - const errorResponse = await response.json(); - if (errorResponse.errorCode === "DEVICE_AUTHORIZATION_PENDING") { - throw new ApiClientError("Authentication pending. Try again later.", response); - } - else if (errorResponse.error === "expired_token") { - throw new ApiClientError("Device code expired. Please restart the authentication process.", response); - } - else { - throw new ApiClientError("Device code expired. Please restart the authentication process.", response); - } - } - catch { - throw new ApiClientError("Failed to retrieve token. Please check your device code.", response); - } - } - async refreshToken(token) { - const endpoint = "api/private/unauth/account/device/token"; - const url = new URL(endpoint, config.apiBaseURL); - const response = await fetch(url, { - method: "POST", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - Accept: "application/json", - }, - body: new URLSearchParams({ - client_id: config.clientID, - refresh_token: (token || this.token)?.refresh_token || "", - grant_type: "refresh_token", - scope: "openid profile offline_access", - }).toString(), - }); - if (!response.ok) { - throw new ApiClientError(`Failed to refresh token: ${response.statusText}`, response); - } - const data = await response.json(); - const buf = Buffer.from(data.access_token.split(".")[1], "base64").toString(); - const jwt = JSON.parse(buf); - const expiry = new Date(jwt.exp * 1000); - const tokenToStore = { - ...data, - expiry, - }; - return await this.storeToken(tokenToStore); - } - async revokeToken(token) { - const endpoint = "api/private/unauth/account/device/token"; - const url = new URL(endpoint, config.apiBaseURL); - const response = await fetch(url, { - method: "POST", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - Accept: "application/json", - "User-Agent": config.userAgent, - }, - body: new URLSearchParams({ - client_id: config.clientID, - token: (token || this.token)?.access_token || "", - token_type_hint: "refresh_token", - }).toString(), - }); - if (!response.ok) { - throw new ApiClientError(`Failed to revoke token: ${response.statusText}`, response); - } - if (!token && this.token) { - this.token = undefined; - } - return; - } - checkTokenExpiry(token) { - try { - token = token || this.token; - if (!token || !token.access_token) { - return false; - } - if (!token.expiry) { - return false; - } - const expiryDelta = 10 * 1000; // 10 seconds in milliseconds - const expiryWithDelta = new Date(token.expiry.getTime() - expiryDelta); - return expiryWithDelta.getTime() > Date.now(); - } - catch { - return false; - } - } - async validateToken(token) { - if (this.checkTokenExpiry(token)) { - return true; - } - try { - await this.refreshToken(token); - return true; - } - catch { - return false; - } - } - /** - * Get all projects for the authenticated user - */ - async listProjects() { - return await this.do("/groups"); - } - /** - * Get a specific project by ID - */ - async getProject(projectId) { - return await this.do(`/groups/${projectId}`); - } - /** - * Get clusters for a specific project - */ - async listProjectClusters(projectId) { - return await this.do(`/groups/${projectId}/clusters`); - } - /** - * Get clusters for a specific project - */ - async listAllClusters() { - return await this.do(`/clusters`); - } -} -//# sourceMappingURL=client.js.map \ No newline at end of file diff --git a/dist/client.js.map b/dist/client.js.map deleted file mode 100644 index 268b387e..00000000 --- a/dist/client.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/config.js b/dist/config.js deleted file mode 100644 index cbac4674..00000000 --- a/dist/config.js +++ /dev/null @@ -1,14 +0,0 @@ -import path from "path"; -import fs from "fs"; -const packageMetadata = fs.readFileSync(path.resolve("./package.json"), "utf8"); -const packageJson = JSON.parse(packageMetadata); -export const config = { - version: packageJson.version, - apiBaseURL: process.env.API_BASE_URL || "https://cloud.mongodb.com/", - clientID: process.env.CLIENT_ID || "0oabtxactgS3gHIR0297", - stateFile: process.env.STATE_FILE || path.resolve("./state.json"), - projectID: process.env.PROJECT_ID, - userAgent: `AtlasMCP/${packageJson.version} (${process.platform}; ${process.arch}; ${process.env.HOSTNAME || "unknown"})`, -}; -export default config; -//# sourceMappingURL=config.js.map \ No newline at end of file diff --git a/dist/config.js.map b/dist/config.js.map deleted file mode 100644 index 5b9fa4fc..00000000 --- a/dist/config.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,eAAe,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC,CAAC;AAChF,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;AAEhD,MAAM,CAAC,MAAM,MAAM,GAAG;IAClB,OAAO,EAAE,WAAW,CAAC,OAAO;IAC5B,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,4BAA4B;IACpE,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,sBAAsB;IACzD,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC;IACjE,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU;IACjC,SAAS,EAAE,YAAY,WAAW,CAAC,OAAO,KAAK,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,SAAS,GAAG;CAC5H,CAAC;AAEF,eAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js deleted file mode 100755 index 9d711694..00000000 --- a/dist/index.js +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env node -import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; -import { Server } from "./server.js"; -async function runServer() { - const server = new Server(); - const transport = new StdioServerTransport(); - await server.connect(transport); -} -runServer().catch((error) => { - console.error(`Fatal error running server:`, error); - process.exit(1); -}); -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/index.js.map b/dist/index.js.map deleted file mode 100644 index fef0a94b..00000000 --- a/dist/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,KAAK,UAAU,SAAS;IACpB,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;IAE5B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACxB,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;IACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/logger.js b/dist/logger.js deleted file mode 100644 index 87d11479..00000000 --- a/dist/logger.js +++ /dev/null @@ -1,5 +0,0 @@ -// TODO: use a proper logger here -export function log(level, message) { - console.error(`[${level.toUpperCase()}] ${message}`); -} -//# sourceMappingURL=logger.js.map \ No newline at end of file diff --git a/dist/logger.js.map b/dist/logger.js.map deleted file mode 100644 index 154034d6..00000000 --- a/dist/logger.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,MAAM,UAAU,GAAG,CAAC,KAAa,EAAE,OAAe;IAC9C,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,WAAW,EAAE,KAAK,OAAO,EAAE,CAAC,CAAC;AACzD,CAAC"} \ No newline at end of file diff --git a/dist/server.js b/dist/server.js deleted file mode 100644 index 8f99a31a..00000000 --- a/dist/server.js +++ /dev/null @@ -1,47 +0,0 @@ -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { ApiClient } from "./client.js"; -import { saveState, loadState } from "./state.js"; -import { registerAtlasTools } from "./tools/atlas/index.js"; -import { registerMongoDBTools } from "./tools/mongodb/index.js"; -import { config } from "./config.js"; -export class Server { - constructor() { - this.state = undefined; - this.apiClient = undefined; - this.initialized = false; - } - async init() { - if (this.initialized) { - return; - } - this.state = await loadState(); - this.apiClient = new ApiClient({ - token: this.state?.auth.token, - saveToken: (token) => { - if (!this.state) { - throw new Error("State is not initialized"); - } - this.state.auth.code = undefined; - this.state.auth.token = token; - this.state.auth.status = "issued"; - saveState(this.state); - }, - }); - this.initialized = true; - } - createMcpServer() { - const server = new McpServer({ - name: "MongoDB Atlas", - version: config.version, - }); - registerAtlasTools(server, this.state, this.apiClient); - registerMongoDBTools(server, this.state); - return server; - } - async connect(transport) { - await this.init(); - const server = this.createMcpServer(); - await server.connect(transport); - } -} -//# sourceMappingURL=server.js.map \ No newline at end of file diff --git a/dist/server.js.map b/dist/server.js.map deleted file mode 100644 index 72dfbe33..00000000 --- a/dist/server.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAS,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,OAAO,MAAM;IAAnB;QACI,UAAK,GAAsB,SAAS,CAAC;QACrC,cAAS,GAA0B,SAAS,CAAC;QAC7C,gBAAW,GAAY,KAAK,CAAC;IAyCjC,CAAC;IAvCW,KAAK,CAAC,IAAI;QACd,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,OAAO;QACX,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;QAE/B,IAAI,CAAC,SAAS,GAAG,IAAI,SAAS,CAAC;YAC3B,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK;YAC7B,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;gBACjB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;oBACd,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;gBAChD,CAAC;gBACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;gBACjC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;gBAC9B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC;gBAClC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC;SACJ,CAAC,CAAC;QAEH,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC5B,CAAC;IAEO,eAAe;QACnB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;YACzB,IAAI,EAAE,eAAe;YACrB,OAAO,EAAE,MAAM,CAAC,OAAO;SAC1B,CAAC,CAAC;QAEH,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,KAAM,EAAE,IAAI,CAAC,SAAU,CAAC,CAAC;QACzD,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,KAAM,CAAC,CAAC;QAE1C,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,SAAoB;QAC9B,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QACtC,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;CACJ"} \ No newline at end of file diff --git a/dist/state.js b/dist/state.js deleted file mode 100644 index 40c95478..00000000 --- a/dist/state.js +++ /dev/null @@ -1,34 +0,0 @@ -import fs from "fs"; -import config from "./config.js"; -export async function saveState(state) { - return new Promise((resolve, reject) => { - fs.writeFile(config.stateFile, JSON.stringify(state), function (err) { - if (err) { - return reject(err); - } - return resolve(); - }); - }); -} -export async function loadState() { - return new Promise((resolve, reject) => { - fs.readFile(config.stateFile, "utf-8", (err, data) => { - if (err) { - if (err.code === "ENOENT") { - // File does not exist, return default state - const defaultState = { - auth: { - status: "not_auth", - }, - }; - return resolve(defaultState); - } - else { - return reject(err); - } - } - return resolve(JSON.parse(data)); - }); - }); -} -//# sourceMappingURL=state.js.map \ No newline at end of file diff --git a/dist/state.js.map b/dist/state.js.map deleted file mode 100644 index 22cd93c8..00000000 --- a/dist/state.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,MAAM,MAAM,aAAa,CAAC;AAWjC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAY;IACxC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG;YAC/D,IAAI,GAAG,EAAE,CAAC;gBACN,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,CAAC;YAED,OAAO,OAAO,EAAE,CAAC;QACrB,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC3B,OAAO,IAAI,OAAO,CAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;YACjD,IAAI,GAAG,EAAE,CAAC;gBACN,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACxB,4CAA4C;oBAC5C,MAAM,YAAY,GAAU;wBACxB,IAAI,EAAE;4BACF,MAAM,EAAE,UAAU;yBACrB;qBACJ,CAAC;oBACF,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC;gBACjC,CAAC;qBAAM,CAAC;oBACJ,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;gBACvB,CAAC;YACL,CAAC;YACD,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAU,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC"} \ No newline at end of file diff --git a/dist/tools/atlas/atlasTool.js b/dist/tools/atlas/atlasTool.js deleted file mode 100644 index fa7a043b..00000000 --- a/dist/tools/atlas/atlasTool.js +++ /dev/null @@ -1,8 +0,0 @@ -import { ToolBase } from "../tool.js"; -export class AtlasToolBase extends ToolBase { - constructor(apiClient) { - super(); - this.apiClient = apiClient; - } -} -//# sourceMappingURL=atlasTool.js.map \ No newline at end of file diff --git a/dist/tools/atlas/atlasTool.js.map b/dist/tools/atlas/atlasTool.js.map deleted file mode 100644 index f0da29f4..00000000 --- a/dist/tools/atlas/atlasTool.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"atlasTool.js","sourceRoot":"","sources":["../../../src/tools/atlas/atlasTool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,MAAM,OAAgB,aAAsD,SAAQ,QAAc;IAC9F,YAAsB,SAAoB;QACtC,KAAK,EAAE,CAAC;QADU,cAAS,GAAT,SAAS,CAAW;IAE1C,CAAC;CACJ"} \ No newline at end of file diff --git a/dist/tools/atlas/auth.js b/dist/tools/atlas/auth.js deleted file mode 100644 index 7de01981..00000000 --- a/dist/tools/atlas/auth.js +++ /dev/null @@ -1,79 +0,0 @@ -import { log } from "../../logger.js"; -import { saveState } from "../../state.js"; -import { AtlasToolBase } from "./atlasTool.js"; -export async function ensureAuthenticated(state, apiClient) { - if (!(await isAuthenticated(state, apiClient))) { - throw new Error("Not authenticated"); - } -} -export async function isAuthenticated(state, apiClient) { - switch (state.auth.status) { - case "not_auth": - return false; - case "requested": - try { - if (!state.auth.code) { - return false; - } - await apiClient.retrieveToken(state.auth.code.device_code); - return !!state.auth.token; - } - catch { - return false; - } - case "issued": - if (!state.auth.token) { - return false; - } - return await apiClient.validateToken(); - default: - throw new Error("Unknown authentication status"); - } -} -export class AuthTool extends AtlasToolBase { - constructor() { - super(...arguments); - this.name = "auth"; - this.description = "Authenticate to MongoDB Atlas"; - this.argsShape = {}; - } - async isAuthenticated() { - return isAuthenticated(this.state, this.apiClient); - } - async execute() { - if (await this.isAuthenticated()) { - log("INFO", "Already authenticated!"); - return { - content: [{ type: "text", text: "You are already authenticated!" }], - }; - } - try { - const code = await this.apiClient.authenticate(); - this.state.auth.status = "requested"; - this.state.auth.code = code; - this.state.auth.token = undefined; - await saveState(this.state); - return { - content: [ - { - type: "text", - text: `Please authenticate by visiting ${code.verification_uri} and entering the code ${code.user_code}`, - }, - ], - }; - } - catch (error) { - if (error instanceof Error) { - log("error", `Authentication error: ${error}`); - return { - content: [{ type: "text", text: `Authentication failed: ${error.message}` }], - }; - } - log("error", `Unknown authentication error: ${error}`); - return { - content: [{ type: "text", text: "Authentication failed due to an unknown error." }], - }; - } - } -} -//# sourceMappingURL=auth.js.map \ No newline at end of file diff --git a/dist/tools/atlas/auth.js.map b/dist/tools/atlas/auth.js.map deleted file mode 100644 index 2068eaad..00000000 --- a/dist/tools/atlas/auth.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/tools/atlas/auth.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/tools/atlas/index.js b/dist/tools/atlas/index.js deleted file mode 100644 index 47ab2911..00000000 --- a/dist/tools/atlas/index.js +++ /dev/null @@ -1,14 +0,0 @@ -import { AuthTool } from "./auth.js"; -import { ListClustersTool } from "./listClusters.js"; -import { ListProjectsTool } from "./listProjects.js"; -export function registerAtlasTools(server, state, apiClient) { - const tools = [ - new AuthTool(apiClient), - new ListClustersTool(apiClient), - new ListProjectsTool(apiClient), - ]; - for (const tool of tools) { - tool.register(server, state); - } -} -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/tools/atlas/index.js.map b/dist/tools/atlas/index.js.map deleted file mode 100644 index adef7f29..00000000 --- a/dist/tools/atlas/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/atlas/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGrD,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,KAAY,EAAE,SAAoB;IACpF,MAAM,KAAK,GAA4B;QACnC,IAAI,QAAQ,CAAC,SAAS,CAAC;QACvB,IAAI,gBAAgB,CAAC,SAAS,CAAC;QAC/B,IAAI,gBAAgB,CAAC,SAAS,CAAC;KAClC,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/dist/tools/atlas/listClusters.js b/dist/tools/atlas/listClusters.js deleted file mode 100644 index c6f1ac37..00000000 --- a/dist/tools/atlas/listClusters.js +++ /dev/null @@ -1,69 +0,0 @@ -import { z } from "zod"; -import { config } from "../../config.js"; -import { ensureAuthenticated } from "./auth.js"; -import { AtlasToolBase } from "./atlasTool.js"; -export class ListClustersTool extends AtlasToolBase { - constructor(apiClient) { - super(apiClient); - this.name = "listClusters"; - this.description = "List MongoDB Atlas clusters"; - let projectIdFilter = z - .string() - .describe("Optional Atlas project ID to filter clusters"); - if (config.projectID) { - projectIdFilter = projectIdFilter.optional(); - } - this.argsShape = { - projectId: projectIdFilter, - }; - } - async execute({ projectId }) { - await ensureAuthenticated(this.state, this.apiClient); - let clusters = undefined; - let introText = "Here are your MongoDB Atlas clusters:"; - const selectedProjectId = projectId || config.projectID; - if (!selectedProjectId) { - return { - content: [{ type: "text", text: "No project ID provided. Please specify a project ID." }], - }; - } - const project = await this.apiClient.getProject(selectedProjectId); - const data = await this.apiClient.listProjectClusters(project.id); - clusters = data.results || []; - introText = `Here are the clusters in project "${project.name}" (${project.id}):`; - if (clusters.length === 0) { - return { - content: [ - { - type: "text", - text: "No clusters found. You may need to create a cluster in your MongoDB Atlas account.", - }, - ], - }; - } - const formattedClusters = this.formatClustersTable(clusters); - return { - content: [ - { type: "text", text: introText }, - { type: "text", text: formattedClusters }, - ], - }; - } - formatClustersTable(clusters) { - if (clusters.length === 0) { - return "No clusters found."; - } - const header = `Cluster Name | State | MongoDB Version | Region | Connection String - ----------------|----------------|----------------|----------------|----------------|----------------`; - const rows = clusters - .map((cluster) => { - const region = cluster.providerSettings?.regionName || "N/A"; - const connectionString = cluster.connectionStrings?.standard || "N/A"; - const mongoDBVersion = cluster.mongoDBVersion || "N/A"; - return `${cluster.name} | ${cluster.stateName} | ${mongoDBVersion} | ${region} | ${connectionString}`; - }) - .join("\n"); - return `${header}\n${rows}`; - } -} -//# sourceMappingURL=listClusters.js.map \ No newline at end of file diff --git a/dist/tools/atlas/listClusters.js.map b/dist/tools/atlas/listClusters.js.map deleted file mode 100644 index 51965c6a..00000000 --- a/dist/tools/atlas/listClusters.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"listClusters.js","sourceRoot":"","sources":["../../../src/tools/atlas/listClusters.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/tools/atlas/listProjects.js b/dist/tools/atlas/listProjects.js deleted file mode 100644 index 6a5ecf91..00000000 --- a/dist/tools/atlas/listProjects.js +++ /dev/null @@ -1,37 +0,0 @@ -import { ensureAuthenticated } from "./auth.js"; -import { AtlasToolBase } from "./atlasTool.js"; -export class ListProjectsTool extends AtlasToolBase { - constructor() { - super(...arguments); - this.name = "listProjects"; - this.description = "List MongoDB Atlas projects"; - this.argsShape = {}; - } - async execute() { - await ensureAuthenticated(this.state, this.apiClient); - const projectsData = await this.apiClient.listProjects(); - const projects = projectsData.results || []; - if (projects.length === 0) { - return { - content: [{ type: "text", text: "No projects found in your MongoDB Atlas account." }], - }; - } - // Format projects as a table - const header = `Project Name | Project ID | Created At -----------------|----------------|----------------`; - const rows = projects - .map((project) => { - const createdAt = project.created ? new Date(project.created.$date).toLocaleString() : "N/A"; - return `${project.name} | ${project.id} | ${createdAt}`; - }) - .join("\n"); - const formattedProjects = `${header}\n${rows}`; - return { - content: [ - { type: "text", text: "Here are your MongoDB Atlas projects:" }, - { type: "text", text: formattedProjects }, - ], - }; - } -} -//# sourceMappingURL=listProjects.js.map \ No newline at end of file diff --git a/dist/tools/atlas/listProjects.js.map b/dist/tools/atlas/listProjects.js.map deleted file mode 100644 index 0f78775d..00000000 --- a/dist/tools/atlas/listProjects.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"listProjects.js","sourceRoot":"","sources":["../../../src/tools/atlas/listProjects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,OAAO,gBAAiB,SAAQ,aAAa;IAAnD;;QACc,SAAI,GAAG,cAAc,CAAC;QACtB,gBAAW,GAAG,6BAA6B,CAAC;QAC5C,cAAS,GAAG,EAAE,CAAC;IA+B7B,CAAC;IA7Ba,KAAK,CAAC,OAAO;QACnB,MAAM,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAEtD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,SAAU,CAAC,YAAY,EAAE,CAAC;QAC1D,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,IAAI,EAAE,CAAC;QAE5C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO;gBACH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kDAAkD,EAAE,CAAC;aACxF,CAAC;QACN,CAAC;QAED,6BAA6B;QAC7B,MAAM,MAAM,GAAG;mDAC4B,CAAC;QAC5C,MAAM,IAAI,GAAG,QAAQ;aAChB,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;YACb,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;YAC7F,OAAO,GAAG,OAAO,CAAC,IAAI,MAAM,OAAO,CAAC,EAAE,MAAM,SAAS,EAAE,CAAC;QAC5D,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;QAChB,MAAM,iBAAiB,GAAG,GAAG,MAAM,KAAK,IAAI,EAAE,CAAC;QAC/C,OAAO;YACH,OAAO,EAAE;gBACL,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,uCAAuC,EAAE;gBAC/D,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE;aAC5C;SACJ,CAAC;IACN,CAAC;CACJ"} \ No newline at end of file diff --git a/dist/tools/mongodb/index.js b/dist/tools/mongodb/index.js deleted file mode 100644 index 16af8455..00000000 --- a/dist/tools/mongodb/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/no-unused-vars -export function registerMongoDBTools(server, state) { } -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/tools/mongodb/index.js.map b/dist/tools/mongodb/index.js.map deleted file mode 100644 index abc9f807..00000000 --- a/dist/tools/mongodb/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/mongodb/index.ts"],"names":[],"mappings":"AAGA,6DAA6D;AAC7D,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,KAAY,IAAG,CAAC"} \ No newline at end of file diff --git a/dist/tools/tool.js b/dist/tools/tool.js deleted file mode 100644 index 4f34b781..00000000 --- a/dist/tools/tool.js +++ /dev/null @@ -1,49 +0,0 @@ -import { log } from "../logger.js"; -export class ToolBase { - constructor() { - this.state = undefined; // We should never use this before it's set - } - register(server, state) { - this.state = state; - const callback = async (args) => { - try { - // TODO: add telemetry here - return await this.execute(args); - } - catch (error) { - log("error", `Error executing ${this.name}: ${error}`); - // If the error is authentication related, suggest using auth tool - if (error instanceof Error && error.message.includes("Not authenticated")) { - return { - content: [ - { type: "text", text: "You need to authenticate before accessing Atlas data." }, - { - type: "text", - text: "Please use the 'auth' tool to log in to your MongoDB Atlas account.", - }, - ], - }; - } - return { - content: [ - { - type: "text", - text: `Error running ${this.name}: ${error instanceof Error ? error.message : String(error)}`, - }, - ], - isError: true, - }; - } - }; - if (this.argsShape) { - // Not sure why typescript doesn't like the type signature of callback. - // eslint-disable-next-line @typescript-eslint/no-explicit-any - server.tool(this.name, this.description, this.argsShape, callback); - } - else { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - server.tool(this.name, this.description, callback); - } - } -} -//# sourceMappingURL=tool.js.map \ No newline at end of file diff --git a/dist/tools/tool.js.map b/dist/tools/tool.js.map deleted file mode 100644 index 8258c42a..00000000 --- a/dist/tools/tool.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/tools/tool.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAInC,MAAM,OAAgB,QAAQ;IAA9B;QACc,UAAK,GAAU,SAAU,CAAC,CAAC,2CAA2C;IAsDpF,CAAC;IA7CU,QAAQ,CAAC,MAAiB,EAAE,KAAY;QAC3C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QAEnB,MAAM,QAAQ,GAAG,KAAK,EAAE,IAA0C,EAA2B,EAAE;YAC3F,IAAI,CAAC;gBACD,2BAA2B;gBAE3B,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACpC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,GAAG,CAAC,OAAO,EAAE,mBAAmB,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC;gBAEvD,kEAAkE;gBAClE,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;oBACxE,OAAO;wBACH,OAAO,EAAE;4BACL,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,uDAAuD,EAAE;4BAC/E;gCACI,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,qEAAqE;6BAC9E;yBACJ;qBACJ,CAAC;gBACN,CAAC;gBAED,OAAO;oBACH,OAAO,EAAE;wBACL;4BACI,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,iBAAiB,IAAI,CAAC,IAAI,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;yBAChG;qBACJ;oBACD,OAAO,EAAE,IAAI;iBAChB,CAAC;YACN,CAAC;QACL,CAAC,CAAC;QAEF,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,uEAAuE;YACvE,8DAA8D;YAC9D,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,EAAE,QAAe,CAAC,CAAC;QAC9E,CAAC;aAAM,CAAC;YACJ,8DAA8D;YAC9D,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,QAAe,CAAC,CAAC;QAC9D,CAAC;IACL,CAAC;CACJ"} \ No newline at end of file diff --git a/src/server.ts b/src/server.ts index ac15873d..052be94b 100644 --- a/src/server.ts +++ b/src/server.ts @@ -2,7 +2,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { ApiClient } from "./client.js"; import { State, saveState, loadState } from "./state.js"; import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js"; -import { registerAtlasTools } from "./tools/atlas/index.js"; +import { registerAtlasTools } from "./tools/atlas/tools.js"; import { registerMongoDBTools } from "./tools/mongodb/index.js"; import { config } from "./config.js"; diff --git a/src/tools/atlas/index.ts b/src/tools/atlas/tools.ts similarity index 100% rename from src/tools/atlas/index.ts rename to src/tools/atlas/tools.ts index 598c17af..76a2ef86 100644 --- a/src/tools/atlas/index.ts +++ b/src/tools/atlas/tools.ts @@ -1,11 +1,11 @@ +import { ZodRawShape } from "zod"; +import { ToolBase } from "../tool.js"; +import { ApiClient } from "../../client.js"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { State } from "../../state.js"; -import { ApiClient } from "../../client.js"; -import { ToolBase } from "../tool.js"; import { AuthTool } from "./auth.js"; import { ListClustersTool } from "./listClusters.js"; import { ListProjectsTool } from "./listProjects.js"; -import { ZodRawShape } from "zod"; export function registerAtlasTools(server: McpServer, state: State, apiClient: ApiClient) { const tools: ToolBase[] = [ From a9b5685c3402f80a0e0e43c335a2e7cc3eef3bdd Mon Sep 17 00:00:00 2001 From: Nikola Irinchev Date: Tue, 8 Apr 2025 16:04:10 +0200 Subject: [PATCH 4/4] provide the state in the ctor --- src/tools/atlas/atlasTool.ts | 8 ++++++-- src/tools/atlas/listClusters.ts | 5 +++-- src/tools/atlas/tools.ts | 8 ++++---- src/tools/tool.ts | 5 ++--- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/tools/atlas/atlasTool.ts b/src/tools/atlas/atlasTool.ts index f0547a54..c504fdf3 100644 --- a/src/tools/atlas/atlasTool.ts +++ b/src/tools/atlas/atlasTool.ts @@ -1,9 +1,13 @@ import { ZodRawShape } from "zod"; import { ToolBase } from "../tool.js"; import { ApiClient } from "../../client.js"; +import { State } from "../../state.js"; export abstract class AtlasToolBase extends ToolBase { - constructor(protected apiClient: ApiClient) { - super(); + constructor( + state: State, + protected apiClient: ApiClient + ) { + super(state); } } diff --git a/src/tools/atlas/listClusters.ts b/src/tools/atlas/listClusters.ts index 916c12ef..b54c5744 100644 --- a/src/tools/atlas/listClusters.ts +++ b/src/tools/atlas/listClusters.ts @@ -4,6 +4,7 @@ import { config } from "../../config.js"; import { ensureAuthenticated } from "./auth.js"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { AtlasToolBase } from "./atlasTool.js"; +import { State } from "../../state.js"; export class ListClustersTool extends AtlasToolBase<{ projectId: ZodString | ZodOptional; @@ -12,8 +13,8 @@ export class ListClustersTool extends AtlasToolBase<{ protected description = "List MongoDB Atlas clusters"; protected argsShape; - constructor(apiClient: ApiClient) { - super(apiClient); + constructor(state: State, apiClient: ApiClient) { + super(state, apiClient); let projectIdFilter: ZodString | ZodOptional = z .string() diff --git a/src/tools/atlas/tools.ts b/src/tools/atlas/tools.ts index 76a2ef86..c5de4a53 100644 --- a/src/tools/atlas/tools.ts +++ b/src/tools/atlas/tools.ts @@ -9,12 +9,12 @@ import { ListProjectsTool } from "./listProjects.js"; export function registerAtlasTools(server: McpServer, state: State, apiClient: ApiClient) { const tools: ToolBase[] = [ - new AuthTool(apiClient), - new ListClustersTool(apiClient), - new ListProjectsTool(apiClient), + new AuthTool(state, apiClient), + new ListClustersTool(state, apiClient), + new ListProjectsTool(state, apiClient), ]; for (const tool of tools) { - tool.register(server, state); + tool.register(server); } } diff --git a/src/tools/tool.ts b/src/tools/tool.ts index db084d31..7227fa97 100644 --- a/src/tools/tool.ts +++ b/src/tools/tool.ts @@ -5,7 +5,6 @@ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { State } from "../state.js"; export abstract class ToolBase { - protected state: State = undefined!; // We should never use this before it's set protected abstract name: string; protected abstract description: string; @@ -14,9 +13,9 @@ export abstract class ToolBase { protected abstract execute(args: z.objectOutputType): Promise; - public register(server: McpServer, state: State): void { - this.state = state; + protected constructor(protected state: State) {} + public register(server: McpServer): void { const callback = async (args: z.objectOutputType): Promise => { try { // TODO: add telemetry here