Skip to main content
Glama

Publish a website

publish_site
Destructive

Publish files as a live website, served over HTTPS at its own URL. Use it when a report, essay, slide-like narrative, dashboard, marketing surface, or other static artifact reads better at a live URL than as conversation text. Honor an artifact form the user requests. Otherwise choose the artifact form and treatment from its audience, job, and material. A request for a live URL chooses delivery, not one long scrolling page.

Apply the governance skill before calling: get_skill with governance says what the organization expects of a published page and names the design-system skill, which supplies identity, not structure. Follow each wherever it speaks.

title and description are required on every publish of files, and a call missing either is refused: title names the site for a person, and description says in one sentence what it holds. A site's name becomes part of its URL, so those two are what a reader has to go on wherever the site is listed. Write them for the person who will come back to this page in a month.

Content is text written here: HTML, CSS, JavaScript, Markdown, JSON, SVG. Images, PDFs, video, and other binary assets are not supported in files — publish those with the Valet CLI, or with push.

Send the site one of two ways. files carries the text of the pages in the call, which suits a few small pages and works from any client. push: {id, commit} publishes a commit you pushed with git: call create_push, run the recipe it returns, then pass the push_id and the commit sha it prints. Use push when you can run git with network access, when the site is large or holds binary files, or when you changed a clone of its source; it needs a site that exists and an account, not anonymous. Pass files or push, not both.

Publishing uses a connected Valet account by default and changes a permanent, private site that already exists: create it first with create_service (kind: site), then publish to its name. A name that holds no site is refused. Pass anonymous: true only when the user explicitly wants a temporary public site, which needs no create_service. It is public to anyone who has the link, and it may be removed 36 hours after it is created, unless it is claimed. The result carries a claim URL that moves the site into a Valet account and makes it permanent, and a site_token that updates the same site on a later call. Give that token back to revise the site instead of publishing a second copy of it; with an account, give the site's name instead.

In an organization with release policies, an account publish may answer with evaluation instead of a version: the release is built and waits for its policies, and get_evaluation with wait_seconds 20 follows it.

Input Schema

NameRequiredDescriptionDefault
nameNoThe site's name, which is the first label of its URL, https://<name>.<org>.valet.run. The site must exist: create it first with create_service. Publishing to it replaces its files. Required with a connected Valet account; leave it out for an anonymous publish.
pushNoPublish a Git push instead of files: the id create_push returned and the commit you pushed to its branch. Use it when you can run git with network access, because it sends only what changed. Pass files or push, not both; every other argument keeps its meaning.
filesNoRequired unless push is given. The site's files. One file named index.html is the minimum; add more for stylesheets, scripts, or further pages.
titleNoRequired with files. What the site is called, written for a person: 'Q3 Migration Audit', not a hostname. It labels the site wherever it is listed, so write the same thing the page's own <title> says.
org_nameNoThe Valet organization to publish into. Omit to use the organization the account joined first.
anonymousNoSet true only when the user explicitly wants a temporary public site without account ownership. Omit for the account-first path, which connects a Valet account when needed.
site_tokenNoThe token an earlier anonymous publish returned. Give it back to update that same site instead of creating another.
descriptionNoRequired with files. One sentence saying what the site holds, for a person deciding whether to open it. It is shown beside the title wherever the site is listed.
idempotency_keyNoAn opaque key of your choosing. Repeating a call with the same key returns the first call's result instead of publishing again, which makes a retry safe.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed7 schema fields changed
    • changedInput schema / properties / description / description
      Previous value: -"Required. One sentence saying what the site holds, for a person deciding whether to open it. It is shown beside the title wherever the site is listed."New value: +"Required with files. One sentence saying what the site holds, for a person deciding whether to open it. It is shown beside the title wherever the site is listed."
    • changedInput schema / properties / files / description
      Previous value: -"Required. The site's files. One file named index.html is the minimum; add more for stylesheets, scripts, or further pages."New value: +"Required unless push is given. The site's files. One file named index.html is the minimum; add more for stylesheets, scripts, or further pages."
    • changedInput schema / properties / idempotency_key / description
      Previous value: -"An opaque key of your choosing. Repeating a call with the same key returns the first call's result instead of publishing a second site, which makes a retry safe."New value: +"An opaque key of your choosing. Repeating a call with the same key returns the first call's result instead of publishing again, which makes a retry safe."
    • changedInput schema / properties / name / description
      Previous value: -"The site's name, which becomes the first label of its URL, https://<name>.<org>.valet.run. Omit to have one generated. Naming a site that already exists republishes it. Requires a connected Valet account."New value: +"The site's name, which is the first label of its URL, https://<name>.<org>.valet.run. The site must exist: create it first with create_service. Publishing to it replaces its files. Required with a connected Valet account; leave it out for an anonymous publish."
    • addedInput schema / properties / push
      Added value: +{
      +  "description": "Publish a Git push instead of files: the id create_push returned and the commit you pushed to its branch. Use it when you can run git with network access, because it sends only what changed. Pass files or push, not both; every other argument keeps its meaning.",
      +  "properties": {
      +    "commit": {
      +      "description": "Required. The full sha of the commit you pushed to the push's branch. The recipe create_push returned prints it.",
      +      "type": "string"
      +    },
      +    "id": {
      +      "description": "Required. The push_id create_push returned.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "id",
      +    "commit"
      +  ],
      +  "type": "object"
      +}
    • changedInput schema / properties / title / description
      Previous value: -"Required. What the site is called, written for a person: 'Q3 Migration Audit', not a hostname. It labels the site wherever it is listed, so write the same thing the page's own <title> says."New value: +"Required with files. What the site is called, written for a person: 'Q3 Migration Audit', not a hostname. It labels the site wherever it is listed, so write the same thing the page's own <title> says."
    • removedInput schema / required
      Removed value: -[
      -  "files",
      -  "title",
      -  "description"
      -]
  2. Changed1 schema field changed
    • changedInput schema / properties / name / description
      Previous value: -"The site's name, which becomes the last segment of its URL, https://<org>.valet.run/<name>. Omit to have one generated. Naming a site that already exists republishes it. Requires a connected Valet account."New value: +"The site's name, which becomes the first label of its URL, https://<name>.<org>.valet.run. Omit to have one generated. Naming a site that already exists republishes it. Requires a connected Valet account."
  3. Changed1 schema field changed
    • changedInput schema / properties / name / description
      Previous value: -"The site's name, which becomes part of its URL. Omit to have one generated. Naming a site that already exists republishes it. Requires a connected Valet account."New value: +"The site's name, which becomes the last segment of its URL, https://<org>.valet.run/<name>. Omit to have one generated. Naming a site that already exists republishes it. Requires a connected Valet account."
  4. Changed5 schema fields changed
    • changedInput schema / properties / description / description
      Previous value: -"One sentence saying what the site holds, for a person deciding whether to open it. It is shown beside the title wherever the site is listed."New value: +"Required. One sentence saying what the site holds, for a person deciding whether to open it. It is shown beside the title wherever the site is listed."
    • changedInput schema / properties / files / description
      Previous value: -"The site's files. One file named index.html is the minimum; add more for stylesheets, scripts, or further pages."New value: +"Required. The site's files. One file named index.html is the minimum; add more for stylesheets, scripts, or further pages."
    • changedInput schema / properties / files / items / properties / content / description
      Previous value: -"The file's complete text content."New value: +"Required. The file's complete text content."
    • changedInput schema / properties / files / items / properties / path / description
      Previous value: -"Path within the site, relative and with no leading slash: index.html, styles/main.css. It may not contain '..'."New value: +"Required. Path within the site, relative and with no leading slash: index.html, styles/main.css. It may not contain '..'."
    • changedInput schema / properties / title / description
      Previous value: -"What the site is called, written for a person: 'Q3 Migration Audit', not a hostname. It labels the site wherever it is listed, so write the same thing the page's own <title> says."New value: +"Required. What the site is called, written for a person: 'Q3 Migration Audit', not a hostname. It labels the site wherever it is listed, so write the same thing the page's own <title> says."
  5. Changed1 schema field changed
    • addedInput schema / properties / anonymous
      Added value: +{
      +  "description": "Set true only when the user explicitly wants a temporary public site without account ownership. Omit for the account-first path, which connects a Valet account when needed.",
      +  "type": "boolean"
      +}
  6. Changed3 schema fields changed
    • addedInput schema / properties / description
      Added value: +{
      +  "description": "One sentence saying what the site holds, for a person deciding whether to open it. It is shown beside the title wherever the site is listed.",
      +  "maxLength": 1024,
      +  "minLength": 1,
      +  "type": "string"
      +}
    • addedInput schema / properties / title
      Added value: +{
      +  "description": "What the site is called, written for a person: 'Q3 Migration Audit', not a hostname. It labels the site wherever it is listed, so write the same thing the page's own <title> says.",
      +  "maxLength": 1024,
      +  "minLength": 1,
      +  "type": "string"
      +}
    • changedInput schema / required
      Previous value: -[
      -  "files"
      -]New value: +[
      +  "files",
      +  "title",
      +  "description"
      +]
  7. First observed

TDQS

A4.4/5.0
Behavior5/5

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

Annotations only declare readOnly=false/destructive=true/openWorld=true, but the description adds real behavioral context the agent could not infer: the site must already exist (create_service first) and a name holding no site is refused; anonymous sites are public to anyone with the link and may be removed 36 hours after creation unless claimed; the response carries a claim URL and a reusable site_token; and a policy-governed account publish may return 'evaluation' requiring get_evaluation(wait_seconds 20). It is consistent with destructiveHint=true ('Publishing to it replaces its files') and idempotentHint=false (idempotency is opt-in via idempotency_key, not a default), so no contradiction.

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?

It is front-loaded correctly (purpose first, then governance, then requirements, then delivery, then account/token, then policies), but it runs to roughly 350+ words and includes style guidance aimed at the writer ('Write them for the person who will come back to this page in a month') that belongs in a skill. Several sentences duplicate the 100%-covered schema rather than adding new information.

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 9-parameter, nested, mutation tool with no output schema, the description supplies everything needed to call it correctly: preconditions, mutual exclusion of the two content paths, failure modes, the shape of the result (claim URL, site_token), and the release-policy follow-up. Without an output schema this coverage is doing the work the schema cannot.

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 genuinely adds semantics beyond the schema: files and push are mutually exclusive ('Pass files or push, not both'), title and description are mandatory with files and a call missing either is refused, and site_token should be reused to revise rather than create a duplicate site. It stops short of 5 because most of this restates the already-rich schema 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?

The description opens with a precise verb+resource: 'Publish files as a live website, served over HTTPS at its own URL,' and adds scope ('static artifact,' 'files carries the text of the pages'). It clearly differentiates from create_push and create_service, but the three 'publish_*' siblings (publish_app, publish_agent, publish_skill) are never named or contrasted, so an agent has no explicit cue here for why this is the site tool rather than the app tool.

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

Usage Guidelines5/5

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

Explicit when-to-use triggers are given ('when a report, essay, slide-like narrative, dashboard ... reads better at a live URL'), plus a decision rule between the two delivery modes ('Use push when you can run git with network access, when the site is large or holds binary files, or when you changed a clone of its source'), plus the precondition for anonymous ('only when the user explicitly wants a temporary public site') and the create_service prerequisite.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources