@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.
Files changed (104) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +882 -0
  3. package/dist/ai/credentials.d.ts +72 -0
  4. package/dist/ai/credentials.js +157 -0
  5. package/dist/ai/credentials.js.map +1 -0
  6. package/dist/ai/login.d.ts +22 -0
  7. package/dist/ai/login.js +189 -0
  8. package/dist/ai/login.js.map +1 -0
  9. package/dist/ai/provider.d.ts +29 -0
  10. package/dist/ai/provider.js +113 -0
  11. package/dist/ai/provider.js.map +1 -0
  12. package/dist/assets.d.ts +20 -0
  13. package/dist/assets.js +56 -0
  14. package/dist/assets.js.map +1 -0
  15. package/dist/branding.d.ts +31 -0
  16. package/dist/branding.js +61 -0
  17. package/dist/branding.js.map +1 -0
  18. package/dist/config.d.ts +65 -0
  19. package/dist/config.js +128 -0
  20. package/dist/config.js.map +1 -0
  21. package/dist/docker/client.d.ts +66 -0
  22. package/dist/docker/client.js +161 -0
  23. package/dist/docker/client.js.map +1 -0
  24. package/dist/docker/compose.d.ts +74 -0
  25. package/dist/docker/compose.js +126 -0
  26. package/dist/docker/compose.js.map +1 -0
  27. package/dist/entry.d.ts +15 -0
  28. package/dist/entry.js +33 -0
  29. package/dist/entry.js.map +1 -0
  30. package/dist/index.d.ts +14 -0
  31. package/dist/index.js +100 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/logger.d.ts +25 -0
  34. package/dist/logger.js +68 -0
  35. package/dist/logger.js.map +1 -0
  36. package/dist/panel/index.d.ts +16 -0
  37. package/dist/panel/index.js +53 -0
  38. package/dist/panel/index.js.map +1 -0
  39. package/dist/panel/public/app.js +1004 -0
  40. package/dist/panel/public/index.html +243 -0
  41. package/dist/panel/public/styles.css +428 -0
  42. package/dist/panel/server.d.ts +23 -0
  43. package/dist/panel/server.js +355 -0
  44. package/dist/panel/server.js.map +1 -0
  45. package/dist/panel/service.d.ts +327 -0
  46. package/dist/panel/service.js +1356 -0
  47. package/dist/panel/service.js.map +1 -0
  48. package/dist/plugins.d.ts +50 -0
  49. package/dist/plugins.js +121 -0
  50. package/dist/plugins.js.map +1 -0
  51. package/dist/ragedocker.d.ts +21 -0
  52. package/dist/ragedocker.js +164 -0
  53. package/dist/ragedocker.js.map +1 -0
  54. package/dist/tools/about.d.ts +15 -0
  55. package/dist/tools/about.js +55 -0
  56. package/dist/tools/about.js.map +1 -0
  57. package/dist/tools/compose.d.ts +19 -0
  58. package/dist/tools/compose.js +145 -0
  59. package/dist/tools/compose.js.map +1 -0
  60. package/dist/tools/containers.d.ts +13 -0
  61. package/dist/tools/containers.js +119 -0
  62. package/dist/tools/containers.js.map +1 -0
  63. package/dist/tools/context.d.ts +37 -0
  64. package/dist/tools/context.js +13 -0
  65. package/dist/tools/context.js.map +1 -0
  66. package/dist/tools/images.d.ts +11 -0
  67. package/dist/tools/images.js +38 -0
  68. package/dist/tools/images.js.map +1 -0
  69. package/dist/tools/index.d.ts +15 -0
  70. package/dist/tools/index.js +34 -0
  71. package/dist/tools/index.js.map +1 -0
  72. package/dist/tools/lifecycle.d.ts +16 -0
  73. package/dist/tools/lifecycle.js +165 -0
  74. package/dist/tools/lifecycle.js.map +1 -0
  75. package/dist/tools/logs.d.ts +15 -0
  76. package/dist/tools/logs.js +110 -0
  77. package/dist/tools/logs.js.map +1 -0
  78. package/dist/tools/system.d.ts +14 -0
  79. package/dist/tools/system.js +108 -0
  80. package/dist/tools/system.js.map +1 -0
  81. package/dist/tui/ansi.d.ts +66 -0
  82. package/dist/tui/ansi.js +118 -0
  83. package/dist/tui/ansi.js.map +1 -0
  84. package/dist/tui/app.d.ts +160 -0
  85. package/dist/tui/app.js +1339 -0
  86. package/dist/tui/app.js.map +1 -0
  87. package/dist/tui/box.d.ts +18 -0
  88. package/dist/tui/box.js +38 -0
  89. package/dist/tui/box.js.map +1 -0
  90. package/dist/tui/index.d.ts +19 -0
  91. package/dist/tui/index.js +66 -0
  92. package/dist/tui/index.js.map +1 -0
  93. package/dist/update/channel.d.ts +82 -0
  94. package/dist/update/channel.js +178 -0
  95. package/dist/update/channel.js.map +1 -0
  96. package/dist/updates.json +42 -0
  97. package/dist/utils/format.d.ts +24 -0
  98. package/dist/utils/format.js +69 -0
  99. package/dist/utils/format.js.map +1 -0
  100. package/dist/utils/result.d.ts +35 -0
  101. package/dist/utils/result.js +31 -0
  102. package/dist/utils/result.js.map +1 -0
  103. package/package.json +90 -0
  104. package/scripts/install.mjs +132 -0
package/dist/assets.js ADDED
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Bundled-asset access — works the same whether we're running from `dist/` on a
3
+ * machine with Node, or as a single-file standalone binary (Node SEA) with no
4
+ * Node installed at all.
5
+ *
6
+ * When packaged, the panel's static files and the update channel are baked into
7
+ * the executable and read from the SEA blob; otherwise they're read from disk.
8
+ * Callers pass both an asset key and the on-disk path, and get back whichever is
9
+ * available — so the same code path serves both builds.
10
+ *
11
+ * Part of Docker MCP Server.
12
+ * Crafted by SoyRage Agency — https://soyrage.es/
13
+ * MIT licensed (see LICENSE).
14
+ */
15
+ import { readFileSync } from "node:fs";
16
+ import { createRequire } from "node:module";
17
+ let seaMod = null;
18
+ try {
19
+ // `node:sea` exists on modern Node; isSea() is false unless we're a binary.
20
+ const require = createRequire(import.meta.url);
21
+ seaMod = require("node:sea");
22
+ }
23
+ catch {
24
+ seaMod = null;
25
+ }
26
+ /** True when running as an injected single-file executable. */
27
+ export function isPackaged() {
28
+ try {
29
+ return Boolean(seaMod?.isSea());
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
35
+ /** Read a bundled asset as a Buffer: from the SEA blob when packaged, else disk. */
36
+ export function readAssetBuffer(key, diskPath) {
37
+ if (seaMod && isPackaged()) {
38
+ try {
39
+ return Buffer.from(seaMod.getRawAsset(key));
40
+ }
41
+ catch {
42
+ /* fall through to disk */
43
+ }
44
+ }
45
+ return readFileSync(diskPath);
46
+ }
47
+ /** Read a bundled asset as UTF-8 text. Returns null if it can't be read. */
48
+ export function readAssetText(key, diskPath) {
49
+ try {
50
+ return readAssetBuffer(key, diskPath).toString("utf8");
51
+ }
52
+ catch {
53
+ return null;
54
+ }
55
+ }
56
+ //# sourceMappingURL=assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAI5C,IAAI,MAAM,GAAkB,IAAI,CAAC;AACjC,IAAI,CAAC;IACH,4EAA4E;IAC5E,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,GAAG,OAAO,CAAC,UAAU,CAAW,CAAC;AACzC,CAAC;AAAC,MAAM,CAAC;IACP,MAAM,GAAG,IAAI,CAAC;AAChB,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,QAAgB;IAC3D,IAAI,MAAM,IAAI,UAAU,EAAE,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,0BAA0B;QAC5B,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,QAAgB;IACzD,IAAI,CAAC;QACH,OAAO,eAAe,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Branding & identity.
3
+ *
4
+ * Single source of truth for the project identity carried by the server:
5
+ * • the startup banner printed to stderr,
6
+ * • the MCP `instructions` string every client shows the LLM,
7
+ * • the `about` tool.
8
+ *
9
+ * Part of Docker MCP Server.
10
+ * Crafted by SoyRage Agency — https://soyrage.es/
11
+ * MIT licensed (see LICENSE).
12
+ */
13
+ /** Identity of the project's author. */
14
+ export declare const BRAND: Readonly<{
15
+ product: "Docker MCP Server";
16
+ author: "SoyRage Agency";
17
+ url: "https://soyrage.es/";
18
+ donate: "https://www.paypal.com/paypalme/soyrageagency";
19
+ tagline: "Chat with your Docker host — safely.";
20
+ version: "1.1.0";
21
+ }>;
22
+ /** ASCII welcome banner (ANSI Shadow style). */
23
+ export declare const ASCII_BANNER: string;
24
+ /** The full welcome block, banner + credits, used by the `about` tool. */
25
+ export declare function welcomeBlock(): string;
26
+ /**
27
+ * The MCP `instructions` payload. MCP clients hand this text to the LLM as
28
+ * system-level guidance, so keep it strictly operational: what the server can
29
+ * do and how to use it safely.
30
+ */
31
+ export declare function mcpInstructions(): string;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Branding & identity.
3
+ *
4
+ * Single source of truth for the project identity carried by the server:
5
+ * • the startup banner printed to stderr,
6
+ * • the MCP `instructions` string every client shows the LLM,
7
+ * • the `about` tool.
8
+ *
9
+ * Part of Docker MCP Server.
10
+ * Crafted by SoyRage Agency — https://soyrage.es/
11
+ * MIT licensed (see LICENSE).
12
+ */
13
+ /** Identity of the project's author. */
14
+ export const BRAND = Object.freeze({
15
+ product: "Docker MCP Server",
16
+ author: "SoyRage Agency",
17
+ url: "https://soyrage.es/",
18
+ donate: "https://www.paypal.com/paypalme/soyrageagency",
19
+ tagline: "Chat with your Docker host — safely.",
20
+ version: "1.1.0",
21
+ });
22
+ /** ASCII welcome banner (ANSI Shadow style). */
23
+ export const ASCII_BANNER = String.raw `
24
+ ███████╗ ██████╗ ██╗ ██╗██████╗ █████╗ ██████╗ ███████╗
25
+ ██╔════╝██╔═══██╗╚██╗ ██╔╝██╔══██╗██╔══██╗██╔════╝ ██╔════╝
26
+ ███████╗██║ ██║ ╚████╔╝ ██████╔╝███████║██║ ███╗█████╗
27
+ ╚════██║██║ ██║ ╚██╔╝ ██╔══██╗██╔══██║██║ ██║██╔══╝
28
+ ███████║╚██████╔╝ ██║ ██║ ██║██║ ██║╚██████╔╝███████╗
29
+ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝
30
+ D O C K E R M C P S E R V E R
31
+ ~ Chat with your Docker host, safely ~
32
+ `;
33
+ /** The full welcome block, banner + credits, used by the `about` tool. */
34
+ export function welcomeBlock() {
35
+ return [
36
+ ASCII_BANNER,
37
+ ` ${BRAND.product} v${BRAND.version}`,
38
+ ` Crafted with care by ${BRAND.author} — ${BRAND.url}`,
39
+ " Free and open source under the MIT License.",
40
+ ` Support the project: ${BRAND.donate}`,
41
+ "",
42
+ ].join("\n");
43
+ }
44
+ /**
45
+ * The MCP `instructions` payload. MCP clients hand this text to the LLM as
46
+ * system-level guidance, so keep it strictly operational: what the server can
47
+ * do and how to use it safely.
48
+ */
49
+ export function mcpInstructions() {
50
+ return [
51
+ `You are connected to "${BRAND.product}", an MCP server for Docker.`,
52
+ "",
53
+ "CAPABILITIES:",
54
+ "- You can inspect containers, read logs, view images/networks/volumes, report host & disk usage, and (unless the server is read-only) start/stop/restart/remove containers and deploy or tear down Compose stacks.",
55
+ "- Prefer read-only tools to understand state before taking any destructive action, and confirm destructive actions (remove_container, compose_down --removeVolumes) with the user first.",
56
+ "",
57
+ "ABOUT:",
58
+ '- Call the "about" tool if the user asks what this server is, who built it or which version is running.',
59
+ ].join("\n");
60
+ }
61
+ //# sourceMappingURL=branding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branding.js","sourceRoot":"","sources":["../src/branding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,wCAAwC;AACxC,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;IACjC,OAAO,EAAE,mBAAmB;IAC5B,MAAM,EAAE,gBAAgB;IACxB,GAAG,EAAE,qBAAqB;IAC1B,MAAM,EAAE,+CAA+C;IACvD,OAAO,EAAE,sCAAsC;IAC/C,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,gDAAgD;AAChD,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;CASrC,CAAC;AAEF,0EAA0E;AAC1E,MAAM,UAAU,YAAY;IAC1B,OAAO;QACL,YAAY;QACZ,KAAK,KAAK,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,EAAE;QACtC,0BAA0B,KAAK,CAAC,MAAM,MAAM,KAAK,CAAC,GAAG,EAAE;QACvD,+CAA+C;QAC/C,0BAA0B,KAAK,CAAC,MAAM,EAAE;QACxC,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO;QACL,yBAAyB,KAAK,CAAC,OAAO,8BAA8B;QACpE,EAAE;QACF,eAAe;QACf,oNAAoN;QACpN,0LAA0L;QAC1L,EAAE;QACF,QAAQ;QACR,yGAAyG;KAC1G,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Runtime configuration.
3
+ *
4
+ * Configuration is layered so the server is *super customizable* without code
5
+ * changes. Precedence, lowest to highest:
6
+ *
7
+ * 1. Built-in defaults (below).
8
+ * 2. An optional JSON config file (`docker-mcp.config.json`, or the path in
9
+ * `DOCKER_MCP_CONFIG`).
10
+ * 3. A local `.env` file.
11
+ * 4. Real environment variables (what your MCP client passes).
12
+ *
13
+ * This lets a user ship a curated `docker-mcp.config.json` (which plugins are
14
+ * enabled, allowlist, panel port…) and still override anything per-launch.
15
+ *
16
+ * Part of Docker MCP Server.
17
+ * Crafted by SoyRage Agency — https://soyrage.es/
18
+ * MIT licensed (see LICENSE).
19
+ */
20
+ /** Supported diagnostic log levels, ordered by verbosity. */
21
+ export type LogLevel = "debug" | "info" | "warn" | "error";
22
+ /** Plugin enable/disable selection. */
23
+ export interface PluginSelection {
24
+ /** When non-empty, ONLY these plugins are considered (allowlist). */
25
+ readonly enabled: readonly string[];
26
+ /** Plugins to switch off (applied after `enabled`). */
27
+ readonly disabled: readonly string[];
28
+ }
29
+ /** Interactive panel settings. */
30
+ export interface PanelConfig {
31
+ readonly host: string;
32
+ readonly port: number;
33
+ /** Serve fabricated demo data instead of touching a real daemon. */
34
+ readonly demo: boolean;
35
+ /** Expose the Prometheus `/metrics` endpoint (for Prometheus/Zabbix/…). */
36
+ readonly metrics: boolean;
37
+ /** Enable the in-panel command terminal (docker/compose runner). */
38
+ readonly terminal: boolean;
39
+ /** Directory where container snapshots/backups are written. */
40
+ readonly backupDir: string;
41
+ /** Optional webhook URL notified after a backup (route to email/Drive). */
42
+ readonly backupWebhook: string;
43
+ /** Optional OpenAI-compatible endpoint powering the AI terminal/editor. */
44
+ readonly aiEndpoint: string;
45
+ /** API key for the AI endpoint (bearer). */
46
+ readonly aiKey: string;
47
+ /** Model name for the AI endpoint. */
48
+ readonly aiModel: string;
49
+ }
50
+ /** Fully-resolved, immutable server configuration. */
51
+ export interface AppConfig {
52
+ readonly dockerHost: string;
53
+ readonly dockerCertPath: string;
54
+ readonly dockerTlsVerify: boolean;
55
+ readonly readOnly: boolean;
56
+ readonly allowExec: boolean;
57
+ readonly containerAllowlist: readonly string[];
58
+ readonly defaultLogTail: number;
59
+ readonly composeCwd: string;
60
+ readonly logLevel: LogLevel;
61
+ readonly plugins: PluginSelection;
62
+ readonly panel: PanelConfig;
63
+ }
64
+ /** Build the configuration object. Called once from each entry point. */
65
+ export declare function loadConfig(): AppConfig;
package/dist/config.js ADDED
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Runtime configuration.
3
+ *
4
+ * Configuration is layered so the server is *super customizable* without code
5
+ * changes. Precedence, lowest to highest:
6
+ *
7
+ * 1. Built-in defaults (below).
8
+ * 2. An optional JSON config file (`docker-mcp.config.json`, or the path in
9
+ * `DOCKER_MCP_CONFIG`).
10
+ * 3. A local `.env` file.
11
+ * 4. Real environment variables (what your MCP client passes).
12
+ *
13
+ * This lets a user ship a curated `docker-mcp.config.json` (which plugins are
14
+ * enabled, allowlist, panel port…) and still override anything per-launch.
15
+ *
16
+ * Part of Docker MCP Server.
17
+ * Crafted by SoyRage Agency — https://soyrage.es/
18
+ * MIT licensed (see LICENSE).
19
+ */
20
+ import { readFileSync, existsSync } from "node:fs";
21
+ import { resolve } from "node:path";
22
+ /** Read and parse the JSON config file, if present. Never throws. */
23
+ function loadConfigFile() {
24
+ const path = resolve(process.cwd(), process.env.DOCKER_MCP_CONFIG?.trim() || "docker-mcp.config.json");
25
+ if (!existsSync(path))
26
+ return {};
27
+ try {
28
+ return JSON.parse(readFileSync(path, "utf8"));
29
+ }
30
+ catch {
31
+ // A malformed config file should not crash startup; fall back to defaults.
32
+ process.stderr.write(`[docker-mcp] Warning: could not parse config file at ${path}; ignoring it.\n`);
33
+ return {};
34
+ }
35
+ }
36
+ /**
37
+ * Minimal, dependency-free `.env` loader. Existing `process.env` values always
38
+ * win so an MCP client can override the file.
39
+ */
40
+ function loadDotEnv() {
41
+ const path = resolve(process.cwd(), ".env");
42
+ if (!existsSync(path))
43
+ return;
44
+ const raw = readFileSync(path, "utf8");
45
+ for (const line of raw.split(/\r?\n/)) {
46
+ const trimmed = line.trim();
47
+ if (!trimmed || trimmed.startsWith("#"))
48
+ continue;
49
+ const eq = trimmed.indexOf("=");
50
+ if (eq === -1)
51
+ continue;
52
+ const key = trimmed.slice(0, eq).trim();
53
+ let value = trimmed.slice(eq + 1).trim();
54
+ if ((value.startsWith('"') && value.endsWith('"')) ||
55
+ (value.startsWith("'") && value.endsWith("'"))) {
56
+ value = value.slice(1, -1);
57
+ }
58
+ if (key && process.env[key] === undefined)
59
+ process.env[key] = value;
60
+ }
61
+ }
62
+ /** Read a boolean flag with a fallback; accepts `true/1/yes/on`. */
63
+ function envFlag(name, fallback) {
64
+ const value = process.env[name];
65
+ if (value === undefined || value === "")
66
+ return fallback;
67
+ return /^(1|true|yes|on)$/i.test(value.trim());
68
+ }
69
+ /** Read a positive integer with a fallback. */
70
+ function envInt(name, fallback) {
71
+ const value = process.env[name];
72
+ if (!value)
73
+ return fallback;
74
+ const parsed = Number.parseInt(value, 10);
75
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
76
+ }
77
+ /** Read a comma-separated list, falling back to `fallback` when unset. */
78
+ function envList(name, fallback) {
79
+ const value = process.env[name];
80
+ if (value === undefined)
81
+ return [...fallback];
82
+ return value
83
+ .split(",")
84
+ .map((item) => item.trim())
85
+ .filter(Boolean);
86
+ }
87
+ /** Read a string with a fallback. */
88
+ function envStr(name, fallback) {
89
+ const value = process.env[name];
90
+ return value === undefined ? fallback : value.trim();
91
+ }
92
+ /** Build the configuration object. Called once from each entry point. */
93
+ export function loadConfig() {
94
+ const file = loadConfigFile();
95
+ loadDotEnv();
96
+ const rawLevel = envStr("DOCKER_MCP_LOG_LEVEL", file.logLevel ?? "info").toLowerCase();
97
+ const logLevel = ["debug", "info", "warn", "error"].includes(rawLevel)
98
+ ? rawLevel
99
+ : "info";
100
+ return Object.freeze({
101
+ dockerHost: envStr("DOCKER_HOST", file.dockerHost ?? ""),
102
+ dockerCertPath: envStr("DOCKER_CERT_PATH", file.dockerCertPath ?? ""),
103
+ dockerTlsVerify: envFlag("DOCKER_TLS_VERIFY", file.dockerTlsVerify ?? false),
104
+ readOnly: envFlag("DOCKER_MCP_READONLY", file.readOnly ?? false),
105
+ allowExec: envFlag("DOCKER_MCP_ALLOW_EXEC", file.allowExec ?? false),
106
+ containerAllowlist: Object.freeze(envList("DOCKER_MCP_CONTAINER_ALLOWLIST", file.containerAllowlist ?? [])),
107
+ defaultLogTail: envInt("DOCKER_MCP_DEFAULT_LOG_TAIL", file.defaultLogTail ?? 200),
108
+ composeCwd: envStr("DOCKER_MCP_COMPOSE_CWD", file.composeCwd ?? "") || process.cwd(),
109
+ logLevel,
110
+ plugins: Object.freeze({
111
+ enabled: Object.freeze(envList("DOCKER_MCP_PLUGINS", file.plugins?.enabled ?? [])),
112
+ disabled: Object.freeze(envList("DOCKER_MCP_DISABLED_PLUGINS", file.plugins?.disabled ?? [])),
113
+ }),
114
+ panel: Object.freeze({
115
+ host: envStr("DOCKER_MCP_PANEL_HOST", file.panel?.host ?? "127.0.0.1"),
116
+ port: envInt("DOCKER_MCP_PANEL_PORT", file.panel?.port ?? 4600),
117
+ demo: envFlag("DOCKER_MCP_PANEL_DEMO", file.panel?.demo ?? false),
118
+ metrics: envFlag("DOCKER_MCP_PANEL_METRICS", file.panel?.metrics ?? true),
119
+ terminal: envFlag("DOCKER_MCP_PANEL_TERMINAL", file.panel?.terminal ?? true),
120
+ backupDir: envStr("DOCKER_MCP_BACKUP_DIR", file.panel?.backupDir ?? "./snapshots"),
121
+ backupWebhook: envStr("DOCKER_MCP_BACKUP_WEBHOOK", file.panel?.backupWebhook ?? ""),
122
+ aiEndpoint: envStr("DOCKER_MCP_AI_ENDPOINT", file.panel?.aiEndpoint ?? ""),
123
+ aiKey: envStr("DOCKER_MCP_AI_KEY", file.panel?.aiKey ?? ""),
124
+ aiModel: envStr("DOCKER_MCP_AI_MODEL", file.panel?.aiModel ?? "gpt-4o-mini"),
125
+ }),
126
+ });
127
+ }
128
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Docker Engine client.
3
+ *
4
+ * Thin, well-typed wrapper around `dockerode`. It centralises connection
5
+ * construction (socket, npipe or secured TCP), applies the optional container
6
+ * allowlist and exposes small helpers the tools build on. Compose operations
7
+ * live in `./compose.ts` because they shell out to the Docker CLI.
8
+ *
9
+ * Part of Docker MCP Server.
10
+ * Crafted by SoyRage Agency — https://soyrage.es/
11
+ * Licensed under the MIT License.
12
+ */
13
+ import Docker from "dockerode";
14
+ import type { AppConfig } from "../config.js";
15
+ import type { Logger } from "../logger.js";
16
+ /** Raised when a caller targets a container excluded by the allowlist. */
17
+ export declare class ContainerNotAllowedError extends Error {
18
+ constructor(reference: string);
19
+ }
20
+ /** Raised when a referenced container simply does not exist. */
21
+ export declare class ContainerNotFoundError extends Error {
22
+ constructor(reference: string);
23
+ }
24
+ /** Normalise a Docker "Names" array or "/name" string into a bare name. */
25
+ export declare function normalizeName(name: string): string;
26
+ /**
27
+ * Application-facing Docker client. Instances are cheap; one is created at
28
+ * startup and shared across every tool.
29
+ */
30
+ export declare class DockerClient {
31
+ private readonly docker;
32
+ private readonly log;
33
+ private readonly allowlist;
34
+ constructor(config: AppConfig, logger: Logger);
35
+ /** Direct access to the underlying dockerode instance (advanced use). */
36
+ get raw(): Docker;
37
+ /** Verify connectivity by pinging the daemon. Throws on failure. */
38
+ ping(): Promise<void>;
39
+ /**
40
+ * Decide whether a container name is permitted by the allowlist.
41
+ * An empty allowlist permits everything. Matching is prefix-based so a
42
+ * single entry (`web`) covers scaled replicas (`web-1`, `web-2`).
43
+ */
44
+ isAllowed(name: string): boolean;
45
+ /** List containers, honouring the allowlist. */
46
+ listContainers(all: boolean): Promise<Docker.ContainerInfo[]>;
47
+ /**
48
+ * Resolve a user-supplied reference (name, short id or full id) to a
49
+ * dockerode Container handle, enforcing the allowlist along the way.
50
+ */
51
+ resolveContainer(reference: string): Promise<Docker.Container>;
52
+ /** Fetch a fresh `ContainerInfo` summary for a resolved container. */
53
+ describeContainer(reference: string): Promise<Docker.ContainerInfo>;
54
+ /** List images. */
55
+ listImages(): Promise<Docker.ImageInfo[]>;
56
+ /** List user-defined and default networks. */
57
+ listNetworks(): Promise<Docker.NetworkInspectInfo[]>;
58
+ /** List named volumes. */
59
+ listVolumes(): Promise<Docker.VolumeInspectInfo[]>;
60
+ /** Daemon-wide info (`docker info`). */
61
+ info(): Promise<Record<string, unknown>>;
62
+ /** Disk usage (`docker system df`). */
63
+ diskUsage(): Promise<Record<string, unknown>>;
64
+ /** Daemon version details (`docker version`). */
65
+ version(): Promise<Record<string, unknown>>;
66
+ }
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Docker Engine client.
3
+ *
4
+ * Thin, well-typed wrapper around `dockerode`. It centralises connection
5
+ * construction (socket, npipe or secured TCP), applies the optional container
6
+ * allowlist and exposes small helpers the tools build on. Compose operations
7
+ * live in `./compose.ts` because they shell out to the Docker CLI.
8
+ *
9
+ * Part of Docker MCP Server.
10
+ * Crafted by SoyRage Agency — https://soyrage.es/
11
+ * Licensed under the MIT License.
12
+ */
13
+ import { readFileSync } from "node:fs";
14
+ import { join } from "node:path";
15
+ import Docker from "dockerode";
16
+ /** Raised when a caller targets a container excluded by the allowlist. */
17
+ export class ContainerNotAllowedError extends Error {
18
+ constructor(reference) {
19
+ super(`Container "${reference}" is not covered by DOCKER_MCP_CONTAINER_ALLOWLIST and cannot be accessed.`);
20
+ this.name = "ContainerNotAllowedError";
21
+ }
22
+ }
23
+ /** Raised when a referenced container simply does not exist. */
24
+ export class ContainerNotFoundError extends Error {
25
+ constructor(reference) {
26
+ super(`No container matches "${reference}".`);
27
+ this.name = "ContainerNotFoundError";
28
+ }
29
+ }
30
+ /**
31
+ * Convert the environment configuration into `dockerode` connection options.
32
+ * Supports three transports:
33
+ * 1. Explicit `unix://` / `npipe://` paths.
34
+ * 2. Secured or plain TCP daemons (`tcp://host:port`), with optional TLS.
35
+ * 3. The platform default socket when nothing is configured.
36
+ */
37
+ function buildDockerOptions(config) {
38
+ const host = config.dockerHost;
39
+ // No host configured → let dockerode pick the platform default socket.
40
+ if (!host)
41
+ return {};
42
+ if (host.startsWith("unix://")) {
43
+ return { socketPath: host.replace("unix://", "") };
44
+ }
45
+ if (host.startsWith("npipe://")) {
46
+ return { socketPath: host.replace("npipe://", "") };
47
+ }
48
+ // TCP (with or without an explicit tcp:// scheme).
49
+ const url = new URL(host.includes("://") ? host : `tcp://${host}`);
50
+ const useTls = config.dockerTlsVerify || url.protocol === "https:";
51
+ const options = {
52
+ host: url.hostname,
53
+ port: url.port ? Number.parseInt(url.port, 10) : useTls ? 2376 : 2375,
54
+ protocol: useTls ? "https" : "http",
55
+ };
56
+ if (useTls && config.dockerCertPath) {
57
+ options.ca = readFileSync(join(config.dockerCertPath, "ca.pem"));
58
+ options.cert = readFileSync(join(config.dockerCertPath, "cert.pem"));
59
+ options.key = readFileSync(join(config.dockerCertPath, "key.pem"));
60
+ }
61
+ return options;
62
+ }
63
+ /** Normalise a Docker "Names" array or "/name" string into a bare name. */
64
+ export function normalizeName(name) {
65
+ return name.replace(/^\//, "");
66
+ }
67
+ /**
68
+ * Application-facing Docker client. Instances are cheap; one is created at
69
+ * startup and shared across every tool.
70
+ */
71
+ export class DockerClient {
72
+ docker;
73
+ log;
74
+ allowlist;
75
+ constructor(config, logger) {
76
+ this.docker = new Docker(buildDockerOptions(config));
77
+ this.log = logger.child("docker");
78
+ this.allowlist = config.containerAllowlist;
79
+ }
80
+ /** Direct access to the underlying dockerode instance (advanced use). */
81
+ get raw() {
82
+ return this.docker;
83
+ }
84
+ /** Verify connectivity by pinging the daemon. Throws on failure. */
85
+ async ping() {
86
+ await this.docker.ping();
87
+ this.log.debug("Daemon ping succeeded");
88
+ }
89
+ /**
90
+ * Decide whether a container name is permitted by the allowlist.
91
+ * An empty allowlist permits everything. Matching is prefix-based so a
92
+ * single entry (`web`) covers scaled replicas (`web-1`, `web-2`).
93
+ */
94
+ isAllowed(name) {
95
+ if (this.allowlist.length === 0)
96
+ return true;
97
+ const bare = normalizeName(name);
98
+ return this.allowlist.some((entry) => bare === entry || bare.startsWith(entry));
99
+ }
100
+ /** List containers, honouring the allowlist. */
101
+ async listContainers(all) {
102
+ const containers = await this.docker.listContainers({ all });
103
+ if (this.allowlist.length === 0)
104
+ return containers;
105
+ return containers.filter((c) => c.Names.some((n) => this.isAllowed(n)));
106
+ }
107
+ /**
108
+ * Resolve a user-supplied reference (name, short id or full id) to a
109
+ * dockerode Container handle, enforcing the allowlist along the way.
110
+ */
111
+ async resolveContainer(reference) {
112
+ const ref = normalizeName(reference.trim());
113
+ const containers = await this.docker.listContainers({ all: true });
114
+ const match = containers.find((c) => {
115
+ const byId = c.Id === ref || c.Id.startsWith(ref);
116
+ const byName = c.Names.some((n) => normalizeName(n) === ref);
117
+ return byId || byName;
118
+ });
119
+ if (!match)
120
+ throw new ContainerNotFoundError(reference);
121
+ const allowed = match.Names.some((n) => this.isAllowed(n));
122
+ if (!allowed)
123
+ throw new ContainerNotAllowedError(reference);
124
+ return this.docker.getContainer(match.Id);
125
+ }
126
+ /** Fetch a fresh `ContainerInfo` summary for a resolved container. */
127
+ async describeContainer(reference) {
128
+ const container = await this.resolveContainer(reference);
129
+ const containers = await this.docker.listContainers({ all: true });
130
+ const info = containers.find((c) => c.Id === container.id);
131
+ if (!info)
132
+ throw new ContainerNotFoundError(reference);
133
+ return info;
134
+ }
135
+ /** List images. */
136
+ async listImages() {
137
+ return this.docker.listImages();
138
+ }
139
+ /** List user-defined and default networks. */
140
+ async listNetworks() {
141
+ return this.docker.listNetworks();
142
+ }
143
+ /** List named volumes. */
144
+ async listVolumes() {
145
+ const result = await this.docker.listVolumes();
146
+ return result.Volumes ?? [];
147
+ }
148
+ /** Daemon-wide info (`docker info`). */
149
+ async info() {
150
+ return (await this.docker.info());
151
+ }
152
+ /** Disk usage (`docker system df`). */
153
+ async diskUsage() {
154
+ return (await this.docker.df());
155
+ }
156
+ /** Daemon version details (`docker version`). */
157
+ async version() {
158
+ return (await this.docker.version());
159
+ }
160
+ }
161
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/docker/client.ts"],"names":[],"mappings":"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"}