@soyrageagency/docker-mcp 1.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/LICENSE +21 -0
- package/README.md +882 -0
- package/dist/ai/credentials.d.ts +72 -0
- package/dist/ai/credentials.js +157 -0
- package/dist/ai/credentials.js.map +1 -0
- package/dist/ai/login.d.ts +22 -0
- package/dist/ai/login.js +189 -0
- package/dist/ai/login.js.map +1 -0
- package/dist/ai/provider.d.ts +29 -0
- package/dist/ai/provider.js +113 -0
- package/dist/ai/provider.js.map +1 -0
- package/dist/assets.d.ts +20 -0
- package/dist/assets.js +56 -0
- package/dist/assets.js.map +1 -0
- package/dist/branding.d.ts +31 -0
- package/dist/branding.js +61 -0
- package/dist/branding.js.map +1 -0
- package/dist/config.d.ts +65 -0
- package/dist/config.js +128 -0
- package/dist/config.js.map +1 -0
- package/dist/docker/client.d.ts +66 -0
- package/dist/docker/client.js +161 -0
- package/dist/docker/client.js.map +1 -0
- package/dist/docker/compose.d.ts +74 -0
- package/dist/docker/compose.js +126 -0
- package/dist/docker/compose.js.map +1 -0
- package/dist/entry.d.ts +15 -0
- package/dist/entry.js +33 -0
- package/dist/entry.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +100 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +25 -0
- package/dist/logger.js +68 -0
- package/dist/logger.js.map +1 -0
- package/dist/panel/index.d.ts +16 -0
- package/dist/panel/index.js +53 -0
- package/dist/panel/index.js.map +1 -0
- package/dist/panel/public/app.js +1004 -0
- package/dist/panel/public/index.html +243 -0
- package/dist/panel/public/styles.css +428 -0
- package/dist/panel/server.d.ts +23 -0
- package/dist/panel/server.js +355 -0
- package/dist/panel/server.js.map +1 -0
- package/dist/panel/service.d.ts +327 -0
- package/dist/panel/service.js +1356 -0
- package/dist/panel/service.js.map +1 -0
- package/dist/plugins.d.ts +50 -0
- package/dist/plugins.js +121 -0
- package/dist/plugins.js.map +1 -0
- package/dist/ragedocker.d.ts +21 -0
- package/dist/ragedocker.js +164 -0
- package/dist/ragedocker.js.map +1 -0
- package/dist/tools/about.d.ts +15 -0
- package/dist/tools/about.js +55 -0
- package/dist/tools/about.js.map +1 -0
- package/dist/tools/compose.d.ts +19 -0
- package/dist/tools/compose.js +145 -0
- package/dist/tools/compose.js.map +1 -0
- package/dist/tools/containers.d.ts +13 -0
- package/dist/tools/containers.js +119 -0
- package/dist/tools/containers.js.map +1 -0
- package/dist/tools/context.d.ts +37 -0
- package/dist/tools/context.js +13 -0
- package/dist/tools/context.js.map +1 -0
- package/dist/tools/images.d.ts +11 -0
- package/dist/tools/images.js +38 -0
- package/dist/tools/images.js.map +1 -0
- package/dist/tools/index.d.ts +15 -0
- package/dist/tools/index.js +34 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/lifecycle.d.ts +16 -0
- package/dist/tools/lifecycle.js +165 -0
- package/dist/tools/lifecycle.js.map +1 -0
- package/dist/tools/logs.d.ts +15 -0
- package/dist/tools/logs.js +110 -0
- package/dist/tools/logs.js.map +1 -0
- package/dist/tools/system.d.ts +14 -0
- package/dist/tools/system.js +108 -0
- package/dist/tools/system.js.map +1 -0
- package/dist/tui/ansi.d.ts +66 -0
- package/dist/tui/ansi.js +118 -0
- package/dist/tui/ansi.js.map +1 -0
- package/dist/tui/app.d.ts +160 -0
- package/dist/tui/app.js +1339 -0
- package/dist/tui/app.js.map +1 -0
- package/dist/tui/box.d.ts +18 -0
- package/dist/tui/box.js +38 -0
- package/dist/tui/box.js.map +1 -0
- package/dist/tui/index.d.ts +19 -0
- package/dist/tui/index.js +66 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/update/channel.d.ts +82 -0
- package/dist/update/channel.js +178 -0
- package/dist/update/channel.js.map +1 -0
- package/dist/updates.json +42 -0
- package/dist/utils/format.d.ts +24 -0
- package/dist/utils/format.js +69 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/result.d.ts +35 -0
- package/dist/utils/result.js +31 -0
- package/dist/utils/result.js.map +1 -0
- package/package.json +90 -0
- package/scripts/install.mjs +132 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Docker Compose driver.
|
|
3
|
+
*
|
|
4
|
+
* The Docker Engine API does not expose Compose directly, so this module
|
|
5
|
+
* shells out to the official `docker compose` CLI. Every invocation is fully
|
|
6
|
+
* argument-quoted (no shell interpolation) to avoid injection, and file paths
|
|
7
|
+
* are resolved against a configurable base directory.
|
|
8
|
+
*
|
|
9
|
+
* Part of Docker MCP Server.
|
|
10
|
+
* Crafted by SoyRage Agency — https://soyrage.es/
|
|
11
|
+
* Licensed under the MIT License.
|
|
12
|
+
*/
|
|
13
|
+
import type { AppConfig } from "../config.js";
|
|
14
|
+
import type { Logger } from "../logger.js";
|
|
15
|
+
/** Result of a Compose CLI invocation. */
|
|
16
|
+
export interface ComposeResult {
|
|
17
|
+
/** Process exit code (0 = success). */
|
|
18
|
+
code: number;
|
|
19
|
+
/** Captured standard output. */
|
|
20
|
+
stdout: string;
|
|
21
|
+
/** Captured standard error. */
|
|
22
|
+
stderr: string;
|
|
23
|
+
}
|
|
24
|
+
/** Options accepted by every Compose command. */
|
|
25
|
+
export interface ComposeTarget {
|
|
26
|
+
/** Path to a compose file OR a directory containing one. */
|
|
27
|
+
file: string;
|
|
28
|
+
/** Optional explicit project name (`-p`). */
|
|
29
|
+
project?: string;
|
|
30
|
+
}
|
|
31
|
+
/** Raised when a compose file path cannot be found on disk. */
|
|
32
|
+
export declare class ComposeFileNotFoundError extends Error {
|
|
33
|
+
constructor(path: string);
|
|
34
|
+
}
|
|
35
|
+
/** Drives the `docker compose` CLI in a safe, promisified way. */
|
|
36
|
+
export declare class ComposeDriver {
|
|
37
|
+
private readonly log;
|
|
38
|
+
private readonly baseCwd;
|
|
39
|
+
constructor(config: AppConfig, logger: Logger);
|
|
40
|
+
/**
|
|
41
|
+
* Resolve a caller-supplied path to an absolute compose file. Accepts either
|
|
42
|
+
* a direct file path or a directory (in which case a conventional filename
|
|
43
|
+
* is discovered).
|
|
44
|
+
*/
|
|
45
|
+
private resolveComposeFile;
|
|
46
|
+
/** Build the base argument list shared by all subcommands. */
|
|
47
|
+
private baseArgs;
|
|
48
|
+
/**
|
|
49
|
+
* Spawn `docker <args>` without a shell. Output is buffered and returned.
|
|
50
|
+
* A non-zero exit code is NOT treated as a throw — callers inspect `code`
|
|
51
|
+
* so they can surface stderr to the LLM verbatim.
|
|
52
|
+
*/
|
|
53
|
+
private run;
|
|
54
|
+
/** `docker compose ps` — list the services of a project. */
|
|
55
|
+
ps(target: ComposeTarget): Promise<ComposeResult>;
|
|
56
|
+
/** `docker compose config` — validate and render the effective config. */
|
|
57
|
+
config(target: ComposeTarget): Promise<ComposeResult>;
|
|
58
|
+
/**
|
|
59
|
+
* `docker compose up -d` — deploy/refresh a stack in the background.
|
|
60
|
+
* Optionally rebuilds images and scopes the action to specific services.
|
|
61
|
+
*/
|
|
62
|
+
up(target: ComposeTarget, options?: {
|
|
63
|
+
build?: boolean;
|
|
64
|
+
services?: string[];
|
|
65
|
+
}): Promise<ComposeResult>;
|
|
66
|
+
/** `docker compose down` — stop and remove a stack. */
|
|
67
|
+
down(target: ComposeTarget, options?: {
|
|
68
|
+
volumes?: boolean;
|
|
69
|
+
}): Promise<ComposeResult>;
|
|
70
|
+
/** `docker compose restart` — restart all or selected services. */
|
|
71
|
+
restart(target: ComposeTarget, services?: string[]): Promise<ComposeResult>;
|
|
72
|
+
/** `docker compose pull` — pull the latest images for a stack. */
|
|
73
|
+
pull(target: ComposeTarget, services?: string[]): Promise<ComposeResult>;
|
|
74
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Docker Compose driver.
|
|
3
|
+
*
|
|
4
|
+
* The Docker Engine API does not expose Compose directly, so this module
|
|
5
|
+
* shells out to the official `docker compose` CLI. Every invocation is fully
|
|
6
|
+
* argument-quoted (no shell interpolation) to avoid injection, and file paths
|
|
7
|
+
* are resolved against a configurable base directory.
|
|
8
|
+
*
|
|
9
|
+
* Part of Docker MCP Server.
|
|
10
|
+
* Crafted by SoyRage Agency — https://soyrage.es/
|
|
11
|
+
* Licensed under the MIT License.
|
|
12
|
+
*/
|
|
13
|
+
import { spawn } from "node:child_process";
|
|
14
|
+
import { existsSync } from "node:fs";
|
|
15
|
+
import { isAbsolute, resolve } from "node:path";
|
|
16
|
+
/** Raised when a compose file path cannot be found on disk. */
|
|
17
|
+
export class ComposeFileNotFoundError extends Error {
|
|
18
|
+
constructor(path) {
|
|
19
|
+
super(`Compose file or directory not found: ${path}`);
|
|
20
|
+
this.name = "ComposeFileNotFoundError";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const DEFAULT_COMPOSE_FILENAMES = [
|
|
24
|
+
"compose.yaml",
|
|
25
|
+
"compose.yml",
|
|
26
|
+
"docker-compose.yaml",
|
|
27
|
+
"docker-compose.yml",
|
|
28
|
+
];
|
|
29
|
+
/** Drives the `docker compose` CLI in a safe, promisified way. */
|
|
30
|
+
export class ComposeDriver {
|
|
31
|
+
log;
|
|
32
|
+
baseCwd;
|
|
33
|
+
constructor(config, logger) {
|
|
34
|
+
this.log = logger.child("compose");
|
|
35
|
+
this.baseCwd = config.composeCwd;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolve a caller-supplied path to an absolute compose file. Accepts either
|
|
39
|
+
* a direct file path or a directory (in which case a conventional filename
|
|
40
|
+
* is discovered).
|
|
41
|
+
*/
|
|
42
|
+
resolveComposeFile(file) {
|
|
43
|
+
const absolute = isAbsolute(file) ? file : resolve(this.baseCwd, file);
|
|
44
|
+
if (existsSync(absolute)) {
|
|
45
|
+
// If it's a directory, look for a conventional compose file inside it.
|
|
46
|
+
const asDir = DEFAULT_COMPOSE_FILENAMES.map((name) => resolve(absolute, name)).find((candidate) => existsSync(candidate));
|
|
47
|
+
// existsSync(absolute) is true for both files and dirs; prefer the file
|
|
48
|
+
// itself unless a compose file is found within (directory case).
|
|
49
|
+
return asDir ?? absolute;
|
|
50
|
+
}
|
|
51
|
+
throw new ComposeFileNotFoundError(absolute);
|
|
52
|
+
}
|
|
53
|
+
/** Build the base argument list shared by all subcommands. */
|
|
54
|
+
baseArgs(target) {
|
|
55
|
+
const composeFile = this.resolveComposeFile(target.file);
|
|
56
|
+
const args = ["compose", "-f", composeFile];
|
|
57
|
+
if (target.project)
|
|
58
|
+
args.push("-p", target.project);
|
|
59
|
+
return args;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Spawn `docker <args>` without a shell. Output is buffered and returned.
|
|
63
|
+
* A non-zero exit code is NOT treated as a throw — callers inspect `code`
|
|
64
|
+
* so they can surface stderr to the LLM verbatim.
|
|
65
|
+
*/
|
|
66
|
+
run(args) {
|
|
67
|
+
this.log.debug("docker " + args.join(" "));
|
|
68
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
69
|
+
const child = spawn("docker", args, {
|
|
70
|
+
cwd: this.baseCwd,
|
|
71
|
+
shell: false,
|
|
72
|
+
windowsHide: true,
|
|
73
|
+
});
|
|
74
|
+
let stdout = "";
|
|
75
|
+
let stderr = "";
|
|
76
|
+
child.stdout.on("data", (chunk) => (stdout += chunk.toString()));
|
|
77
|
+
child.stderr.on("data", (chunk) => (stderr += chunk.toString()));
|
|
78
|
+
child.on("error", (err) => {
|
|
79
|
+
if (err.code === "ENOENT") {
|
|
80
|
+
rejectPromise(new Error("The `docker` CLI was not found on PATH. Compose tools require Docker Desktop or the docker-compose-plugin to be installed."));
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
rejectPromise(err);
|
|
84
|
+
});
|
|
85
|
+
child.on("close", (code) => {
|
|
86
|
+
resolvePromise({ code: code ?? -1, stdout, stderr });
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/** `docker compose ps` — list the services of a project. */
|
|
91
|
+
ps(target) {
|
|
92
|
+
return this.run([...this.baseArgs(target), "ps", "--format", "json"]);
|
|
93
|
+
}
|
|
94
|
+
/** `docker compose config` — validate and render the effective config. */
|
|
95
|
+
config(target) {
|
|
96
|
+
return this.run([...this.baseArgs(target), "config"]);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* `docker compose up -d` — deploy/refresh a stack in the background.
|
|
100
|
+
* Optionally rebuilds images and scopes the action to specific services.
|
|
101
|
+
*/
|
|
102
|
+
up(target, options = {}) {
|
|
103
|
+
const args = [...this.baseArgs(target), "up", "-d", "--remove-orphans"];
|
|
104
|
+
if (options.build)
|
|
105
|
+
args.push("--build");
|
|
106
|
+
if (options.services?.length)
|
|
107
|
+
args.push(...options.services);
|
|
108
|
+
return this.run(args);
|
|
109
|
+
}
|
|
110
|
+
/** `docker compose down` — stop and remove a stack. */
|
|
111
|
+
down(target, options = {}) {
|
|
112
|
+
const args = [...this.baseArgs(target), "down", "--remove-orphans"];
|
|
113
|
+
if (options.volumes)
|
|
114
|
+
args.push("--volumes");
|
|
115
|
+
return this.run(args);
|
|
116
|
+
}
|
|
117
|
+
/** `docker compose restart` — restart all or selected services. */
|
|
118
|
+
restart(target, services = []) {
|
|
119
|
+
return this.run([...this.baseArgs(target), "restart", ...services]);
|
|
120
|
+
}
|
|
121
|
+
/** `docker compose pull` — pull the latest images for a stack. */
|
|
122
|
+
pull(target, services = []) {
|
|
123
|
+
return this.run([...this.baseArgs(target), "pull", ...services]);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=compose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../../src/docker/compose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsBhD,+DAA+D;AAC/D,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IACjD,YAAY,IAAY;QACtB,KAAK,CAAC,wCAAwC,IAAI,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;IACzC,CAAC;CACF;AAED,MAAM,yBAAyB,GAAG;IAChC,cAAc;IACd,aAAa;IACb,qBAAqB;IACrB,oBAAoB;CACrB,CAAC;AAEF,kEAAkE;AAClE,MAAM,OAAO,aAAa;IACP,GAAG,CAAS;IACZ,OAAO,CAAS;IAEjC,YAAY,MAAiB,EAAE,MAAc;QAC3C,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACnC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACK,kBAAkB,CAAC,IAAY;QACrC,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAEvE,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,uEAAuE;YACvE,MAAM,KAAK,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACnD,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CACxB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;YAC7C,wEAAwE;YACxE,iEAAiE;YACjE,OAAO,KAAK,IAAI,QAAQ,CAAC;QAC3B,CAAC;QAED,MAAM,IAAI,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED,8DAA8D;IACtD,QAAQ,CAAC,MAAqB;QACpC,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzD,MAAM,IAAI,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;QAC5C,IAAI,MAAM,CAAC,OAAO;YAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;OAIG;IACK,GAAG,CAAC,IAAc;QACxB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAE3C,OAAO,IAAI,OAAO,CAAC,CAAC,cAAc,EAAE,aAAa,EAAE,EAAE;YACnD,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE;gBAClC,GAAG,EAAE,IAAI,CAAC,OAAO;gBACjB,KAAK,EAAE,KAAK;gBACZ,WAAW,EAAE,IAAI;aAClB,CAAC,CAAC;YAEH,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,IAAI,MAAM,GAAG,EAAE,CAAC;YAEhB,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YACzE,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YAEzE,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;gBAC/C,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC1B,aAAa,CACX,IAAI,KAAK,CACP,4HAA4H,CAC7H,CACF,CAAC;oBACF,OAAO;gBACT,CAAC;gBACD,aAAa,CAAC,GAAG,CAAC,CAAC;YACrB,CAAC,CAAC,CAAC;YAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;gBACzB,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YACvD,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,4DAA4D;IAC5D,EAAE,CAAC,MAAqB;QACtB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,0EAA0E;IAC1E,MAAM,CAAC,MAAqB;QAC1B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;IACxD,CAAC;IAED;;;OAGG;IACH,EAAE,CACA,MAAqB,EACrB,UAAoD,EAAE;QAEtD,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,kBAAkB,CAAC,CAAC;QACxE,IAAI,OAAO,CAAC,KAAK;YAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,OAAO,CAAC,QAAQ,EAAE,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC7D,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,uDAAuD;IACvD,IAAI,CACF,MAAqB,EACrB,UAAiC,EAAE;QAEnC,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,kBAAkB,CAAC,CAAC;QACpE,IAAI,OAAO,CAAC,OAAO;YAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,mEAAmE;IACnE,OAAO,CACL,MAAqB,EACrB,WAAqB,EAAE;QAEvB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,kEAAkE;IAClE,IAAI,CAAC,MAAqB,EAAE,WAAqB,EAAE;QACjD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;IACnE,CAAC;CACF"}
|
package/dist/entry.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Is this module the one Node was launched with?
|
|
3
|
+
*
|
|
4
|
+
* Each entry point (`tui`, `panel`, the MCP server) doubles as both a standalone
|
|
5
|
+
* binary and something the unified `ragedocker` launcher imports and calls. When
|
|
6
|
+
* imported, its top-level auto-run must stay silent; when it *is* the process
|
|
7
|
+
* entry, it should run. Comparing the module URL to `process.argv[1]` — resolved
|
|
8
|
+
* to a file URL so the two are the same shape — tells them apart.
|
|
9
|
+
*
|
|
10
|
+
* Part of Docker MCP Server.
|
|
11
|
+
* Crafted by SoyRage Agency — https://soyrage.es/
|
|
12
|
+
* MIT licensed (see LICENSE).
|
|
13
|
+
*/
|
|
14
|
+
/** True when `moduleUrl` (an `import.meta.url`) is Node's entry script. */
|
|
15
|
+
export declare function isEntryPoint(moduleUrl: string): boolean;
|
package/dist/entry.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Is this module the one Node was launched with?
|
|
3
|
+
*
|
|
4
|
+
* Each entry point (`tui`, `panel`, the MCP server) doubles as both a standalone
|
|
5
|
+
* binary and something the unified `ragedocker` launcher imports and calls. When
|
|
6
|
+
* imported, its top-level auto-run must stay silent; when it *is* the process
|
|
7
|
+
* entry, it should run. Comparing the module URL to `process.argv[1]` — resolved
|
|
8
|
+
* to a file URL so the two are the same shape — tells them apart.
|
|
9
|
+
*
|
|
10
|
+
* Part of Docker MCP Server.
|
|
11
|
+
* Crafted by SoyRage Agency — https://soyrage.es/
|
|
12
|
+
* MIT licensed (see LICENSE).
|
|
13
|
+
*/
|
|
14
|
+
import { pathToFileURL } from "node:url";
|
|
15
|
+
import { isPackaged } from "./assets.js";
|
|
16
|
+
/** True when `moduleUrl` (an `import.meta.url`) is Node's entry script. */
|
|
17
|
+
export function isEntryPoint(moduleUrl) {
|
|
18
|
+
// In the standalone binary every module shares one __filename, so this check
|
|
19
|
+
// is meaningless — the `ragedocker` launcher is always the entry and drives
|
|
20
|
+
// the run-functions itself, so the per-module auto-run guards must stay quiet.
|
|
21
|
+
if (isPackaged())
|
|
22
|
+
return false;
|
|
23
|
+
const entry = process.argv[1];
|
|
24
|
+
if (!entry)
|
|
25
|
+
return false;
|
|
26
|
+
try {
|
|
27
|
+
return moduleUrl === pathToFileURL(entry).href;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.js","sourceRoot":"","sources":["../src/entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,2EAA2E;AAC3E,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,6EAA6E;IAC7E,4EAA4E;IAC5E,+EAA+E;IAC/E,IAAI,UAAU,EAAE;QAAE,OAAO,KAAK,CAAC;IAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,SAAS,KAAK,aAAa,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Docker MCP Server — entry point.
|
|
4
|
+
*
|
|
5
|
+
* Boots a Model Context Protocol server over stdio that lets any MCP-capable
|
|
6
|
+
* LLM (Claude Desktop, Cursor, Continue, …) manage a Docker host in natural
|
|
7
|
+
* language: list containers, tail logs, restart services and deploy Compose
|
|
8
|
+
* stacks — with built-in read-only and allowlist safety rails.
|
|
9
|
+
*
|
|
10
|
+
* Part of Docker MCP Server.
|
|
11
|
+
* Crafted by SoyRage Agency — https://soyrage.es/
|
|
12
|
+
* Licensed under the MIT License.
|
|
13
|
+
*/
|
|
14
|
+
export declare function runMcp(): Promise<void>;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Docker MCP Server — entry point.
|
|
4
|
+
*
|
|
5
|
+
* Boots a Model Context Protocol server over stdio that lets any MCP-capable
|
|
6
|
+
* LLM (Claude Desktop, Cursor, Continue, …) manage a Docker host in natural
|
|
7
|
+
* language: list containers, tail logs, restart services and deploy Compose
|
|
8
|
+
* stacks — with built-in read-only and allowlist safety rails.
|
|
9
|
+
*
|
|
10
|
+
* Part of Docker MCP Server.
|
|
11
|
+
* Crafted by SoyRage Agency — https://soyrage.es/
|
|
12
|
+
* Licensed under the MIT License.
|
|
13
|
+
*/
|
|
14
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
15
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
16
|
+
import { loadConfig } from "./config.js";
|
|
17
|
+
import { Logger } from "./logger.js";
|
|
18
|
+
import { DockerClient } from "./docker/client.js";
|
|
19
|
+
import { ComposeDriver } from "./docker/compose.js";
|
|
20
|
+
import { BUILTIN_PLUGINS, selectPlugins } from "./plugins.js";
|
|
21
|
+
import { isEntryPoint } from "./entry.js";
|
|
22
|
+
import { ASCII_BANNER, BRAND, mcpInstructions } from "./branding.js";
|
|
23
|
+
/** Human-readable identity advertised to MCP clients. */
|
|
24
|
+
const SERVER_NAME = "docker-mcp-server";
|
|
25
|
+
const SERVER_VERSION = BRAND.version;
|
|
26
|
+
export async function runMcp() {
|
|
27
|
+
const config = loadConfig();
|
|
28
|
+
const logger = new Logger(config.logLevel);
|
|
29
|
+
// Print the welcome banner to stderr (never stdout, which is reserved for
|
|
30
|
+
// the JSON-RPC protocol stream).
|
|
31
|
+
process.stderr.write(`${ASCII_BANNER}\n`);
|
|
32
|
+
process.stderr.write(` ${BRAND.product} v${BRAND.version} — by ${BRAND.author} (${BRAND.url})\n\n`);
|
|
33
|
+
logger.info(`Starting ${SERVER_NAME} v${SERVER_VERSION}`);
|
|
34
|
+
logger.debug("Configuration", {
|
|
35
|
+
dockerHost: config.dockerHost || "(platform default)",
|
|
36
|
+
readOnly: config.readOnly,
|
|
37
|
+
allowExec: config.allowExec,
|
|
38
|
+
allowlist: config.containerAllowlist,
|
|
39
|
+
});
|
|
40
|
+
// Build collaborators.
|
|
41
|
+
const docker = new DockerClient(config, logger);
|
|
42
|
+
const compose = new ComposeDriver(config, logger);
|
|
43
|
+
// Fail fast (with a helpful hint) if the daemon is unreachable.
|
|
44
|
+
try {
|
|
45
|
+
await docker.ping();
|
|
46
|
+
logger.info("Connected to the Docker daemon.");
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
logger.error("Could not reach the Docker daemon. Is Docker running and is DOCKER_HOST correct?", error);
|
|
50
|
+
// We still start the server: individual tool calls will return a clean
|
|
51
|
+
// error, which is friendlier inside a chat client than a hard crash.
|
|
52
|
+
}
|
|
53
|
+
// Construct the MCP server and register every tool group. The `instructions`
|
|
54
|
+
// string is surfaced to the LLM by the client — it is where we make the
|
|
55
|
+
// assistant aware that this integration is a SoyRage Agency product and ask
|
|
56
|
+
// it to welcome the user with the ASCII banner.
|
|
57
|
+
const server = new McpServer({
|
|
58
|
+
name: SERVER_NAME,
|
|
59
|
+
version: SERVER_VERSION,
|
|
60
|
+
}, {
|
|
61
|
+
instructions: mcpInstructions(),
|
|
62
|
+
});
|
|
63
|
+
// Resolve the modular plugin selection from configuration, then register
|
|
64
|
+
// each enabled plugin. The full catalogue (with per-plugin enabled state) is
|
|
65
|
+
// handed to tools via the context so `list_plugins` can report it.
|
|
66
|
+
const selected = selectPlugins(config, logger);
|
|
67
|
+
const enabledNames = new Set(selected.map((p) => p.name));
|
|
68
|
+
const pluginInfo = BUILTIN_PLUGINS.map((p) => ({
|
|
69
|
+
name: p.name,
|
|
70
|
+
title: p.title,
|
|
71
|
+
category: p.category,
|
|
72
|
+
mutating: p.mutating,
|
|
73
|
+
enabled: enabledNames.has(p.name),
|
|
74
|
+
}));
|
|
75
|
+
const context = { server, docker, compose, config, logger, plugins: pluginInfo };
|
|
76
|
+
for (const plugin of selected)
|
|
77
|
+
plugin.register(context);
|
|
78
|
+
logger.info(config.readOnly
|
|
79
|
+
? "Tools registered in READ-ONLY mode."
|
|
80
|
+
: "Tools registered in full read/write mode.");
|
|
81
|
+
// Connect over stdio. STDOUT is reserved for JSON-RPC; logs go to STDERR.
|
|
82
|
+
const transport = new StdioServerTransport();
|
|
83
|
+
await server.connect(transport);
|
|
84
|
+
logger.info("MCP server is ready and listening on stdio.");
|
|
85
|
+
// Graceful shutdown so the client sees a clean disconnect.
|
|
86
|
+
const shutdown = (signal) => {
|
|
87
|
+
logger.info(`Received ${signal}, shutting down.`);
|
|
88
|
+
void server.close().finally(() => process.exit(0));
|
|
89
|
+
};
|
|
90
|
+
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
91
|
+
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
92
|
+
}
|
|
93
|
+
if (isEntryPoint(import.meta.url)) {
|
|
94
|
+
runMcp().catch((error) => {
|
|
95
|
+
// Last-resort handler: write to stderr and exit non-zero.
|
|
96
|
+
process.stderr.write(`Fatal: ${error instanceof Error ? error.stack : error}\n`);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny structured logger.
|
|
3
|
+
*
|
|
4
|
+
* IMPORTANT: An MCP stdio server communicates with its client over STDOUT.
|
|
5
|
+
* Anything written to STDOUT that is not a JSON-RPC message will corrupt the
|
|
6
|
+
* protocol stream. Therefore every diagnostic line goes to STDERR only.
|
|
7
|
+
*
|
|
8
|
+
* Part of Docker MCP Server.
|
|
9
|
+
* Crafted by SoyRage Agency — https://soyrage.es/
|
|
10
|
+
* Licensed under the MIT License.
|
|
11
|
+
*/
|
|
12
|
+
import type { LogLevel } from "./config.js";
|
|
13
|
+
/** A namespaced logger that writes human-readable lines to stderr. */
|
|
14
|
+
export declare class Logger {
|
|
15
|
+
private readonly threshold;
|
|
16
|
+
private readonly scope;
|
|
17
|
+
constructor(threshold: LogLevel, scope?: string);
|
|
18
|
+
/** Derive a child logger with an extended scope (e.g. "docker-mcp:compose"). */
|
|
19
|
+
child(scope: string): Logger;
|
|
20
|
+
debug(message: string, meta?: unknown): void;
|
|
21
|
+
info(message: string, meta?: unknown): void;
|
|
22
|
+
warn(message: string, meta?: unknown): void;
|
|
23
|
+
error(message: string, meta?: unknown): void;
|
|
24
|
+
private write;
|
|
25
|
+
}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny structured logger.
|
|
3
|
+
*
|
|
4
|
+
* IMPORTANT: An MCP stdio server communicates with its client over STDOUT.
|
|
5
|
+
* Anything written to STDOUT that is not a JSON-RPC message will corrupt the
|
|
6
|
+
* protocol stream. Therefore every diagnostic line goes to STDERR only.
|
|
7
|
+
*
|
|
8
|
+
* Part of Docker MCP Server.
|
|
9
|
+
* Crafted by SoyRage Agency — https://soyrage.es/
|
|
10
|
+
* Licensed under the MIT License.
|
|
11
|
+
*/
|
|
12
|
+
const LEVEL_WEIGHT = {
|
|
13
|
+
debug: 10,
|
|
14
|
+
info: 20,
|
|
15
|
+
warn: 30,
|
|
16
|
+
error: 40,
|
|
17
|
+
};
|
|
18
|
+
/** A namespaced logger that writes human-readable lines to stderr. */
|
|
19
|
+
export class Logger {
|
|
20
|
+
threshold;
|
|
21
|
+
scope;
|
|
22
|
+
constructor(threshold, scope = "docker-mcp") {
|
|
23
|
+
this.threshold = threshold;
|
|
24
|
+
this.scope = scope;
|
|
25
|
+
}
|
|
26
|
+
/** Derive a child logger with an extended scope (e.g. "docker-mcp:compose"). */
|
|
27
|
+
child(scope) {
|
|
28
|
+
return new Logger(this.threshold, `${this.scope}:${scope}`);
|
|
29
|
+
}
|
|
30
|
+
debug(message, meta) {
|
|
31
|
+
this.write("debug", message, meta);
|
|
32
|
+
}
|
|
33
|
+
info(message, meta) {
|
|
34
|
+
this.write("info", message, meta);
|
|
35
|
+
}
|
|
36
|
+
warn(message, meta) {
|
|
37
|
+
this.write("warn", message, meta);
|
|
38
|
+
}
|
|
39
|
+
error(message, meta) {
|
|
40
|
+
this.write("error", message, meta);
|
|
41
|
+
}
|
|
42
|
+
write(level, message, meta) {
|
|
43
|
+
if (LEVEL_WEIGHT[level] < LEVEL_WEIGHT[this.threshold])
|
|
44
|
+
return;
|
|
45
|
+
const timestamp = new Date().toISOString();
|
|
46
|
+
const tag = level.toUpperCase().padEnd(5);
|
|
47
|
+
let line = `${timestamp} ${tag} [${this.scope}] ${message}`;
|
|
48
|
+
if (meta !== undefined) {
|
|
49
|
+
const rendered = meta instanceof Error
|
|
50
|
+
? meta.stack ?? meta.message
|
|
51
|
+
: typeof meta === "string"
|
|
52
|
+
? meta
|
|
53
|
+
: safeJson(meta);
|
|
54
|
+
line += ` ${rendered}`;
|
|
55
|
+
}
|
|
56
|
+
process.stderr.write(`${line}\n`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** JSON.stringify that never throws (handles cycles gracefully). */
|
|
60
|
+
function safeJson(value) {
|
|
61
|
+
try {
|
|
62
|
+
return JSON.stringify(value);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return String(value);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,YAAY,GAA6B;IAC7C,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;CACV,CAAC;AAEF,sEAAsE;AACtE,MAAM,OAAO,MAAM;IAEE;IACA;IAFnB,YACmB,SAAmB,EACnB,QAAQ,YAAY;QADpB,cAAS,GAAT,SAAS,CAAU;QACnB,UAAK,GAAL,KAAK,CAAe;IACpC,CAAC;IAEJ,gFAAgF;IAChF,KAAK,CAAC,KAAa;QACjB,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,KAAK,IAAI,KAAK,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAAc;QACnC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAAc;QAClC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAAc;QAClC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAAc;QACnC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;IAEO,KAAK,CAAC,KAAe,EAAE,OAAe,EAAE,IAAc;QAC5D,IAAI,YAAY,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,OAAO;QAE/D,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1C,IAAI,IAAI,GAAG,GAAG,SAAS,IAAI,GAAG,KAAK,IAAI,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;QAE5D,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,QAAQ,GACZ,IAAI,YAAY,KAAK;gBACnB,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO;gBAC5B,CAAC,CAAC,OAAO,IAAI,KAAK,QAAQ;oBACxB,CAAC,CAAC,IAAI;oBACN,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACvB,IAAI,IAAI,IAAI,QAAQ,EAAE,CAAC;QACzB,CAAC;QAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;IACpC,CAAC;CACF;AAED,oEAAoE;AACpE,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Interactive panel — entry point.
|
|
4
|
+
*
|
|
5
|
+
* A separate binary (`docker-mcp-panel`) that launches the minimalist web
|
|
6
|
+
* dashboard. It reuses the exact same configuration, Docker client and safety
|
|
7
|
+
* rails as the MCP server, so read-only mode and the allowlist apply here too.
|
|
8
|
+
*
|
|
9
|
+
* Run in demo mode to preview it without a daemon:
|
|
10
|
+
* DOCKER_MCP_PANEL_DEMO=true npm run panel
|
|
11
|
+
*
|
|
12
|
+
* Part of Docker MCP Server.
|
|
13
|
+
* Crafted by SoyRage Agency — https://soyrage.es/
|
|
14
|
+
* MIT licensed (see LICENSE).
|
|
15
|
+
*/
|
|
16
|
+
export declare function runPanel(): Promise<void>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Interactive panel — entry point.
|
|
4
|
+
*
|
|
5
|
+
* A separate binary (`docker-mcp-panel`) that launches the minimalist web
|
|
6
|
+
* dashboard. It reuses the exact same configuration, Docker client and safety
|
|
7
|
+
* rails as the MCP server, so read-only mode and the allowlist apply here too.
|
|
8
|
+
*
|
|
9
|
+
* Run in demo mode to preview it without a daemon:
|
|
10
|
+
* DOCKER_MCP_PANEL_DEMO=true npm run panel
|
|
11
|
+
*
|
|
12
|
+
* Part of Docker MCP Server.
|
|
13
|
+
* Crafted by SoyRage Agency — https://soyrage.es/
|
|
14
|
+
* MIT licensed (see LICENSE).
|
|
15
|
+
*/
|
|
16
|
+
import { loadConfig } from "../config.js";
|
|
17
|
+
import { Logger } from "../logger.js";
|
|
18
|
+
import { DockerClient } from "../docker/client.js";
|
|
19
|
+
import { PanelService } from "./service.js";
|
|
20
|
+
import { startPanel } from "./server.js";
|
|
21
|
+
import { ASCII_BANNER, BRAND } from "../branding.js";
|
|
22
|
+
import { isEntryPoint } from "../entry.js";
|
|
23
|
+
export async function runPanel() {
|
|
24
|
+
const config = loadConfig();
|
|
25
|
+
const logger = new Logger(config.logLevel, "panel");
|
|
26
|
+
process.stdout.write(`${ASCII_BANNER}\n`);
|
|
27
|
+
process.stdout.write(` ${BRAND.product} · Interactive Panel — by ${BRAND.author} (${BRAND.url})\n\n`);
|
|
28
|
+
const docker = new DockerClient(config, logger);
|
|
29
|
+
if (!config.panel.demo) {
|
|
30
|
+
try {
|
|
31
|
+
await docker.ping();
|
|
32
|
+
logger.info("Connected to the Docker daemon.");
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
logger.warn("Docker daemon unreachable — start with DOCKER_MCP_PANEL_DEMO=true to preview with mock data.", error);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const service = new PanelService(docker, config, logger);
|
|
39
|
+
await startPanel(service, config, logger);
|
|
40
|
+
const shutdown = (signal) => {
|
|
41
|
+
logger.info(`Received ${signal}, shutting down panel.`);
|
|
42
|
+
process.exit(0);
|
|
43
|
+
};
|
|
44
|
+
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
45
|
+
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
46
|
+
}
|
|
47
|
+
if (isEntryPoint(import.meta.url)) {
|
|
48
|
+
runPanel().catch((error) => {
|
|
49
|
+
process.stderr.write(`Fatal: ${error instanceof Error ? error.stack : error}\n`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/panel/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAEpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,YAAY,IAAI,CAAC,CAAC;IAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,KAAK,KAAK,CAAC,OAAO,6BAA6B,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,GAAG,OAAO,CACjF,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CACT,8FAA8F,EAC9F,KAAK,CACN,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACzD,MAAM,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAE1C,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAE,EAAE;QAClC,MAAM,CAAC,IAAI,CAAC,YAAY,MAAM,wBAAwB,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,IAAI,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IAClC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAC3D,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|