@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.
- package/dist/cli/index.js +11788 -0
- package/dist/coolify/config.d.ts +64 -0
- package/dist/coolify/config.d.ts.map +1 -0
- package/dist/coolify/index.d.ts +201 -0
- package/dist/coolify/index.d.ts.map +1 -0
- package/dist/coolify/types.d.ts +282 -0
- package/dist/coolify/types.d.ts.map +1 -0
- package/dist/index.cjs +29150 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29127 -0
- package/dist/index.js.map +1 -0
- package/dist/server/sse.d.ts +11 -0
- package/dist/server/sse.d.ts.map +1 -0
- package/dist/server/sse.js +32 -0
- package/dist/server/stdio.d.ts +13 -0
- package/dist/server/stdio.d.ts.map +1 -0
- package/dist/server/stdio.js +18326 -0
- package/dist/tools/definitions.d.ts +13 -0
- package/dist/tools/definitions.d.ts.map +1 -0
- package/dist/tools/handlers.d.ts +19 -0
- package/dist/tools/handlers.d.ts.map +1 -0
- package/dist/utils/format.d.ts +38 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/package.json +67 -0
- package/src/cli/commands/config.ts +83 -0
- package/src/cli/commands/deploy.ts +56 -0
- package/src/cli/commands/env.ts +60 -0
- package/src/cli/commands/list.ts +63 -0
- package/src/cli/commands/logs.ts +49 -0
- package/src/cli/commands/servers.ts +52 -0
- package/src/cli/index.ts +81 -0
- package/src/coolify/config.ts +113 -0
- package/src/coolify/index.ts +688 -0
- package/src/coolify/types.ts +297 -0
- package/src/index.ts +864 -0
- package/src/server/sse.ts +50 -0
- package/src/server/stdio.ts +52 -0
- package/src/tools/definitions.ts +435 -0
- package/src/tools/handlers.ts +605 -0
- 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
|
+
}
|
package/src/cli/index.ts
ADDED
|
@@ -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()
|