metheus-governance-mcp-cli 0.2.47 → 0.2.49
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/README.md +46 -15
- package/cli.mjs +121 -10
- package/package.json +5 -3
- package/postinstall.mjs +47 -0
package/README.md
CHANGED
|
@@ -20,6 +20,27 @@ Compatibility note: legacy command alias `metheus-governance-mcp` is still suppo
|
|
|
20
20
|
npm install -g metheus-governance-mcp-cli@latest
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
Install creates a local Telegram settings template here:
|
|
24
|
+
|
|
25
|
+
- `~/.metheus/telegram.env`
|
|
26
|
+
|
|
27
|
+
This file is for local bot secrets only.
|
|
28
|
+
|
|
29
|
+
- Store locally:
|
|
30
|
+
- `TELEGRAM_BOT_TOKEN`
|
|
31
|
+
- Server-side Metheus stores project Telegram destination metadata separately:
|
|
32
|
+
- `chat_id`
|
|
33
|
+
- label / active state
|
|
34
|
+
|
|
35
|
+
Example template:
|
|
36
|
+
|
|
37
|
+
```env
|
|
38
|
+
TELEGRAM_BOT_TOKEN=
|
|
39
|
+
TELEGRAM_DEFAULT_CHAT_ID=
|
|
40
|
+
TELEGRAM_ALLOWED_CHAT_IDS=
|
|
41
|
+
TELEGRAM_DEFAULT_PARSE_MODE=
|
|
42
|
+
```
|
|
43
|
+
|
|
23
44
|
## One command bootstrap (recommended)
|
|
24
45
|
|
|
25
46
|
Run in your project folder:
|
|
@@ -36,31 +57,34 @@ If auth is not ready, login starts automatically, then MCP registration is compl
|
|
|
36
57
|
metheus-governance-mcp-cli setup --project-id <project_uuid> --ctxpack-key "<ctxpack_key>" --base-url https://metheus.gesiaplatform.com
|
|
37
58
|
```
|
|
38
59
|
|
|
39
|
-
`project-id` can be
|
|
60
|
+
Technical fallback: `project-id` can be auto-detected if your current folder (or parent) has `.metheus_ctxpack_sync.json`.
|
|
40
61
|
`setup` defaults to `--workspace-dir auto` (dynamic workspace detection).
|
|
41
62
|
Use an explicit path only when you intentionally want a fixed workspace.
|
|
42
63
|
|
|
64
|
+
Ops policy (recommended):
|
|
65
|
+
- Always pass explicit `--project-id <project_uuid>` during setup.
|
|
66
|
+
- Omit `--project-id` only in advanced cases where `.metheus_ctxpack_sync.json` is already present and verified.
|
|
67
|
+
|
|
43
68
|
Recommended for Codex/Claude/Gemini/Antigravity/Cursor multi-workspace sessions:
|
|
44
69
|
|
|
45
70
|
```bash
|
|
46
71
|
metheus-governance-mcp-cli setup --project-id <project_uuid> --ctxpack-key "<ctxpack_key>" --base-url https://metheus.gesiaplatform.com --workspace-dir auto
|
|
47
72
|
```
|
|
48
73
|
|
|
74
|
+
`setup` also ensures the local Telegram template exists:
|
|
75
|
+
|
|
76
|
+
- `~/.metheus/telegram.env`
|
|
77
|
+
|
|
78
|
+
Fill only the bot token locally. Project Telegram `chat_id` destinations should be managed on the Metheus server.
|
|
79
|
+
|
|
49
80
|
Gemini CLI note:
|
|
50
81
|
- `gemini mcp` commands require Gemini auth to be configured first (`GEMINI_API_KEY` or `~/.gemini/settings.json` auth).
|
|
51
82
|
- `setup` registers Gemini in both `user` and `project` scopes to improve auto-discovery across folders.
|
|
52
83
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
metheus-governance-mcp-cli setup --project-id <project_uuid> --ctxpack-key "<ctxpack_key>" --base-url https://metheus.gesiaplatform.com --workspace-dir auto --workspace-fallback-dir C:\code_test
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
This sets fallback workspace context for clients that do not pass workspace metadata:
|
|
61
|
-
- Codex/Antigravity/Cursor: `METHEUS_WORKSPACE_DIR` env
|
|
62
|
-
- Gemini: pinned `--workspace-dir <fallback>` and `METHEUS_WORKSPACE_DIR` in MCP registration
|
|
63
|
-
- fallback env is used only when workspace cannot be resolved (or resolves to home); when current `cwd` is a real project folder, sync uses that folder.
|
|
84
|
+
Workspace signal guardrail:
|
|
85
|
+
- default recommendation is `--workspace-dir auto` with no fixed fallback path.
|
|
86
|
+
- if a client session does not provide trusted workspace signals (`workspaceFolders` / `rootUri` / `cwd`), ctxpack local write is blocked (`sync_status=guarded`, `local_file_count=0`).
|
|
87
|
+
- use `--workspace-fallback-dir` only when you intentionally want a shared fallback root.
|
|
64
88
|
|
|
65
89
|
Guardrail note:
|
|
66
90
|
- By default, CLI blocks reading/writing ctxpack sync metadata when workspace root resolves to the home directory.
|
|
@@ -83,6 +107,7 @@ metheus-governance-mcp-cli doctor --project-id <project_uuid> --base-url https:/
|
|
|
83
107
|
|
|
84
108
|
Checks:
|
|
85
109
|
- auth token status (+ auto refresh attempt)
|
|
110
|
+
- local Telegram env template presence
|
|
86
111
|
- codex/claude/gemini/antigravity/cursor registration state
|
|
87
112
|
- gateway `tools/list` reachability
|
|
88
113
|
- `project.summary` access
|
|
@@ -105,8 +130,8 @@ Cursor note:
|
|
|
105
130
|
|
|
106
131
|
Tool naming compatibility:
|
|
107
132
|
- Claude/Codex/Gemini keep canonical MCP tool names (`project.summary`, `ctxpack.merge.brief`, ...).
|
|
108
|
-
- Cursor/Antigravity sessions
|
|
109
|
-
- Proxy maps alias calls back to canonical names automatically.
|
|
133
|
+
- Cursor/Antigravity sessions use safe aliases only (`project_summary`, `ctxpack_merge_brief`, ...).
|
|
134
|
+
- Proxy maps safe alias calls back to canonical names automatically.
|
|
110
135
|
|
|
111
136
|
Local bootstrap tools exposed by proxy:
|
|
112
137
|
|
|
@@ -127,7 +152,13 @@ These tools accept `project_id` and return:
|
|
|
127
152
|
- same version -> keep current
|
|
128
153
|
- newer server version -> update local cache
|
|
129
154
|
- workspace path -> auto-detected from client metadata/env by default
|
|
130
|
-
-
|
|
155
|
+
- if workspace signal is missing in auto mode, sync is guarded (no local write)
|
|
156
|
+
- use `--workspace-fallback-dir <path>` only when you intentionally want fallback writes
|
|
157
|
+
|
|
158
|
+
Project-ID first-call rule:
|
|
159
|
+
- when user gives only `Project ID`, call `project.summary` first.
|
|
160
|
+
- call `ctxpack.ensure` after `project.summary` only when extra ctxpack refresh/export context is needed.
|
|
161
|
+
- for support/ops workflows, do not run ctxpack sync/download before a successful `project.summary`.
|
|
131
162
|
|
|
132
163
|
Ctxpack merge safety flow:
|
|
133
164
|
- call `ctxpack.merge.brief` first
|
package/cli.mjs
CHANGED
|
@@ -15,6 +15,7 @@ const DEFAULT_SITE_URL = "https://metheus.gesiaplatform.com";
|
|
|
15
15
|
const DEFAULT_BASE_URL = `${DEFAULT_SITE_URL}/governance/mcp`;
|
|
16
16
|
const DEFAULT_SERVER_NAME = "metheus-governance-mcp";
|
|
17
17
|
const AUTH_STORE_RELATIVE_PATH = path.join(".metheus", "governance-mcp-auth.json");
|
|
18
|
+
const TELEGRAM_ENV_RELATIVE_PATH = path.join(".metheus", "telegram.env");
|
|
18
19
|
const SELF_UPDATE_STATE_RELATIVE_PATH = path.join(".metheus", "governance-mcp-cli-update.json");
|
|
19
20
|
const CTXPACK_CACHE_RELATIVE_DIR = path.join(".metheus", "ctxpack-cache");
|
|
20
21
|
const CTXPACK_META_FILENAME = ".metheus_ctxpack_sync.json";
|
|
@@ -57,6 +58,8 @@ function printUsage() {
|
|
|
57
58
|
` ${ALLOW_HOME_WORKSPACE_ENV_KEY}=1 to allow using home directory as workspace root (disabled by default).`,
|
|
58
59
|
" If env is missing, stored token file is used:",
|
|
59
60
|
` ${AUTH_STORE_RELATIVE_PATH}`,
|
|
61
|
+
" Local Telegram bot token template is stored at:",
|
|
62
|
+
` ${TELEGRAM_ENV_RELATIVE_PATH}`,
|
|
60
63
|
"",
|
|
61
64
|
].join("\n"),
|
|
62
65
|
);
|
|
@@ -66,7 +69,7 @@ function loadCLIMeta() {
|
|
|
66
69
|
try {
|
|
67
70
|
const dir = path.dirname(fileURLToPath(import.meta.url));
|
|
68
71
|
const raw = fs.readFileSync(path.join(dir, "package.json"), "utf8");
|
|
69
|
-
const parsed = JSON.parse(raw);
|
|
72
|
+
const parsed = JSON.parse(stripUTF8BOM(raw));
|
|
70
73
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
71
74
|
return {};
|
|
72
75
|
}
|
|
@@ -80,6 +83,12 @@ function printVersion() {
|
|
|
80
83
|
process.stdout.write(`${CLI_NAME} ${CLI_VERSION}\n`);
|
|
81
84
|
}
|
|
82
85
|
|
|
86
|
+
function stripUTF8BOM(rawText) {
|
|
87
|
+
const text = String(rawText || "");
|
|
88
|
+
if (!text) return "";
|
|
89
|
+
return text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;
|
|
90
|
+
}
|
|
91
|
+
|
|
83
92
|
function resolveHomeFilePath(relativePath) {
|
|
84
93
|
const home = String(process.env.USERPROFILE || process.env.HOME || "").trim();
|
|
85
94
|
if (!home) {
|
|
@@ -284,7 +293,7 @@ function loadSelfUpdateState() {
|
|
|
284
293
|
const filePath = updateStateFilePath();
|
|
285
294
|
try {
|
|
286
295
|
const raw = fs.readFileSync(filePath, "utf8");
|
|
287
|
-
const parsed = JSON.parse(raw);
|
|
296
|
+
const parsed = JSON.parse(stripUTF8BOM(raw));
|
|
288
297
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
289
298
|
return { filePath, checkedAt: "", latestVersion: "", installedVersion: "", updatedAt: "" };
|
|
290
299
|
}
|
|
@@ -470,6 +479,41 @@ function authStoreFilePath() {
|
|
|
470
479
|
return resolveHomeFilePath(AUTH_STORE_RELATIVE_PATH);
|
|
471
480
|
}
|
|
472
481
|
|
|
482
|
+
function telegramEnvFilePath() {
|
|
483
|
+
return resolveHomeFilePath(TELEGRAM_ENV_RELATIVE_PATH);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function telegramEnvTemplate() {
|
|
487
|
+
return [
|
|
488
|
+
"# Metheus local Telegram bot settings",
|
|
489
|
+
"# Keep this file on your machine only. Do not commit it.",
|
|
490
|
+
"# Server-side project Telegram destinations store chat_id metadata separately.",
|
|
491
|
+
"",
|
|
492
|
+
"TELEGRAM_BOT_TOKEN=",
|
|
493
|
+
"# Optional local default for quick tests. Project chat_id is normally resolved from Metheus server.",
|
|
494
|
+
"TELEGRAM_DEFAULT_CHAT_ID=",
|
|
495
|
+
"# Optional CSV allowlist to avoid accidental sends to the wrong chats.",
|
|
496
|
+
"TELEGRAM_ALLOWED_CHAT_IDS=",
|
|
497
|
+
"# Optional parse mode: Markdown, MarkdownV2, HTML",
|
|
498
|
+
"TELEGRAM_DEFAULT_PARSE_MODE=",
|
|
499
|
+
"",
|
|
500
|
+
].join("\n");
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
function ensureTelegramEnvTemplate() {
|
|
504
|
+
const filePath = telegramEnvFilePath();
|
|
505
|
+
try {
|
|
506
|
+
if (fs.existsSync(filePath)) {
|
|
507
|
+
return { filePath, created: false, existed: true };
|
|
508
|
+
}
|
|
509
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
510
|
+
fs.writeFileSync(filePath, telegramEnvTemplate(), "utf8");
|
|
511
|
+
return { filePath, created: true, existed: false };
|
|
512
|
+
} catch (err) {
|
|
513
|
+
return { filePath, created: false, existed: false, error: String(err?.message || err) };
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
473
517
|
function resolveWorkspaceDir(rawPath) {
|
|
474
518
|
const input = String(rawPath || "").trim();
|
|
475
519
|
if (input) {
|
|
@@ -757,9 +801,9 @@ function resolveProjectIDForRequest({
|
|
|
757
801
|
}) {
|
|
758
802
|
const resolvedWorkspaceDir = resolveWorkspaceDir(workspaceDir || process.cwd());
|
|
759
803
|
const workspaceMeta = loadWorkspaceMeta(resolvedWorkspaceDir);
|
|
804
|
+
const toolProjectID = resolveProjectIDFromToolArgs(toolArgs);
|
|
760
805
|
return firstNonEmptyString([
|
|
761
|
-
|
|
762
|
-
toolArgs?.projectID,
|
|
806
|
+
toolProjectID,
|
|
763
807
|
responseProjectID,
|
|
764
808
|
envelopeProjectID,
|
|
765
809
|
args?.projectID,
|
|
@@ -795,7 +839,7 @@ function loadStoredAuth() {
|
|
|
795
839
|
return { filePath, token: "", refreshToken: "", baseURL: "", updatedAt: "" };
|
|
796
840
|
}
|
|
797
841
|
const raw = fs.readFileSync(filePath, "utf8");
|
|
798
|
-
const parsed = JSON.parse(raw);
|
|
842
|
+
const parsed = JSON.parse(stripUTF8BOM(raw));
|
|
799
843
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
800
844
|
return { filePath, token: "", refreshToken: "", baseURL: "", updatedAt: "" };
|
|
801
845
|
}
|
|
@@ -1461,7 +1505,7 @@ function currentAccessTokenSource() {
|
|
|
1461
1505
|
|
|
1462
1506
|
function tryJsonParse(raw) {
|
|
1463
1507
|
try {
|
|
1464
|
-
return JSON.parse(raw);
|
|
1508
|
+
return JSON.parse(stripUTF8BOM(raw));
|
|
1465
1509
|
} catch {
|
|
1466
1510
|
return null;
|
|
1467
1511
|
}
|
|
@@ -1505,7 +1549,7 @@ function loadWorkspaceMeta(startDir) {
|
|
|
1505
1549
|
if (!metaFile) return {};
|
|
1506
1550
|
try {
|
|
1507
1551
|
const raw = fs.readFileSync(metaFile, "utf8");
|
|
1508
|
-
const parsed = JSON.parse(raw);
|
|
1552
|
+
const parsed = JSON.parse(stripUTF8BOM(raw));
|
|
1509
1553
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
1510
1554
|
return parsed;
|
|
1511
1555
|
}
|
|
@@ -1552,6 +1596,40 @@ function isUUID(raw) {
|
|
|
1552
1596
|
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
|
|
1553
1597
|
}
|
|
1554
1598
|
|
|
1599
|
+
function extractUUIDFromText(raw) {
|
|
1600
|
+
const text = String(raw || "").trim();
|
|
1601
|
+
if (!text) return "";
|
|
1602
|
+
const match = text.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i);
|
|
1603
|
+
return String(match?.[0] || "").trim();
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
function resolveProjectIDFromToolArgs(rawToolArgs) {
|
|
1607
|
+
const toolArgs = safeObject(rawToolArgs);
|
|
1608
|
+
const direct = firstNonEmptyString([
|
|
1609
|
+
toolArgs.project_id,
|
|
1610
|
+
toolArgs.projectID,
|
|
1611
|
+
toolArgs.projectId,
|
|
1612
|
+
toolArgs["project-id"],
|
|
1613
|
+
toolArgs.project_uuid,
|
|
1614
|
+
toolArgs.projectUUID,
|
|
1615
|
+
toolArgs.projectUuid,
|
|
1616
|
+
]);
|
|
1617
|
+
if (isUUID(direct)) return direct;
|
|
1618
|
+
|
|
1619
|
+
const hinted = firstNonEmptyString([
|
|
1620
|
+
extractUUIDFromText(toolArgs.project),
|
|
1621
|
+
extractUUIDFromText(toolArgs.project_id_text),
|
|
1622
|
+
extractUUIDFromText(toolArgs.projectIdText),
|
|
1623
|
+
extractUUIDFromText(toolArgs.input),
|
|
1624
|
+
extractUUIDFromText(toolArgs.text),
|
|
1625
|
+
extractUUIDFromText(toolArgs.query),
|
|
1626
|
+
extractUUIDFromText(toolArgs.prompt),
|
|
1627
|
+
]);
|
|
1628
|
+
if (isUUID(hinted)) return hinted;
|
|
1629
|
+
|
|
1630
|
+
return "";
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1555
1633
|
async function runAuthStatus() {
|
|
1556
1634
|
const resolved = resolveCurrentAccessToken();
|
|
1557
1635
|
const token = resolved.token;
|
|
@@ -2067,6 +2145,18 @@ async function runDoctor(flags) {
|
|
|
2067
2145
|
});
|
|
2068
2146
|
const rows = [];
|
|
2069
2147
|
|
|
2148
|
+
const telegramEnv = ensureTelegramEnvTemplate();
|
|
2149
|
+
if (telegramEnv.error) {
|
|
2150
|
+
addDoctorCheck(rows, "warn", "local telegram env", `unavailable (${telegramEnv.error})`);
|
|
2151
|
+
} else {
|
|
2152
|
+
addDoctorCheck(
|
|
2153
|
+
rows,
|
|
2154
|
+
telegramEnv.created ? "warn" : "ok",
|
|
2155
|
+
"local telegram env",
|
|
2156
|
+
`${telegramEnv.created ? "created template" : "ready"} (${telegramEnv.filePath})`,
|
|
2157
|
+
);
|
|
2158
|
+
}
|
|
2159
|
+
|
|
2070
2160
|
const resolved = await resolveAccessTokenForCommand(context.baseURL, timeoutSeconds);
|
|
2071
2161
|
const token = resolved.token;
|
|
2072
2162
|
if (!token) {
|
|
@@ -2720,7 +2810,7 @@ function loadCtxpackMeta(metaPath) {
|
|
|
2720
2810
|
try {
|
|
2721
2811
|
if (!fs.existsSync(metaPath)) return null;
|
|
2722
2812
|
const raw = fs.readFileSync(metaPath, "utf8");
|
|
2723
|
-
const parsed = JSON.parse(raw);
|
|
2813
|
+
const parsed = JSON.parse(stripUTF8BOM(raw));
|
|
2724
2814
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
2725
2815
|
return parsed;
|
|
2726
2816
|
} catch {
|
|
@@ -3730,6 +3820,7 @@ function appendProjectHintToInitialize(responseObj, args, options = {}) {
|
|
|
3730
3820
|
]
|
|
3731
3821
|
: []),
|
|
3732
3822
|
`- MUST call \`${projectSummaryTool}\` first when the user provides only a Project ID or asks project overview/agenda.`,
|
|
3823
|
+
`- If user enters a Project ID in text (e.g., "Project ID <uuid>"), pass that exact UUID as \`project_id\` argument when calling \`${projectSummaryTool}\`.`,
|
|
3733
3824
|
`- \`${projectDescribeTool}\` and \`${projectGetTool}\` are aliases of \`${projectSummaryTool}\`.`,
|
|
3734
3825
|
`- Never handle a bare Project ID by local file/transcript search before \`${projectSummaryTool}\` succeeds.`,
|
|
3735
3826
|
`- Run \`${ctxpackEnsureTool}\` only after \`${projectSummaryTool}\`, and only when additional ctxpack refresh/export context is needed.`,
|
|
@@ -4505,7 +4596,13 @@ async function runProxy(flags) {
|
|
|
4505
4596
|
}),
|
|
4506
4597
|
).trim();
|
|
4507
4598
|
if (!projectID) {
|
|
4508
|
-
writeProxyJson(
|
|
4599
|
+
writeProxyJson(
|
|
4600
|
+
jsonRpcError(
|
|
4601
|
+
requestObj,
|
|
4602
|
+
-32001,
|
|
4603
|
+
'project_id is required. Enter a valid UUID (e.g., {"project_id":"00000000-0000-0000-0000-000000000000"}) or set --project-id during setup.',
|
|
4604
|
+
),
|
|
4605
|
+
);
|
|
4509
4606
|
return;
|
|
4510
4607
|
}
|
|
4511
4608
|
if (!isUUID(projectID)) {
|
|
@@ -4561,7 +4658,13 @@ async function runProxy(flags) {
|
|
|
4561
4658
|
}),
|
|
4562
4659
|
).trim();
|
|
4563
4660
|
if (!projectID) {
|
|
4564
|
-
writeProxyJson(
|
|
4661
|
+
writeProxyJson(
|
|
4662
|
+
jsonRpcError(
|
|
4663
|
+
requestObj,
|
|
4664
|
+
-32001,
|
|
4665
|
+
'project_id is required. Enter a valid UUID (e.g., {"project_id":"00000000-0000-0000-0000-000000000000"}) or set --project-id during setup.',
|
|
4666
|
+
),
|
|
4667
|
+
);
|
|
4565
4668
|
return;
|
|
4566
4669
|
}
|
|
4567
4670
|
if (!isUUID(projectID)) {
|
|
@@ -5198,6 +5301,7 @@ function runSetupInternal(flags, options = {}) {
|
|
|
5198
5301
|
const context = resolveSetupContext(flags);
|
|
5199
5302
|
const clients = [...MCP_CLIENTS];
|
|
5200
5303
|
const results = [];
|
|
5304
|
+
const telegramEnv = ensureTelegramEnvTemplate();
|
|
5201
5305
|
|
|
5202
5306
|
for (const cliBin of clients) {
|
|
5203
5307
|
if (!commandExists(cliBin)) continue;
|
|
@@ -5247,6 +5351,13 @@ function runSetupInternal(flags, options = {}) {
|
|
|
5247
5351
|
process.stdout.write(`Fallback: ${context.workspaceFallbackDir} (METHEUS_WORKSPACE_DIR)\n`);
|
|
5248
5352
|
}
|
|
5249
5353
|
process.stdout.write(`Project: ${context.projectID || "auto-detect from .metheus_ctxpack_sync.json"}\n`);
|
|
5354
|
+
if (telegramEnv.error) {
|
|
5355
|
+
process.stdout.write(`Telegram: template unavailable (${telegramEnv.error})\n`);
|
|
5356
|
+
} else {
|
|
5357
|
+
process.stdout.write(
|
|
5358
|
+
`Telegram: ${telegramEnv.created ? "template created" : "template ready"} (${telegramEnv.filePath})\n`,
|
|
5359
|
+
);
|
|
5360
|
+
}
|
|
5250
5361
|
if (context.ctxpackKey) {
|
|
5251
5362
|
process.stdout.write(`Ctxpack: ${context.ctxpackKey}\n`);
|
|
5252
5363
|
}
|
package/package.json
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metheus-governance-mcp-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.49",
|
|
4
4
|
"description": "Metheus Governance MCP CLI (setup + stdio proxy)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"bin/metheus-governance-mcp.js",
|
|
8
8
|
"cli.mjs",
|
|
9
|
+
"postinstall.mjs",
|
|
9
10
|
"README.md",
|
|
10
11
|
".env.npm.local.example"
|
|
11
12
|
],
|
|
12
13
|
"scripts": {
|
|
13
|
-
"check": "node --check cli.mjs && node --check release.mjs",
|
|
14
|
+
"check": "node --check cli.mjs && node --check postinstall.mjs && node --check release.mjs",
|
|
14
15
|
"test:compat": "node cli.mjs selftest --json",
|
|
15
16
|
"smoke:proxy": "node scripts/smoke-proxy.mjs",
|
|
16
17
|
"pack:dry": "npm pack --dry-run",
|
|
17
18
|
"publish:dry": "node release.mjs --dry-run",
|
|
18
|
-
"publish:public": "node release.mjs"
|
|
19
|
+
"publish:public": "node release.mjs",
|
|
20
|
+
"postinstall": "node postinstall.mjs"
|
|
19
21
|
},
|
|
20
22
|
"bin": {
|
|
21
23
|
"metheus-governance-mcp": "bin/metheus-governance-mcp.js",
|
package/postinstall.mjs
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
|
|
7
|
+
const RELATIVE_PATH = path.join(".metheus", "telegram.env");
|
|
8
|
+
|
|
9
|
+
function resolveTargetPath() {
|
|
10
|
+
const home = String(process.env.USERPROFILE || process.env.HOME || os.homedir() || "").trim();
|
|
11
|
+
if (!home) return "";
|
|
12
|
+
return path.join(home, RELATIVE_PATH);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function template() {
|
|
16
|
+
return [
|
|
17
|
+
"# Metheus local Telegram bot settings",
|
|
18
|
+
"# Keep this file on your machine only. Do not commit it.",
|
|
19
|
+
"# Server-side project Telegram destinations store chat_id metadata separately.",
|
|
20
|
+
"",
|
|
21
|
+
"TELEGRAM_BOT_TOKEN=",
|
|
22
|
+
"# Optional local default for quick tests. Project chat_id is normally resolved from Metheus server.",
|
|
23
|
+
"TELEGRAM_DEFAULT_CHAT_ID=",
|
|
24
|
+
"# Optional CSV allowlist to avoid accidental sends to the wrong chats.",
|
|
25
|
+
"TELEGRAM_ALLOWED_CHAT_IDS=",
|
|
26
|
+
"# Optional parse mode: Markdown, MarkdownV2, HTML",
|
|
27
|
+
"TELEGRAM_DEFAULT_PARSE_MODE=",
|
|
28
|
+
"",
|
|
29
|
+
].join("\n");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function main() {
|
|
33
|
+
const filePath = resolveTargetPath();
|
|
34
|
+
if (!filePath) return;
|
|
35
|
+
try {
|
|
36
|
+
if (fs.existsSync(filePath)) return;
|
|
37
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
38
|
+
fs.writeFileSync(filePath, template(), "utf8");
|
|
39
|
+
process.stdout.write(`[metheus-governance-mcp-cli] created ${filePath}\n`);
|
|
40
|
+
} catch (err) {
|
|
41
|
+
process.stderr.write(
|
|
42
|
+
`[metheus-governance-mcp-cli] could not create ${filePath}: ${String(err?.message || err)}\n`,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
main();
|