Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
7a27749
feat: Adds scaffolding for atlas-local tools MCP-155 (#498)
Luke-Sanderson Sep 1, 2025
a27f2d4
Merge branch 'main' into feat-MCP-40
jeroenvervaeke Sep 5, 2025
8a2db27
feat(atlas-local): Added Atlas Local List Deployments tool (#520)
jeroenvervaeke Sep 9, 2025
6938a8f
feat(atlas-local): Add Atlas Local List Deployments tool (#538)
Luke-Sanderson Sep 11, 2025
e774083
feat(atlas-local): Add Atlas Local Create Deployment tool (#546)
Luke-Sanderson Sep 12, 2025
bb717ab
feat(atlas-local): Accuracy tests for Atlas Local (#554)
Luke-Sanderson Sep 15, 2025
0d14679
feat(atlas-local): Split Atlas Local tests from Atlas (#552)
Luke-Sanderson Sep 15, 2025
cb5d335
feat(atlas-local): Adds Atlas Local Connect Deployment tool (#612)
cveticm Oct 7, 2025
91c11cc
feat: added atlas local deployment id to telemetry (#627)
jeroenvervaeke Oct 9, 2025
8efb029
refactor: Replace z.string with CommonArgs.string (#629)
Luke-Sanderson Oct 9, 2025
c0f3e49
Merge branch 'main' into feat-MCP-40
Luke-Sanderson Oct 9, 2025
cac14ae
Merge branch 'main' into feat-MCP-40
Luke-Sanderson Oct 9, 2025
bd4a061
Merge branch 'main' into feat-MCP-40
Luke-Sanderson Oct 9, 2025
14ade77
fix: knip ignore atlas-local dependency
Luke-Sanderson Oct 9, 2025
5c5c2e7
Merge branch 'main' into feat-MCP-40
Luke-Sanderson Oct 10, 2025
5afc312
docs(atlas-local): Adds the Atlas Local Tools to the readme
Luke-Sanderson Oct 10, 2025
c4a44e0
fix: Small changes from PR suggestions
Luke-Sanderson Oct 10, 2025
9eb0c1a
refactor: Move all lookupDeploymentId calls to resolveTelemetryMetadata
Luke-Sanderson Oct 10, 2025
74d2218
refactor: Update atlas local error handling
Luke-Sanderson Oct 10, 2025
eb488ff
Merge branch 'main' into feat-MCP-40
jeroenvervaeke Oct 14, 2025
e33df95
move atlas local client initialization to 'TransportRunnerBase'
jeroenvervaeke Oct 16, 2025
c3efcd1
use the @mongodb-js/atlas-local package instead of the @mongodb-js-pr…
jeroenvervaeke Oct 16, 2025
123ab82
fix bug with fetching deployment id caused by refactor
jeroenvervaeke Oct 17, 2025
eda00a2
Merge branch 'main' into feat-MCP-40
jeroenvervaeke Oct 17, 2025
a8e10bd
only lookup deploymentid in atlas local delete tool when telemetry is…
jeroenvervaeke Oct 20, 2025
c29581f
fix integration tests
jeroenvervaeke Oct 20, 2025
e38743f
fix error message in listSearchIndexes test
jeroenvervaeke Oct 20, 2025
08eb04c
removed debug log
jeroenvervaeke Oct 20, 2025
a197b08
Merge branch 'main' into feat-MCP-40
jeroenvervaeke Oct 20, 2025
30aabae
Merge branch 'main' into feat-MCP-40
jeroenvervaeke Oct 20, 2025
3e46dbb
adressed pr comments in atlasLocal.ts
jeroenvervaeke Oct 21, 2025
035d4c7
addressed PR comments in atlasLocalTools + simplified telemetry, clos…
jeroenvervaeke Oct 21, 2025
4730bfb
reverted emitToolEvent to be sync again
jeroenvervaeke Oct 21, 2025
e0c8a72
move AtlasLocalTools to toolConstructors
jeroenvervaeke Oct 21, 2025
13b989e
return json instead of markdown table for list deployments
jeroenvervaeke Oct 21, 2025
78fd715
fix list deployments test
jeroenvervaeke Oct 21, 2025
596a783
Merge branch 'main' into feat-MCP-40
jeroenvervaeke Oct 21, 2025
f20c09f
Update src/tools/atlasLocal/read/listDeployments.ts
jeroenvervaeke Oct 21, 2025
318e429
Update src/tools/atlasLocal/atlasLocalTool.ts
jeroenvervaeke Oct 21, 2025
939cfd5
Update src/tools/atlasLocal/atlasLocalTool.ts
jeroenvervaeke Oct 21, 2025
d535757
ran npm run fix, and cleaned up code after accepting suggestions
jeroenvervaeke Oct 21, 2025
db06cc1
fix accuracy tests
jeroenvervaeke Oct 21, 2025
04e505c
updated listDeployments.test.ts after accepting suggestions
jeroenvervaeke Oct 21, 2025
5ae9405
addressed test comments
jeroenvervaeke Oct 21, 2025
3de5b26
added comment describing test in 'should return an error when creatin…
jeroenvervaeke Oct 21, 2025
e3c6708
ran 'npm run fix'
jeroenvervaeke Oct 21, 2025
56d981d
prefixed list deployments accuacy prompts with 'local'
jeroenvervaeke Oct 21, 2025
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix: Small changes from PR suggestions
  • Loading branch information
Luke-Sanderson committed Oct 10, 2025
commit c4a44e022cd431dda3720544dc84cb8c13926168
1 change: 1 addition & 0 deletions .github/workflows/code-health.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ jobs:
- name: Run tests
run: npm test
env:
SKIP_ATLAS_TESTS: "true"
SKIP_ATLAS_LOCAL_TESTS: "true"
- name: Upload test results
if: always() && matrix.os == 'ubuntu-latest'
Expand Down
4 changes: 0 additions & 4 deletions src/common/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,6 @@ export class Session extends EventEmitter<SessionEvents> {
this.connectionManager.setClientName(this.mcpClient.name || "unknown");
}

setAtlasLocalClient(atlasLocalClient: Client): void {
this.atlasLocalClient = atlasLocalClient;
}

async disconnect(): Promise<void> {
const atlasCluster = this.connectedAtlasCluster;

Expand Down
2 changes: 1 addition & 1 deletion src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ export class Server {
const client = AtlasLocalClient.connect();

// Set Atlas Local client
this.session.setAtlasLocalClient(client);
this.session.atlasLocalClient = client;

// Register Atlas Local tools
for (const toolConstructor of AtlasLocalTools) {
Expand Down
3 changes: 1 addition & 2 deletions src/tools/atlasLocal/atlasLocalTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@ export abstract class AtlasLocalToolBase extends ToolBase {
}

protected async execute(...args: Parameters<ToolCallback<typeof this.argsShape>>): Promise<CallToolResult> {
// Get the client
const client = this.session.atlasLocalClient;

// If the client is not found, throw an error
// This should never happen:
// - atlas-local tools are only added after the client is set
// this means that if we were unable to get the client, the tool will not be registered
// - in case the tool was registered by accident
// verifyAllowed in the base class would still return false preventing the tool from being registered,
// verifyAllowed would still return false preventing the tool from being registered,
// preventing the tool from being executed
if (!client) {
return {
Expand Down
1 change: 1 addition & 0 deletions src/tools/atlasLocal/create/createDeployment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export class CreateDeploymentTool extends AtlasLocalToolBase {
type: "MCPServer" as CreationSourceType,
source: "MCPServer",
},
doNotTrack: !this.telemetry.isTelemetryEnabled(),
};
// Create the deployment
const deployment = await client.createDeployment(deploymentOptions);
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ export function waitUntil<T extends ConnectionState>(
});
}

export function waitUntilMcpClientIsSet(
export function waitUntilAtlasLocalClientIsSet(
mcpServer: Server,
signal: AbortSignal,
timeout: number = 5000
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
getResponseElements,
setupIntegrationTest,
validateToolMetadata,
waitUntilMcpClientIsSet,
waitUntilAtlasLocalClientIsSet,
} from "../../helpers.js";
import { afterEach, describe, expect, it } from "vitest";

Expand All @@ -20,7 +20,7 @@ const integration = setupIntegrationTest(
// That's why we skip the tests on macOS in GitHub Actions
describe.skipIf(isMacOSInGitHubActions)("atlas-local-connect-deployment", () => {
beforeEach(async ({ signal }) => {
await waitUntilMcpClientIsSet(integration.mcpServer(), signal);
await waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal);
});

validateToolMetadata(integration, "atlas-local-connect-deployment", "Connect to a MongoDB Atlas Local deployment", [
Expand Down Expand Up @@ -57,7 +57,7 @@ describe.skipIf(isMacOSInGitHubActions)("atlas-local-connect-deployment with dep
let deploymentNamesToCleanup: string[] = [];

beforeEach(async ({ signal }) => {
await waitUntilMcpClientIsSet(integration.mcpServer(), signal);
await waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal);

// Create deployments
deploymentName = `test-deployment-1-${Date.now()}`;
Expand Down Expand Up @@ -105,7 +105,7 @@ describe.skipIf(isMacOSInGitHubActions)("atlas-local-connect-deployment with dep
describe.skipIf(!isMacOSInGitHubActions)("atlas-local-connect-deployment [MacOS in GitHub Actions]", () => {
it("should not have the atlas-local-connect-deployment tool", async ({ signal }) => {
// This should throw an error because the client is not set within the timeout of 5 seconds (default)
await expect(waitUntilMcpClientIsSet(integration.mcpServer(), signal)).rejects.toThrow();
await expect(waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal)).rejects.toThrow();

const { tools } = await integration.mcpClient().listTools();
const connectDeployment = tools.find((tool) => tool.name === "atlas-local-connect-deployment");
Expand Down
16 changes: 8 additions & 8 deletions tests/integration/tools/atlas-local/createDeployment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
expectDefined,
getResponseElements,
setupIntegrationTest,
waitUntilMcpClientIsSet,
waitUntilAtlasLocalClientIsSet,
} from "../../helpers.js";
import { afterEach, describe, expect, it } from "vitest";

Expand Down Expand Up @@ -35,7 +35,7 @@ describe("atlas-local-create-deployment", () => {
);

it.skipIf(isMacOSInGitHubActions)("should have the atlas-local-create-deployment tool", async ({ signal }) => {
await waitUntilMcpClientIsSet(integration.mcpServer(), signal);
await waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal);

const { tools } = await integration.mcpClient().listTools();
const createDeployment = tools.find((tool) => tool.name === "atlas-local-create-deployment");
Expand All @@ -46,7 +46,7 @@ describe("atlas-local-create-deployment", () => {
"[MacOS in GitHub Actions] should not have the atlas-local-create-deployment tool",
async ({ signal }) => {
// This should throw an error because the client is not set within the timeout of 5 seconds (default)
await expect(waitUntilMcpClientIsSet(integration.mcpServer(), signal)).rejects.toThrow();
await expect(waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal)).rejects.toThrow();

const { tools } = await integration.mcpClient().listTools();
const createDeployment = tools.find((tool) => tool.name === "atlas-local-create-deployment");
Expand All @@ -55,7 +55,7 @@ describe("atlas-local-create-deployment", () => {
);

it.skipIf(isMacOSInGitHubActions)("should have correct metadata", async ({ signal }) => {
await waitUntilMcpClientIsSet(integration.mcpServer(), signal);
await waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal);
const { tools } = await integration.mcpClient().listTools();
const createDeployment = tools.find((tool) => tool.name === "atlas-local-create-deployment");
expectDefined(createDeployment);
Expand All @@ -65,7 +65,7 @@ describe("atlas-local-create-deployment", () => {
});

it.skipIf(isMacOSInGitHubActions)("should create a deployment when calling the tool", async ({ signal }) => {
await waitUntilMcpClientIsSet(integration.mcpServer(), signal);
await waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal);
const deploymentName = `test-deployment-${Date.now()}`;

// Check that deployment doesn't exist before creation
Expand Down Expand Up @@ -98,7 +98,7 @@ describe("atlas-local-create-deployment", () => {
it.skipIf(isMacOSInGitHubActions)(
"should return an error when creating a deployment that already exists",
async ({ signal }) => {
await waitUntilMcpClientIsSet(integration.mcpServer(), signal);
await waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal);

// Create a deployment
const deploymentName = `test-deployment-${Date.now()}`;
Expand All @@ -120,7 +120,7 @@ describe("atlas-local-create-deployment", () => {
);

it.skipIf(isMacOSInGitHubActions)("should create a deployment with the correct name", async ({ signal }) => {
await waitUntilMcpClientIsSet(integration.mcpServer(), signal);
await waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal);

// Create a deployment
const deploymentName = `test-deployment-${Date.now()}`;
Expand Down Expand Up @@ -148,7 +148,7 @@ describe("atlas-local-create-deployment", () => {
});

it.skipIf(isMacOSInGitHubActions)("should create a deployment when name is not provided", async ({ signal }) => {
await waitUntilMcpClientIsSet(integration.mcpServer(), signal);
await waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal);

// Create a deployment
const createResponse = await integration.mcpClient().callTool({
Expand Down
12 changes: 6 additions & 6 deletions tests/integration/tools/atlas-local/deleteDeployment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
expectDefined,
getResponseElements,
setupIntegrationTest,
waitUntilMcpClientIsSet,
waitUntilAtlasLocalClientIsSet,
} from "../../helpers.js";
import { describe, expect, it } from "vitest";

Expand All @@ -19,7 +19,7 @@ describe("atlas-local-delete-deployment", () => {
);

it.skipIf(isMacOSInGitHubActions)("should have the atlas-local-delete-deployment tool", async ({ signal }) => {
await waitUntilMcpClientIsSet(integration.mcpServer(), signal);
await waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal);

const { tools } = await integration.mcpClient().listTools();
const deleteDeployment = tools.find((tool) => tool.name === "atlas-local-delete-deployment");
Expand All @@ -30,7 +30,7 @@ describe("atlas-local-delete-deployment", () => {
"[MacOS in GitHub Actions] should not have the atlas-local-delete-deployment tool",
async ({ signal }) => {
// This should throw an error because the client is not set within the timeout of 5 seconds (default)
await expect(waitUntilMcpClientIsSet(integration.mcpServer(), signal)).rejects.toThrow();
await expect(waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal)).rejects.toThrow();

const { tools } = await integration.mcpClient().listTools();
const deleteDeployment = tools.find((tool) => tool.name === "atlas-local-delete-deployment");
Expand All @@ -39,7 +39,7 @@ describe("atlas-local-delete-deployment", () => {
);

it.skipIf(isMacOSInGitHubActions)("should have correct metadata", async ({ signal }) => {
await waitUntilMcpClientIsSet(integration.mcpServer(), signal);
await waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal);
const { tools } = await integration.mcpClient().listTools();
const deleteDeployment = tools.find((tool) => tool.name === "atlas-local-delete-deployment");
expectDefined(deleteDeployment);
Expand All @@ -51,7 +51,7 @@ describe("atlas-local-delete-deployment", () => {
it.skipIf(isMacOSInGitHubActions)(
"should return 'no such container' error when deployment to delete does not exist",
async ({ signal }) => {
await waitUntilMcpClientIsSet(integration.mcpServer(), signal);
await waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal);
const deploymentName = "non-existent";

const response = await integration.mcpClient().callTool({
Expand All @@ -67,7 +67,7 @@ describe("atlas-local-delete-deployment", () => {
);

it.skipIf(isMacOSInGitHubActions)("should delete a deployment when calling the tool", async ({ signal }) => {
await waitUntilMcpClientIsSet(integration.mcpServer(), signal);
await waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal);
// Create a deployment
const deploymentName = `test-deployment-${Date.now()}`;
await integration.mcpClient().callTool({
Expand Down
10 changes: 5 additions & 5 deletions tests/integration/tools/atlas-local/listDeployments.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
expectDefined,
getResponseElements,
setupIntegrationTest,
waitUntilMcpClientIsSet,
waitUntilAtlasLocalClientIsSet,
} from "../../helpers.js";
import { describe, expect, it } from "vitest";

Expand All @@ -19,7 +19,7 @@ describe("atlas-local-list-deployments", () => {
);

it.skipIf(isMacOSInGitHubActions)("should have the atlas-local-list-deployments tool", async ({ signal }) => {
await waitUntilMcpClientIsSet(integration.mcpServer(), signal);
await waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal);

const { tools } = await integration.mcpClient().listTools();
const listDeployments = tools.find((tool) => tool.name === "atlas-local-list-deployments");
Expand All @@ -30,7 +30,7 @@ describe("atlas-local-list-deployments", () => {
"[MacOS in GitHub Actions] should not have the atlas-local-list-deployments tool",
async ({ signal }) => {
// This should throw an error because the client is not set within the timeout of 5 seconds (default)
await expect(waitUntilMcpClientIsSet(integration.mcpServer(), signal)).rejects.toThrow();
await expect(waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal)).rejects.toThrow();

const { tools } = await integration.mcpClient().listTools();
const listDeployments = tools.find((tool) => tool.name === "atlas-local-list-deployments");
Expand All @@ -39,7 +39,7 @@ describe("atlas-local-list-deployments", () => {
);

it.skipIf(isMacOSInGitHubActions)("should have correct metadata", async ({ signal }) => {
await waitUntilMcpClientIsSet(integration.mcpServer(), signal);
await waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal);
const { tools } = await integration.mcpClient().listTools();
const listDeployments = tools.find((tool) => tool.name === "atlas-local-list-deployments");
expectDefined(listDeployments);
Expand All @@ -49,7 +49,7 @@ describe("atlas-local-list-deployments", () => {
});

it.skipIf(isMacOSInGitHubActions)("should not crash when calling the tool", async ({ signal }) => {
await waitUntilMcpClientIsSet(integration.mcpServer(), signal);
await waitUntilAtlasLocalClientIsSet(integration.mcpServer(), signal);

const response = await integration.mcpClient().callTool({
name: "atlas-local-list-deployments",
Expand Down
4 changes: 4 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ const vitestDefaultExcludes = [
"**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier}.config.*",
];

if (process.env.SKIP_ATLAS_TESTS === "true") {
vitestDefaultExcludes.push("**/atlas/**");
}

if (process.env.SKIP_ATLAS_LOCAL_TESTS === "true") {
vitestDefaultExcludes.push("**/atlas-local/**");
}
Expand Down
Loading