
fmrl
io.github.toogreatwtfPublished by GitHub account toogreatwtfv0.17.5Updated Nov 8, 2026
Publish HTML or Markdown from any agent to fmrl.site and get a link back. Private by default.
Overview
Publishes HTML or Markdown pages made by an agent to fmrl.site and returns a link, private and encrypted by default.
- What you can do
- Publish pages from inline content or a local HTML/Markdown file, choosing private (encrypted) or public visibility
- Fetch a page by id or link, optionally writing it to a file in a local fmrl folder
- Edit pages with revision checks, and switch a page between private and public with a confirmation preview
- Watch pages and list revisions others made in an inbox
- List, delete and manage pages owned by the key, and attach the agent to a person via a one-time link
- Check key, quota, versions and status, and redeem or rotate the API key
- When to use it
- Useful when an agent produces a report, prototype or document that someone else should open in a browser, and you want a shareable link without setting up hosting or an account. Also handy for handing work to a reviewer and tracking their revisions.
- Requirements
- Runs locally over stdio, typically via npx fmrl-mcp. No account is needed: the server mints an API key on first publish and stores it in the user's config directory. Optional environment variables: FMRL_API_KEY, FMRL_API_URL, FMRL_AGENT_NAME and FMRL_RING. Network access to fmrl.site is required.
Installation
In SourceWeft
- Open fmrl in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
fmrl
Share anything your AI made. fmrl is a Claude Code plugin and an MCP server (fmrl-mcp) that publish a page to fmrl.site and hand back a link. No account. Pages are private by default: encrypted on your machine, readable by anyone you give the full link, but not by fmrl.site. A page lasts seven days; a public one, published only when asked, can be kept from the page itself.
Install
Claude Code:
Keep it current: auto-update is your switch — no marketplace can set it for you. The plugin offers once to turn it on; you can flip it yourself in /plugin → Marketplaces → fmrl-plugin → Enable auto-update. In the Claude desktop app the switch does nothing: update by hand, or when the plugin says it is out of date. By hand: claude plugin marketplace update fmrl-plugin, then claude plugin update fmrl@fmrl-plugin, and restart Claude Code.
Cursor: open Customize, then Plugins, choose Add and Import Marketplace, paste https://github.com/toogreatwtf/fmrl-plugin as the repository (the full address; Cursor rejects the short owner/repo form), and add fmrl. It brings the share, whoami, attach and status skills and the same fourteen tools. The plugin runs the fmrl-mcp version it names, so the tools and skills both stay at the version Cursor installed until you update the plugin there.
Any MCP client (Claude Desktop, Cursor, Codex, Windsurf, and the rest):
No key step. The server mints a key the first time it publishes and keeps it in the user's config directory. FMRL_API_KEY overrides it; FMRL_API_URL points the server at a preview or a local make dev (default https://fmrl.site); FMRL_AGENT_NAME names the revisions this key makes, replacing any name already set (without it, the MCP client's own name fills an unset one).
curl, for people who want neither:
What you get
In Claude Code, /fmrl:share publishes what is at hand — a file you named or something the agent composed — and replies with the link, the expiry, and a recovery link that grants management and editing, never deletion. Before publishing a canvas that hands work to someone else to review, it offers the handoff-review starter — eight sections and a fmrl-profile block recording their shape, readable at fmrl.site/h4ndrv. /fmrl:whoami shows the key, this month's quota, where the key ring is kept, and whether the plugin is up to date. /fmrl:status answers at once from local state — fmrl-mcp and plugin versions, what launched the server, the key and ring on this machine, the last API call — and /fmrl:status verbose adds the network checks: whether fmrl.site answers, quota, inbox, and the newest fmrl-mcp on npm.
Any MCP client gets fourteen tools:
Keys and limits
fmrl_get's to_file writes, and fmrl_edit's content_file reads, only in one folder: ~/fmrl (%USERPROFILE%\fmrl on Windows), made with mode 0700 on first use, or the absolute folder FMRL_FILES_DIR names; a folder that already exists must be yours and writable by no one else. content_file reads only the edited page's own file there. So a page, or an instruction planted in one, can't get a note from elsewhere on the machine uploaded, can't publish one page's opened private copy under another page, and can't have page content written over a file outside the folder.
The server mints a key on first use and stores it in ~/.config/fmrl/credentials.json ($XDG_CONFIG_HOME/fmrl/credentials.json; %APPDATA%\fmrl\credentials.json on Windows), one key per API base URL, file mode 0600. FMRL_API_KEY overrides the file, and then fmrl_redeem and fmrl_rotate refuse rather than store a key it would shadow. A stored key that stops working is replaced with a fresh one on the next call, except that fmrl_whoami reports a revoked key first; a rotated key keeps its prefix, so its key ring still applies. A private page's key travels with it, sealed under a key ring kept in the same file (FMRL_RING overrides it) and handed to a browser only inside the link, so fmrl.site stores the sealed record and cannot open it; back up that file to keep every page's key. In a container that sets FMRL_API_KEY on a filesystem that does not persist, set FMRL_RING too — 32 random bytes as unpadded base64url, e.g. node -e "console.log(require('node:crypto').randomBytes(32).toString('base64url'))" — or every restart starts a new ring. FMRL_AGENT_NAME names the revisions this key makes on fmrl.site (so other editors know who made them); without it, the MCP client's own name fills a key that has none. Beside credentials.json, pages.json (same directory, same protections) remembers, per page this machine has opened or edited, its content key (private pages only) and any manage token that worked — so a page's link or manage link needs pasting only once. 25 publishes a month per key, 5 keys a day per network, 2 MiB per page — a private page's cap is on the sealed envelope, so roughly 1.4 MB of HTML fits. Content is subject to fmrl.site's acceptable use policy. Full API reference: fmrl.site/api.
Account vault ring sync
Sharing requires no account. When a key belongs to an account with private-page sync enabled, the local MCP server seals credential-file rings to the advertised account vault. Every successful public or private fmrl_publish or fmrl_publish_file makes a fresh GET /api/v1/me after publishing; every fmrl_whoami uses its own fresh response and syncs too. Nothing about the vault goes through the hosted /mcp endpoint.
The server validates the vault public key and recomputes its fingerprint before pinning it on first use (TOFU). Pins are stored per viewer origin in credentials.json, still version 1, with additive vault_pins alongside existing keys and rings. Historical slots now also record ring_origins, a locally established origin for each ring. A changed fingerprint stops uploads until the person explicitly confirms the fingerprint on /account and supplies that exact grouped value through fmrl_whoami's optional trust_vault. The agent must never trust a changed fingerprint automatically.
Only rings with local provenance for the configured origin are eligible: stored keys under that origin (including URL aliases), and historical slots whose ring_origins entry names it. Legacy history with no origin stays on disk and is excluded unless its exact prefix/ring pair matches a same-origin stored key. A server advertising a matching prefix cannot authorize exporting another origin's ring. This reduces recovery coverage for unscoped legacy rings; they require the original backup until an explicit migration is available.
The actual active ring, if eligible and stored in the credentials file, goes first in its own request. Superseded variants under that active prefix remain local and are not uploaded, preventing them from exhausting the budget or overwriting the active box. Other eligible prefixes retain numeric historical order with stored-key variants last. The vault retains one box per prefix, so it cannot recover every historical variant.
Each PUT /api/v1/me/rings contains at most 50 boxes and no repeated prefix. Requests share the edit budget (API_EDITS_PER_HOUR, default 60/hour), not the publish quota. Only on atomic HTTP 400 ring_ownership rejection, the client tries each member of a multi-row batch once separately and continues other prefixes; a refused singleton is not retried. The active request costs one edit; isolating a refused N-row batch costs up to 1+N requests. Each pass is capped at 10 PUT attempts and stops immediately on 429 or any other operational failure. Each call can consume 10 shared edit tokens; repeated calls still consume the hourly budget. The next authorized tool call starts afresh; there is no throttle, boxed-ring cache or background timer. HTTP 403/409 refusals remain silent; 409 always leaves status unknown. Credential recovery preserves the moved-aside file and emits only a fixed warning. Refused, unfinished or partially uploaded requested scope is unknown and produces no synced/not-synced claim. Malformed vault data, persistence failures and network/5xx failures preserve the original tool success and log a fixed non-secret diagnostic. A primary whoami /me failure retains its normal error/revocation behavior.
FMRL_RING is never added to the file snapshot. An environment-only or different override excludes stale file variants for the active prefix and omits a sync-status claim based on those uploads. An unavailable vault may still report the approved not-synced status. An override identical to an eligible stored active-prefix ring can qualify for the approved synced line after successful upload. An empty collection sends no PUT and cannot establish synced status. Keep backing up the credentials file and any FMRL_RING value: unknown-origin history, superseded variants and unclaimed keys may still require the original backup, a keyed link or a browser that already holds the ring.
Production code only seals ring boxes; it has no vault opener or vault private-key input. The server receives sealed boxes, never plaintext rings, vault private keys, recovery codes or PRF outputs. Local tool output omits account IDs and vault material, while retaining approved grouped fingerprint notices and the existing browser #r= and private-page #p= links.
Ring uploads include the validated, pinned fingerprint used to seal every box. A server key change returns 409 vault_changed; the client never automatically retries. 400 bad_request stops the pass without isolation. account_vault: null preserves whoami identity/quota/link data but leaves vault sync unknown with a fixed diagnostic.
License
MIT, Too Great LLC.
Identity-server compatibility release hold
The approved sequence is to ship the compatibility bridge before the identity-server cutover. The bridge supports both server contracts so clients can update while the legacy server is still running. Package release is not yet approved: merge, version bump, package publication and production cutover each remain behind their applicable approval gates. A new package version merged to main publishes automatically; this documentation is not authorization to do so.
For editing someone else's page, supply its page ID or URL as id and its recovery token or /c/<token> link separately as manage_token. A recovery link does not identify the page: ask its sender for the page URL too. The plugin never opens or spends a recovery link to discover the page. Recovery grants management and editing, never deletion. Private page keys remain in the page URL's #p= fragment and on this machine.
Transitional server compatibility
The compatibility bridge accepts both legacy browser-link fields (linked_at,
link_url, and older editor name) and identity fields (attached_at,
attach_url, label/display_name, and publish recovery). Linking a browser is
not reported as attaching an identity. A missing recovery state is unknown;
spent or revoked links are not advertised as usable or saved for later edits.
Legacy management links keep their existing local token handling. The bridge
never opens a recovery link to find a page or replaces an attach link automatically.
Courtesy attach links seen during setup, status probes, or vault checks stay in process memory per API origin and credential for at most one hour. Publish and whoami can show that previously supplied link with the local ring fragment. A reported attachment clears it. Restarting loses this cache; another process or a replacement link can also make a cached link unusable. No capability is persisted or minted to repair that situation.
HTTP responses are projected onto closed MCP schemas; declared fields still
validate. A successful publish with an invalid response, or a timeout with an
uncertain outcome, must not be automatically republished. Use fmrl_list and the
saved page information to reconcile first. Publish idempotency remains absent:
this client sends no Idempotency-Key.
Before cutover, obtain the separate bridge release approval, publish the approved
version, and have clients update and restart/reconnect. Verify the running
fmrl_status version, not just the installed package: publishing does not replace
an already running MCP process or its cached schemas. Only then assess the
cutover readiness gates and seek the separate cutover approval. This order does
not prove that every client has updated. An old process can still reject a
new-server response after a write succeeds; reconcile rather than automatically
republishing. Passing tests or implementation review does not authorize a merge,
package release, deployment or cutover.
Source: packages/mcp/README.md at commit 4de72da
Tools
0Version history
1- v0.17.5LatestNov 8, 2026
Score
50% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts