Skip to content

Commit e9789c5

Browse files
committed
feat: add atlas-list-orgs
1 parent 15a85b7 commit e9789c5

File tree

7 files changed

+280
-25
lines changed

7 files changed

+280
-25
lines changed

scripts/filter.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ function filterOpenapi(openapi: OpenAPIV3_1.Document): OpenAPIV3_1.Document {
2222
"listOrganizations",
2323
"getProject",
2424
"createProject",
25+
"deleteProject",
2526
"listClusters",
2627
"getCluster",
2728
"createCluster",
@@ -33,6 +34,7 @@ function filterOpenapi(openapi: OpenAPIV3_1.Document): OpenAPIV3_1.Document {
3334
"listProjectIpAccessLists",
3435
"createProjectIpAccessList",
3536
"deleteProjectIpAccessList",
37+
"listOrganizationProjects",
3638
];
3739

3840
const filteredPaths = {};

src/common/atlas/apiClient.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ export class ApiClient {
132132
return data;
133133
}
134134

135+
async deleteProject(options: FetchOptions<operations["deleteProject"]>) {
136+
await this.client.DELETE("/api/atlas/v2/groups/{groupId}", options);
137+
}
138+
135139
async getProject(options: FetchOptions<operations["getProject"]>) {
136140
const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}", options);
137141
return data;
@@ -189,5 +193,10 @@ export class ApiClient {
189193
return data;
190194
}
191195

196+
async listOrganizationProjects(options: FetchOptions<operations["listOrganizationProjects"]>) {
197+
const { data } = await this.client.GET("/api/atlas/v2/orgs/{orgId}/groups", options);
198+
return data;
199+
}
200+
192201
// DO NOT EDIT. This is auto-generated code.
193202
}

src/common/atlas/openapi.d.ts

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,11 @@ export interface paths {
6262
get: operations["getProject"];
6363
put?: never;
6464
post?: never;
65-
delete?: never;
65+
/**
66+
* Remove One Project
67+
* @description Removes the specified project. Projects group clusters into logical collections that support an application environment, workload, or both. Each project can have its own users, teams, security, tags, and alert settings. You can delete a project only if there are no Online Archives for the clusters in the project. To use this resource, the requesting Service Account or API Key must have the Project Owner role.
68+
*/
69+
delete: operations["deleteProject"];
6670
options?: never;
6771
head?: never;
6872
patch?: never;
@@ -232,6 +236,33 @@ export interface paths {
232236
patch?: never;
233237
trace?: never;
234238
};
239+
"/api/atlas/v2/orgs/{orgId}/groups": {
240+
parameters: {
241+
query?: never;
242+
header?: never;
243+
path?: never;
244+
cookie?: never;
245+
};
246+
/**
247+
* Return One or More Projects in One Organization
248+
* @description Returns multiple projects in the specified organization. Each organization can have multiple projects. Use projects to:
249+
*
250+
* - Isolate different environments, such as development, test, or production environments, from each other.
251+
* - Associate different MongoDB Cloud users or teams with different environments, or give different permission to MongoDB Cloud users in different environments.
252+
* - Maintain separate cluster security configurations.
253+
* - Create different alert settings.
254+
*
255+
* To use this resource, the requesting Service Account or API Key must have the Organization Member role.
256+
*/
257+
get: operations["listOrganizationProjects"];
258+
put?: never;
259+
post?: never;
260+
delete?: never;
261+
options?: never;
262+
head?: never;
263+
patch?: never;
264+
trace?: never;
265+
};
235266
}
236267
export type webhooks = Record<string, never>;
237268
export interface components {
@@ -4901,6 +4932,8 @@ export interface components {
49014932
includeCount: boolean;
49024933
/** @description Number of items that the response returns per page. */
49034934
itemsPerPage: number;
4935+
/** @description Unique 24-hexadecimal digit string that identifies the organization that contains your projects. Use the [/orgs](#tag/Organizations/operation/listOrganizations) endpoint to retrieve all organizations to which the authenticated user has access. */
4936+
orgId: string;
49044937
/** @description Number of the page that displays the current set of the total objects that the response returns. */
49054938
pageNum: number;
49064939
/** @description Flag that indicates whether the response body should be in the prettyprint format. */
@@ -5147,6 +5180,7 @@ export type ParameterEnvelope = components['parameters']['envelope'];
51475180
export type ParameterGroupId = components['parameters']['groupId'];
51485181
export type ParameterIncludeCount = components['parameters']['includeCount'];
51495182
export type ParameterItemsPerPage = components['parameters']['itemsPerPage'];
5183+
export type ParameterOrgId = components['parameters']['orgId'];
51505184
export type ParameterPageNum = components['parameters']['pageNum'];
51515185
export type ParameterPretty = components['parameters']['pretty'];
51525186
export type $defs = Record<string, never>;
@@ -5289,6 +5323,40 @@ export interface operations {
52895323
500: components["responses"]["internalServerError"];
52905324
};
52915325
};
5326+
deleteProject: {
5327+
parameters: {
5328+
query?: {
5329+
/** @description Flag that indicates whether Application wraps the response in an `envelope` JSON object. Some API clients cannot access the HTTP response headers or status code. To remediate this, set envelope=true in the query. Endpoints that return a list of results use the results object as an envelope. Application adds the status parameter to the response body. */
5330+
envelope?: components["parameters"]["envelope"];
5331+
/** @description Flag that indicates whether the response body should be in the prettyprint format. */
5332+
pretty?: components["parameters"]["pretty"];
5333+
};
5334+
header?: never;
5335+
path: {
5336+
/** @description Unique 24-hexadecimal digit string that identifies your project. Use the [/groups](#tag/Projects/operation/listProjects) endpoint to retrieve all projects to which the authenticated user has access.
5337+
*
5338+
* **NOTE**: Groups and projects are synonymous terms. Your group id is the same as your project id. For existing groups, your group/project id remains the same. The resource and corresponding endpoints use the term groups. */
5339+
groupId: components["parameters"]["groupId"];
5340+
};
5341+
cookie?: never;
5342+
};
5343+
requestBody?: never;
5344+
responses: {
5345+
/** @description This endpoint does not return a response body. */
5346+
204: {
5347+
headers: {
5348+
[name: string]: unknown;
5349+
};
5350+
content: {
5351+
"application/vnd.atlas.2023-01-01+json": unknown;
5352+
};
5353+
};
5354+
400: components["responses"]["badRequest"];
5355+
404: components["responses"]["notFound"];
5356+
409: components["responses"]["conflict"];
5357+
500: components["responses"]["internalServerError"];
5358+
};
5359+
};
52925360
listProjectIpAccessLists: {
52935361
parameters: {
52945362
query?: {
@@ -5735,6 +5803,46 @@ export interface operations {
57355803
500: components["responses"]["internalServerError"];
57365804
};
57375805
};
5806+
listOrganizationProjects: {
5807+
parameters: {
5808+
query?: {
5809+
/** @description Flag that indicates whether Application wraps the response in an `envelope` JSON object. Some API clients cannot access the HTTP response headers or status code. To remediate this, set envelope=true in the query. Endpoints that return a list of results use the results object as an envelope. Application adds the status parameter to the response body. */
5810+
envelope?: components["parameters"]["envelope"];
5811+
/** @description Flag that indicates whether the response returns the total number of items (**totalCount**) in the response. */
5812+
includeCount?: components["parameters"]["includeCount"];
5813+
/** @description Number of items that the response returns per page. */
5814+
itemsPerPage?: components["parameters"]["itemsPerPage"];
5815+
/** @description Number of the page that displays the current set of the total objects that the response returns. */
5816+
pageNum?: components["parameters"]["pageNum"];
5817+
/** @description Flag that indicates whether the response body should be in the prettyprint format. */
5818+
pretty?: components["parameters"]["pretty"];
5819+
/** @description Human-readable label of the project to use to filter the returned list. Performs a case-insensitive search for a project within the organization which is prefixed by the specified name. */
5820+
name?: string;
5821+
};
5822+
header?: never;
5823+
path: {
5824+
/** @description Unique 24-hexadecimal digit string that identifies the organization that contains your projects. Use the [/orgs](#tag/Organizations/operation/listOrganizations) endpoint to retrieve all organizations to which the authenticated user has access. */
5825+
orgId: components["parameters"]["orgId"];
5826+
};
5827+
cookie?: never;
5828+
};
5829+
requestBody?: never;
5830+
responses: {
5831+
/** @description OK */
5832+
200: {
5833+
headers: {
5834+
[name: string]: unknown;
5835+
};
5836+
content: {
5837+
"application/vnd.atlas.2023-01-01+json": components["schemas"]["PaginatedAtlasGroupView"];
5838+
};
5839+
};
5840+
400: components["responses"]["badRequest"];
5841+
401: components["responses"]["unauthorized"];
5842+
404: components["responses"]["notFound"];
5843+
500: components["responses"]["internalServerError"];
5844+
};
5845+
};
57385846
}
57395847
type WithRequired<T, K extends keyof T> = T & {
57405848
[P in K]-?: T[P];

src/tools/atlas/listOrgs.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2+
import { AtlasToolBase } from "./atlasTool.js";
3+
import { OperationType } from "../tool.js";
4+
5+
export class ListOrganizationsTool extends AtlasToolBase {
6+
protected name = "atlas-list-orgs";
7+
protected description = "List MongoDB Atlas organizations";
8+
protected operationType: OperationType = "read";
9+
protected argsShape = {};
10+
11+
protected async execute(): Promise<CallToolResult> {
12+
this.session.ensureAuthenticated();
13+
14+
const data = await this.session.apiClient.listOrganizations();
15+
16+
if (!data?.results?.length) {
17+
throw new Error("No projects found in your MongoDB Atlas account.");
18+
}
19+
20+
// Format projects as a table
21+
const output =
22+
`Organization Name | Organization ID
23+
----------------| ----------------
24+
` +
25+
data.results
26+
.map((org) => {
27+
return `${org.name} | ${org.id}`;
28+
})
29+
.join("\n");
30+
return {
31+
content: [{ type: "text", text: output }],
32+
};
33+
}
34+
}

src/tools/atlas/listProjects.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
11
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
22
import { AtlasToolBase } from "./atlasTool.js";
33
import { OperationType } from "../tool.js";
4+
import { z } from "zod";
5+
import { ToolArgs } from "../tool.js";
46

57
export class ListProjectsTool extends AtlasToolBase {
68
protected name = "atlas-list-projects";
79
protected description = "List MongoDB Atlas projects";
810
protected operationType: OperationType = "read";
9-
protected argsShape = {};
11+
protected argsShape = {
12+
orgId: z.string().describe("Atlas organization ID to filter projects").optional(),
13+
};
1014

11-
protected async execute(): Promise<CallToolResult> {
15+
protected async execute({ orgId }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
1216
this.session.ensureAuthenticated();
1317

14-
const data = await this.session.apiClient.listProjects();
18+
const data = orgId
19+
? await this.session.apiClient.listOrganizationProjects({
20+
params: {
21+
orgId,
22+
},
23+
})
24+
: await this.session.apiClient.listProjects();
1525

1626
if (!data?.results?.length) {
1727
throw new Error("No projects found in your MongoDB Atlas account.");

src/tools/atlas/tools.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { InspectAccessListTool } from "./inspectAccessList.js";
77
import { ListDBUsersTool } from "./listDBUsers.js";
88
import { CreateDBUserTool } from "./createDBUser.js";
99
import { CreateProjectTool } from "./createProject.js";
10+
import { ListOrganizationsTool } from "./listOrgs.js";
1011

1112
export const AtlasTools = [
1213
ListClustersTool,
@@ -18,4 +19,5 @@ export const AtlasTools = [
1819
ListDBUsersTool,
1920
CreateDBUserTool,
2021
CreateProjectTool,
22+
ListOrganizationsTool
2123
];

0 commit comments

Comments
 (0)