brewpage-mcp 1.15.5 → 1.16.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 +21 -13
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +53 -26
- 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.
|
|
20
|
+
npx -y brewpage-mcp@1.16.1
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
Requires Node.js 20 or newer. This starts the stdio server for an MCP client.
|
|
@@ -50,7 +50,7 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
|
|
50
50
|
"mcpServers": {
|
|
51
51
|
"brewpage": {
|
|
52
52
|
"command": "npx",
|
|
53
|
-
"args": ["-y", "brewpage-mcp@1.
|
|
53
|
+
"args": ["-y", "brewpage-mcp@1.16.1"]
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
}
|
|
@@ -61,7 +61,7 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
|
|
61
61
|
Register a project-scoped stdio server:
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
|
-
claude mcp add --transport stdio --scope project brewpage -- npx -y brewpage-mcp@1.
|
|
64
|
+
claude mcp add --transport stdio --scope project brewpage -- npx -y brewpage-mcp@1.16.1
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
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).
|
|
@@ -75,7 +75,7 @@ Open **Settings > MCP** and add:
|
|
|
75
75
|
"mcpServers": {
|
|
76
76
|
"brewpage": {
|
|
77
77
|
"command": "npx",
|
|
78
|
-
"args": ["-y", "brewpage-mcp@1.
|
|
78
|
+
"args": ["-y", "brewpage-mcp@1.16.1"]
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
}
|
|
@@ -89,7 +89,7 @@ Open the Cline MCP settings panel and add:
|
|
|
89
89
|
{
|
|
90
90
|
"brewpage": {
|
|
91
91
|
"command": "npx",
|
|
92
|
-
"args": ["-y", "brewpage-mcp@1.
|
|
92
|
+
"args": ["-y", "brewpage-mcp@1.16.1"]
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
```
|
|
@@ -97,13 +97,13 @@ Open the Cline MCP settings panel and add:
|
|
|
97
97
|
### Global Install
|
|
98
98
|
|
|
99
99
|
```bash
|
|
100
|
-
npm install -g brewpage-mcp@1.
|
|
100
|
+
npm install -g brewpage-mcp@1.16.1
|
|
101
101
|
brewpage-mcp
|
|
102
102
|
```
|
|
103
103
|
|
|
104
104
|
## Tools
|
|
105
105
|
|
|
106
|
-
Twenty tools are available. Creation returns an owner token; keep it to modify or delete the resource later. Owner tools take `ownerToken`, else `BREWPAGE_OWNER_TOKEN
|
|
106
|
+
Twenty tools are available. Creation returns an owner token; keep it to modify or delete the resource later. Owner tools take `ownerToken`, else `BREWPAGE_OWNER_TOKEN` (local server only). Supported password inputs use `X-Password`. Secrets allowed; likely ones are flagged in notices. For a secret: private namespace + password.
|
|
107
107
|
|
|
108
108
|
| Tool | Purpose |
|
|
109
109
|
|------|---------|
|
|
@@ -130,7 +130,7 @@ Twenty tools are available. Creation returns an owner token; keep it to modify o
|
|
|
130
130
|
|
|
131
131
|
All five publish tools accept optional `deliveryMode: "path" | "subdomain"`, sent only as `X-Delivery-Mode`; authored JSON and multipart bodies keep their existing format. Visibility and password protection are separate choices. Omitted namespace is private (a generated `priv-<random>` namespace): unlisted and not indexed; anyone with the link can still open it. `public` lists HTML, sites and files in the gallery and sitemap, so Google, Bing and AI search can find and index them; public pages are served on the brewpage.app domain for the strongest reach (a site always gets its own subdomain). Never put secrets in a public publication. Password-protected publications, JSON and KV are never listed.
|
|
132
132
|
|
|
133
|
-
The MCP server wraps a subset of the backend-generated public [REST contract](../openapi/openapi.json). TTL inputs take days or a string such as `2w`/`36h` (default 15); the server rounds to whole days and clamps to 1–30 (owner-specific caps and eligible automatic extensions can differ). Use returned `expiresAt`. Every tolerated-input adjustment (TTL clamp, format alias, skipped site member, normalised namespace) comes back in the response `notices` array and is printed as `Notice (code): message`; `secret-detected`
|
|
133
|
+
The MCP server wraps a subset of the backend-generated public [REST contract](../openapi/openapi.json). TTL inputs take days or a string such as `2w`/`36h` (default 15); the server rounds to whole days and clamps to 1–30 (owner-specific caps and eligible automatic extensions can differ). Use returned `expiresAt`. Every tolerated-input adjustment (TTL clamp, format alias, skipped site member, normalised namespace) comes back in the response `notices` array and is printed as `Notice (code): message`; `secret-detected` prints as `WARNING (code): message`: relay it to the user. A live BrewPage token or manage link in public content (`credential-published`) prints first as `SECURITY ALERT (credential-published): …`: tell the user to remove and reset it; that result is hidden from the gallery, so it prints no `VISIBILITY` line. A minted `manageUrl` prints as `MANAGE LINK (private): …`: give it to the user privately, never publish it. A listed public result prints `VISIBILITY: public, listed. Hide: set_visibility listed=false`. `get_page` reads stored rendered HTML or format-specific code/text from the API; it does not call the owner-only original-source endpoint or a browser viewer. `publish_file` uploads from a source URL and does not expose password or TTL inputs.
|
|
134
134
|
|
|
135
135
|
For a fresh publication, sites and HTML pages of format `HTML` outside `public` (including the generated unlisted namespace) always use Dedicated subdomain (`subdomain`); omit `deliveryMode` there. An explicit `path` there is not rejected: the publication is created on its subdomain and the result reports `deliveryModeMatched: false`, `deliveryModeReason: "policy:subdomain-required"` and a `Delivery notice:` line. Everything else in any namespace (Markdown, code/text, files, JSON, KV, public HTML) defaults to Promotion (`path`) and may choose Dedicated subdomain, including password-protected content. Promotion uses a BrewPage path with stricter active-document restrictions. Each NEW site gets one publication-specific host for its complete bundle, preserving relative/root-relative paths; missing assets return 404, with no SPA fallback. Third-party widgets may still need provider configuration.
|
|
136
136
|
|
|
@@ -232,7 +232,7 @@ publish_file(url="https://example.com/diagram.png")
|
|
|
232
232
|
|
|
233
233
|
Publish a single-page or multi-file HTML site. Pass `entryContent` for a single page or `files` (array of `{path, content}`) for a multi-file site. Supports password protection, TTL, and owner token grouping. The result prints `Title:` (entry page title) after `ID:` when the server derives one.
|
|
234
234
|
|
|
235
|
-
Limits (current values from `get_limits`): a request is at most 25
|
|
235
|
+
Limits (current values from `get_limits`): a request is at most 25 MiB; a site at most 200 files, 5 MiB per file and 20 MiB in total; each path at most 380 characters. System files such as `.DS_Store` and `__MACOSX/` are skipped and never count; files with an unsupported extension or a too-long path are skipped and reported in notices. Entry: `entry`, else root `index.html`, else the shallowest HTML file. A site limit hit answers 400 with a message naming the limit, as does a PDF/Office file that is unreadable or password-protected; 413 means the request is over 25 MiB, has too many files and form fields, or a file name/path is too long; 422 means no servable file is left; 503 means busy: retry after `Retry-After` seconds (failed publish tools print it).
|
|
236
236
|
|
|
237
237
|
Parameters: exactly one of `entryContent` (string) or non-empty `files` (array of `{path, content}`), `entry` (optional entry file path, default `index.html`), `namespace` (optional -- omit for private, unlisted content; `public` lists the site in the gallery and sitemap for Google, Bing and AI search; a site always gets its own subdomain), `password` (optional), `ttlDays` (days or a string such as `2w`; default 15; the server clamps to 1--30), `ownerToken` (optional, groups site under an existing owner), `deliveryMode` (optional; fresh sites require `subdomain`).
|
|
238
238
|
|
|
@@ -382,7 +382,7 @@ search_gallery(mine=true, ownerToken="tok_...", sort="date")
|
|
|
382
382
|
|
|
383
383
|
Delete a BrewPage resource (HTML page, site, KV store, JSON document, or file) using the owner token received at creation.
|
|
384
384
|
|
|
385
|
-
Parameters: `type` (`html` | `site` | `kv` | `json` | `file`), `namespace` (string), `id` (string), `ownerToken` (optional; default `BREWPAGE_OWNER_TOKEN
|
|
385
|
+
Parameters: `type` (`html` | `site` | `kv` | `json` | `file`), `namespace` (string), `id` (string), `ownerToken` (optional; default `BREWPAGE_OWNER_TOKEN`, local server only). Path segments are URL-encoded.
|
|
386
386
|
|
|
387
387
|
Example prompt:
|
|
388
388
|
|
|
@@ -412,7 +412,7 @@ Output: `LISTED: false · link unchanged`.
|
|
|
412
412
|
|
|
413
413
|
Add an owner token to your BrewPage profile (as `publish`) with an `admin` token of that profile (`POST /api/owner-token/bind`). Output: `BOUND …ab12 · 3/20 active`; tokens are never printed in full.
|
|
414
414
|
|
|
415
|
-
Parameters: `token`, `ownerToken` (admin token; optional, default `BREWPAGE_OWNER_TOKEN
|
|
415
|
+
Parameters: `token`, `ownerToken` (admin token; optional, default `BREWPAGE_OWNER_TOKEN`, local server only).
|
|
416
416
|
|
|
417
417
|
---
|
|
418
418
|
|
|
@@ -442,9 +442,9 @@ get_stats()
|
|
|
442
442
|
|
|
443
443
|
### `get_limits`
|
|
444
444
|
|
|
445
|
-
Read the current limits from `GET /api/limits` (no auth;
|
|
445
|
+
Read the current limits from `GET /api/limits` (no auth needed; an owner token goes as `X-Owner-Token`). Always returns `reach`: `profile` only when the owner token is active in a profile, else `token` (also with no token); with a usable owner token also `ownerMaxTtlDays`. Sizes are bytes, TTLs days: `requestMaxBytes`; `html`, `json`, `kv` and `files` max size, counts and TTL default/maximum; `profileMaxTtlDays` (TTL cap for a token in a profile); `sites.maxFiles`, `maxFileBytes`, `maxTotalBytes` (uncompressed), `maxArchiveExpansionBytes`, `maxPathChars`, `maxPathBytes`, `maxNameBytes`, `defaultTtlDays`, `maxTtlDays`, `allowedExtensions`, `skippedFileNames` and `skippedRootFolders`. Call it before publishing a large or multi-file site.
|
|
446
446
|
|
|
447
|
-
Parameters:
|
|
447
|
+
Parameters: `ownerToken` (optional; default `BREWPAGE_OWNER_TOKEN`, local server only).
|
|
448
448
|
|
|
449
449
|
Example prompt:
|
|
450
450
|
|
|
@@ -530,6 +530,14 @@ Every publish response includes an **owner token** -- the only credential that a
|
|
|
530
530
|
|
|
531
531
|
## Changelog
|
|
532
532
|
|
|
533
|
+
## 1.16.1 -- 2026-10-30
|
|
534
|
+
|
|
535
|
+
- Update tools (`update_html`, `update_json`, `set_kv`, `republish_site`) state that tokens and manage links never go in public content.
|
|
536
|
+
|
|
537
|
+
## 1.16.0 -- 2026-10-29
|
|
538
|
+
|
|
539
|
+
- `get_limits` accepts `ownerToken` (remote `/mcp` gets `reach`/`ownerMaxTtlDays`). Results open with `SECURITY ALERT (credential-published)` when public content holds a live BrewPage token or manage link. Wording: limits reach, local-only env token, MiB.
|
|
540
|
+
|
|
533
541
|
## 1.15.5 -- 2026-10-29
|
|
534
542
|
|
|
535
543
|
- `publish_html` prints the page title (`Title:`) when the server reports one; tool texts state plain size limits; `get_limits` names the per-type limits and the profile TTL cap.
|
package/dist/tools.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/server";
|
|
2
2
|
export declare const DEFAULT_BASE_URL = "https://brewpage.app";
|
|
3
|
-
export declare const USER_AGENT = "brewpage-mcp/1.
|
|
3
|
+
export declare const USER_AGENT = "brewpage-mcp/1.16.1";
|
|
4
4
|
export declare const OWNER_TOKEN_ENV = "BREWPAGE_OWNER_TOKEN";
|
|
5
5
|
export interface ServerOptions {
|
|
6
6
|
/** BrewPage origin for API calls; default https://brewpage.app. */
|
package/dist/tools.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/server";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
export const DEFAULT_BASE_URL = "https://brewpage.app";
|
|
4
|
-
export const USER_AGENT = "brewpage-mcp/1.
|
|
4
|
+
export const USER_AGENT = "brewpage-mcp/1.16.1";
|
|
5
5
|
export const OWNER_TOKEN_ENV = "BREWPAGE_OWNER_TOKEN";
|
|
6
6
|
const READ_ONLY = { readOnlyHint: true };
|
|
7
7
|
const DESTRUCTIVE = { readOnlyHint: false, destructiveHint: true };
|
|
@@ -10,15 +10,23 @@ const ADDITIVE = { readOnlyHint: false, destructiveHint: false };
|
|
|
10
10
|
function toolMeta(title, hints) {
|
|
11
11
|
return { title, annotations: { title, ...hints } };
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
13
|
+
/** Env default exists only in the local (stdio) server; remote /mcp takes ownerToken per call. */
|
|
14
|
+
const ENV_DEFAULT = `env ${OWNER_TOKEN_ENV} (local server only)`;
|
|
15
|
+
const NO_OWNER_TOKEN = `No owner token: pass ownerToken (local server: or set ${OWNER_TOKEN_ENV}).`;
|
|
16
|
+
const CREATE_OWNER_TOKEN_DESCRIPTION = `Optional. Default: ${ENV_DEFAULT}, else a new token per create.`;
|
|
17
|
+
const OWNER_TOKEN_DESCRIPTION = `Owner token from create. Default: ${ENV_DEFAULT}.`;
|
|
18
|
+
/** Backend guard checks create and update content alike. */
|
|
19
|
+
const NO_PUBLIC_CREDENTIALS = "BrewPage tokens and manage links must never be in public content.";
|
|
20
|
+
const SECRETS = "Secrets allowed; likely ones are flagged in notices. Private namespace + password suit secrets. " +
|
|
21
|
+
NO_PUBLIC_CREDENTIALS;
|
|
17
22
|
const MANAGE_URL_TEXT = "Returns manageUrl, a private management link (grants control; not for public sharing).";
|
|
18
23
|
const OLD_READ_ONLY_CODE = "OLD_PUBLICATION_READ_ONLY";
|
|
19
24
|
const OLD_READ_ONLY_TEXT = ` Old publications (made before 5 October 2026) are read-only: 409 ${OLD_READ_ONLY_CODE} with createUrl to publish anew.`;
|
|
20
25
|
/** Notice codes the agent must relay to the user. */
|
|
21
|
-
const WARNING_CODES = new Set(["secret-detected"
|
|
26
|
+
const WARNING_CODES = new Set(["secret-detected"]);
|
|
27
|
+
/** Live BrewPage token or manage link in public content: printed first as a security alert, never listed. */
|
|
28
|
+
const CREDENTIAL_CODE = "credential-published";
|
|
29
|
+
const CREDENTIAL_ALERT_TAIL = "Tell the user now: anyone with this link can use that token; they must remove it and reset it.";
|
|
22
30
|
/** MCP type name -> REST path segment. */
|
|
23
31
|
const TYPE_SEGMENTS = { html: "html", site: "sites", file: "files", json: "json", kv: "kv" };
|
|
24
32
|
/** `/api/<segments>` with each segment encoded; empty, `.` and `..` refused (URL parsing would resolve them away). */
|
|
@@ -108,11 +116,11 @@ const DELIVERY_MODE_SCHEMA = z.enum(["path", "subdomain"]).optional().describe("
|
|
|
108
116
|
"Everything else in any namespace (Markdown, code/text, files, JSON, KV, public HTML) defaults to path (Promotion); public HTML may automatically choose subdomain for browser features. " +
|
|
109
117
|
"When creation returns an existing publication, it keeps its actual mode and URL.");
|
|
110
118
|
/** Site upload rules shared by publish_site and republish_site; current values come from get_limits. */
|
|
111
|
-
const SITE_LIMITS_TEXT = "Default limits (current values: GET /api/limits): a request is at most 25
|
|
119
|
+
const SITE_LIMITS_TEXT = "Default limits (current values: GET /api/limits): a request is at most 25 MiB; a site at most 200 files, 5 MiB per file and 20 MiB in total; " +
|
|
112
120
|
"each path at most 380 characters. System files (.DS_Store, __MACOSX/ and similar) are skipped and never count; files with an unsupported extension " +
|
|
113
121
|
"or a too-long path are skipped and listed in notices. Entry: `entry`, else root index.html, else the shallowest HTML file. " +
|
|
114
122
|
"Errors: 400 = a site limit exceeded (the message names it), invalid path, no HTML file, or a PDF/Office file unreadable " +
|
|
115
|
-
"or password-protected; 413 = request over 25
|
|
123
|
+
"or password-protected; 413 = request over 25 MiB, too many files and form fields, or a file name/path too long; " +
|
|
116
124
|
"422 = no servable file left; 503 = busy, retry after Retry-After seconds.";
|
|
117
125
|
function hostingResponseLines(data) {
|
|
118
126
|
const fields = ["routingCohort", "deliveryMode", "requestedDeliveryMode", "effectiveDeliveryMode",
|
|
@@ -126,14 +134,26 @@ function hostingResponseLines(data) {
|
|
|
126
134
|
lines.push(...noticeLines(data));
|
|
127
135
|
return lines;
|
|
128
136
|
}
|
|
129
|
-
/** Server `notices` ({code, message}) on publish/update responses
|
|
130
|
-
function
|
|
137
|
+
/** Server `notices` ({code, message}) on publish/update responses, well-formed only. */
|
|
138
|
+
function notices(data) {
|
|
131
139
|
if (!Array.isArray(data.notices))
|
|
132
140
|
return [];
|
|
133
|
-
return data.notices
|
|
134
|
-
|
|
141
|
+
return data.notices.filter((n) => typeof n === "object" && n !== null && typeof n.code === "string" && typeof n.message === "string");
|
|
142
|
+
}
|
|
143
|
+
/** Each tolerated-input adjustment, verbatim; the credential alert prints separately, first. */
|
|
144
|
+
function noticeLines(data) {
|
|
145
|
+
return notices(data).filter((n) => n.code !== CREDENTIAL_CODE)
|
|
135
146
|
.map((n) => `${WARNING_CODES.has(n.code) ? "WARNING" : "Notice"} (${n.code}): ${n.message}`);
|
|
136
147
|
}
|
|
148
|
+
function hasCredentialNotice(data) {
|
|
149
|
+
return notices(data).some((n) => n.code === CREDENTIAL_CODE);
|
|
150
|
+
}
|
|
151
|
+
/** Opening lines of a result whose public content holds a live BrewPage credential, else none. */
|
|
152
|
+
function credentialAlertLines(data) {
|
|
153
|
+
const alerts = notices(data).filter((n) => n.code === CREDENTIAL_CODE)
|
|
154
|
+
.map((n) => `SECURITY ALERT (${CREDENTIAL_CODE}): ${n.message} ${CREDENTIAL_ALERT_TAIL}`);
|
|
155
|
+
return alerts.length ? [...alerts, ``] : [];
|
|
156
|
+
}
|
|
137
157
|
const SIGN_IN_HINT = "Optional: sign in free (Google or any email) at https://account.brewpage.app to never lose your pages or tokens and to mint tokens that never expire. Not needed to publish.";
|
|
138
158
|
/** Private management link (present only when minted) and the public listing state. */
|
|
139
159
|
function ownerLinkLines(data) {
|
|
@@ -141,7 +161,7 @@ function ownerLinkLines(data) {
|
|
|
141
161
|
if (typeof data.manageUrl === "string" && data.manageUrl.length > 0) {
|
|
142
162
|
lines.push(``, `MANAGE LINK (private): ${data.manageUrl}`, `Give it to the user privately; never publish it.`);
|
|
143
163
|
}
|
|
144
|
-
if (data.listed === true)
|
|
164
|
+
if (data.listed === true && !hasCredentialNotice(data))
|
|
145
165
|
lines.push(``, `VISIBILITY: public, listed. Hide: set_visibility listed=false`);
|
|
146
166
|
return lines;
|
|
147
167
|
}
|
|
@@ -157,6 +177,7 @@ function deliveryReasonLines(data) {
|
|
|
157
177
|
}
|
|
158
178
|
function formatUpdateResponse(data) {
|
|
159
179
|
const lines = [
|
|
180
|
+
...credentialAlertLines(data),
|
|
160
181
|
`Updated successfully!`,
|
|
161
182
|
``,
|
|
162
183
|
`URL: ${data.link || data.url || "N/A"}`,
|
|
@@ -188,7 +209,7 @@ export function createServer(options = {}) {
|
|
|
188
209
|
const apiFetch = options.fetch ?? fetch;
|
|
189
210
|
const server = new McpServer({
|
|
190
211
|
name: "brewpage-mcp",
|
|
191
|
-
version: "1.
|
|
212
|
+
version: "1.16.1",
|
|
192
213
|
});
|
|
193
214
|
/** Caller argument first, then the configured default; `fromEnv` marks the configured one. */
|
|
194
215
|
function ownerTokenFor(argument) {
|
|
@@ -242,6 +263,7 @@ export function createServer(options = {}) {
|
|
|
242
263
|
}
|
|
243
264
|
function formatPublishResponse(data, effectiveNamespace, sentOwnerToken, listable = true) {
|
|
244
265
|
const lines = [
|
|
266
|
+
...credentialAlertLines(data),
|
|
245
267
|
`Published successfully!`,
|
|
246
268
|
``,
|
|
247
269
|
`URL: ${data.link || data.url || "N/A"}`,
|
|
@@ -595,6 +617,7 @@ export function createServer(options = {}) {
|
|
|
595
617
|
}
|
|
596
618
|
const site = data;
|
|
597
619
|
const lines = [
|
|
620
|
+
...credentialAlertLines(site),
|
|
598
621
|
`Site published successfully!`,
|
|
599
622
|
``,
|
|
600
623
|
`URL: ${site.link || "N/A"}`,
|
|
@@ -625,7 +648,7 @@ export function createServer(options = {}) {
|
|
|
625
648
|
});
|
|
626
649
|
server.registerTool("republish_site", {
|
|
627
650
|
...toolMeta("Republish site", DESTRUCTIVE),
|
|
628
|
-
description: "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: `entryContent`. Multi-page: `files` (array of `{path, content}`). Optional `entry` overrides the default `index.html`. Republishing preserves existing expiry." + OLD_READ_ONLY_TEXT + " " + SITE_LIMITS_TEXT,
|
|
651
|
+
description: "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: `entryContent`. Multi-page: `files` (array of `{path, content}`). Optional `entry` overrides the default `index.html`. Republishing preserves existing expiry." + OLD_READ_ONLY_TEXT + " " + SITE_LIMITS_TEXT + " " + NO_PUBLIC_CREDENTIALS,
|
|
629
652
|
inputSchema: {
|
|
630
653
|
namespace: z.string().describe("Site namespace"),
|
|
631
654
|
id: z.string().describe("Site ID"),
|
|
@@ -687,6 +710,7 @@ export function createServer(options = {}) {
|
|
|
687
710
|
return ownerFailure("republish site", res.status, data, auth.fromEnv, res.headers);
|
|
688
711
|
const site = data;
|
|
689
712
|
const lines = [
|
|
713
|
+
...credentialAlertLines(site),
|
|
690
714
|
`Site republished successfully (full replace)!`,
|
|
691
715
|
``,
|
|
692
716
|
`URL: ${site.link || "N/A"}`,
|
|
@@ -716,7 +740,7 @@ export function createServer(options = {}) {
|
|
|
716
740
|
server.registerTool("update_html", {
|
|
717
741
|
...toolMeta("Update page", DESTRUCTIVE),
|
|
718
742
|
description: "Update an existing BrewPage HTML, Markdown, code or JSON page. Requires owner token. Returns the updated page metadata. " +
|
|
719
|
-
"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,
|
|
743
|
+
"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 + " " + NO_PUBLIC_CREDENTIALS,
|
|
720
744
|
inputSchema: {
|
|
721
745
|
namespace: z.string().describe("Page namespace"),
|
|
722
746
|
id: z.string().describe("Page ID"),
|
|
@@ -850,7 +874,7 @@ export function createServer(options = {}) {
|
|
|
850
874
|
});
|
|
851
875
|
server.registerTool("update_json", {
|
|
852
876
|
...toolMeta("Update JSON document", DESTRUCTIVE),
|
|
853
|
-
description: "Update an existing BrewPage JSON document. Requires owner token. Accepts a JSON object, array, or a JSON-encoded string." + OLD_READ_ONLY_TEXT,
|
|
877
|
+
description: "Update an existing BrewPage JSON document. Requires owner token. Accepts a JSON object, array, or a JSON-encoded string." + OLD_READ_ONLY_TEXT + " " + NO_PUBLIC_CREDENTIALS,
|
|
854
878
|
inputSchema: {
|
|
855
879
|
namespace: z.string().describe("Document namespace"),
|
|
856
880
|
id: z.string().describe("Document ID"),
|
|
@@ -943,7 +967,7 @@ export function createServer(options = {}) {
|
|
|
943
967
|
});
|
|
944
968
|
server.registerTool("set_kv", {
|
|
945
969
|
...toolMeta("Set KV value", DESTRUCTIVE),
|
|
946
|
-
description: "Set or update a key in an existing BrewPage KV store. Requires owner token. The key name `hosting` is reserved." + OLD_READ_ONLY_TEXT,
|
|
970
|
+
description: "Set or update a key in an existing BrewPage KV store. Requires owner token. The key name `hosting` is reserved." + OLD_READ_ONLY_TEXT + " " + NO_PUBLIC_CREDENTIALS,
|
|
947
971
|
inputSchema: {
|
|
948
972
|
namespace: z.string().describe("KV store namespace"),
|
|
949
973
|
id: z.string().describe("KV store ID"),
|
|
@@ -1014,10 +1038,13 @@ export function createServer(options = {}) {
|
|
|
1014
1038
|
description: "Get the current BrewPage limits (GET /api/limits): request size; per type (html, json, kv, files, sites) max size, " +
|
|
1015
1039
|
"counts and TTL default/maximum; profileMaxTtlDays (TTL cap for a token in a profile); site ZIP expansion, path and name lengths, " +
|
|
1016
1040
|
"allowed file extensions and skipped system files. Sizes are bytes, TTLs days. " +
|
|
1017
|
-
`
|
|
1018
|
-
inputSchema: {
|
|
1019
|
-
|
|
1020
|
-
|
|
1041
|
+
`The answer always has reach: \`profile\` only when the owner token is active in a profile, else \`token\` (also with no token). With a usable owner token also ownerMaxTtlDays.`,
|
|
1042
|
+
inputSchema: {
|
|
1043
|
+
ownerToken: z.string().optional().describe(OWNER_TOKEN_DESCRIPTION),
|
|
1044
|
+
},
|
|
1045
|
+
}, async ({ ownerToken }) => {
|
|
1046
|
+
const { token } = ownerTokenFor(ownerToken);
|
|
1047
|
+
const headers = token ? { "X-Owner-Token": token } : {};
|
|
1021
1048
|
const { ok, status, data } = await apiRequest("GET", "/api/limits", undefined, headers);
|
|
1022
1049
|
if (!ok) {
|
|
1023
1050
|
return {
|
|
@@ -1068,7 +1095,7 @@ export function createServer(options = {}) {
|
|
|
1068
1095
|
ownerToken: z
|
|
1069
1096
|
.string()
|
|
1070
1097
|
.optional()
|
|
1071
|
-
.describe(`Owner token; only sent as X-Owner-Token when 'mine' is true. Default: ${
|
|
1098
|
+
.describe(`Owner token; only sent as X-Owner-Token when 'mine' is true. Default: ${ENV_DEFAULT}.`),
|
|
1072
1099
|
},
|
|
1073
1100
|
}, async ({ q, page, size, sort, mine, ownerToken }) => {
|
|
1074
1101
|
const auth = ownerTokenFor(ownerToken);
|
|
@@ -1119,14 +1146,14 @@ export function createServer(options = {}) {
|
|
|
1119
1146
|
if (!ok)
|
|
1120
1147
|
return ownerFailure("set visibility", status, data, auth.fromEnv);
|
|
1121
1148
|
const result = data;
|
|
1122
|
-
return textResult([`LISTED: ${result.listed} · link unchanged`, ...noticeLines(result)].join("\n"));
|
|
1149
|
+
return textResult([...credentialAlertLines(result), `LISTED: ${result.listed} · link unchanged`, ...noticeLines(result)].join("\n"));
|
|
1123
1150
|
});
|
|
1124
1151
|
server.registerTool("bind_token", {
|
|
1125
1152
|
...toolMeta("Add token to profile", ADDITIVE),
|
|
1126
1153
|
description: "Add an owner token to your BrewPage profile (as publish). Needs an admin token of that profile.",
|
|
1127
1154
|
inputSchema: {
|
|
1128
1155
|
token: z.string().describe("Owner token to add"),
|
|
1129
|
-
ownerToken: z.string().optional().describe(`Admin token of the profile. Default: ${
|
|
1156
|
+
ownerToken: z.string().optional().describe(`Admin token of the profile. Default: ${ENV_DEFAULT}.`),
|
|
1130
1157
|
},
|
|
1131
1158
|
}, async ({ token, ownerToken }) => {
|
|
1132
1159
|
const auth = ownerTokenFor(ownerToken);
|
|
@@ -1145,7 +1172,7 @@ export function createServer(options = {}) {
|
|
|
1145
1172
|
label: z.string().optional().describe("Optional label shown in the profile"),
|
|
1146
1173
|
scope: z.enum(["publish", "admin"]).optional().describe("publish (default) or admin (can manage tokens)"),
|
|
1147
1174
|
expiresIn: z.enum(["30d", "90d", "1y", "never"]).optional().describe("Default: admin 90d, publish never"),
|
|
1148
|
-
ownerToken: z.string().optional().describe(`Admin token of the profile. Default: ${
|
|
1175
|
+
ownerToken: z.string().optional().describe(`Admin token of the profile. Default: ${ENV_DEFAULT}.`),
|
|
1149
1176
|
},
|
|
1150
1177
|
}, async ({ label, scope, expiresIn, ownerToken }) => {
|
|
1151
1178
|
const auth = ownerTokenFor(ownerToken);
|
package/package.json
CHANGED