premanmcp 0.9.0 → 0.10.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/bin/shared.js CHANGED
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import { spawn, spawnSync } from "node:child_process";
11
- import { chmodSync, existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
11
+ import { chmodSync, existsSync, readFileSync, rmSync, writeFileSync, mkdirSync } from "node:fs";
12
12
  import os from "node:os";
13
13
  import path from "node:path";
14
14
  import { createInterface } from "node:readline/promises";
@@ -93,6 +93,18 @@ export function saveStoredCredentials(creds) {
93
93
  writeFileSync(CREDENTIALS_FILE, `${JSON.stringify(creds, null, 2)}\n`, { mode: 0o600 });
94
94
  }
95
95
 
96
+ /** Forget the stored key. Returns whether there was one. */
97
+ export function clearStoredCredentials() {
98
+ if (!existsSync(CREDENTIALS_FILE)) return false;
99
+ rmSync(CREDENTIALS_FILE, { force: true });
100
+ return true;
101
+ }
102
+
103
+ /** True when the key in play came from a flag or the environment, not our store. */
104
+ export function apiKeyIsExplicit(args) {
105
+ return Boolean(args.value("--api-key", "") || process.env.PREMAN_API_KEY);
106
+ }
107
+
96
108
  export function backendUrl(args) {
97
109
  return args.value("--backend", process.env.PREMAN_BACKEND || DEFAULT_BACKEND).replace(/\/+$/, "");
98
110
  }
package/dist/server.js CHANGED
@@ -9,11 +9,7 @@ import path from "node:path";
9
9
  import os from "node:os";
10
10
  import { randomUUID } from "node:crypto";
11
11
  import { MCP_PREVIEW_RESOURCE_URI, RESOURCE_URI_META_KEY, buildConversionPanelHtml, writeMcpPreviewFile, } from "./mcp-preview-panel.js";
12
- /**
13
- * Load ``PREMAN_*`` from repo JSON so project URLs win over stale **global** Cursor MCP env
14
- * (which often sets the wrong ``PREMAN_BACKEND``, e.g. app port instead of API port).
15
- * First match wins: ``.cursor/preman-mcp.config.json``, then ``preman-mcp.config.json`` (cwd).
16
- */
12
+ let REPO_CONFIG = null;
17
13
  function applyRepoPremanConfig() {
18
14
  const candidates = [
19
15
  path.join(process.cwd(), ".cursor", "preman-mcp.config.json"),
@@ -24,13 +20,19 @@ function applyRepoPremanConfig() {
24
20
  if (!existsSync(p))
25
21
  continue;
26
22
  const j = JSON.parse(readFileSync(p, "utf8"));
23
+ const override = j.PREMAN_CONFIG_OVERRIDE === true || j.PREMAN_CONFIG_OVERRIDE === "true";
24
+ const applied = [];
27
25
  for (const [key, val] of Object.entries(j)) {
28
- if (!key.startsWith("PREMAN_"))
26
+ if (!key.startsWith("PREMAN_") || key === "PREMAN_CONFIG_OVERRIDE")
29
27
  continue;
30
- if (typeof val === "string" && val.trim()) {
31
- process.env[key] = val.trim();
32
- }
28
+ if (typeof val !== "string" || !val.trim())
29
+ continue;
30
+ if (!override && process.env[key])
31
+ continue;
32
+ process.env[key] = val.trim();
33
+ applied.push(key);
33
34
  }
35
+ REPO_CONFIG = { path: p, override, applied };
34
36
  return;
35
37
  }
36
38
  catch {
@@ -42,6 +44,22 @@ applyRepoPremanConfig();
42
44
  const BACKEND_URL = process.env.PREMAN_BACKEND || "https://api.preman.live";
43
45
  const FRONTEND_URL = process.env.PREMAN_FRONTEND || "https://app.preman.live";
44
46
  let API_KEY = process.env.PREMAN_API_KEY || "";
47
+ /**
48
+ * Where the URLs this process is using came from.
49
+ *
50
+ * Reported by `preman_status` because the most confusing failure in setup is a
51
+ * server that works perfectly against the wrong backend: the key is fine, the
52
+ * config on disk is fine, and every call still 401s. Naming the file that
53
+ * redirected it turns that into a one-line diagnosis.
54
+ */
55
+ function configSource() {
56
+ return {
57
+ backend_url: BACKEND_URL,
58
+ repo_config: REPO_CONFIG
59
+ ? { path: REPO_CONFIG.path, override: REPO_CONFIG.override, applied: REPO_CONFIG.applied }
60
+ : null,
61
+ };
62
+ }
45
63
  function detectCodingAgent() {
46
64
  const forced = (process.env.PREMAN_CODING_AGENT || "").trim().toLowerCase();
47
65
  if (forced)
@@ -1040,6 +1058,7 @@ export function createServer() {
1040
1058
  backend_url: BACKEND_URL,
1041
1059
  frontend_base_url: FRONTEND_BASE,
1042
1060
  endpoints_page_url: buildAgentDashboardUrl("/endpoints"),
1061
+ config: configSource(),
1043
1062
  message: "Stored API key is no longer valid. Run `npm exec -y premanmcp@latest -- login`, or use user_auth_* then preman_create_api_key, or run preman_login.",
1044
1063
  }),
1045
1064
  }],
@@ -1056,6 +1075,7 @@ export function createServer() {
1056
1075
  backend_url: BACKEND_URL,
1057
1076
  frontend_base_url: FRONTEND_BASE,
1058
1077
  endpoints_page_url: buildAgentDashboardUrl("/endpoints"),
1078
+ config: configSource(),
1059
1079
  coding_agent: workbench,
1060
1080
  _agent_hints: {
1061
1081
  next_actions: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "premanmcp",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Turn APIs into agent-callable MCP tools with auth, testing, and audit logs",
5
5
  "type": "module",
6
6
  "bin": {