diff --git a/src/mcp/tools/compose/composeCleanQueues.ts b/src/mcp/tools/compose/composeCleanQueues.ts new file mode 100644 index 0000000..50e2d61 --- /dev/null +++ b/src/mcp/tools/compose/composeCleanQueues.ts @@ -0,0 +1,30 @@ +import { z } from "zod"; +import apiClient from "../../../utils/apiClient.js"; +import { ResponseFormatter } from "../../../utils/responseFormatter.js"; +import { createTool } from "../toolFactory.js"; + +export const composeCleanQueues = createTool({ + name: "compose-cleanQueues", + description: + "Cleans the deployment queues for a compose stack in Dokploy. Use this to unstick a stuck deployment.", + schema: z.object({ + composeId: z + .string() + .min(1) + .describe("The ID of the compose stack to clean queues for."), + }), + annotations: { + title: "Clean Compose Queues", + destructiveHint: false, + idempotentHint: true, + openWorldHint: true, + }, + handler: async (input) => { + const response = await apiClient.post("/compose.cleanQueues", input); + + return ResponseFormatter.success( + `Compose stack "${input.composeId}" queues cleaned successfully`, + response.data + ); + }, +}); diff --git a/src/mcp/tools/compose/composeDeploy.ts b/src/mcp/tools/compose/composeDeploy.ts new file mode 100644 index 0000000..96446d7 --- /dev/null +++ b/src/mcp/tools/compose/composeDeploy.ts @@ -0,0 +1,29 @@ +import { z } from "zod"; +import apiClient from "../../../utils/apiClient.js"; +import { ResponseFormatter } from "../../../utils/responseFormatter.js"; +import { createTool } from "../toolFactory.js"; + +export const composeDeploy = createTool({ + name: "compose-deploy", + description: "Deploys a compose stack in Dokploy.", + schema: z.object({ + composeId: z + .string() + .min(1) + .describe("The ID of the compose stack to deploy."), + }), + annotations: { + title: "Deploy Compose Stack", + destructiveHint: false, + idempotentHint: false, + openWorldHint: true, + }, + handler: async (input) => { + const response = await apiClient.post("/compose.deploy", input); + + return ResponseFormatter.success( + `Compose stack "${input.composeId}" deployment started successfully`, + response.data + ); + }, +}); diff --git a/src/mcp/tools/compose/composeOne.ts b/src/mcp/tools/compose/composeOne.ts new file mode 100644 index 0000000..5c29422 --- /dev/null +++ b/src/mcp/tools/compose/composeOne.ts @@ -0,0 +1,32 @@ +import { z } from "zod"; +import apiClient from "../../../utils/apiClient.js"; +import { ResponseFormatter } from "../../../utils/responseFormatter.js"; +import { createTool } from "../toolFactory.js"; + +export const composeOne = createTool({ + name: "compose-one", + description: "Retrieves details of a specific compose stack in Dokploy.", + schema: z.object({ + composeId: z + .string() + .min(1) + .describe("The ID of the compose stack to retrieve."), + }), + annotations: { + title: "Get Compose Stack", + readOnlyHint: true, + destructiveHint: false, + idempotentHint: true, + openWorldHint: true, + }, + handler: async (input) => { + const response = await apiClient.get("/compose.one", { + params: input, + }); + + return ResponseFormatter.success( + `Compose stack "${input.composeId}" retrieved successfully`, + response.data + ); + }, +}); diff --git a/src/mcp/tools/compose/composeRedeploy.ts b/src/mcp/tools/compose/composeRedeploy.ts new file mode 100644 index 0000000..59a1bc9 --- /dev/null +++ b/src/mcp/tools/compose/composeRedeploy.ts @@ -0,0 +1,29 @@ +import { z } from "zod"; +import apiClient from "../../../utils/apiClient.js"; +import { ResponseFormatter } from "../../../utils/responseFormatter.js"; +import { createTool } from "../toolFactory.js"; + +export const composeRedeploy = createTool({ + name: "compose-redeploy", + description: "Redeploys a compose stack in Dokploy (pulls latest images and restarts).", + schema: z.object({ + composeId: z + .string() + .min(1) + .describe("The ID of the compose stack to redeploy."), + }), + annotations: { + title: "Redeploy Compose Stack", + destructiveHint: false, + idempotentHint: false, + openWorldHint: true, + }, + handler: async (input) => { + const response = await apiClient.post("/compose.redeploy", input); + + return ResponseFormatter.success( + `Compose stack "${input.composeId}" redeployment started successfully`, + response.data + ); + }, +}); diff --git a/src/mcp/tools/compose/composeStart.ts b/src/mcp/tools/compose/composeStart.ts new file mode 100644 index 0000000..59d9f05 --- /dev/null +++ b/src/mcp/tools/compose/composeStart.ts @@ -0,0 +1,29 @@ +import { z } from "zod"; +import apiClient from "../../../utils/apiClient.js"; +import { ResponseFormatter } from "../../../utils/responseFormatter.js"; +import { createTool } from "../toolFactory.js"; + +export const composeStart = createTool({ + name: "compose-start", + description: "Starts a compose stack in Dokploy.", + schema: z.object({ + composeId: z + .string() + .min(1) + .describe("The ID of the compose stack to start."), + }), + annotations: { + title: "Start Compose Stack", + destructiveHint: false, + idempotentHint: false, + openWorldHint: true, + }, + handler: async (input) => { + const response = await apiClient.post("/compose.start", input); + + return ResponseFormatter.success( + `Compose stack "${input.composeId}" started successfully`, + response.data + ); + }, +}); diff --git a/src/mcp/tools/compose/composeStop.ts b/src/mcp/tools/compose/composeStop.ts new file mode 100644 index 0000000..d1e7c16 --- /dev/null +++ b/src/mcp/tools/compose/composeStop.ts @@ -0,0 +1,29 @@ +import { z } from "zod"; +import apiClient from "../../../utils/apiClient.js"; +import { ResponseFormatter } from "../../../utils/responseFormatter.js"; +import { createTool } from "../toolFactory.js"; + +export const composeStop = createTool({ + name: "compose-stop", + description: "Stops a running compose stack in Dokploy.", + schema: z.object({ + composeId: z + .string() + .min(1) + .describe("The ID of the compose stack to stop."), + }), + annotations: { + title: "Stop Compose Stack", + destructiveHint: false, + idempotentHint: false, + openWorldHint: true, + }, + handler: async (input) => { + const response = await apiClient.post("/compose.stop", input); + + return ResponseFormatter.success( + `Compose stack "${input.composeId}" stopped successfully`, + response.data + ); + }, +}); diff --git a/src/mcp/tools/compose/index.ts b/src/mcp/tools/compose/index.ts new file mode 100644 index 0000000..bcd0d3d --- /dev/null +++ b/src/mcp/tools/compose/index.ts @@ -0,0 +1,6 @@ +export { composeOne } from "./composeOne.js"; +export { composeDeploy } from "./composeDeploy.js"; +export { composeRedeploy } from "./composeRedeploy.js"; +export { composeStart } from "./composeStart.js"; +export { composeStop } from "./composeStop.js"; +export { composeCleanQueues } from "./composeCleanQueues.js"; diff --git a/src/mcp/tools/index.ts b/src/mcp/tools/index.ts index 5a9e1ac..91ba2a0 100644 --- a/src/mcp/tools/index.ts +++ b/src/mcp/tools/index.ts @@ -1,4 +1,5 @@ import * as applicationTools from "./application/index.js"; +import * as composeTools from "./compose/index.js"; import * as domainTools from "./domain/index.js"; import * as mysqlTools from "./mysql/index.js"; import * as postgresTools from "./postgres/index.js"; @@ -7,6 +8,7 @@ import * as projectTools from "./project/index.js"; export const allTools = [ ...Object.values(projectTools), ...Object.values(applicationTools), + ...Object.values(composeTools), ...Object.values(domainTools), ...Object.values(mysqlTools), ...Object.values(postgresTools),