@mks2508/coolify-mks-cli-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/cli/index.js +11788 -0
  2. package/dist/coolify/config.d.ts +64 -0
  3. package/dist/coolify/config.d.ts.map +1 -0
  4. package/dist/coolify/index.d.ts +201 -0
  5. package/dist/coolify/index.d.ts.map +1 -0
  6. package/dist/coolify/types.d.ts +282 -0
  7. package/dist/coolify/types.d.ts.map +1 -0
  8. package/dist/index.cjs +29150 -0
  9. package/dist/index.cjs.map +1 -0
  10. package/dist/index.d.ts +14 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +29127 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/server/sse.d.ts +11 -0
  15. package/dist/server/sse.d.ts.map +1 -0
  16. package/dist/server/sse.js +32 -0
  17. package/dist/server/stdio.d.ts +13 -0
  18. package/dist/server/stdio.d.ts.map +1 -0
  19. package/dist/server/stdio.js +18326 -0
  20. package/dist/tools/definitions.d.ts +13 -0
  21. package/dist/tools/definitions.d.ts.map +1 -0
  22. package/dist/tools/handlers.d.ts +19 -0
  23. package/dist/tools/handlers.d.ts.map +1 -0
  24. package/dist/utils/format.d.ts +38 -0
  25. package/dist/utils/format.d.ts.map +1 -0
  26. package/package.json +67 -0
  27. package/src/cli/commands/config.ts +83 -0
  28. package/src/cli/commands/deploy.ts +56 -0
  29. package/src/cli/commands/env.ts +60 -0
  30. package/src/cli/commands/list.ts +63 -0
  31. package/src/cli/commands/logs.ts +49 -0
  32. package/src/cli/commands/servers.ts +52 -0
  33. package/src/cli/index.ts +81 -0
  34. package/src/coolify/config.ts +113 -0
  35. package/src/coolify/index.ts +688 -0
  36. package/src/coolify/types.ts +297 -0
  37. package/src/index.ts +864 -0
  38. package/src/server/sse.ts +50 -0
  39. package/src/server/stdio.ts +52 -0
  40. package/src/tools/definitions.ts +435 -0
  41. package/src/tools/handlers.ts +605 -0
  42. package/src/utils/format.ts +104 -0
@@ -0,0 +1,13 @@
1
+ /**
2
+ * MCP Tool definitions for Coolify.
3
+ *
4
+ * Defines all 21 tools with their input schemas.
5
+ *
6
+ * @module
7
+ */
8
+ import type { Tool } from '@modelcontextprotocol/sdk/types.js';
9
+ /**
10
+ * All Coolify MCP tool definitions.
11
+ */
12
+ export declare const coolifyTools: Tool[];
13
+ //# sourceMappingURL=definitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/tools/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAA;AAE9D;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,IAAI,EAqa9B,CAAA"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * MCP Tool handlers for Coolify.
3
+ *
4
+ * Handles execution of all 21 Coolify MCP tools.
5
+ *
6
+ * @module
7
+ */
8
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
9
+ import type { CoolifyService } from '../coolify/index.js';
10
+ /**
11
+ * Handler function for tool calls.
12
+ *
13
+ * @param name - Tool name
14
+ * @param args - Tool arguments
15
+ * @param coolify - CoolifyService instance
16
+ * @returns Tool call result
17
+ */
18
+ export declare function handleToolCall(name: string, args: Record<string, unknown>, coolify: CoolifyService): Promise<CallToolResult>;
19
+ //# sourceMappingURL=handlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/tools/handlers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAA;AAExE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEzD;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,cAAc,CAAC,CA0DzB"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Formatting utilities for CLI output.
3
+ *
4
+ * Provides table formatting and color helpers.
5
+ *
6
+ * @module
7
+ */
8
+ import Table from 'cli-table3';
9
+ /**
10
+ * Creates a formatted table with headers.
11
+ *
12
+ * @param headers - Column headers
13
+ * @param colWidths - Optional column widths
14
+ * @returns Configured Table instance
15
+ */
16
+ export declare function createTable(headers: string[], colWidths?: number[]): Table.Table;
17
+ /**
18
+ * Formats application status with colored indicator.
19
+ *
20
+ * @param status - Application status string
21
+ * @returns Formatted status string
22
+ */
23
+ export declare function formatStatus(status: string): string;
24
+ /**
25
+ * Formats bytes to human-readable format.
26
+ *
27
+ * @param bytes - Number of bytes
28
+ * @returns Formatted string with unit
29
+ */
30
+ export declare function formatBytes(bytes: number): string;
31
+ /**
32
+ * Formats timestamp to relative time.
33
+ *
34
+ * @param timestamp - ISO timestamp string
35
+ * @returns Relative time string
36
+ */
37
+ export declare function formatRelativeTime(timestamp: string): string;
38
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,YAAY,CAAA;AAY9B;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,eAOlE;AAgBD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAWnD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQjD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAY5D"}
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@mks2508/coolify-mks-cli-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server and CLI for Coolify deployment management",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "bin": {
10
+ "coolify-mcp": "./dist/cli/index.js",
11
+ "coolify-mcp-server": "./dist/server/stdio.js"
12
+ },
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ },
18
+ "./coolify": {
19
+ "types": "./dist/coolify/index.d.ts",
20
+ "import": "./dist/coolify/index.js"
21
+ },
22
+ "./tools": {
23
+ "types": "./dist/tools/definitions.d.ts",
24
+ "import": "./dist/tools/definitions.js"
25
+ },
26
+ "./server": {
27
+ "types": "./dist/server/stdio.d.ts",
28
+ "import": "./dist/server/stdio.js"
29
+ },
30
+ "./package.json": "./package.json"
31
+ },
32
+ "files": [
33
+ "dist",
34
+ "src"
35
+ ],
36
+ "scripts": {
37
+ "dev": "bun --watch src/index.ts",
38
+ "dev:mcp": "bun --watch src/server/stdio.ts",
39
+ "dev:sse": "bun --watch src/server/sse.ts",
40
+ "dev:cli": "bun --watch src/cli/index.ts",
41
+ "build": "bun run build:mcp && bun run build:cli",
42
+ "build:mcp": "rolldown --config rolldown.config.ts && tsc --project tsconfig.build.json",
43
+ "build:cli": "bun build ./src/cli/index.ts --outdir ./dist/cli --target node && bun build ./src/server/stdio.ts --outdir ./dist/server --target node && bun build ./src/server/sse.ts --outdir ./dist/server --target node",
44
+ "typecheck": "tsgo --noEmit"
45
+ },
46
+ "dependencies": {
47
+ "@anthropic-ai/claude-agent-sdk": "^0.2.1",
48
+ "@mks2508/better-logger": "^4.0.0",
49
+ "@mks2508/no-throw": "^0.1.0",
50
+ "@modelcontextprotocol/sdk": "^1.25.2",
51
+ "chalk": "^5.4.1",
52
+ "cli-table3": "^0.6.5",
53
+ "commander": "^12.1.0",
54
+ "ora": "^8.1.1",
55
+ "prompts": "^2.4.2",
56
+ "zod": "^3.24.1"
57
+ },
58
+ "devDependencies": {
59
+ "@types/node": "^22.10.5",
60
+ "@types/prompts": "^2.4.9",
61
+ "rolldown": "^1.0.0-beta.58",
62
+ "typescript": "^5.8.0"
63
+ },
64
+ "engines": {
65
+ "node": ">=18.0.0"
66
+ }
67
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Config command for CLI.
3
+ *
4
+ * @module
5
+ */
6
+
7
+ import { isOk } from '@mks2508/no-throw'
8
+ import chalk from 'chalk'
9
+ import { existsSync } from 'node:fs'
10
+ import { loadConfig, saveConfig, CONFIG_FILE } from '../../coolify/config.js'
11
+
12
+ /**
13
+ * Config command handler.
14
+ *
15
+ * @param action - Config action (set, get, path)
16
+ * @param args - Action arguments
17
+ */
18
+ export async function configCommand(
19
+ action: string | undefined,
20
+ args: { key?: string; value?: string }
21
+ ) {
22
+ if (action === 'set') {
23
+ if (!args.key || !args.value) {
24
+ console.error(chalk.red('Error: key and value are required for "set" command'))
25
+ console.log(chalk.gray('Usage: coolify-mcp config set <key> <value>'))
26
+ console.log(chalk.gray('Keys: url, token'))
27
+ return
28
+ }
29
+
30
+ const result = await loadConfig()
31
+ if (isOk(result)) {
32
+ const config = result.value
33
+ if (args.key === 'url') {
34
+ config.url = args.value
35
+ } else if (args.key === 'token') {
36
+ config.token = args.value
37
+ } else {
38
+ console.error(chalk.red(`Error: Unknown key "${args.key}"`))
39
+ return
40
+ }
41
+
42
+ const saveResult = await saveConfig(config)
43
+ if (isOk(saveResult)) {
44
+ console.log(chalk.green(`Config updated: ${args.key} = ${args.value}`))
45
+ } else {
46
+ console.error(chalk.red(`Error: ${saveResult.error.message}`))
47
+ }
48
+ }
49
+ } else if (action === 'get') {
50
+ const result = await loadConfig()
51
+ if (isOk(result)) {
52
+ const config = result.value
53
+ console.log(chalk.cyan('Current configuration:'))
54
+ console.log(` URL: ${chalk.gray(config.url || '(not set)')}`)
55
+ console.log(` Token: ${chalk.gray(config.token ? '(set)' : '(not set)')}`)
56
+ } else {
57
+ console.error(chalk.red(`Error: ${result.error.message}`))
58
+ }
59
+ } else if (action === 'path') {
60
+ console.log(chalk.cyan('Config file:'))
61
+ console.log(` ${CONFIG_FILE}`)
62
+ if (existsSync(CONFIG_FILE)) {
63
+ console.log(chalk.gray(' Status: File exists'))
64
+ } else {
65
+ console.log(chalk.yellow(' Status: File does not exist'))
66
+ }
67
+ } else {
68
+ console.log(chalk.cyan('Coolify MCP Configuration'))
69
+ console.log()
70
+ console.log(chalk.gray('Commands:'))
71
+ console.log(' coolify-mcp config set <key> <value> Set a config value')
72
+ console.log(' coolify-mcp config get Show current config')
73
+ console.log(' coolify-mcp config path Show config file path')
74
+ console.log()
75
+ console.log(chalk.gray('Keys:'))
76
+ console.log(' url - Coolify instance URL')
77
+ console.log(' token - Coolify API token')
78
+ console.log()
79
+ console.log(chalk.gray('Environment variables:'))
80
+ console.log(' COOLIFY_URL - Coolify instance URL')
81
+ console.log(' COOLIFY_TOKEN - Coolify API token')
82
+ }
83
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Deploy command for CLI.
3
+ *
4
+ * @module
5
+ */
6
+
7
+ import { isOk, isErr } from '@mks2508/no-throw'
8
+ import ora from 'ora'
9
+ import chalk from 'chalk'
10
+ import { getCoolifyService } from '../../coolify/index.js'
11
+
12
+ /**
13
+ * Deploy command handler.
14
+ *
15
+ * @param uuid - Application UUID
16
+ * @param options - Deploy options
17
+ */
18
+ export async function deployCommand(uuid: string, options: { force?: boolean; tag?: string }) {
19
+ const spinner = ora('Initializing Coolify connection...').start()
20
+
21
+ try {
22
+ const coolify = getCoolifyService()
23
+ const initResult = await coolify.init()
24
+
25
+ if (isErr(initResult)) {
26
+ spinner.fail(chalk.red(`Failed to initialize: ${initResult.error.message}`))
27
+ return
28
+ }
29
+
30
+ spinner.text = 'Triggering deployment...'
31
+
32
+ const result = await coolify.deploy(
33
+ {
34
+ uuid,
35
+ force: options.force,
36
+ tag: options.tag,
37
+ },
38
+ (percent, message) => {
39
+ spinner.text = `${chalk.bold(`[${percent}%]`)} ${message}`
40
+ }
41
+ )
42
+
43
+ if (isOk(result)) {
44
+ spinner.succeed(
45
+ chalk.green(`Deployment triggered! UUID: ${chalk.cyan(result.value.deploymentUuid?.slice(0, 8))}`)
46
+ )
47
+ console.log(` Resource UUID: ${chalk.cyan(result.value.resourceUuid?.slice(0, 8))}`)
48
+ } else {
49
+ spinner.fail(chalk.red(`Deployment failed: ${result.error.message}`))
50
+ }
51
+ } catch (error) {
52
+ spinner.fail(
53
+ chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`)
54
+ )
55
+ }
56
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Env vars command for CLI.
3
+ *
4
+ * @module
5
+ */
6
+
7
+ import { isErr } from '@mks2508/no-throw'
8
+ import chalk from 'chalk'
9
+ import { getCoolifyService } from '../../coolify/index.js'
10
+
11
+ /**
12
+ * Env vars command handler.
13
+ *
14
+ * @param uuid - Application UUID
15
+ */
16
+ export async function envCommand(uuid: string) {
17
+ const coolify = getCoolifyService()
18
+ const initResult = await coolify.init()
19
+
20
+ if (isErr(initResult)) {
21
+ console.error(chalk.red(`Error: ${initResult.error.message}`))
22
+ return
23
+ }
24
+
25
+ const result = await coolify.getEnvironmentVariables(uuid)
26
+
27
+ if (isErr(result)) {
28
+ console.error(chalk.red(`Error: ${result.error.message}`))
29
+ return
30
+ }
31
+
32
+ const envVars = result.value
33
+
34
+ if (envVars.length === 0) {
35
+ console.log(chalk.yellow('No environment variables found'))
36
+ return
37
+ }
38
+
39
+ console.log(chalk.cyan(`Environment variables (${envVars.length}):\n`))
40
+
41
+ // Separar runtime de buildtime
42
+ const runtimeVars = envVars.filter(ev => ev.is_runtime)
43
+ const buildtimeVars = envVars.filter(ev => ev.is_buildtime)
44
+
45
+ if (runtimeVars.length > 0) {
46
+ console.log(chalk.yellow.bold('Runtime:'))
47
+ for (const ev of runtimeVars) {
48
+ const required = ev.is_required ? chalk.red(' *') : ''
49
+ console.log(` ${chalk.green(ev.key)}${required} = ${chalk.gray(ev.value)}`)
50
+ }
51
+ console.log()
52
+ }
53
+
54
+ if (buildtimeVars.length > 0) {
55
+ console.log(chalk.blue.bold('Buildtime:'))
56
+ for (const ev of buildtimeVars) {
57
+ console.log(` ${chalk.green(ev.key)} = ${chalk.gray(ev.value)}`)
58
+ }
59
+ }
60
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * List command for CLI.
3
+ *
4
+ * @module
5
+ */
6
+
7
+ import { isErr } from '@mks2508/no-throw'
8
+ import chalk from 'chalk'
9
+ import Table from 'cli-table3'
10
+ import { getCoolifyService } from '../../coolify/index.js'
11
+ import { formatStatus } from '../../utils/format.js'
12
+
13
+ /**
14
+ * List command handler.
15
+ *
16
+ * @param options - List options
17
+ */
18
+ export async function listCommand(options: { team?: string; project?: string }) {
19
+ const coolify = getCoolifyService()
20
+ const initResult = await coolify.init()
21
+
22
+ if (isErr(initResult)) {
23
+ console.error(chalk.red(`Error: ${initResult.error.message}`))
24
+ return
25
+ }
26
+
27
+ const result = await coolify.listApplications(options.team, options.project)
28
+
29
+ if (isErr(result)) {
30
+ console.error(chalk.red(`Error: ${result.error.message}`))
31
+ return
32
+ }
33
+
34
+ const apps = result.value
35
+
36
+ if (apps.length === 0) {
37
+ console.log(chalk.yellow('No applications found'))
38
+ return
39
+ }
40
+
41
+ // Usar ancho dinámico basado en el contenido
42
+ const table = new Table({
43
+ head: [
44
+ chalk.cyan('UUID'),
45
+ chalk.cyan('Name'),
46
+ chalk.cyan('Status'),
47
+ chalk.cyan('Server')
48
+ ],
49
+ // Sin anchos fijos, dejar que cli-table3 auto-ajuste
50
+ })
51
+
52
+ for (const app of apps) {
53
+ table.push([
54
+ app.uuid,
55
+ app.name,
56
+ formatStatus(app.status),
57
+ app.destination?.server?.name || 'N/A',
58
+ ])
59
+ }
60
+
61
+ console.log(table.toString())
62
+ console.log(chalk.gray(`Total: ${apps.length} application(s)`))
63
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Logs command for CLI.
3
+ *
4
+ * @module
5
+ */
6
+
7
+ import { isErr } from '@mks2508/no-throw'
8
+ import chalk from 'chalk'
9
+ import { getCoolifyService } from '../../coolify/index.js'
10
+
11
+ /**
12
+ * Logs command handler.
13
+ *
14
+ * @param uuid - Application UUID
15
+ * @param options - Logs options
16
+ */
17
+ export async function logsCommand(uuid: string, options: { lines?: number; follow?: boolean }) {
18
+ const coolify = getCoolifyService()
19
+ const initResult = await coolify.init()
20
+
21
+ if (isErr(initResult)) {
22
+ console.error(chalk.red(`Error: ${initResult.error.message}`))
23
+ return
24
+ }
25
+
26
+ const result = await coolify.getApplicationLogs(uuid, { tail: options.lines || 50 })
27
+
28
+ if (isErr(result)) {
29
+ console.error(chalk.red(`Error: ${result.error.message}`))
30
+ return
31
+ }
32
+
33
+ const logs = result.value
34
+
35
+ if (logs.logs.length === 0) {
36
+ console.log(chalk.yellow('No logs available'))
37
+ return
38
+ }
39
+
40
+ console.log(chalk.gray(`Application logs (${logs.logs.length} lines):\n`))
41
+
42
+ for (const line of logs.logs) {
43
+ console.log(line)
44
+ }
45
+
46
+ if (options.follow) {
47
+ console.log(chalk.yellow('\nFollow mode not yet implemented'))
48
+ }
49
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Servers command for CLI.
3
+ *
4
+ * @module
5
+ */
6
+
7
+ import { isErr } from '@mks2508/no-throw'
8
+ import chalk from 'chalk'
9
+ import { getCoolifyService } from '../../coolify/index.js'
10
+ import { createTable } from '../../utils/format.js'
11
+
12
+ /**
13
+ * Servers command handler.
14
+ */
15
+ export async function serversCommand() {
16
+ const coolify = getCoolifyService()
17
+ const initResult = await coolify.init()
18
+
19
+ if (isErr(initResult)) {
20
+ console.error(chalk.red(`Error: ${initResult.error.message}`))
21
+ return
22
+ }
23
+
24
+ const result = await coolify.listServers()
25
+
26
+ if (isErr(result)) {
27
+ console.error(chalk.red(`Error: ${result.error.message}`))
28
+ return
29
+ }
30
+
31
+ const servers = result.value
32
+
33
+ if (servers.length === 0) {
34
+ console.log(chalk.yellow('No servers found'))
35
+ return
36
+ }
37
+
38
+ const table = createTable(['UUID', 'Name', 'IP', 'Status'], [36, 25, 20, 15])
39
+
40
+ for (const server of servers) {
41
+ const statusColor = server.is_usable ? chalk.green : chalk.red
42
+ table.push([
43
+ server.uuid.slice(0, 8),
44
+ server.name,
45
+ server.ip || 'N/A',
46
+ statusColor(server.is_usable ? '● Usable' : '○ Unusable'),
47
+ ])
48
+ }
49
+
50
+ console.log(table.toString())
51
+ console.log(chalk.gray(`Total: ${servers.length} server(s)`))
52
+ }
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Coolify MCP CLI - Entry point.
4
+ *
5
+ * Command-line interface for Coolify deployment management.
6
+ *
7
+ * @module
8
+ */
9
+
10
+ import { Command } from 'commander'
11
+ import chalk from 'chalk'
12
+ import { deployCommand } from './commands/deploy.js'
13
+ import { listCommand } from './commands/list.js'
14
+ import { logsCommand } from './commands/logs.js'
15
+ import { serversCommand } from './commands/servers.js'
16
+ import { configCommand } from './commands/config.js'
17
+ import { envCommand } from './commands/env.js'
18
+
19
+ const program = new Command()
20
+
21
+ program
22
+ .name('coolify-mcp')
23
+ .description('CLI for Coolify deployment management')
24
+ .version('0.1.0')
25
+
26
+ // Config command
27
+ program
28
+ .command('config')
29
+ .description('Manage configuration')
30
+ .argument('[action]', 'Action to perform (set, get, path)')
31
+ .option('--key <key>', 'Configuration key (for "set" action)')
32
+ .option('--value <value>', 'Configuration value (for "set" action)')
33
+ .action(configCommand)
34
+
35
+ // List applications
36
+ program
37
+ .command('list')
38
+ .description('List all applications')
39
+ .option('-t, --team <id>', 'Filter by team ID')
40
+ .option('-p, --project <id>', 'Filter by project ID')
41
+ .action(listCommand)
42
+
43
+ // Deploy application
44
+ program
45
+ .command('deploy <uuid>')
46
+ .description('Deploy an application')
47
+ .option('-f, --force', 'Force rebuild without cache')
48
+ .option('-t, --tag <tag>', 'Deploy specific tag/version')
49
+ .action(deployCommand)
50
+
51
+ // Logs command
52
+ program
53
+ .command('logs <uuid>')
54
+ .description('Get application logs')
55
+ .option('-n, --lines <number>', 'Number of lines to retrieve', '50')
56
+ .option('-f, --follow', 'Follow logs in real-time')
57
+ .action((uuid, options) => {
58
+ const lines = parseInt(options.lines, 10)
59
+ logsCommand(uuid, { lines, follow: options.follow })
60
+ })
61
+
62
+ // Servers command
63
+ program
64
+ .command('servers')
65
+ .description('List available servers')
66
+ .action(serversCommand)
67
+
68
+ // Env vars command
69
+ program
70
+ .command('env <uuid>')
71
+ .description('Get environment variables for an application')
72
+ .action(envCommand)
73
+
74
+ // Show help by default
75
+ program.action(() => {
76
+ console.log(chalk.cyan('Coolify MCP CLI'))
77
+ console.log(chalk.gray('Manage Coolify deployments from the command line\n'))
78
+ program.help()
79
+ })
80
+
81
+ program.parse()