@showly/mcp-server 0.4.3 → 0.4.4

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/dist/cli.d.ts CHANGED
@@ -142,6 +142,17 @@ export declare function buildCodexAuthSnippet(opts: {
142
142
  /** Secrets used by the two remote-agent targets the Hero prompt exercises. */
143
143
  export declare const OPENCLAW_TOKEN_ENV_VAR = "SHOWLY_MCP_TOKEN";
144
144
  export declare const HERMES_TOKEN_ENV_VAR = "MCP_SHOWLY_API_KEY";
145
+ /**
146
+ * Give every OpenClaw credential its own environment variable name.
147
+ *
148
+ * A managed Gateway can keep the old process environment alive while its
149
+ * user config is reloaded. With one fixed SHOWLY_MCP_TOKEN name, that stale
150
+ * process value wins over the freshly-written env.vars value and a successful
151
+ * re-login immediately fails with token_revoked until the whole instance is
152
+ * restarted. The token fingerprint is not a credential, but makes the new
153
+ * config reference a name the old process cannot already contain.
154
+ */
155
+ export declare function openClawTokenEnvVar(token: string): string;
145
156
  /**
146
157
  * Merge Showly into OpenClaw's user config without disturbing other Gateway
147
158
  * settings. The token lives in the Gateway-owned env.vars store; the MCP entry
package/dist/cli.js CHANGED
@@ -34,6 +34,7 @@ import { readFileSync, readdirSync, mkdirSync, rmSync, writeFileSync, existsSync
34
34
  import { dirname, join } from "node:path";
35
35
  import { homedir } from "node:os";
36
36
  import { pathToFileURL } from "node:url";
37
+ import { createHash } from "node:crypto";
37
38
  import { parseDocument } from "yaml";
38
39
  import { loadManifest } from "./index.js";
39
40
  import { SHOWLY_HOSTING_SKILL_DIRECTORY, SHOWLY_HOSTING_SKILL_NAME, SHOWLY_LEGACY_SKILL_NAME, } from "./showly-hosting-skill.js";
@@ -99,7 +100,7 @@ function usage() {
99
100
  "host, pass --agent <cursor|openclaw|hermes|cline> so My Agents can name it.",
100
101
  "",
101
102
  "Environment overrides:",
102
- " SHOWLY_MCP_URL full URL to your MCP endpoint (default https://mcp.showly.ai)",
103
+ " SHOWLY_MCP_URL full URL to your MCP endpoint (default https://mcp.showly.ai/mcp)",
103
104
  " SHOWLY_API_URL full URL to your API (default https://api.showly.ai)",
104
105
  "",
105
106
  "--with-skill installs a reusable showly-hosting skill for Claude Code or Codex.",
@@ -490,6 +491,24 @@ export function buildCodexAuthSnippet(opts) {
490
491
  /** Secrets used by the two remote-agent targets the Hero prompt exercises. */
491
492
  export const OPENCLAW_TOKEN_ENV_VAR = "SHOWLY_MCP_TOKEN";
492
493
  export const HERMES_TOKEN_ENV_VAR = "MCP_SHOWLY_API_KEY";
494
+ /**
495
+ * Give every OpenClaw credential its own environment variable name.
496
+ *
497
+ * A managed Gateway can keep the old process environment alive while its
498
+ * user config is reloaded. With one fixed SHOWLY_MCP_TOKEN name, that stale
499
+ * process value wins over the freshly-written env.vars value and a successful
500
+ * re-login immediately fails with token_revoked until the whole instance is
501
+ * restarted. The token fingerprint is not a credential, but makes the new
502
+ * config reference a name the old process cannot already contain.
503
+ */
504
+ export function openClawTokenEnvVar(token) {
505
+ const fingerprint = createHash("sha256")
506
+ .update(token)
507
+ .digest("hex")
508
+ .slice(0, 12)
509
+ .toUpperCase();
510
+ return `${OPENCLAW_TOKEN_ENV_VAR}_${fingerprint}`;
511
+ }
493
512
  function asRecord(value) {
494
513
  return typeof value === "object" && value !== null && !Array.isArray(value)
495
514
  ? value
@@ -509,11 +528,14 @@ export function buildOpenClawAuthConfig(opts) {
509
528
  const currentShowly = asRecord(servers.showly);
510
529
  const currentHeaders = asRecord(currentShowly.headers);
511
530
  const { auth: _nativeOauth, ...showlyWithoutOauth } = currentShowly;
531
+ const tokenEnvVar = openClawTokenEnvVar(opts.token);
532
+ const varsWithoutOldShowlyTokens = Object.fromEntries(Object.entries(vars).filter(([name]) => name !== OPENCLAW_TOKEN_ENV_VAR &&
533
+ !name.startsWith(`${OPENCLAW_TOKEN_ENV_VAR}_`)));
512
534
  return {
513
535
  ...opts.existing,
514
536
  env: {
515
537
  ...env,
516
- vars: { ...vars, [OPENCLAW_TOKEN_ENV_VAR]: opts.token },
538
+ vars: { ...varsWithoutOldShowlyTokens, [tokenEnvVar]: opts.token },
517
539
  },
518
540
  mcp: {
519
541
  ...mcp,
@@ -525,7 +547,7 @@ export function buildOpenClawAuthConfig(opts) {
525
547
  transport: "streamable-http",
526
548
  headers: {
527
549
  ...currentHeaders,
528
- Authorization: `Bearer \${${OPENCLAW_TOKEN_ENV_VAR}}`,
550
+ Authorization: `Bearer \${${tokenEnvVar}}`,
529
551
  },
530
552
  },
531
553
  },
@@ -1102,7 +1124,15 @@ export function buildLoginOutput(result, opts = {}) {
1102
1124
  });
1103
1125
  lines.push({ stream: "out", line: result.snippet });
1104
1126
  }
1105
- for (const name of envVarsReferencedBy(result.snippet)) {
1127
+ // OpenClaw and Hermes have already received the value in their protected
1128
+ // user-level credential store. Printing an export for them is both false
1129
+ // (the variable is set) and needlessly exposes the token in terminal/chat
1130
+ // logs. Codex and stdout are the two handoff targets whose config really
1131
+ // does depend on the human setting the referenced environment variable.
1132
+ const handoffEnvVars = result.target === "codex" || result.target === "stdout"
1133
+ ? envVarsReferencedBy(result.snippet)
1134
+ : [];
1135
+ for (const name of handoffEnvVars) {
1106
1136
  lines.push({
1107
1137
  stream: "err",
1108
1138
  line: `That config reads the token from ${name}, and nothing sets it yet. Put this in the environment your agent starts in:`,
package/manifest.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://showly.ai/schemas/skill-manifest-v1.json",
3
3
  "name": "showly",
4
4
  "displayName": "Showly",
5
- "version": "0.4.3",
5
+ "version": "0.4.4",
6
6
  "description": "Deploy and manage Showly sites from inside Claude Code / Codex.",
7
7
  "homepage": "https://showly.ai/docs/mcp/overview",
8
8
  "publisher": "Showly",
@@ -26,7 +26,7 @@
26
26
  },
27
27
  "endpoints": {
28
28
  "url_env": "SHOWLY_MCP_URL",
29
- "default_url": "https://mcp.showly.ai",
29
+ "default_url": "https://mcp.showly.ai/mcp",
30
30
  "api_url_env": "SHOWLY_API_URL"
31
31
  }
32
32
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@showly/mcp-server",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "Connect Claude Code / Codex to the Showly MCP server — preview and deploy sites from your agent.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -52,11 +52,11 @@
52
52
  },
53
53
  "claude-code-skill": {
54
54
  "name": "showly",
55
- "version": "0.4.3",
55
+ "version": "0.4.4",
56
56
  "description": "Deploy and manage Showly sites from inside Claude Code.",
57
57
  "mcp-server": {
58
58
  "url-env": "SHOWLY_MCP_URL",
59
- "default-url": "https://mcp.showly.ai",
59
+ "default-url": "https://mcp.showly.ai/mcp",
60
60
  "auth": "oauth",
61
61
  "api-url-env": "SHOWLY_API_URL"
62
62
  },
@@ -65,7 +65,7 @@
65
65
  },
66
66
  "codex-plugin": {
67
67
  "name": "showly",
68
- "version": "0.4.3",
68
+ "version": "0.4.4",
69
69
  "type": "mcp-server",
70
70
  "manifest": "manifest.json"
71
71
  },