Skip to main content
Glama

Publish site

publish_site

Publishes a static HTML site, as a single page or multi-file bundle, to BrewPage hosting and returns a shareable link plus an owner token for later management.

Instructions

Publish an HTML site to BrewPage. Send namespace=public to be found: gallery + Google, Bing & AI search. Omitted: private. Single-page: entryContent. Multi-page: files ({path, content} array). Optional entry overrides index.html. Returns its primary share link and owner token. Static only: HTML, CSS, JS (incl. built React/Vue bundles) run in the browser; server code (PHP etc.) never runs. Default limits (current: GET /api/limits): request 25 MiB; site 200 files, 5 MiB per file, 20 MiB total; path 380 characters. System files (.DS_Store, __MACOSX/ and similar) are skipped and never count; files with an unsupported extension or too-long path are skipped and listed in notices. Entry: entry, else root index.html, else the shallowest HTML file. Errors: 400 = a site limit exceeded (the message names it), invalid path, no HTML file, or a PDF/Office file unreadable or password-protected; 413 = request over 25 MiB, too many files and form fields, or a file name/path too long; 422 = no servable file left; 503 = busy, retry after Retry-After seconds. Optional domain connects a custom domain the user owns. Returns manageUrl, a private management link (grants control; not for public sharing). Secrets allowed; likely ones are flagged in notices. Private namespace + password suit secrets. BrewPage tokens and manage links must never be in public content. Page code must not hide or alter the BrewPage badge; a profile can turn the badge off for a page. If the page should save what visitors enter (form answers, game progress, guestbook, votes), load https://brewpage.app/js/state.js in it and pass state. Without state a page cannot save data; {} is enough. Page script calls: bp.state() -> s|null (guard it); c=s.col("name"); c.set(key,value) c.get(key) c.remove(key) c.add(value) c.list({order,limit}) c.stats({countBy})

Tool call template

This tool declares no required parameters. Add optional parameters from the input schema as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {},
    "name": "publish_site"
  }
}

Input Schema

NameRequiredDescriptionDefault
entryNoEntry file path, default index.html
filesNoMulti-file site: array of `{path, content}`. Mutually exclusive with `entryContent`.
stateNoPage data config (the `state` API): `{collections: {<name>: {mode: 'private'|'shared', write?: 'author'}}}`; full reference: guide topic `page-data`. HTML pages and sites, not Markdown; the page gets its own address.
domainNoOptional custom domain for the new publication: a bare hostname the user owns (www.example.com or example.com, no scheme or path). Needs a profile token or an owner token added to a free BrewPage profile, and no password. The publication is always created; the result lists the DNS records for the domain owner to create, or says why the custom domain was not set.
ttlDaysNoTTL in days: up to 30 days without an account, up to 90 with a free profile (pass an ownerToken held in the profile); a default applies when omitted. Accepts whole days: 15, '15d', '15 days'. The returned expiresAt is the actual expiry.
passwordNoOptional password to protect the site
namespaceNoSend namespace=public for anything meant to be found or shared (docs, guides, demos, portfolios, reports, landing pages): listed in the public gallery and sitemap, so Google, Bing and AI search index it and people discover it. A site always gets its own subdomain. Anyone can find and read a public page, so it is unsuitable for secrets, tokens or personal data. Omit (default): private, a generated priv-* namespace; unlisted, not indexed; the link still opens it. Lowercase only: 1-32 of a-z, 0-9, hyphen.
ownerTokenNoOptional; the ownerToken from your first create keeps publications under one owner. Default: env BREWPAGE_OWNER_TOKEN (local server only), else a new token per create.
deliveryModeNoOptional delivery choice for a fresh publication, independent of password/namespace. Fresh sites and HTML-format pages outside public (including the default unlisted namespace) always use subdomain; an explicit path there still publishes, on subdomain, with a delivery notice. 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. When creation returns an existing publication, it keeps its actual mode and URL.
entryContentNoHTML content for a single-page site (entry file). Mutually exclusive with `files`.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changedv1.22.0
    • changedInput schema / properties / domain / description
      Previous value: -"Optional domain the user owns (www.example.com or example.com) to connect to the new publication. Works when the owner token is in a free BrewPage profile, without a password. The publication is always created; the result lists the DNS records for the domain owner to create, or says why the domain was not set."New value: +"Optional custom domain for the new publication: a bare hostname the user owns (www.example.com or example.com, no scheme or path). Needs a profile token or an owner token added to a free BrewPage profile, and no password. The publication is always created; the result lists the DNS records for the domain owner to create, or says why the custom domain was not set."
    • changedInput schema / properties / ttlDays / description
      Previous value: -"Requested TTL: days as a number, or a string such as '2w', '36h' or '1 month' (default 15 days). The server rounds to whole days and clamps to the allowed range (1-30; up to 90 with an owner token in a profile), reporting each adjustment in notices; the returned expiresAt is the actual expiry."New value: +"TTL in days: up to 30 days without an account, up to 90 with a free profile (pass an ownerToken held in the profile); a default applies when omitted. Accepts whole days: 15, '15d', '15 days'. The returned expiresAt is the actual expiry."
  2. Changed1 schema field changedv1.21.0
    • addedInput schema / properties / state
      Added value: +{
      +  "anyOf": [
      +    {
      +      "additionalProperties": {},
      +      "propertyNames": {
      +        "type": "string"
      +      },
      +      "type": "object"
      +    },
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "Page data config (the `state` API): `{collections: {<name>: {mode: 'private'|'shared', write?: 'author'}}}`; full reference: guide topic `page-data`. HTML pages and sites, not Markdown; the page gets its own address."
      +}
  3. Changed1 schema field changedv1.18.0
    • addedInput schema / properties / domain
      Added value: +{
      +  "description": "Optional domain the user owns (www.example.com or example.com) to connect to the new publication. Works when the owner token is in a free BrewPage profile, without a password. The publication is always created; the result lists the DNS records for the domain owner to create, or says why the domain was not set.",
      +  "type": "string"
      +}
  4. Changed1 schema field changedv1.16.6
    • changedInput schema / properties / namespace / description
      Previous value: -"namespace=public: listed in the public gallery and the sitemap, so Google, Bing and AI search can find and index it and people can discover it. Suits anything meant to be found or shared: docs, guides, demos, portfolios, reports, landing pages. A site always gets its own subdomain. Anyone can find and read a public page, so it is unsuitable for secrets, tokens or personal data. Omit (default): private. Unlisted and not indexed; anyone who has the link can still open it. Lowercase only: 1-32 of a-z, 0-9, hyphen."New value: +"Send namespace=public for anything meant to be found or shared (docs, guides, demos, portfolios, reports, landing pages): listed in the public gallery and sitemap, so Google, Bing and AI search index it and people discover it. A site always gets its own subdomain. Anyone can find and read a public page, so it is unsuitable for secrets, tokens or personal data. Omit (default): private, a generated priv-* namespace; unlisted, not indexed; the link still opens it. Lowercase only: 1-32 of a-z, 0-9, hyphen."
  5. Changed2 schema fields changedv1.16.3
    • changedInput schema / properties / ownerToken / description
      Previous value: -"Optional. Default: BREWPAGE_OWNER_TOKEN, else a new token per create."New value: +"Optional; the ownerToken from your first create keeps publications under one owner. Default: env BREWPAGE_OWNER_TOKEN (local server only), else a new token per create."
    • changedInput schema / properties / ttlDays / description
      Previous value: -"Requested TTL: days as a number, or a string such as '2w', '36h' or '1 month' (default 15 days). The server rounds to whole days and clamps to the allowed range (1-30 by default; owner caps differ), reporting each adjustment in notices; the returned expiresAt is the actual expiry."New value: +"Requested TTL: days as a number, or a string such as '2w', '36h' or '1 month' (default 15 days). The server rounds to whole days and clamps to the allowed range (1-30; up to 90 with an owner token in a profile), reporting each adjustment in notices; the returned expiresAt is the actual expiry."
  6. Changed3 schema fields changedv1.15.0
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • removedInput schema / additionalProperties
      Removed value: -false
    • removedInput schema / properties / files / items / additionalProperties
      Removed value: -false
  7. Changed2 schema fields changedv1.14.5
    • changedInput schema / properties / namespace / description
      Previous value: -"namespace=public: listed in the public gallery and the sitemap, so Google, Bing and AI search can find and index it and people can discover it. Use it for anything meant to be found or shared: docs, guides, demos, portfolios, reports, landing pages. A site always gets its own subdomain. Anyone can find and read a public page: never put secrets, tokens or personal data there. Omit (default): private. Unlisted and not indexed; anyone who has the link can still open it. Lowercase only: 1-32 of a-z, 0-9, hyphen."New value: +"namespace=public: listed in the public gallery and the sitemap, so Google, Bing and AI search can find and index it and people can discover it. Suits anything meant to be found or shared: docs, guides, demos, portfolios, reports, landing pages. A site always gets its own subdomain. Anyone can find and read a public page, so it is unsuitable for secrets, tokens or personal data. Omit (default): private. Unlisted and not indexed; anyone who has the link can still open it. Lowercase only: 1-32 of a-z, 0-9, hyphen."
    • changedInput schema / properties / ttlDays / description
      Previous value: -"Requested TTL: days as a number, or a string such as '2w', '36h' or '1 month' (default 15 days). The server rounds to whole days and clamps to the allowed range (1-30 by default; owner caps differ), reporting each adjustment in notices; use returned expiresAt."New value: +"Requested TTL: days as a number, or a string such as '2w', '36h' or '1 month' (default 15 days). The server rounds to whole days and clamps to the allowed range (1-30 by default; owner caps differ), reporting each adjustment in notices; the returned expiresAt is the actual expiry."
  8. Changed1 schema field changedv1.14.2
    • changedInput schema / properties / namespace / description
      Previous value: -"Optional. Omit to generate an unlisted namespace: anyone with its unpassworded link can read it, but it is excluded from gallery/search. Pass a custom namespace to group unlisted content, or pass `public` ONLY when the user explicitly wants gallery/search eligibility. Password-protected content stays excluded; unlisted, protected or otherwise ineligible native responses carry noindex; eligible public HTML, sites and files may permit indexing. Lowercase only: 1-32 of a-z, 0-9, hyphen."New value: +"namespace=public: listed in the public gallery and the sitemap, so Google, Bing and AI search can find and index it and people can discover it. Use it for anything meant to be found or shared: docs, guides, demos, portfolios, reports, landing pages. A site always gets its own subdomain. Anyone can find and read a public page: never put secrets, tokens or personal data there. Omit (default): private. Unlisted and not indexed; anyone who has the link can still open it. Lowercase only: 1-32 of a-z, 0-9, hyphen."
  9. Changed2 schema fields changedv1.13.0
    • changedInput schema / properties / namespace / description
      Previous value: -"Optional. Omit to generate an unlisted namespace: anyone with its unpassworded link can read it, but it is excluded from gallery/search. Pass a custom namespace to group unlisted content, or pass `public` ONLY when the user explicitly wants gallery/search eligibility. Password-protected content stays excluded; unlisted, protected or otherwise ineligible native responses carry noindex; eligible public HTML, sites and files may permit indexing."New value: +"Optional. Omit to generate an unlisted namespace: anyone with its unpassworded link can read it, but it is excluded from gallery/search. Pass a custom namespace to group unlisted content, or pass `public` ONLY when the user explicitly wants gallery/search eligibility. Password-protected content stays excluded; unlisted, protected or otherwise ineligible native responses carry noindex; eligible public HTML, sites and files may permit indexing. Lowercase only: 1-32 of a-z, 0-9, hyphen."
    • changedInput schema / properties / ownerToken / description
      Previous value: -"Existing owner token to group this site under the same owner as previous content"New value: +"Optional. Default: BREWPAGE_OWNER_TOKEN, else a new token per create."
  10. First observedv0.1.0

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnly=false and destructive=false; the description goes far beyond them with static-only execution rules, default quotas, error-code meanings, badge restrictions, and warnings that tokens/manage links must never appear in public content. The entry-resolution chain and the Retry-After guidance are behavior an agent could not get from the structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose and shape are front-loaded, but the body is one dense paragraph mixing quotas, error codes, badge policy, and a full state API method listing (c.set/c.get/c.list). Much of that is reference material that would read better in a guide or as bullets; the wall-of-text form hurts scanability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter, zero-required creation tool with no output schema, the description covers return values (share link, owner token, manageUrl), limits, failure modes, and the static-serving model. An agent has everything needed to call it and interpret failures.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds genuine meaning: entry resolution order (entry, else root index.html, else shallowest HTML), files/entryContent mutual exclusivity, what omitting namespace means, and that `{}` suffices for state. These clarify behavior beyond the schema's per-parameter text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Publish an HTML site to BrewPage') and clarifies the single-page vs multi-page shapes. It does not, however, distinguish itself from siblings like publish_html or publish_file, so an agent must infer which publish tool fits.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete usage conditions: namespace=public for discoverable content, omitted for private, private+password for secrets, and loading state.js when a page must persist visitor data. It never explicitly names an alternative sibling tool, so routing between the several publish_* tools is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.