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.
- package/README.md +10 -6
- package/dist/index.js +15 -7
- 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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
6
|
+
const USER_AGENT = "brewpage-mcp/1.13.1";
|
|
7
7
|
const server = new McpServer({
|
|
8
8
|
name: "brewpage-mcp",
|
|
9
|
-
version: "1.13.
|
|
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