Skip to content

Commit dd003e6

Browse files
committed
update all args
1 parent 7682f5c commit dd003e6

File tree

14 files changed

+453
-86
lines changed

14 files changed

+453
-86
lines changed
Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
import { z, type ZodString } from "zod";
22

3-
export const ToolArgs = {
3+
export const CommonArgs = {
44
string: (): ZodString =>
55
z.string().regex(/^[\x20-\x7E]*$/, "String cannot contain special characters or Unicode symbols"),
66
};
77

8-
/**
9-
* Common Zod validators for Atlas tools
10-
* These can be reused across different Atlas tools for consistent validation
11-
*/
128
export const AtlasArgs = {
139
objectId: (fieldName: string): z.ZodString =>
14-
ToolArgs.string()
10+
CommonArgs.string()
1511
.min(1, `${fieldName} is required`)
1612
.regex(/^[0-9a-fA-F]{24}$/, `${fieldName} must be a valid 24-character hexadecimal string`),
1713

@@ -20,27 +16,32 @@ export const AtlasArgs = {
2016
organizationId: (): z.ZodString => AtlasArgs.objectId("organizationId"),
2117

2218
clusterName: (): z.ZodString =>
23-
ToolArgs.string()
19+
CommonArgs.string()
2420
.min(1, "Cluster name is required")
2521
.max(64, "Cluster name must be 64 characters or less")
22+
.regex(/^[^/]*$/, "String cannot contain '/'")
2623
.regex(/^[a-zA-Z0-9_-]+$/, "Cluster name can only contain letters, numbers, hyphens, and underscores"),
2724

25+
projectName: (): z.ZodString =>
26+
CommonArgs.string()
27+
.min(1, "Project name is required")
28+
.max(64, "Project name must be 64 characters or less")
29+
.regex(/^[^/]*$/, "String cannot contain '/'")
30+
.regex(/^[a-zA-Z0-9_-]+$/, "Project name can only contain letters, numbers, hyphens, and underscores"),
31+
2832
username: (): z.ZodString =>
29-
ToolArgs.string()
33+
CommonArgs.string()
3034
.min(1, "Username is required")
3135
.max(100, "Username must be 100 characters or less")
36+
.regex(/^[^/]*$/, "String cannot contain '/'")
3237
.regex(/^[a-zA-Z0-9._-]+$/, "Username can only contain letters, numbers, dots, hyphens, and underscores"),
3338

34-
ipAddress: (): z.ZodString => ToolArgs.string().ip({ version: "v4" }),
39+
ipAddress: (): z.ZodString => CommonArgs.string().ip({ version: "v4" }),
3540

36-
cidrBlock: (): z.ZodString =>
37-
ToolArgs.string().regex(
38-
/^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$/,
39-
"Must be a valid CIDR block (e.g., 192.168.1.0/24)"
40-
),
41+
cidrBlock: (): z.ZodString => CommonArgs.string().cidr(),
4142

4243
region: (): z.ZodString =>
43-
ToolArgs.string().regex(
44+
CommonArgs.string().regex(
4445
/^[a-zA-Z0-9_-]+$/,
4546
"Region can only contain letters, numbers, hyphens, and underscores"
4647
),

src/tools/atlas/atlasTool.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import type { ToolCategory, TelemetryToolMetadata, ToolArgs } from "../tool.js";
2-
import { ToolBase } from "../tool.js";
31
import type { ToolCallback } from "@modelcontextprotocol/sdk/server/mcp.js";
2+
import { ToolBase, type ToolArgs, type ToolCategory, type TelemetryToolMetadata } from "../tool.js";
43
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
54
import { LogId } from "../../common/logger.js";
65
import { z } from "zod";

src/tools/atlas/connect/connectCluster.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import { z } from "zod";
21
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2+
import { type OperationType, type ToolArgs } from "../../tool.js";
33
import { AtlasToolBase } from "../atlasTool.js";
4-
import type { ToolArgs, OperationType } from "../../tool.js";
54
import { generateSecurePassword } from "../../../helpers/generatePassword.js";
65
import { LogId } from "../../../common/logger.js";
76
import { inspectCluster } from "../../../common/atlas/cluster.js";
87
import { ensureCurrentIpInAccessList } from "../../../common/atlas/accessListUtils.js";
98
import type { AtlasClusterConnectionInfo } from "../../../common/connectionManager.js";
109
import { getDefaultRoleFromConfig } from "../../../common/atlas/roles.js";
10+
import { AtlasArgs } from "../../args.js";
1111

1212
const EXPIRY_MS = 1000 * 60 * 60 * 12; // 12 hours
1313
const addedIpAccessListMessage =
@@ -20,13 +20,17 @@ function sleep(ms: number): Promise<void> {
2020
return new Promise((resolve) => setTimeout(resolve, ms));
2121
}
2222

23+
export const ConnectClusterArgs = {
24+
projectId: AtlasArgs.projectId().describe("Atlas project ID"),
25+
clusterName: AtlasArgs.clusterName().describe("Atlas cluster name"),
26+
};
27+
2328
export class ConnectClusterTool extends AtlasToolBase {
2429
public name = "atlas-connect-cluster";
2530
protected description = "Connect to MongoDB Atlas cluster";
2631
public operationType: OperationType = "connect";
2732
protected argsShape = {
28-
projectId: z.string().describe("Atlas project ID"),
29-
clusterName: z.string().describe("Atlas cluster name"),
33+
...ConnectClusterArgs,
3034
};
3135

3236
private queryConnection(

src/tools/atlas/create/createAccessList.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
11
import { z } from "zod";
2+
import { type OperationType, type ToolArgs } from "../../tool.js";
23
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
34
import { AtlasToolBase } from "../atlasTool.js";
4-
import type { ToolArgs, OperationType } from "../../tool.js";
55
import { makeCurrentIpAccessListEntry, DEFAULT_ACCESS_LIST_COMMENT } from "../../../common/atlas/accessListUtils.js";
6+
import { AtlasArgs, CommonArgs } from "../../args.js";
7+
8+
export const CreateAccessListArgs = {
9+
projectId: AtlasArgs.projectId().describe("Atlas project ID"),
10+
ipAddresses: z.array(AtlasArgs.ipAddress()).describe("IP addresses to allow access from").optional(),
11+
cidrBlocks: z.array(AtlasArgs.cidrBlock()).describe("CIDR blocks to allow access from").optional(),
12+
currentIpAddress: z.boolean().describe("Add the current IP address").default(false),
13+
comment: CommonArgs.string()
14+
.describe("Comment for the access list entries")
15+
.default(DEFAULT_ACCESS_LIST_COMMENT)
16+
.optional(),
17+
};
618

719
export class CreateAccessListTool extends AtlasToolBase {
820
public name = "atlas-create-access-list";
921
protected description = "Allow Ip/CIDR ranges to access your MongoDB Atlas clusters.";
1022
public operationType: OperationType = "create";
1123
protected argsShape = {
12-
projectId: z.string().describe("Atlas project ID"),
13-
ipAddresses: z
14-
.array(z.string().ip({ version: "v4" }))
15-
.describe("IP addresses to allow access from")
16-
.optional(),
17-
cidrBlocks: z.array(z.string().cidr()).describe("CIDR blocks to allow access from").optional(),
18-
currentIpAddress: z.boolean().describe("Add the current IP address").default(false),
19-
comment: z
20-
.string()
21-
.describe("Comment for the access list entries")
22-
.default(DEFAULT_ACCESS_LIST_COMMENT)
23-
.optional(),
24+
...CreateAccessListArgs,
2425
};
2526

2627
protected async execute({

src/tools/atlas/create/createDBUser.ts

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,46 @@
11
import { z } from "zod";
2+
import type { ToolArgs, OperationType } from "../../tool.js";
23
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
34
import { AtlasToolBase } from "../atlasTool.js";
4-
import type { ToolArgs, OperationType } from "../../tool.js";
55
import type { CloudDatabaseUser, DatabaseUserRole } from "../../../common/atlas/openapi.js";
66
import { generateSecurePassword } from "../../../helpers/generatePassword.js";
77
import { ensureCurrentIpInAccessList } from "../../../common/atlas/accessListUtils.js";
8+
import { AtlasArgs, CommonArgs } from "../../args.js";
9+
10+
export const CreateDBUserArgs = {
11+
projectId: AtlasArgs.projectId().describe("Atlas project ID"),
12+
username: AtlasArgs.username().describe("Username for the new user"),
13+
// Models will generate overly simplistic passwords like SecurePassword123 or
14+
// AtlasPassword123, which are easily guessable and exploitable. We're instructing
15+
// the model not to try and generate anything and instead leave the field unset.
16+
password: z
17+
.string()
18+
.optional()
19+
.nullable()
20+
.describe(
21+
"Password for the new user. IMPORTANT: If the user hasn't supplied an explicit password, leave it unset and under no circumstances try to generate a random one. A secure password will be generated by the MCP server if necessary."
22+
),
23+
roles: z
24+
.array(
25+
z.object({
26+
roleName: CommonArgs.string().describe("Role name"),
27+
databaseName: CommonArgs.string().describe("Database name").default("admin"),
28+
collectionName: CommonArgs.string().describe("Collection name").optional(),
29+
})
30+
)
31+
.describe("Roles for the new user"),
32+
clusters: z
33+
.array(CommonArgs.string())
34+
.describe("Clusters to assign the user to, leave empty for access to all clusters")
35+
.optional(),
36+
};
837

938
export class CreateDBUserTool extends AtlasToolBase {
1039
public name = "atlas-create-db-user";
1140
protected description = "Create an MongoDB Atlas database user";
1241
public operationType: OperationType = "create";
1342
protected argsShape = {
14-
projectId: z.string().describe("Atlas project ID"),
15-
username: z.string().describe("Username for the new user"),
16-
// Models will generate overly simplistic passwords like SecurePassword123 or
17-
// AtlasPassword123, which are easily guessable and exploitable. We're instructing
18-
// the model not to try and generate anything and instead leave the field unset.
19-
password: z
20-
.string()
21-
.optional()
22-
.nullable()
23-
.describe(
24-
"Password for the new user. IMPORTANT: If the user hasn't supplied an explicit password, leave it unset and under no circumstances try to generate a random one. A secure password will be generated by the MCP server if necessary."
25-
),
26-
roles: z
27-
.array(
28-
z.object({
29-
roleName: z.string().describe("Role name"),
30-
databaseName: z.string().describe("Database name").default("admin"),
31-
collectionName: z.string().describe("Collection name").optional(),
32-
})
33-
)
34-
.describe("Roles for the new user"),
35-
clusters: z
36-
.array(z.string())
37-
.describe("Clusters to assign the user to, leave empty for access to all clusters")
38-
.optional(),
43+
...CreateDBUserArgs,
3944
};
4045

4146
protected async execute({

src/tools/atlas/create/createFreeCluster.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2+
import { type ToolArgs, type OperationType } from "../../tool.js";
23
import { AtlasToolBase } from "../atlasTool.js";
3-
import type { ToolArgs, OperationType } from "../../tool.js";
44
import type { ClusterDescription20240805 } from "../../../common/atlas/openapi.js";
55
import { ensureCurrentIpInAccessList } from "../../../common/atlas/accessListUtils.js";
6-
import { AtlasArgs } from "../validators.js";
6+
import { AtlasArgs } from "../../args.js";
77

88
export class CreateFreeClusterTool extends AtlasToolBase {
99
public name = "atlas-create-free-cluster";

src/tools/atlas/create/createProject.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1-
import { z } from "zod";
21
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2+
import { type OperationType, type ToolArgs } from "../../tool.js";
33
import { AtlasToolBase } from "../atlasTool.js";
4-
import type { ToolArgs, OperationType } from "../../tool.js";
54
import type { Group } from "../../../common/atlas/openapi.js";
5+
import { AtlasArgs } from "../../args.js";
6+
7+
export const CreateProjectArgs = {
8+
projectName: AtlasArgs.projectName().optional().describe("Name for the new project"),
9+
organizationId: AtlasArgs.organizationId().optional().describe("Organization ID for the new project"),
10+
};
611

712
export class CreateProjectTool extends AtlasToolBase {
813
public name = "atlas-create-project";
914
protected description = "Create a MongoDB Atlas project";
1015
public operationType: OperationType = "create";
1116
protected argsShape = {
12-
projectName: z.string().optional().describe("Name for the new project"),
13-
organizationId: z.string().optional().describe("Organization ID for the new project"),
17+
...CreateProjectArgs,
1418
};
1519

1620
protected async execute({ projectName, organizationId }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {

src/tools/atlas/read/inspectAccessList.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2+
import { type OperationType, type ToolArgs, formatUntrustedData } from "../../tool.js";
23
import { AtlasToolBase } from "../atlasTool.js";
3-
import type { ToolArgs, OperationType } from "../../tool.js";
4-
import { formatUntrustedData } from "../../tool.js";
5-
import { AtlasArgs } from "../validators.js";
4+
import { AtlasArgs } from "../../args.js";
5+
6+
export const InspectAccessListArgs = {
7+
projectId: AtlasArgs.projectId().describe("Atlas project ID"),
8+
};
69

710
export class InspectAccessListTool extends AtlasToolBase {
811
public name = "atlas-inspect-access-list";
912
protected description = "Inspect Ip/CIDR ranges with access to your MongoDB Atlas clusters.";
1013
public operationType: OperationType = "read";
1114
protected argsShape = {
12-
projectId: AtlasArgs.projectId().describe("Atlas project ID"),
15+
...InspectAccessListArgs,
1316
};
1417

1518
protected async execute({ projectId }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {

src/tools/atlas/read/inspectCluster.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1-
import { z } from "zod";
21
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2+
import { type OperationType, type ToolArgs, formatUntrustedData } from "../../tool.js";
33
import { AtlasToolBase } from "../atlasTool.js";
4-
import type { ToolArgs, OperationType } from "../../tool.js";
5-
import { formatUntrustedData } from "../../tool.js";
64
import type { Cluster } from "../../../common/atlas/cluster.js";
75
import { inspectCluster } from "../../../common/atlas/cluster.js";
8-
import { AtlasArgs } from "../validators.js";
6+
import { AtlasArgs } from "../../args.js";
7+
8+
export const InspectClusterArgs = {
9+
projectId: AtlasArgs.projectId().describe("Atlas project ID"),
10+
clusterName: AtlasArgs.clusterName().describe("Atlas cluster name"),
11+
};
912

1013
export class InspectClusterTool extends AtlasToolBase {
1114
public name = "atlas-inspect-cluster";
1215
protected description = "Inspect MongoDB Atlas cluster";
1316
public operationType: OperationType = "read";
1417
protected argsShape = {
15-
projectId: AtlasArgs.projectId().describe("Atlas project ID"),
16-
clusterName: z.string().describe("Atlas cluster name"),
18+
...InspectClusterArgs,
1719
};
1820

1921
protected async execute({ projectId, clusterName }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {

src/tools/atlas/read/listAlerts.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2+
import { type OperationType, type ToolArgs, formatUntrustedData } from "../../tool.js";
23
import { AtlasToolBase } from "../atlasTool.js";
3-
import type { ToolArgs, OperationType } from "../../tool.js";
4-
import { formatUntrustedData } from "../../tool.js";
5-
import { AtlasArgs } from "../validators.js";
4+
import { AtlasArgs } from "../../args.js";
5+
6+
export const ListAlertsArgs = {
7+
projectId: AtlasArgs.projectId().describe("Atlas project ID to list alerts for"),
8+
};
69

710
export class ListAlertsTool extends AtlasToolBase {
811
public name = "atlas-list-alerts";
912
protected description = "List MongoDB Atlas alerts";
1013
public operationType: OperationType = "read";
1114
protected argsShape = {
12-
projectId: AtlasArgs.projectId().describe("Atlas project ID to list alerts for"),
15+
...ListAlertsArgs,
1316
};
1417

1518
protected async execute({ projectId }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {

0 commit comments

Comments
 (0)