@jurislm/coolify-plugin 4.0.26 → 4.0.27
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/.codex-plugin/plugin.json +1 -1
- package/.mcp.json +2 -2
- package/.mcp.json.example +2 -2
- package/README.md +2 -2
- package/dist/config.d.ts +1 -0
- package/dist/config.js +5 -0
- package/dist/index.js +3 -2
- package/dist/plugin-env.d.ts +6 -0
- package/dist/plugin-env.js +66 -0
- package/launchers/coolify-desktop.zsh +1 -1
- package/mcp.json +2 -2
- package/package.json +1 -1
- package/plugin.json +1 -1
package/.mcp.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"mcpServers": {
|
|
3
3
|
"coolify": {
|
|
4
4
|
"type": "stdio",
|
|
5
|
-
"command": "
|
|
6
|
-
"args": ["
|
|
5
|
+
"command": "bun",
|
|
6
|
+
"args": ["x", "@jurislm/coolify-plugin@latest"],
|
|
7
7
|
"env_vars": ["COOLIFY_CLOUD_BASE_URL", "COOLIFY_CLOUD_ACCESS_TOKEN", "CURSOR_COOLIFY_BASE_URL", "CURSOR_COOLIFY_ACCESS_TOKEN", "COOLIFY_BASE_URL", "COOLIFY_ACCESS_TOKEN"]
|
|
8
8
|
}
|
|
9
9
|
}
|
package/.mcp.json.example
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"mcpServers": {
|
|
3
3
|
"coolify": {
|
|
4
|
-
"command": "
|
|
5
|
-
"args": ["
|
|
4
|
+
"command": "bun",
|
|
5
|
+
"args": ["x", "@jurislm/coolify-plugin@latest"],
|
|
6
6
|
"env": {
|
|
7
7
|
"COOLIFY_BASE_URL": "https://coolify.example",
|
|
8
8
|
"COOLIFY_ACCESS_TOKEN": "<set-in-host-environment>"
|
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ bun run check
|
|
|
27
27
|
bun dist/index.js
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
`mcp.json` and
|
|
30
|
+
`mcp.json`, `.mcp.json` and `plugins/cursor/mcp.json` launch the published package with `bun x` (not the separate `bunx` executable, which some package-manager shims break). When a connection variable is missing, empty, or an unsubstituted `${...}` placeholder, the server fills it from `~/.config/jurislm/plugin.env` (`KEY=value` or `export KEY=value` lines; override the path with `JURISLM_PLUGIN_ENV`); host values always take precedence and values are never logged. `.mcp.json.example` contains placeholder environment values only. NPM package release is allowed.
|
|
31
31
|
|
|
32
32
|
For Codex repository marketplace installation, use the repository root and leave the sparse path empty. The supported marketplace manifest is `.agents/plugins/marketplace.json`; do not enter `plugins/codex`.
|
|
33
33
|
The native Codex registration forwards `COOLIFY_CLOUD_BASE_URL`, `COOLIFY_CLOUD_ACCESS_TOKEN`, `CURSOR_COOLIFY_BASE_URL`, `CURSOR_COOLIFY_ACCESS_TOKEN`, `COOLIFY_BASE_URL` and `COOLIFY_ACCESS_TOKEN` from its owning environment. Portable `mcp.json` contains no host-specific fields or credential defaults.
|
|
@@ -51,7 +51,7 @@ args = ["-f", "-c", 'source "$HOME/.codex/bin/coolify-mcp.zsh"']
|
|
|
51
51
|
startup_timeout_sec = 30
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
The launcher checks startup-file syntax before explicitly sourcing `${ZDOTDIR:-$HOME}/.zshenv`, suppresses stdout and preserves stderr. Source status 0 or 1 is accepted because a final optional guard can return 1; higher statuses stop startup. It retains only the six supported connection variables, `HOME`, `PATH`, `TMPDIR` and `LANG`, fixes PATH to `$HOME/.bun/bin:/usr/bin:/bin` and executes the absolute `$HOME/.bun/bin/
|
|
54
|
+
The launcher checks startup-file syntax before explicitly sourcing `${ZDOTDIR:-$HOME}/.zshenv`, suppresses stdout and preserves stderr. Source status 0 or 1 is accepted because a final optional guard can return 1; higher statuses stop startup. It retains only the six supported connection variables, `HOME`, `PATH`, `TMPDIR` and `LANG`, fixes PATH to `$HOME/.bun/bin:/usr/bin:/bin` and executes the absolute `$HOME/.bun/bin/bun x` path. The `--require-config` option reuses `loadConfig` to require the selected complete URL/token pair before starting stdio; trim, placeholder handling and pair precedence remain the same. Ordinary portable initialization and tool discovery can still start without credentials.
|
|
55
55
|
|
|
56
56
|
Check `codex mcp get coolify`, restart Codex and open a fresh chat. Read `coolify_get_mcp_version` before connection checks and authenticated reads. Record the resolved package version, actual registration source, HTTP status and returned counts. Standalone stdio checks establish process behavior; fresh chat registration and provider reads require their own evidence.
|
|
57
57
|
|
package/dist/config.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare const CREDENTIAL_GROUPS: readonly [readonly ["COOLIFY_CLOUD_BASE_URL", "COOLIFY_CLOUD_ACCESS_TOKEN"], readonly ["CURSOR_COOLIFY_BASE_URL", "CURSOR_COOLIFY_ACCESS_TOKEN"], readonly ["COOLIFY_BASE_URL", "COOLIFY_ACCESS_TOKEN"]];
|
|
1
2
|
export interface CoolifyConfig {
|
|
2
3
|
baseUrl?: string;
|
|
3
4
|
token?: string;
|
package/dist/config.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
export const CREDENTIAL_GROUPS = [
|
|
2
|
+
["COOLIFY_CLOUD_BASE_URL", "COOLIFY_CLOUD_ACCESS_TOKEN"],
|
|
3
|
+
["CURSOR_COOLIFY_BASE_URL", "CURSOR_COOLIFY_ACCESS_TOKEN"],
|
|
4
|
+
["COOLIFY_BASE_URL", "COOLIFY_ACCESS_TOKEN"],
|
|
5
|
+
];
|
|
1
6
|
export class ConfigError extends Error {
|
|
2
7
|
constructor(message) {
|
|
3
8
|
super(message);
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import { ConfigError, loadConfig } from "./config.js";
|
|
2
|
+
import { CREDENTIAL_GROUPS, ConfigError, loadConfig } from "./config.js";
|
|
3
|
+
import { withPluginEnv } from "./plugin-env.js";
|
|
3
4
|
import { createServer } from "./server.js";
|
|
4
5
|
import { createStdioTransport } from "./transports/stdio.js";
|
|
5
6
|
try {
|
|
6
|
-
const config = loadConfig();
|
|
7
|
+
const config = loadConfig(withPluginEnv(process.env, CREDENTIAL_GROUPS));
|
|
7
8
|
if (process.argv.includes("--require-config") && (!config.baseUrl || !config.token))
|
|
8
9
|
throw new ConfigError("A complete URL/token pair is required for the selected Coolify configuration");
|
|
9
10
|
await createServer(config).connect(createStdioTransport());
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type Environment = Record<string, string | undefined>;
|
|
2
|
+
export type CredentialGroups = readonly (readonly string[])[];
|
|
3
|
+
export declare const PLUGIN_ENV_PATH_VARIABLE = "JURISLM_PLUGIN_ENV";
|
|
4
|
+
export declare function parsePluginEnv(text: string): Record<string, string>;
|
|
5
|
+
export declare function pluginEnvPath(env: Environment): string;
|
|
6
|
+
export declare function withPluginEnv(env: Environment, groups: CredentialGroups, readText?: (path: string) => string, warn?: (message: string) => void): Environment;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
export const PLUGIN_ENV_PATH_VARIABLE = "JURISLM_PLUGIN_ENV";
|
|
5
|
+
const PLACEHOLDER = /^\$\{[^}]*\}$/u;
|
|
6
|
+
const ASSIGNMENT = /^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/u;
|
|
7
|
+
function isUnset(value) {
|
|
8
|
+
const trimmed = value?.trim();
|
|
9
|
+
return !trimmed || PLACEHOLDER.test(trimmed);
|
|
10
|
+
}
|
|
11
|
+
export function parsePluginEnv(text) {
|
|
12
|
+
const values = {};
|
|
13
|
+
for (const rawLine of text.split(/\r?\n/u)) {
|
|
14
|
+
const match = ASSIGNMENT.exec(rawLine.trim());
|
|
15
|
+
if (!match)
|
|
16
|
+
continue;
|
|
17
|
+
const [, name, rawValue] = match;
|
|
18
|
+
const quote = rawValue[0];
|
|
19
|
+
if (quote === '"' || quote === "'") {
|
|
20
|
+
const end = rawValue.indexOf(quote, 1);
|
|
21
|
+
if (end > 0)
|
|
22
|
+
values[name] = rawValue.slice(1, end);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
values[name] = rawValue.replace(/\s+#.*$/u, "").trim();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return values;
|
|
29
|
+
}
|
|
30
|
+
export function pluginEnvPath(env) {
|
|
31
|
+
const home = env.HOME?.trim() || homedir();
|
|
32
|
+
const override = env[PLUGIN_ENV_PATH_VARIABLE];
|
|
33
|
+
if (!override || isUnset(override))
|
|
34
|
+
return join(home, ".config", "jurislm", "plugin.env");
|
|
35
|
+
const path = override.trim();
|
|
36
|
+
return resolve(path === "~" || path.startsWith("~/") ? join(home, path.slice(1)) : path);
|
|
37
|
+
}
|
|
38
|
+
function readPluginEnv(path, readText, warn) {
|
|
39
|
+
try {
|
|
40
|
+
return parsePluginEnv(readText(path));
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
const code = error.code;
|
|
44
|
+
if (code !== "ENOENT")
|
|
45
|
+
warn(`Could not read plugin env file ${path} (${code ?? "unknown error"})`);
|
|
46
|
+
return {};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export function withPluginEnv(env, groups, readText = (path) => readFileSync(path, "utf8"), warn = (message) => console.error(message)) {
|
|
50
|
+
if (groups.every((group) => group.every((name) => !isUnset(env[name]))))
|
|
51
|
+
return env;
|
|
52
|
+
const fileValues = groups.some((group) => group.every((name) => isUnset(env[name]))) ? readPluginEnv(pluginEnvPath(env), readText, warn) : {};
|
|
53
|
+
const resolved = { ...env };
|
|
54
|
+
for (const group of groups) {
|
|
55
|
+
const fillFromFile = group.every((name) => isUnset(env[name]));
|
|
56
|
+
for (const name of group) {
|
|
57
|
+
if (!isUnset(env[name]))
|
|
58
|
+
continue;
|
|
59
|
+
if (fillFromFile && !isUnset(fileValues[name]))
|
|
60
|
+
resolved[name] = fileValues[name];
|
|
61
|
+
else
|
|
62
|
+
delete resolved[name];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return resolved;
|
|
66
|
+
}
|
package/mcp.json
CHANGED
package/package.json
CHANGED
package/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "coolify-plugin",
|
|
4
|
-
"version": "4.0.
|
|
4
|
+
"version": "4.0.27",
|
|
5
5
|
"description": "Portable Coolify MCP plugin with local stdio tools generated from the official OpenAPI contract.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "JurisLM",
|