Repository navigation
add delete-sub-account tool #144
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| import deleteSubAccount from "../deleteSubAccount"; | ||
| import { getOrganizationClient } from "../../../client"; | ||
|
|
||
| const mockClient = { | ||
| organizations: { | ||
| subAccounts: { | ||
| delete: jest.fn(), | ||
| }, | ||
| }, | ||
| }; | ||
|
|
||
| jest.mock("../../../client", () => ({ | ||
| getOrganizationClient: jest.fn(() => mockClient), | ||
| })); | ||
|
|
||
| describe("deleteSubAccount", () => { | ||
| beforeEach(() => { | ||
| jest.clearAllMocks(); | ||
| (getOrganizationClient as jest.Mock).mockReturnValue(mockClient); | ||
| }); | ||
|
|
||
| it("deletes the sub-account via the organization client and confirms deletion", async () => { | ||
| mockClient.organizations.subAccounts.delete.mockResolvedValue(undefined); | ||
|
|
||
| const result = await deleteSubAccount({ sub_account_id: 99 }); | ||
|
|
||
| expect(getOrganizationClient).toHaveBeenCalledWith(); | ||
| expect(mockClient.organizations.subAccounts.delete).toHaveBeenCalledWith( | ||
| 99 | ||
| ); | ||
| expect(result.content[0].text).toContain('"sub_account_id": 99'); | ||
| expect(result.content[0].text).toContain('"deleted": true'); | ||
| expect(result.isError).toBeUndefined(); | ||
| }); | ||
|
|
||
| it("rejects invalid input before calling the SDK", async () => { | ||
| const result = await deleteSubAccount({ sub_account_id: "abc" }); | ||
|
|
||
| expect(result.isError).toBe(true); | ||
| expect(result.content[0].text).toContain( | ||
| "Failed to delete sub-account: Invalid input:" | ||
| ); | ||
| expect(result.content[0].text).toContain("sub_account_id"); | ||
| expect(mockClient.organizations.subAccounts.delete).not.toHaveBeenCalled(); | ||
| }); | ||
|
|
||
| it("surfaces API errors", async () => { | ||
| mockClient.organizations.subAccounts.delete.mockRejectedValue( | ||
| new Error("Not Found") | ||
| ); | ||
|
|
||
| const result = await deleteSubAccount({ sub_account_id: 99 }); | ||
|
|
||
| expect(result.isError).toBe(true); | ||
| expect(result.content[0].text).toBe( | ||
| "Failed to delete sub-account: Not Found" | ||
| ); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import { getOrganizationClient } from "../../client"; | ||
| import { deleteSubAccountZod } from "./schemas/deleteSubAccount"; | ||
| import { | ||
| buildErrorResponse, | ||
| buildSuccessResponse, | ||
| ToolResponse, | ||
| } from "../utils/responses"; | ||
|
|
||
| async function deleteSubAccount(raw: unknown): Promise<ToolResponse> { | ||
| const parsed = deleteSubAccountZod.safeParse(raw); | ||
| if (!parsed.success) { | ||
| const msg = parsed.error.errors | ||
| .map((e) => `${e.path.join(".")}: ${e.message}`) | ||
| .join("; "); | ||
| return buildErrorResponse( | ||
| "delete sub-account", | ||
| new Error(`Invalid input: ${msg}`) | ||
| ); | ||
| } | ||
|
|
||
| const subAccountId = parsed.data.sub_account_id; | ||
|
|
||
| try { | ||
| const mailtrap = getOrganizationClient(); | ||
|
|
||
| // TODO: drop the cast after bumping mailtrap to the release that ships subAccounts.delete | ||
| const subAccounts = mailtrap.organizations.subAccounts as unknown as { | ||
| delete(id: number): Promise<void>; | ||
| }; | ||
|
Comment on lines
+27
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
set -euo pipefail
# Confirm the effective repository dependency declaration.
fd -HI -t f '^(package\.json|package-lock\.json|npm-shrinkwrap\.json|pnpm-lock\.yaml|yarn\.lock)$' . \
-x rg -n -C 2 '"mailtrap"|mailtrap@' {}
# Inspect the published 4.10.0 package without executing repository code.
tmp_dir="$(mktemp -d)"
trap 'rm -rf "$tmp_dir"' EXIT
curl -fsSL 'https://registry.npmjs.org/mailtrap/4.10.0' > "$tmp_dir/metadata.json"
tarball_url="$(jq -r '.dist.tarball' "$tmp_dir/metadata.json")"
curl -fsSL "$tarball_url" | tar -xzf - -C "$tmp_dir"
rg -n -C 3 'subAccounts|delete\s*\(' "$tmp_dir/package"Repository: mailtrap/mailtrap-mcp Length of output: 30595 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- dependency resolution ---'
for f in package.json package-lock.json npm-shrinkwrap.json pnpm-lock.yaml yarn.lock; do
if [ -f "$f" ]; then
echo "### $f"
rg -n -C 4 'mailtrap' "$f" || true
fi
done
printf '%s\n' '--- reviewed implementation ---'
cat -n src/tools/organizations/deleteSubAccount.ts
printf '%s\n' '--- SDK method bindings in repository ---'
rg -n -C 3 'subAccounts|deleteSubAccount' src test tests .github 2>/dev/null || trueRepository: mailtrap/mailtrap-mcp Length of output: 21367 Upgrade the SDK or use a supported API before release.
🤖 Prompt for AI Agents |
||
|
|
||
| await subAccounts.delete(subAccountId); | ||
|
|
||
| return buildSuccessResponse( | ||
| JSON.stringify({ sub_account_id: subAccountId, deleted: true }, null, 2) | ||
| ); | ||
| } catch (error) { | ||
| return buildErrorResponse("delete sub-account", error); | ||
|
Comment on lines
+36
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Rethrow a descriptive error from this catch block. This catch block returns a 🤖 Prompt for AI AgentsSource: Coding guidelines |
||
| } | ||
| } | ||
|
|
||
| export default deleteSubAccount; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,10 +2,14 @@ import listSubAccountsSchema from "./schemas/listSubAccounts"; | |
| import listSubAccounts from "./listSubAccounts"; | ||
| import createSubAccountSchema from "./schemas/createSubAccount"; | ||
| import createSubAccount from "./createSubAccount"; | ||
| import deleteSubAccountSchema from "./schemas/deleteSubAccount"; | ||
| import deleteSubAccount from "./deleteSubAccount"; | ||
|
Comment on lines
+5
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift Use the required per-tool directory layout. These imports keep As per path instructions, tools under 🤖 Prompt for AI AgentsSource: Path instructions |
||
|
|
||
| export { | ||
| listSubAccountsSchema, | ||
| listSubAccounts, | ||
| createSubAccountSchema, | ||
| createSubAccount, | ||
| deleteSubAccountSchema, | ||
| deleteSubAccount, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,21 @@ | ||||||||
| import { z } from "zod"; | ||||||||
|
|
||||||||
| const deleteSubAccountSchema = { | ||||||||
| type: "object", | ||||||||
| properties: { | ||||||||
| sub_account_id: { | ||||||||
| type: "number", | ||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win Make the MCP schema match the Zod contract.
Proposed fix- type: "number",
+ type: "integer",
+ minimum: 1,📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||
| description: "ID of the sub-account to delete.", | ||||||||
| }, | ||||||||
| }, | ||||||||
| required: ["sub_account_id"], | ||||||||
| additionalProperties: false, | ||||||||
| }; | ||||||||
|
|
||||||||
| export const deleteSubAccountZod = z | ||||||||
| .object({ | ||||||||
| sub_account_id: z.number().int().positive(), | ||||||||
| }) | ||||||||
| .strict(); | ||||||||
|
|
||||||||
| export default deleteSubAccountSchema; | ||||||||
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.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Use the required per-tool directory layout.
Move this tool into one tool directory. Use
index.ts,schema.ts,implementation.ts, and__tests__/. Keep the implementation, schema, and tests together.🤖 Prompt for AI Agents
Source: Coding guidelines