brewpage-mcp 1.13.0 → 1.13.1

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 (3) hide show
  1. package/README.md +10 -6
  2. package/dist/index.js +15 -7
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -17,7 +17,7 @@ Choosing a host? See how BrewPage compares with GitHub Pages, Netlify Drop, Tiin
17
17
  ## Quick Start
18
18
 
19
19
  ```bash
20
- npx -y brewpage-mcp@1.13.0
20
+ npx -y brewpage-mcp@1.13.1
21
21
  ```
22
22
 
23
23
  Requires Node.js 20 or newer. This starts the stdio server for an MCP client.
@@ -33,7 +33,7 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
33
33
  "mcpServers": {
34
34
  "brewpage": {
35
35
  "command": "npx",
36
- "args": ["-y", "brewpage-mcp@1.13.0"]
36
+ "args": ["-y", "brewpage-mcp@1.13.1"]
37
37
  }
38
38
  }
39
39
  }
@@ -44,7 +44,7 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
44
44
  Register a project-scoped stdio server:
45
45
 
46
46
  ```bash
47
- claude mcp add --transport stdio --scope project brewpage -- npx -y brewpage-mcp@1.13.0
47
+ claude mcp add --transport stdio --scope project brewpage -- npx -y brewpage-mcp@1.13.1
48
48
  ```
49
49
 
50
50
  This writes `.mcp.json` in the project root. Use `--scope user` for user-scoped registration. See the [official Claude Code MCP guide](https://code.claude.com/docs/en/mcp).
@@ -58,7 +58,7 @@ Open **Settings > MCP** and add:
58
58
  "mcpServers": {
59
59
  "brewpage": {
60
60
  "command": "npx",
61
- "args": ["-y", "brewpage-mcp@1.13.0"]
61
+ "args": ["-y", "brewpage-mcp@1.13.1"]
62
62
  }
63
63
  }
64
64
  }
@@ -72,7 +72,7 @@ Open the Cline MCP settings panel and add:
72
72
  {
73
73
  "brewpage": {
74
74
  "command": "npx",
75
- "args": ["-y", "brewpage-mcp@1.13.0"]
75
+ "args": ["-y", "brewpage-mcp@1.13.1"]
76
76
  }
77
77
  }
78
78
  ```
@@ -80,7 +80,7 @@ Open the Cline MCP settings panel and add:
80
80
  ### Global Install
81
81
 
82
82
  ```bash
83
- npm install -g brewpage-mcp@1.13.0
83
+ npm install -g brewpage-mcp@1.13.1
84
84
  brewpage-mcp
85
85
  ```
86
86
 
@@ -491,6 +491,10 @@ Every publish response includes an **owner token** -- the only credential that a
491
491
 
492
492
  ## Changelog
493
493
 
494
+ ## 1.13.1 -- 2026-10-25
495
+
496
+ - Old publications (created before the new link format): update tools say they answer `409 OLD_PUBLICATION_READ_ONLY`; that failure adds a hint to publish the content anew and give the user the new URL and owner token.
497
+
494
498
  ## 1.13.0 -- 2026-10-25
495
499
 
496
500
  - Identifying `User-Agent: brewpage-mcp/1.13.0` on every BrewPage call.
package/dist/index.js CHANGED
@@ -3,10 +3,10 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
4
  import { z } from "zod";
5
5
  const BASE_URL = process.env.BREWPAGE_URL || "https://brewpage.app";
6
- const USER_AGENT = "brewpage-mcp/1.13.0";
6
+ const USER_AGENT = "brewpage-mcp/1.13.1";
7
7
  const server = new McpServer({
8
8
  name: "brewpage-mcp",
9
- version: "1.13.0",
9
+ version: "1.13.1",
10
10
  });
11
11
  const OWNER_TOKEN_SHAPE = /^[A-Za-z0-9]{32}$/;
12
12
  const OWNER_TOKEN_ENV = "BREWPAGE_OWNER_TOKEN";
@@ -25,6 +25,8 @@ const CREATE_OWNER_TOKEN_DESCRIPTION = `Optional. Default: ${OWNER_TOKEN_ENV}, e
25
25
  const OWNER_TOKEN_DESCRIPTION = `Owner token from create. Default: ${OWNER_TOKEN_ENV}.`;
26
26
  const SECRETS = "Secrets allowed; likely ones are flagged in notices. For a secret: private namespace + password.";
27
27
  const MANAGE_URL_TEXT = "Returns manageUrl (private): give it to the user privately; never publish it.";
28
+ const OLD_READ_ONLY_CODE = "OLD_PUBLICATION_READ_ONLY";
29
+ const OLD_READ_ONLY_TEXT = ` Old publications (created before the new link format) answer 409 ${OLD_READ_ONLY_CODE}.`;
28
30
  /** Notice codes the agent must relay to the user. */
29
31
  const WARNING_CODES = new Set(["secret-detected", "manage-link-disabled"]);
30
32
  /** MCP type name -> REST path segment. */
@@ -42,13 +44,19 @@ function maskToken(token) {
42
44
  function textResult(text, isError = false) {
43
45
  return isError ? { content: [{ type: "text", text }], isError: true } : { content: [{ type: "text", text }] };
44
46
  }
45
- /** Owner-tool failure: the server answer verbatim plus a hint for a plain wrong-token 403. */
47
+ /** Owner-tool failure: the server answer verbatim plus a hint for a plain wrong-token 403 or a frozen old publication. */
46
48
  function ownerFailure(operation, status, data, fromEnv) {
47
49
  const lines = [`Failed to ${operation} (${status}): ${JSON.stringify(data)}`];
48
50
  const code = data?.code;
49
51
  if (status === 403 && (code === undefined || code === "OWNER_AUTHORIZATION_FAILED")) {
50
52
  lines.push(`Wrong owner token for this publication. Use ownerToken from create.${fromEnv ? ` Sent: ${OWNER_TOKEN_ENV}.` : ""}`);
51
53
  }
54
+ if (status === 409 && code === OLD_READ_ONLY_CODE) {
55
+ lines.push("Read-only old publication: cannot be updated. Publish the content anew with the matching " +
56
+ "publish tool in the same namespace; give the user the NEW URL and owner token. The old URL keeps its old content " +
57
+ "until it expires. Ignore republishUrl (browser-only)." +
58
+ (operation === "set KV" ? " For KV, read all keys with get_kv and publish them together with publish_kv." : ""));
59
+ }
52
60
  return textResult(lines.join("\n"), true);
53
61
  }
54
62
  /** Every BrewPage call identifies the client; source-file downloads use plain fetch. */
@@ -563,7 +571,7 @@ server.tool("publish_site", "Publish an HTML site to BrewPage. Single-page: pass
563
571
  content: [{ type: "text", text: lines.join("\n") }],
564
572
  };
565
573
  });
566
- server.tool("republish_site", "Republish (full-replace) an existing multi-file BrewPage site in place at the SAME URL/ID. Requires owner token. The uploaded bundle becomes the complete new file set — files absent from it are removed, new files added, matching files overwritten. Single-page: pass `entryContent`. Multi-page: pass `files` (array of `{path, content}`). Optional `entry` overrides the default `index.html`. Republishing preserves existing expiry. " + SITE_LIMITS_TEXT, {
574
+ server.tool("republish_site", "Republish (full-replace) an existing multi-file BrewPage site in place at the SAME URL/ID. Requires owner token. The uploaded bundle becomes the complete new file set — files absent from it are removed, new files added, matching files overwritten. Single-page: pass `entryContent`. Multi-page: pass `files` (array of `{path, content}`). Optional `entry` overrides the default `index.html`. Republishing preserves existing expiry." + OLD_READ_ONLY_TEXT + " " + SITE_LIMITS_TEXT, {
567
575
  namespace: z.string().describe("Site namespace"),
568
576
  id: z.string().describe("Site ID"),
569
577
  ownerToken: z.string().optional().describe(OWNER_TOKEN_DESCRIPTION),
@@ -656,7 +664,7 @@ server.tool("republish_site", "Republish (full-replace) an existing multi-file B
656
664
  };
657
665
  });
658
666
  server.tool("update_html", "Update an existing BrewPage HTML/Markdown page. Requires owner token. Returns the updated page metadata. " +
659
- "The link and delivery mode never change on update; an advisory deliveryModeReason and delivery notice are included when the new content uses browser features that may not work fully on a BrewPage link.", {
667
+ "The link and delivery mode never change on update; an advisory deliveryModeReason and delivery notice are included when the new content uses browser features that may not work fully on a BrewPage link." + OLD_READ_ONLY_TEXT, {
660
668
  namespace: z.string().describe("Page namespace"),
661
669
  id: z.string().describe("Page ID"),
662
670
  content: z.string().describe("New HTML or Markdown content"),
@@ -786,7 +794,7 @@ server.tool("get_json", "Fetch a published BrewPage JSON document by namespace a
786
794
  ],
787
795
  };
788
796
  });
789
- server.tool("update_json", "Update an existing BrewPage JSON document. Requires owner token. Accepts a JSON object, array, or a JSON-encoded string.", {
797
+ server.tool("update_json", "Update an existing BrewPage JSON document. Requires owner token. Accepts a JSON object, array, or a JSON-encoded string." + OLD_READ_ONLY_TEXT, {
790
798
  namespace: z.string().describe("Document namespace"),
791
799
  id: z.string().describe("Document ID"),
792
800
  json: z
@@ -879,7 +887,7 @@ server.tool("publish_kv", "Publish a key/value entry to BrewPage. Creates a KV s
879
887
  ],
880
888
  };
881
889
  });
882
- server.tool("set_kv", "Set or update a key in an existing BrewPage KV store. Requires owner token. The key name `hosting` is reserved.", {
890
+ server.tool("set_kv", "Set or update a key in an existing BrewPage KV store. Requires owner token. The key name `hosting` is reserved." + OLD_READ_ONLY_TEXT, {
883
891
  namespace: z.string().describe("KV store namespace"),
884
892
  id: z.string().describe("KV store ID"),
885
893
  key: z.string().describe("Key to set"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brewpage-mcp",
3
- "version": "1.13.0",
3
+ "version": "1.13.1",
4
4
  "mcpName": "io.github.kochetkov-ma/brewpage-mcp",
5
5
  "description": "MCP server for BrewPage — publish and manage HTML, sites, KV, JSON and files from AI assistants",
6
6
  "type": "module",