-
Notifications
You must be signed in to change notification settings - Fork 43
add create project tool #82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 3 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
904d598
add create project tool
blva 128695c
lint
blva dd9fb36
Add integration test
blva 70c0c6d
Merge remote-tracking branch 'origin/main' into create-project
blva 2e95780
remove tests
blva ad27017
clean up
blva 7d1f975
list orgs if not available
blva e3ceb9d
lint
blva 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
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { z } from "zod"; | ||
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; | ||
import { AtlasToolBase } from "./atlasTool.js"; | ||
import { ToolArgs, OperationType } from "../tool.js"; | ||
import { Group } from "../../common/atlas/openapi.js"; | ||
|
||
export class CreateProjectTool extends AtlasToolBase { | ||
protected name = "atlas-create-project"; | ||
protected description = "Create a MongoDB Atlas project"; | ||
protected operationType: OperationType = "create"; | ||
protected argsShape = { | ||
projectName: z.string().describe("Name for the new project"), | ||
organizationId: z.string().describe("Organization ID for the new project"), | ||
}; | ||
|
||
protected async execute({ projectName, organizationId }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> { | ||
this.session.ensureAuthenticated(); | ||
|
||
const input = { | ||
name: projectName, | ||
orgId: organizationId, | ||
} as Group; | ||
blva marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
await this.session.apiClient.createProject({ | ||
body: input, | ||
}); | ||
|
||
return { | ||
content: [{ type: "text", text: `Project "${projectName}" created successfully.` }], | ||
}; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { jestTestMCPClient, validateParameters, getResponseContent } from "../../helpers.js"; | ||
import { McpError } from "@modelcontextprotocol/sdk/types.js"; | ||
|
||
describe("createProject tool", () => { | ||
const client = jestTestMCPClient(); | ||
// atlas client mockk | ||
|
||
it("should have correct metadata", async () => { | ||
const { tools } = await client().listTools(); | ||
const createProject = tools.find((tool) => tool.name === "atlas-create-project")!; | ||
expect(createProject).toBeDefined(); | ||
expect(createProject.description).toBe("Create a MongoDB Atlas project"); | ||
|
||
// Validate the parameters match the schema | ||
validateParameters(createProject, [ | ||
{ | ||
name: "projectName", | ||
type: "string", | ||
description: "Name for the new project", | ||
required: true, | ||
}, | ||
{ | ||
name: "organizationId", | ||
type: "string", | ||
description: "Organization ID for the new project", | ||
required: true, | ||
}, | ||
]); | ||
}); | ||
|
||
describe("with invalid arguments", () => { | ||
const args = [ | ||
{}, // Empty args | ||
{ projectName: 123, organizationId: "org-1" }, // Invalid projectName type | ||
{ projectName: "Test Project" }, // Missing organizationId | ||
{ projectName: "Test Project", organizationId: 456 }, // Invalid organizationId type | ||
{ projectName: "", organizationId: "org-1" }, // Empty projectName | ||
]; | ||
|
||
for (const arg of args) { | ||
it(`throws a schema error for: ${JSON.stringify(arg)}`, async () => { | ||
try { | ||
await client().callTool({ name: "atlas-create-project", arguments: arg }); | ||
expect.fail("Expected an error to be thrown"); | ||
} catch (error) { | ||
expect(error).toBeInstanceOf(McpError); | ||
const mcpError = error as McpError; | ||
expect(mcpError.code).toEqual(-32602); | ||
expect(mcpError.message).toContain("Invalid arguments for tool atlas-create-project"); | ||
} | ||
}); | ||
} | ||
}); | ||
|
||
describe("with valid arguments", () => { | ||
blva marked this conversation as resolved.
Show resolved
Hide resolved
|
||
it("creates a new project", async () => { | ||
blva marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const projectName = "Test Project"; | ||
const organizationId = "test-org-id"; | ||
|
||
const response = await client().callTool({ | ||
name: "atlas-create-project", | ||
arguments: { projectName, organizationId }, | ||
}); | ||
|
||
expect(response).toBeDefined(); | ||
const content = getResponseContent(response.content); | ||
expect(content).toEqual(`Project "${projectName}" created successfully.`); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When testing, have you noticed models be consistently good about discovering the correct org id or is this something users will be prompted to fill out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, this one is a bit more tricky since it involves project creation it can be expected that uses didn't do any operations to their org. but your comment made me realize that we might have room to generate the project name at least, we don't need to prompt for that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the org id would be quite annoying for people to figure out - is there no way to obtain the org id from the token or some other API? If I'm chatting with an LLM and I need to go open the browser to figure out what my org id is, I might as well go ahead and create my project then and there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we will need an
atlas-list-orgs
tool otherwise this is unusableThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't create a tool to create orgs given service accounts are scoped per orgs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I'll add list orgs and try
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added it, however I'm wondering if we should ask the user first if we can create it with the found org id, but i added using assumption