Skip to main content
Glama
htmlradar

HTMLRadar

Official

HTMLRadar

The open-source DocSend alternative for HTML files.

Read tracking for the decks, reports and proposals you now send as HTML.

License: AGPL v3 GitHub stars Self-hostable PRs welcome

HTMLRadar is an open-source tool for sharing an HTML deck, brief, or proposal as a tracked link, and seeing who opened it, which sections they read, and for how long. Not just that it was opened — dwell time, section by section. You know who a reader is when the share's email gate collected an address; otherwise the reader is an anonymous row with the same reading detail.

htmlradar.com · free for 2 tracked links, $15/mo or $150/yr for unlimited · or self-host the whole thing.

Try the public demo, no sign-up — a live tracked link you can open in a browser.

Using Claude? Add HTMLRadar as a connector by pasting one address — https://mcp.htmlradar.com/mcp. Nothing to install and no API key to make first; how it works.

Issues and PRs · roadmap · changelog documents v1.2; latest published tag is v1.1.2.

HTMLRadar dashboard walkthrough using synthetic sample data

Walkthrough uses synthetic sample data in the real sender dashboard.


Why this exists

The documents that matter — decks, client reports, proposals, board updates — are becoming HTML, because an HTML page can be interactive, reflows to whatever screen opens it, and can be changed after it has been sent. A PDF you have sent is fixed. More of them are written with AI tools now, and ChatGPT, Claude, v0, Lovable and Anthropic Artifacts all produce HTML. The format is what makes these documents better; who typed them is beside the point.

The tracking tooling never followed. When I went looking, I could not find an open-source tool that reported reading at section level for an HTML document. The document-tracking products I did find grew up around uploading a file and tracking that file.

HTMLRadar tracks the document people actually send now, and reports reading at section level rather than a single "opened" flag.


Related MCP server: Artifacts

What this is

Send-side analytics for HTML documents. Upload an HTML file (or paste a URL you already host), send a tracked link htmlradar.page/r/{slug}, see who opened it, which sections they dwelled on, and when they bounced. Section-level dwell, not "opened."

What it does

  • Section-level dwell. At least half a section must stay visible for one continuous second before its dwell starts qualifying; the read signal fires after three qualified seconds. The tracker auto-detects sections from your HTML: explicit anchored headings → bare h1/h2/h3 (slugged from text) → slide/page containers (section, .slide, .page) → paragraph buckets on plain prose. Dashboard tells you a recipient spent 2m 41s on §03 The Ask, 12s on Problem, and skipped Market sizing.

  • Per-viewer dashboard, aggregated across every share. One row per person who actually opened the doc, with email + country + device + referrer + total time + scroll depth + visits + first/last seen. Updates live every 30 seconds while the tab is in focus.

  • Per-recipient share links. One document, many shares. Each share carries its own email gate, password, expiry, revocation, and email-domain or per-email allow-list.

  • Files alongside the deck. Attach PDFs, financial models, images, and ZIPs to any share. Recipients see a small corner pill that opens a side drawer; files are always available when present (the per-share "Lock the deck" toggle controls deck save/print only, never attachments). Every download is logged per session and per filename, and tied to the viewer record when one exists.

  • Version history. Replace the HTML after partner feedback. Every existing share keeps the same link and serves the new version on next open. The v{n} chip on the doc page is a popover with every upload's original local filename, byte size, and timestamp.

  • Retroactive share access. Change a share's password, expiry, or allow-list without revoking. The proxy re-checks the allow-list on every request — removing an email kicks them out immediately on their next click, not their next browser session.

  • Edit + preview without leaving the dashboard. Preview the doc as the recipient sees it before sending (short-lived HMAC token, no gate). Both "Preview document" and "Preview as you" open in a new tab so your dashboard stays where you left it.

  • Branded first-open email. When a recipient creates their first real session, HTMLRadar requests an HTML notification — viewer email + doc title + a single "See the read →" CTA back to the dashboard. Tease, not report.

  • Engaged-time, not tab-open time. Both per-section dwell and per-session active time apply a 5-second idle watchdog (keydown / scroll / touchstart, mousemove deliberately excluded). That is the same five-second inactivity window engaged-time tools such as Chartbeat and Parse.ly use; those tools also read further interaction signals that HTMLRadar deliberately does not collect. A tab parked while the reader walked away stops counting after 5 seconds.

  • Bot / accidental-tap filter. After the document loads, HTMLRadar waits through a 5-second warm-up before creating the session. If the recipient backgrounds the tab or bounces during that wait, there is no session, notification request, or inflated viewer count.

  • Data collected. A recipient record holds an email address when a share's gate collects one, otherwise a random identifier (kept in the browser's localStorage where the page can reach it, freshly generated on each load where it cannot — which is the case on the sandboxed proxy-served links); first-seen and last-seen times; visit count; the browser identification string; referrer; country and city; device type; operating system; browser. A session record holds the document version seen, start and last-heartbeat times, active seconds, and maximum scroll depth. A section record holds dwell per section. These records are kept until the owner deletes the document — there is no automatic purge. Not stored in recipient records: raw IP address, cursor positions, keystrokes, page snapshots, session replay. An ungated document shows no tracking notice; the email-gate page shows one sentence ("Reading activity on this document is shared with the sender") and a link to the privacy page. Opt-out is a developer-console call, window.HTMLRadar.optOut(), followed by a confirmation page — documented, but not something an ordinary recipient will discover. Audit for comparison: what each of seven tools loads in a recipient's browser, HTMLRadar included.

What it deliberately is not

A sender-side analytics tool for one document at a time. Not a CMS, deck builder, static-site host, PDF viewer, or website analytics platform. You bring the HTML.


Architecture

Six packages, two storage backends. Three of the six are Cloudflare Workers, one is the Next.js app on Cloudflare Pages, and two are libraries that ship as bundles.

htmlradar/
├── packages/
│   ├── tracker/      # 8.5 KB gzipped browser IIFE — embedded in the recipient's view
│   ├── proxy/        # Cloudflare Worker at htmlradar.page/r/{slug} — gates + HTML fetch + tracker inject + attachment serving
│   ├── app/          # Next.js 14 on Cloudflare Pages — sender's dashboard
│   ├── monitor/      # Cloudflare cron Worker — checks Supabase every 5 min, pages the founder on regressions, and answers the Telegram webhook
│   ├── connector/    # Cloudflare Worker at mcp.htmlradar.com — the remote MCP server, so Claude can be connected by pasting one address
│   └── mcp/          # stdio MCP server on npm — lets an agent publish HTML and read back who opened it
├── schema/           # Ordered idempotent SQL migrations — tables, RLS, SECURITY DEFINER RPCs, triggers
├── examples/         # Demo HTML for trying it locally
└── docs/             # Architecture, privacy, quickstart, self-hosting

Document HTML + attachment bytes live in Cloudflare R2. Everything else (sessions, sections, viewers, shares, attachments metadata, version history) lives in Supabase Postgres.

Recipient links live on a second domain, htmlradar.page, while the dashboard and the marketing site stay on htmlradar.com. A recipient document is HTML somebody else wrote, and serving it on the application's own domain would put a stranger's markup on the same origin as a signed-in session, and would let anyone who uploaded a convincing fake sign-in page have it served under our certificate and our reputation. A separate registrable domain removes both problems at once: the document's origin carries no application cookies, and if the content domain ever ends up on a phishing blocklist, the application domain does not. Links sent before the split still work — the worker answers htmlradar.com/r/… with a permanent redirect. Self-hosters choose their own two hosts, or run both roles on one; see docs/self-hosting.md.

The architecture decisions — why a Cloudflare Worker proxy, why hand-rolled PostgREST instead of @supabase/supabase-js, why per-session bearer tokens instead of HMAC, the engagement-time methodology, the retroactive allow-list — are in docs/architecture.md.

Stack

  • Frontend: Next.js 14 (App Router, Server Components), Tailwind CSS, Newsreader + Geist (self-hosted via next/font)

  • Backend: Supabase Postgres — RLS + SECURITY DEFINER RPCs + pg_net triggers for email

  • Proxy: Cloudflare Worker, HTMLRewriter for tracker injection

  • Remote MCP connector: Cloudflare Worker on mcp.htmlradar.com, OAuth on top of ordinary API keys, one KV namespace for grants and tokens

  • Storage: Cloudflare R2 for uploaded HTML

  • Auth: Supabase Auth (Google OAuth + magic-link)

  • Email: Resend, invoked from Postgres via pg_net

  • Payments: Polar.sh checkout link (Stripe Connect Express under the hood for Indian indie founders)

Core hosting runs on Cloudflare and Supabase. Resend is optional for notification email, and Polar handles billing for the hosted Pro plan.


Quick start — hosted

  1. Sign in at htmlradar.com with Google or magic link.

  2. Upload an HTML file or paste a URL.

  3. Create a per-recipient share. Email gate / password / expiry / allow-list optional per share.

  4. Send the tracked link.

  5. Watch the dashboard. HTMLRadar requests a first-read email when the recipient creates their first real session.

Free tier: 2 tracked links lifetime across unlimited documents, 20 attachments per doc up to 25 MB each and 100 MB total per doc. Pro tier ($15/month, or $150/year — two months free): unlimited tracked links, your own link names (htmlradar.page/r/acme-proposal rather than a generated one), no "Powered by HTMLRadar" footer on the recipient view, priority support. Coming soon on Pro: custom domain on share URLs, dynamic per-viewer watermark, repeat-open alerts. What's next is on the public roadmap.

Quick start — self-host

You'll need:

  • A Cloudflare account (Workers + R2 + Pages)

  • A Supabase project (free tier is enough)

  • A domain on Cloudflare DNS

  • Node ≥20, PNPM ≥10

  • A Resend account for outbound email (optional — without it, the first-read trigger writes a skipped row to notifications_log and the rest of the product still works)

Then:

git clone https://github.com/htmlradar/htmlradar
cd htmlradar
pnpm install
cp .env.example .env.local           # then fill it in, see the note below
pnpm typecheck && pnpm test          # sanity check
pnpm build                           # builds app, tracker and mcp — the three packages that have a build script

pnpm build needs two variables filled in before it will finish. Copying .env.example is not enough on its own: several marketing pages are pre-rendered at build time and they create a Supabase client while doing it, so NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY have to hold real values in .env.local first. Leave them blank and the build stops on /, /pricing, /privacy, /terms and /why with Your project's URL and Key are required to create a Supabase client!, which does not say which file it wanted. Everything else in .env.example can wait until you deploy.

Schema setup: apply every numbered SQL file directly under schema/, in order, via the Supabase SQL editor — and nothing in schema/tests/. There is no last file to stop at; the folder grows, so apply whatever is in it, from 001 upwards, and add each new one as you pull it. The files in schema/tests/ are destructive test programs for a scratch database (they create auth users and sample rows) and must never run against a real install. Each migration is idempotent (CREATE TABLE IF NOT EXISTS, CREATE OR REPLACE FUNCTION, DO $$ ... IF NOT EXISTS ... $$), so re-running any of them is safe, and so is re-running the whole chain.

Two Postgres extensions have to be available, and both are on every Supabase tier: pgcrypto, for gen_random_uuid and the hashing the schema does, and pg_net, for the asynchronous HTTP call the notification triggers make. 001_init.sql creates both itself. A third, pg_cron, is optional: migrations 044 and 045 use it to schedule the notification reconciler and the expired-handle sweep, and where it is missing they log a notice, skip the scheduling and carry on, leaving both functions callable by hand or by any scheduler you already run.

The five most recent migrations, as of this commit:

  • 043_trust_layer_foundation.sql — per-customer handles, the permanent registry of claimed names behind them, the per-share hostname the proxy routes on, and the private share_lookup view the proxy reads instead of three separate tables.

  • 044_notification_reconciler.sqlreconcile_notification_sends(), which finally moves a notification row off queued by joining it against pg_net's own response table; scheduled every ten minutes where pg_cron exists.

  • 045_connect_handles.sql — the short-lived, single-use handoff from the signed-in consent page to the remote MCP connector. The table stores only a hash of the handle. Run it after 040.

  • 046_connector_grants.sql — what the application knows about each remote-connector connection and what became of it, so a revocation whose OAuth clean-up failed is a row somebody can find.

  • 047_radar_drafts.sql — the drafted-reply queue and the reservation ledger that makes "one comment per thread, five a day" an enforced fact rather than an intention.

One migration wants editing before you run it: 032_comped_accounts.sql carries a placeholder list of internal addresses that are never billed. Put your own addresses in it, or none.

Resend secrets go in Supabase Vault (works on free tier — no ALTER DATABASE SET required):

select vault.create_secret('re_your_resend_api_key', 'resend_api_key');
select vault.create_secret('hello@yourdomain.com',  'resend_from');

Full guide with deployment commands in docs/self-hosting.md.


Use it from your agent

HTMLRadar ships an MCP server, so the agent that wrote the HTML can publish it as a tracked link — and ask, the next day, whether anyone read it.

Claude Desktop and claude.ai — one address, no install

Settings → Connectors → Add custom connector, and paste:

https://mcp.htmlradar.com/mcp

Nothing to install and no API key to make first. The first time Claude reaches for a tool it shows a Connect card; you sign in to HTMLRadar, choose read-only or read-and-publish, and the key is minted for that connection. Revoke it any time under Connected apps in Settings — access ends on the next tool call.

Every other client — run the package

Create an API key at htmlradar.com/settings under API keys — the same key also calls the HTTP API directly, if you would rather script it than run an agent — then export it, so the key never becomes a command-line argument that lands in your shell history:

export HTMLRADAR_API_KEY=hr_live_xxx

Claude Code

claude mcp add htmlradar -e HTMLRADAR_API_KEY=$HTMLRADAR_API_KEY -- npx -y htmlradar-mcp

Or install the plugin, which wires up the same server and adds a skill that knows when to offer a tracked link and when to stay quiet:

/plugin marketplace add htmlradar/htmlradar
/plugin install htmlradar@htmlradar

Cursor — put this in .cursor/mcp.json in your project, or ~/.cursor/mcp.json to make it global. Cursor expands ${env:NAME} inside env, which keeps the key out of a file you might commit:

{
  "mcpServers": {
    "htmlradar": {
      "command": "npx",
      "args": ["-y", "htmlradar-mcp"],
      "env": { "HTMLRADAR_API_KEY": "${env:HTMLRADAR_API_KEY}" }
    }
  }
}

There is a one-click Add to Cursor button on htmlradar.com/mcp. It installs the server with a placeholder key, which you then replace with your own.

Codex CLI

codex mcp add htmlradar --env HTMLRADAR_API_KEY=$HTMLRADAR_API_KEY -- npx -y htmlradar-mcp

Seven tools: whoami, list_shares and get_share_activity read; share_html, create_share, replace_document and revoke_share write. Every option, the self-hosting variable and the privacy notes are in packages/mcp/README.md. The connector at mcp.htmlradar.com serves the same seven, imported from this package rather than copied — see packages/connector/README.md.

If you modify the source and run a network service from it, AGPL-3.0 requires you to make your modifications available. See LICENSE.


Development

pnpm dev                              # runs app, monitor, proxy, connector, tracker in parallel (mcp has no dev script)
pnpm typecheck                        # tsc --noEmit across all six packages
pnpm lint                             # eslint + prettier
pnpm test                             # vitest across app, mcp, monitor, proxy, connector, tracker

Local URLs after pnpm dev:

  • Web app: http://localhost:3000

  • Proxy worker: http://localhost:8787

  • Tracker bundle: packages/tracker/dist/tracker.js (after pnpm --filter @htmlradar/tracker build)

Tracker bundle size budget: ≤14 KB gzipped. Build will warn if you cross it.


Contributing

PRs welcome. DCO sign-off is required — just git commit -s. No CLA.

  • Big features: open an issue first to discuss scope.

  • Bug fixes + small improvements: PR directly.

  • Style is enforced by pnpm lint. CI runs the full suite on every push.

See CONTRIBUTING.md for the full guide.

Security

Found a vulnerability? Email security@htmlradar.com. Please don't open a public issue. See SECURITY.md for the disclosure policy.

License

AGPL-3.0-or-later. See LICENSE.

Want to run a hosted service from a closed-source modified version, or embed the tracker in a closed-source product? A commercial license is available — see COMMERCIAL-LICENSE.md, or email hello@htmlradar.com.


Engineering deep-dive: htmlradar.com/blog/how-we-built-htmlradar

Available Tools

7 tools
create_shareMake another tracked link for an existing documentAInspect

Creates an additional tracked link for a document already on HTMLRadar, with its own recipient label, gate, password, expiry and address. One link per recipient is what separates their reading reports. It uploads nothing and creates no second copy of the document, and it cannot publish new markup: it takes a document id, which list_shares returns and share_html returned when the document was first published. The link is live the moment it is returned.

ParametersJSON Schema
NameRequiredDescriptionDefault
slugNoCustom link name, so the URL reads /r/acme-proposal. Paid plans only.
passwordNoExtra password gate on top of the email gate.
lock_deckNoBlocks save and print and adds a watermark; default true. Pass false for a document the recipient is meant to keep a copy of.
document_idYesThe document to make another link for — the document id from list_shares, or the one share_html returned when the document was first published.
require_emailNoAsk the recipient for their email before the document opens. Defaults to true.
recipient_labelNoWho this link is for, e.g. "Acme". One link per recipient reads best.
expires_in_hoursNoLink stops working after this many hours.
allowed_email_domainsNoOnly these email domains may open the link, e.g. ["acme.com"].

TDQS

A4.7/5.0
Behavior5/5

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

Discloses non-destructive behavior ('uploads nothing', 'creates no second copy'), immediate effect ('link is live the moment it is returned'), and clarifies it does not publish new markup. These details go beyond the annotations.

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

Conciseness4/5

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

Three sentences, first sentence states the core purpose, second gives guidance, third clarifies constraints and sources. Slightly verbose but well-organized and each sentence earns its place.

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

Completeness4/5

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

Combined with the rich parameter descriptions and sibling tools, the description gives sufficient context for an agent to know when and how to use the tool. It does not describe output, but no output schema is provided, so this is acceptable.

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 already describes all parameters with 100% coverage. The description adds meaningful context by explaining that document_id comes from list_shares or share_html, and that recipient_label should be per-recipient, reinforcing the schema rather than merely repeating it.

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

Purpose5/5

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

Clearly states the action: 'Creates an additional tracked link for a document already on HTMLRadar'. It also distinguishes itself from share_html by explicitly saying it 'cannot publish new markup' and works with an existing document id.

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?

Provides explicit when-to-use guidance: use for additional links to existing documents, while share_html is for first publication. Also advises 'One link per recipient' to separate reading reports.

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

get_share_activityCheck who read a tracked linkA
Read-only
Inspect

Reports whether a tracked HTMLRadar link has been opened, by whom, for how long, how far they scrolled, and which sections held their attention. Per viewer it names the five sections with the most reading time, and every figure is rounded down, so no number it prints is above the recorded one. It accepts a share id, a slug or a link; list_shares returns all three.

ParametersJSON Schema
NameRequiredDescriptionDefault
share_idYesThe share id returned by share_html, or the share's slug (the part after /r/ in its link), or the link itself.
include_detailNoAlso return each reader's country, city, device and referrer. Off by default: that is a named person's location and device, and whether the document was read and which parts of it is answered without them.

TDQS

A4.5/5.0
Behavior5/5

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

Annotations declare readOnlyHint and openWorldHint, and the description adds privacy caveats about including reader location/device by default, exceeding the annotation's minimal information.

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

Conciseness4/5

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

Description is dense but not overly long; each clause serves a purpose (reporting scope, input formats, rounding behavior, privacy), though the note about rounding down could be considered slightly tangential.

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

Completeness4/5

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

No output schema, but the description clearly states what is reported (read status, reader, duration, scroll depth, top sections) and optional details, making the tool's behavior understandable without an explicit output structure.

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 covers 100% of parameters with descriptions; the tool description adds practical details about share_id formats and the privacy implications of include_detail, going beyond the schema.

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

Purpose5/5

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

States a specific verb ('Reports') and resource ('tracked link') and distinguishes from siblings by clarifying inputs (share id, slug, or link) and referencing list_shares for obtaining them.

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?

Provides explicit context about the input forms and mentions list_shares as the source for all three, giving clear guidance on how to use compared to siblings, though it doesn't explicitly say when not to use it.

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

list_sharesList tracked links on this accountA
Read-only
Inspect

Lists the account's tracked links, newest first: the slug, the recipient label, the document title, whether it has been opened and when, and the share and document ids the other tools take. This is where the identifiers for a link made in an earlier conversation come from. Returns at most 50 per call; the before cursor pages back through older links.

ParametersJSON Schema
NameRequiredDescriptionDefault
beforeNoCursor for the next page: the `next_before` value printed at the end of a previous list_shares result, of the form <created_at>|<share id>. Pass it back exactly as printed. Omit for the most recent links.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds concrete behavioral details beyond annotations: newest-first ordering, a 50-per-call limit, and pagination semantics via the `before` cursor. It also indicates the return includes open status and timestamps, enriching the agent's expectations.

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

Conciseness5/5

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

The description is three sentences with no fluff. The primary purpose and output fields are front-loaded, followed by the pagination behavior and usage context. Every sentence adds value, and it is appropriately concise for a simple list operation.

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 tool with one optional parameter and no output schema, the description is complete. It specifies what is returned, the ordering, pagination mechanics, and the practical purpose (obtaining identifiers for other tools). An agent has all the information needed to call it correctly without additional inference.

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

Parameters3/5

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

The only parameter (`before`) is fully described in the schema (100% coverage), including its format and usage. The description reinforces this by mentioning the cursor pages through older links and the 50-per-call limit, but it does not add significant new meaning beyond the schema. Baseline of 3 is appropriate when the schema carries the semantic weight.

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

Purpose5/5

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

The description states a specific verb ('Lists') and resource ('the account's tracked links'), and specifies the exact fields returned (slug, recipient label, document title, open status, ids). It distinguishes itself from siblings by noting it provides 'the share and document ids the other tools take,' clarifying its role as a listing operation.

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?

It provides clear context for when to use it: 'This is where the identifiers for a link made in an earlier conversation come from,' implying use when you need IDs from previous links. It also explains pagination via the `before` cursor. However, it does not explicitly state when not to use it or name alternative tools for exclusion, though the sibling list makes that inferable.

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

replace_documentReplace a document, keeping every linkA
Destructive
Inspect

Replaces the contents of a document already on HTMLRadar. Every existing link stays exactly as it is — same address, same settings, same reading history — and serves the new contents from the next time it is opened, so nobody is sent a second link. The new HTML is screened for phishing signals as every upload is, and the previous version is kept in the document's history. Recipients may already have read the old contents, and there is no partial update: the markup supplied replaces the document.

ParametersJSON Schema
NameRequiredDescriptionDefault
htmlYesThe new HTML markup, in full. It replaces the document; there is no partial update.
document_idYesThe document whose contents are being replaced. Every link to it keeps working.

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false. The description adds meaningful behavioral context: links and reading history remain intact, new content is served on next open (so no second link is sent), the upload is screened for phishing, the previous version is kept in history, and there is no partial update. These details exceed what annotations alone provide and accurately reflect the destructive nature of the operation.

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

Conciseness4/5

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

The description is three sentences long, each serving a distinct purpose: core action and link preservation, security screening and history, and the no-partial-update caveat. It is well-structured, front-loads the primary behavior, and avoids redundancy with the schema. A slightly tighter phrasing might earn a 5, but the current length is justified by the important behavioral nuances.

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

Completeness4/5

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

Given a two-parameter tool with no output schema, the description covers the essential outcomes: content replacement, link stability, phishing screening, history retention, and the lack of partial updates. It does not mention error conditions or idempotency, but annotations already convey idempotentHint=false. The description is sufficiently complete for an agent to call the tool correctly without additional context.

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

Parameters3/5

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

Schema description coverage is 100%, so both parameters are already documented. The description reinforces the semantics (e.g., html is a full replacement, document_id retains links) but does not introduce new information beyond the schema. Since the schema does the heavy lifting, a baseline score of 3 is appropriate; the description adds minimal extra meaning.

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

Purpose5/5

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

The description opens with a specific verb and resource: 'Replaces the contents of a document already on HTMLRadar.' It clearly distinguishes the tool's purpose from the sibling tools (which are all share-related) and states the key differentiator: links are preserved. No ambiguity remains about what action this tool performs.

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?

The description implicitly guides usage by stating it targets existing documents ('already on HTMLRadar') and emphasizes the link-preserving behavior. It does not explicitly name alternative tools for creation or sharing, but given the sibling list contains no other document-manipulation tools, the context is sufficient. A clear when-to-use is implied but not spelled out as an exclusion.

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

revoke_shareSwitch a tracked link offA
DestructiveIdempotent
Inspect

Switches off a tracked link that has already been sent. Anyone who opens it afterwards sees that it is no longer available, and the sender is emailed that somebody tried. This changes what a recipient can see. It is reversible — revoked: false switches the link back on — and it deletes nothing: the link, its settings and its whole reading history survive. Deleting a link is possible only on the website.

ParametersJSON Schema
NameRequiredDescriptionDefault
revokedNoTrue (the default) switches the link off. False switches it back on.
share_idYesThe share id, the share's slug (the part after /r/ in its link), or the link itself. list_shares returns all three.

TDQS

A5/5.0
Behavior5/5

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

The description fully discloses behavior: it reverses with revoked:false, does not delete the link, and changes what recipients see. This aligns with idempotentHint and clarifies the destructiveHint annotation by stating no data is deleted.

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

Conciseness5/5

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

The description is concise—three sentences—and front-loads the primary action and effects. No unnecessary detail or repetition.

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?

Given the two parameters and the absence of an output schema, the description provides all needed context: what it does, effects, reversibility, and the limitation of deletion to the website. An agent can confidently invoke it.

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

Parameters5/5

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

Both parameters are described in the schema and the description adds semantic depth: share_id includes alternative forms (id, slug, link), and revoked explains that true is default and false re-enables. This goes beyond the schema alone.

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

Purpose5/5

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

The description clearly states the verb 'Switches off' and resource 'tracked link', making its purpose unambiguous. It is immediately distinguishable from sibling tools like create_share or list_shares.

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?

It explains when to use it (for links already sent), describes effects (recipient sees unavailable, sender notified), and notes that deletion only happens on the website, guiding the agent away from confusion with destructive alternatives.

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

share_htmlShare HTML as a tracked linkAInspect

Publishes an HTML document — a deck, proposal, report or one-pager — as a tracked HTMLRadar link, and returns two addresses: the link for the recipient, and a dashboard address for the sender. The recipient sees the document as written and never the tracking. The markup goes in html; there is no file-path argument, so a document on disk reaches this tool only as markup the caller has already read, which leaves the user's permissions on their own file tools in charge of what is published. The link is live the moment it is returned.

ParametersJSON Schema
NameRequiredDescriptionDefault
htmlYesThe HTML markup to publish, in full. There is no file-path argument: a document on disk reaches this tool only as markup the caller has already read.
slugNoCustom link name, so the URL reads /r/acme-proposal. Paid plans only.
titleNoName shown on your dashboard. Recipients do not see it.
passwordNoExtra password gate on top of the email gate.
lock_deckNoBlocks save and print and adds a watermark; default true. Pass false for a document the recipient is meant to keep a copy of.
require_emailNoAsk the recipient for their email before the document opens. Defaults to true.
recipient_labelNoWho this link is for, e.g. "Acme". One link per recipient reads best.
expires_in_hoursNoLink stops working after this many hours.
allowed_email_domainsNoOnly these email domains may open the link, e.g. ["acme.com"].

TDQS

A4/5.0
Behavior4/5

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

Annotations indicate a non-read-only, non-destructive operation, and the description expands on this by noting the link is live immediately, the recipient never sees tracking, and the permissions nuance regarding file tools. It adds meaningful behavioral context beyond the annotations without contradicting them.

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

Conciseness5/5

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

The description is dense but every sentence contributes value: it states the outcome, clarifies the recipient experience, explains the input format, and mentions the permission consideration. It is front-loaded with the core purpose and avoids fluff.

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

Completeness4/5

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

Given the tool's complexity (9 parameters, no output schema), the description covers the key operational aspects: what is returned (two addresses), when the link becomes active, and the permission model. It does not enumerate every parameter but relies on the schema for that, which is acceptable. Minor gaps like the exact format of the dashboard address are not critical.

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

Parameters3/5

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

Schema description coverage is 100%, so all nine parameters are documented. The description adds minimal parameter-specific detail beyond the schema (e.g., reiterating the no-file-path rule already in the html schema). It does not significantly enhance parameter understanding, keeping it at the baseline.

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

Purpose5/5

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

The description clearly states the tool's purpose: publishing an HTML document as a tracked link and returning two addresses. It specifies the resource (HTMLRadar link) and the action (publish), and it distinguishes the recipient experience from the sender's dashboard, making it distinct from generic 'create' or 'share' tools.

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

Usage Guidelines3/5

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

The description provides some usage context (e.g., the html parameter must contain markup, no file-path argument) but does not explicitly state when to choose this tool over siblings like create_share or list_shares. It implies the workflow but offers no exclusions or alternative routing.

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

whoamiShow the HTMLRadar plan and free links leftA
Read-only
Inspect

Reports the plan the HTMLRadar API key's account is on and how many of its free tracked links remain. It returns no account identifier and no email address.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

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

The description is consistent with the readOnlyHint annotation, using 'Reports' to indicate a non-mutating operation. It also proactively notes the absence of identity data, providing transparency beyond the annotation.

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

Conciseness5/5

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

Two clear, compact sentences convey all required information without redundancy. The structure is front-loaded with the primary purpose and includes a helpful explicit exclusion.

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?

Given no output schema, the description adequately describes the return content (plan and free links left) and explicitly states what is not included. This fully covers the necessary context for a simple read-only tool.

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?

The tool has no parameters, so the description adds no parameter-specific meaning. The baseline of 4 applies since there are no parameters to document.

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

Purpose5/5

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

Description clearly states the specific verb 'Reports' and the resource: the account's plan and remaining free tracked links. It distinguishes itself from sibling tools focused on share management by focusing on account-level information.

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?

The description explicitly states what the tool does and, more importantly, what it does not return ('no account identifier and no email address'), setting clear expectations for when not to use it. Sibling tools provide alternative context, making the use case evident.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 7 tool updatesv0.3.1
    • First observedcreate_share
    • First observedget_share_activity
    • First observedlist_shares
    • First observedreplace_document
    • First observedrevoke_share
    • First observedshare_html
    • First observedwhoami

TDQS

A4.2/5.0

Scored across 7 tools

Disambiguation4/5

Most tools are distinct, but 'share_html' and 'create_share' both create tracked links and could be confused by an agent, especially since one is initial and one is additional. 'revoke_share' also has toggle semantics ('revoked: false' switches it back on) that the name does not clearly convey.

Naming Consistency4/5

The naming pattern is mostly consistent lowercase snake_case verb_noun, e.g. list_shares, get_share_activity, replace_document. The exceptions are 'whoami' and the slightly inconsistent pairing of 'share_html' vs 'create_share'.

Tool Count5/5

Seven tools is well-scoped for this domain, covering account info, initial sharing, additional shares, listing, activity, revocation, and document replacement without being overwhelming.

Completeness3/5

The surface covers create, read, update, and soft-disable operations, but there is no permanent delete for shares or documents, and no way to update share settings like recipient label, password, or expiry. This leaves notable lifecycle gaps.

Maintenance

ActivityActive
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Publishes HTML pages straight from your AI assistant to a shareable URL, then lets you manage them - update, list, search, fetch, and delete pages in a public or private workspace. Turns "share what I just made" into a single tool call from Claude, Cursor, or any MCP client.
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables publishing sanitized static HTML pages from an MCP agent and receiving shareable URLs, with tools for updating, listing, publishing, and deleting pages.
    12
    7 npm
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Web analytics and AI session replay for agents: visitors, breakdowns, funnels, goals, revenue attribution, and AI-found site issues. Connects to the hosted Flowsery MCP server.
    27
    MIT