2026-05-31

Return Links, Not HTML: Tool Results for Published Artifacts

When agents publish generated HTML, return a share URL + metadata—not raw markup. A practical tool-result contract for MCP/API workflows that stay small, safe, and reviewable.

developer workflowMCPtool resultsHTML artifactsAI agents

Table of contents

  1. The problem with returning HTML blobs
  2. The contract: what a publish tool should return
  3. MCP-friendly outputs (structured + human)
  4. A BinHTML pattern: share URL + management + source
  5. A checklist you can copy into your tool description

The problem with returning HTML blobs

It’s tempting to make a publish tool return the same sourceHtml it received. In practice, that usually makes the workflow worse:

  • **Context bloat:** tool results get appended to the conversation history, so you pay token + latency for the same markup twice.
  • **Accidental re-sharing:** once the HTML is in the transcript, it can leak into logs, exports, or future tool calls where it doesn’t belong.
  • **Unclear ownership:** is the “real” output the HTML in the chat, the hosted artifact, or some post-processed version? Humans (and agents) get confused.

Publishing should behave more like “upload → get an ID + URLs” than “echo back a blob”.

If you’re using BinHTML, this matches how the product is meant to be used: publish once, then pass around the link. See MCP docs and API docs.

The contract: what a publish tool should return

A practical publish tool result has two layers:

  • **Human layer:** a short sentence that includes the share URL so the user can click it.
  • **Machine layer:** a structured object an agent can reuse to update versions, attach the artifact to a project, or generate follow-up links.

At minimum, return:

  • artifactId (stable identifier for updates)
  • shareUrl (what the user shares)
  • visibility and expiresAt (so downstream steps don’t accidentally widen access)

Nice-to-have fields that reduce support load:

  • a dashboard/management URL
  • a source download URL (owner-only)
  • version number + size (for troubleshooting and plan limits)

This pattern also makes a clean boundary for your security checks: sanitize, validate, and sandbox at publish time, then only expose the link.

MCP-friendly outputs (structured + human)

MCP tool results can contain multiple content blocks, and MCP also supports structured tool output via structuredContent (with the recommendation to include a serialized form for compatibility). If your MCP server returns a JSON object describing the artifact, also include a short text summary so humans and older clients don’t lose the meaning.

The same idea shows up in non-MCP tool calling ecosystems too: if you want reliable downstream automation, return a schema-shaped object and validate it (OpenAI’s function calling / structured outputs guidance is explicit about this).

A BinHTML pattern: share URL + management + source

BinHTML’s MCP tool (publish_html) and REST API both follow the “return links + metadata” approach:

  • **Share URL** is what an agent should show to the user.
  • **Management URL** is for the signed-in owner to edit, move, or delete.
  • **Source download URL** is for audits or handoff (without pasting HTML into chat).

Once you have an artifactId, you can update the artifact in place (new version) while keeping the same share URL. That makes agent iteration loops cleaner: “revise → republish → re-open the same link” instead of sending a trail of near-duplicate URLs.

If you need to compare revisions, use BinHTML’s compare flow instead of pasting two HTML blobs into chat. Start at /compare.

A checklist you can copy into your tool description

When you’re defining a publish tool (or describing how an agent should use it), spell out the contract so the model doesn’t guess:

  • The tool **returns URLs and IDs**, not raw HTML.
  • The tool result includes a **human-readable line** with the share URL.
  • The tool result includes a **structured object** with artifactId, shareUrl, and access fields (visibility, expiresAt).
  • The tool supports **updates** via artifactId (new version, same share link).
  • The tool enforces **sandboxing and validation at publish time** (reject incomplete HTML, block dangerous rendering surfaces, apply limits).

If you’re building a workflow around this, pair it with a second rule: share *links* across systems (PRs, tickets, Slack), but keep the raw HTML inside BinHTML. That’s the difference between “a blob that spreads” and “an artifact with lifecycle controls”.

Related reading: Publishing HTML from AI agents and API vs MCP: publishing AI-generated HTML.

Sources