Skip to content

Commit 2b080d5

Browse files
authored
feat: add structured content for response in atlas tools - MCP-374 (#1288)
1 parent c1e92cb commit 2b080d5

41 files changed

Lines changed: 3521 additions & 252 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

api-extractor/reports/tools.public.api.md

Lines changed: 291 additions & 30 deletions
Large diffs are not rendered by default.

src/tools/atlas/create/createAccessList.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { z } from "zod";
2-
import { type OperationType, type ToolArgs, type ToolExecutionContext } from "../../tool.js";
3-
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2+
import { type OperationType, type ToolArgs, type ToolExecutionContext, type ToolResult } from "../../tool.js";
43
import { AtlasToolBase } from "../atlasTool.js";
54
import { makeCurrentIpAccessListEntry, DEFAULT_ACCESS_LIST_COMMENT } from "../../../common/atlas/accessListUtils.js";
65
import { AtlasArgs, CommonArgs } from "../../args.js";
@@ -16,18 +15,23 @@ export const CreateAccessListArgs = {
1615
.optional(),
1716
};
1817

18+
const CreateAccessListOutputSchema = {
19+
projectId: z.string(),
20+
};
21+
1922
export class CreateAccessListTool extends AtlasToolBase {
2023
static toolName = "atlas-create-access-list";
2124
public description = "Allow Ip/CIDR ranges to access your MongoDB Atlas clusters.";
2225
static operationType: OperationType = "create";
2326
public argsShape = {
2427
...CreateAccessListArgs,
2528
};
29+
public override outputSchema = CreateAccessListOutputSchema;
2630

2731
protected async execute(
2832
{ projectId, ipAddresses, cidrBlocks, comment, currentIpAddress }: ToolArgs<typeof this.argsShape>,
2933
context: ToolExecutionContext
30-
): Promise<CallToolResult> {
34+
): Promise<ToolResult<typeof this.outputSchema>> {
3135
if (!ipAddresses?.length && !cidrBlocks?.length && !currentIpAddress) {
3236
throw new Error("One of ipAddresses, cidrBlocks, currentIpAddress must be provided.");
3337
}
@@ -74,6 +78,9 @@ export class CreateAccessListTool extends AtlasToolBase {
7478
text: `IP/CIDR ranges added to access list for project ${projectId}.`,
7579
},
7680
],
81+
structuredContent: {
82+
projectId,
83+
},
7784
};
7885
}
7986

src/tools/atlas/create/createDBUser.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { z } from "zod";
2-
import type { ToolArgs, OperationType, ToolExecutionContext } from "../../tool.js";
3-
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2+
import type { ToolArgs, OperationType, ToolExecutionContext, ToolResult } from "../../tool.js";
43
import { AtlasToolBase } from "../atlasTool.js";
54
import type { CloudDatabaseUser, DatabaseUserRole } from "../../../common/atlas/openapi.js";
65
import { generateSecurePassword } from "../../../helpers/generatePassword.js";
@@ -14,7 +13,7 @@ export const CreateDBUserArgs = {
1413
// AtlasPassword123, which are easily guessable and exploitable. We're instructing
1514
// the model not to try and generate anything and instead leave the field unset.
1615
password: AtlasArgs.password()
17-
.nullish()
16+
.optional()
1817
.describe(
1918
"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."
2019
),
@@ -33,18 +32,24 @@ export const CreateDBUserArgs = {
3332
.optional(),
3433
};
3534

35+
const CreateDBUserOutputSchema = {
36+
username: z.string(),
37+
password: z.string().optional(),
38+
};
39+
3640
export class CreateDBUserTool extends AtlasToolBase {
3741
static toolName = "atlas-create-db-user";
3842
public description = "Create an MongoDB Atlas database user";
3943
static operationType: OperationType = "create";
4044
public argsShape = {
4145
...CreateDBUserArgs,
4246
};
47+
public override outputSchema = CreateDBUserOutputSchema;
4348

4449
protected async execute(
4550
{ projectId, username, password, roles, clusters }: ToolArgs<typeof this.argsShape>,
4651
context: ToolExecutionContext
47-
): Promise<CallToolResult> {
52+
): Promise<ToolResult<typeof this.outputSchema>> {
4853
await ensureCurrentIpInAccessList(this.apiClient, projectId, context);
4954
const shouldGeneratePassword = !password;
5055
if (shouldGeneratePassword) {
@@ -93,6 +98,10 @@ export class CreateDBUserTool extends AtlasToolBase {
9398
text: `User "${username}" created successfully${shouldGeneratePassword ? ` with password: \`${password}\`` : ""}.`,
9499
},
95100
],
101+
structuredContent: {
102+
username,
103+
...(shouldGeneratePassword && { password }),
104+
},
96105
};
97106
}
98107

src/tools/atlas/create/createFreeCluster.ts

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

8+
const CreateFreeClusterOutputSchema = {
9+
created: z.boolean().describe("Whether the cluster was created successfully"),
10+
};
11+
812
export class CreateFreeClusterTool extends AtlasToolBase {
913
static toolName = "atlas-create-free-cluster";
1014
public description = "Create a free MongoDB Atlas cluster";
@@ -14,11 +18,12 @@ export class CreateFreeClusterTool extends AtlasToolBase {
1418
name: AtlasArgs.clusterName().describe("Name of the cluster"),
1519
region: AtlasArgs.region().describe("Region of the cluster").default("US_EAST_1"),
1620
};
21+
public override outputSchema = CreateFreeClusterOutputSchema;
1722

1823
protected async execute(
1924
{ projectId, name, region }: ToolArgs<typeof this.argsShape>,
2025
context: ToolExecutionContext
21-
): Promise<CallToolResult> {
26+
): Promise<ToolResult<typeof this.outputSchema>> {
2227
const input = {
2328
groupId: projectId,
2429
name,
@@ -59,6 +64,9 @@ export class CreateFreeClusterTool extends AtlasToolBase {
5964
{ type: "text", text: `Cluster "${name}" has been created in region "${region}".` },
6065
{ type: "text", text: `Double check your access lists to enable your current IP.` },
6166
],
67+
structuredContent: {
68+
created: true,
69+
},
6270
};
6371
}
6472
}

src/tools/atlas/create/createProject.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
2-
import { type OperationType, type ToolArgs, type ToolExecutionContext } from "../../tool.js";
1+
import { z } from "zod";
2+
import { type OperationType, type ToolArgs, type ToolExecutionContext, type ToolResult } from "../../tool.js";
33
import { AtlasToolBase } from "../atlasTool.js";
44
import type { Group } from "../../../common/atlas/openapi.js";
55
import { AtlasArgs } from "../../args.js";
66

7+
const CreateProjectOutputSchema = {
8+
projectName: z.string(),
9+
organizationId: z.string().optional(),
10+
};
11+
712
export class CreateProjectTool extends AtlasToolBase {
813
static toolName = "atlas-create-project";
914
public description = "Create a MongoDB Atlas project";
@@ -12,11 +17,12 @@ export class CreateProjectTool extends AtlasToolBase {
1217
projectName: AtlasArgs.projectName().optional().describe("Name for the new project"),
1318
organizationId: AtlasArgs.organizationId().optional().describe("Organization ID for the new project"),
1419
};
20+
public override outputSchema = CreateProjectOutputSchema;
1521

1622
protected async execute(
1723
{ projectName, organizationId }: ToolArgs<typeof this.argsShape>,
1824
context: ToolExecutionContext
19-
): Promise<CallToolResult> {
25+
): Promise<ToolResult<typeof this.outputSchema>> {
2026
let assumedOrg = false;
2127

2228
if (!projectName) {
@@ -69,6 +75,10 @@ export class CreateProjectTool extends AtlasToolBase {
6975
text: `Project "${projectName}" created successfully${assumedOrg ? ` (using organizationId ${organizationId}).` : ""}.`,
7076
},
7177
],
78+
structuredContent: {
79+
projectName,
80+
...(assumedOrg && { organizationId }),
81+
},
7282
};
7383
}
7484
}

0 commit comments

Comments
 (0)