Back to Browse

Artifacts Server MCP Server

Developer ToolsModerate5.2MCP RegistryLocalRemote
Free

Server data from the Official MCP Registry

Publish what Claude makes (HTML, PDF, small site) to a private link only chosen people can open.

About

Publish what Claude makes (HTML, PDF, small site) to a private link only chosen people can open.

Remote endpoints: streamable-http: https://mcp.rtfx.pro/mcp

Security Report

5.2
Moderate5.2Moderate Risk

This is a publishing MCP server for rtfx.pro/self-hosted artifacts-server that authenticates via a scoped bearer token from an environment variable, with no hardcoded credentials and a closed schema for tool inputs. The main considerations are the network access to the configured endpoint, the filesystem reads needed to package bundles, and the optional update_access tool that changes artifact visibility, which is gated behind an environment variable. The visible code shows no exfiltration or shell execution; the truncated portions were not reviewed. Supply chain analysis found 9 known vulnerabilities in dependencies (1 critical, 1 high severity).

5 files analyzed ยท 13 issues found

Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.

Permissions Required

This plugin requests these system permissions. Most are normal for its category.

File System Read

Reads files on your machine. Normal for tools that analyze or process local data.

File System Write

Writes or modifies files on your machine. Check that this is expected for the tool.

HTTP Network Access

Connects to external APIs or services over the internet.

env_vars

Check that this permission is expected for this type of plugin.

process_spawn

Check that this permission is expected for this type of plugin.

What You'll Need

Set these up before or after installing:

Comma-separated emails with admin rights.Optional

Environment variable: ADMIN_EMAILS

Verified sender address for OTP/magic-link email. Must match the Email Sending binding.Optional

Environment variable: MAIL_FROM

ARTIFACTS_URLRequired
RTFX_API_TOKENRequired

How to Install & Connect

Available as Local & Remote

This plugin can run on your machine or connect to a hosted endpoint. during install.

Documentation

View on GitHub

From the project's GitHub README.

artifacts-server

Private, access-gated hosting for landing pages and HTML/Claude artifacts, running entirely on Cloudflare Workers. A public product site at / (plus /docs, /signup and /login) explains the product and lets people start on the Free plan. Sign-in is app-owned and passwordless: rtfx.pro emails a one-time code or magic link, then a host-only rtfx_session keeps the browser signed in. One dashboard at /admin handles publishing, sharing and the gallery of everything shared with you. Artifacts โ€” single HTML files or multi-file static bundles โ€” are published from a web dashboard, a CLI, or an agent session (Claude Code, Hermes). With per-artifact permissions and versioning.

  • ๐Ÿค– Agent-native publishing โ€” Claude Code, a native MCP server, Hermes, the CLI and the HTTP API all take the same path a human takes; no separate, weaker agent route. See plugins/rtfx-local and docs/MCP.md.
  • ๐Ÿ‘ฅ Access by identity first โ€” each artifact is private, shared with named people, or open to all signed-in users. Unauthorized and non-existent both return 404.
  • ๐Ÿ”— Revocable share links โ€” for someone who will not have an account, create a capability URL for exactly one artifact, optionally expiring in 1โ€“365 days. Only a hash is stored.
  • ๐Ÿ•“ Versioning โ€” every re-publish is a new immutable version; roll back within your plan's retention window (free keeps the last 5; paid plans keep everything).
  • ๐Ÿ“ˆ Views log + read receipts โ€” see who viewed each artifact, when, which version, and from where, with an email the first time each named recipient opens it.
  • ๐Ÿข Workspaces & roles โ€” artifacts belong to an account with owner/admin/member/viewer roles; instance privilege is re-derived from config, never read from a table.
  • ๐Ÿ”— Canonical workspace addresses โ€” every workspace has an address (generated as w-xxxxxxxx; a paid workspace can claim a custom one) and every artifact link is rtfx.pro/<workspace>/<artifact> โ€” e.g. rtfx.pro/yogev/q3-board-report. It is the only URL the product shows or returns: the viewer renders on the app host and frames the sandboxed content origin, which is never an address. Old a.rtfx.pro/<slug>/ links redirect browsers to it. A path on the app host, not a custom domain.
  • ๐ŸŒ Public product site โ€” /, /docs, /signup, /login, /privacy and /terms are reachable by anyone, with SEO metadata, sitemap.xml, robots.txt and llms.txt; everything else needs an identity.
  • ๐Ÿ”’ Access-gated dashboard โ€” app-owned email OTP/magic-link sign-in for /admin and the API; the app stores no passwords.
  • ๐Ÿ–ผ๏ธ One dashboard โ€” publish and manage under Artifacts; everything shared with you under Gallery. Same shell, same nav, same brand.
  • ๐Ÿ”‘ API tokens โ€” hashed bearer tokens for server-to-server publishing (Hermes Cloud, CI), scoped, owner-bound and revocable.
  • โ˜๏ธ All Cloudflare โ€” Worker + R2 (files) + D1 (metadata). No servers, no database to run.

Stack: TypeScript ยท Hono ยท Cloudflare Workers / R2 / D1 / Email Sending ยท Lemon Squeezy

Not built yet, and deliberately not implied anywhere in the copy: per-link passwords, custom domains for artifacts (branded workspace addresses are a path on the app host, not your own hostname), comments/approvals, a public gallery of artifacts, usage-based billing, and per-seat billing beyond the fixed seats included in each plan. Access is by identity first; share links are separate capability URLs with optional expiry and immediate revocation. The competitive reasoning, and the full table-stakes-vs-differentiators split, is in docs/POSITIONING.md. The public site is one page: rtfx.pro โ€” connect the MCP server, then publish, share, delete.


How it works

                    /, /docs, /signup, /login and legal pages (public)
                                        โ”‚
Browser / CLI โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ  Worker (Hono)
                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ app-owned email OTP / magic link โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚
                    โ”‚  rtfx_session cookie + users/accounts tables    โ”‚โ”€โ”€โ”€โ”€โ”˜
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            files ยท /admin ยท /api                          โ”‚
                        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”‚
                        โ–ผ                       โ–ผ                    โ–ผ      โ”‚
                  R2  (files at            D1 (metadata:        Email +     โ”‚
                  <slug>/v<N>/โ€ฆ)           artifacts, grants,   billing     โ”‚
                                           versions, sessions)  webhooks    โ”‚
  • /, /signup, /login, /docs, /privacy, /terms, robots.txt, sitemap.xml and llms.txt are public product/crawler pages.
  • rtfx.pro sessions authenticate dashboard/API/artifact requests with a signed rtfx_session cookie created after email-code or magic-link verification.
  • The Worker authorizes per-artifact (who sees what), serves the current version of each artifact, renders the public site and the dashboard, and exposes a JSON API.
  • R2 stores files under <slug>/v<N>/โ€ฆ; D1 stores metadata.

See docs/ARCHITECTURE.md for details.

Prerequisites

  • Node.js 18+
  • A Cloudflare account with a domain (zone) on the account (you'll serve from a hostname you control, plus a separate content hostname if you want the same isolation as rtfx.pro).
  • Cloudflare Workers, R2, D1 and Email Sending enabled.
  • npx wrangler login (authorizes Workers/R2/D1/deploy)

Quick deploy

git clone https://github.com/yogevgab/artifacts-server.git
cd artifacts-server
npm install
npx wrangler login

npm run setup

npm run setup is the simple, single-hostname path: it creates the R2 bucket + D1 database, applies the schema, fills the basic Worker config, deploys, and leaves you to add production-only choices such as a separate content hostname, Email Sending, billing secrets and legal values. For a multi-hostname deployment like rtfx.pro, use docs/SELF_HOSTING.md plus the manual steps below instead of relying on the setup script.

When it finishes, configure Email Sending and SESSION_SECRET, then open https://<your-domain>/signup or /login to create the first account. ADMIN_EMAILS in wrangler.jsonc decides who gets platform-admin rights.

Manual deployment

Deploying with a separate content-only hostname (multiple routes entries, e.g. app + content-host isolation)? npm run setup only supports a single hostname โ€” see docs/DEPLOY_RTFX.md for a worked example runbook.

npm install
npx wrangler login

# 1. Storage
npx wrangler r2 bucket create artifacts-files
npx wrangler d1 create artifacts-meta        # copy the database_id into wrangler.jsonc
npx wrangler d1 execute artifacts-meta --remote --file schema.sql

# 2. Edit wrangler.jsonc: set route patterns to your app/content hostnames,
#    ADMIN_EMAILS, PUBLIC_BASE_URL, CONTENT_HOSTNAMES and the database_id.

# 3. Required secrets / mail
npx wrangler secret put SESSION_SECRET
# Optional, only if selling paid plans:
# npx wrangler secret put LEMONSQUEEZY_WEBHOOK_SECRET

# 4. Deploy (creates the custom domains)
npx wrangler deploy

Email Sending is required for sign-in. Enable it for the domain, verify SPF/DKIM/DMARC, and keep MAIL_FROM inside the Worker send_email.allowed_sender_addresses. The app sends a one-time code or magic link, then issues its own host-only rtfx_session cookie. Fresh deployments do not need Cloudflare Access.

Configuration

All config lives in wrangler.jsonc (vars) plus one secret. See the comments there.

SettingWhat it is
routes[0].patternHostname to serve from (a zone on your account).
ADMIN_EMAILSComma-separated emails with admin rights.
SUPER_ADMIN_EMAILS (optional)The operator/owner account(s). A super admin may manage other admins, and can never be paused or removed โ€” the anti-lockout invariant. Defaults to the first ADMIN_EMAILS entry, so every deployment has one.
MAIL_FROMVerified sender address for OTP/magic-link email. Must match the Email Sending binding.
SESSION_SECRET (secret)At least 32 bytes; signs the app-owned rtfx_session cookie.
LEMONSQUEEZY_WEBHOOK_SECRET (secret, optional)Verifies billing webhooks when paid plans are enabled.
PUBLIC_BASE_URL (optional)Canonical public origin, e.g. https://rtfx.pro. Canonical links, OpenGraph URLs, sitemap.xml and llms.txt are absolute against it, and any other hostname serves a disallow-everything robots.txt. Defaults to https://rtfx.pro (SITE.origin in src/seo.ts).
CONTENT_HOSTNAMES (optional)Hostnames that serve artifact files only โ€” no dashboard, API or product pages.

Usage

Public product site

https://<your-domain>/ โ€” public, no login required. Positions the product, covers use cases and differentiators, and collects /waitlist access requests. Its two CTAs are deliberately distinct: Request access (for people without an account) and Sign in (/login, for people with one). /docs is the public documentation page (publishing, Claude Code/Hermes, the access model, #why-rtfx, FAQ). See docs/PUBLIC_SITE.md for the SEO/crawler surface and the copy rules, and docs/POSITIONING.md for what the copy may claim.

Sign-in

https://<your-domain>/login โ€” public, app-owned sign-in. It emails a one-time code or magic link, verifies it, then sets a host-only rtfx_session cookie. It renders signed-out, already signed-in and paused-account states. There is no password auth and no Cloudflare Access dependency in a fresh deployment.

Dashboard

https://<your-domain>/admin โ€” publish artifacts, manage per-artifact access, upload new versions / roll back, and (admins only) manage people. Every user, admins included, sees only the artifacts they own or belong to; platform admins get no access to other people's artifact content, versions, view log, access list or share links. The Platform section (super admin) lists every artifact as metadata only (owner, size, counts, dates) and offers an audited abuse-delete. The Gallery section at /admin/gallery is filtered to what each viewer may open โ€” what they own plus what has been shared with them. /gallery is kept as a redirect into it; visiting it signed out goes to /login.

People (user management)

Admin-only, in the dashboard and at /api/users. The app owns identity with signed sessions and stores account/user state in D1:

LayerHoldsSource of truth for
rtfx_session cookieSigned email/account identityWho this browser request is
users / accounts tablesstatus, display name, workspace membership, roles and audit stateWhether this app serves them and what they can manage
ADMIN_EMAILS / SUPER_ADMIN_EMAILSPlatform privilegeWho is an operator/admin for the whole instance

The Worker re-derives platform privilege from config, never from a user-writable table. Lifecycle actions can pause/re-enable/remove accounts and revoke API tokens, but API tokens are refused from user-management routes entirely.

CLI

export ARTIFACTS_URL=https://<your-domain>
# One credential: the artifact commands go to /api/machine/โ€ฆ, which authenticates
# this bearer token and nothing else.
export RTFX_API_TOKEN=<rtfx_โ€ฆ token>

node cli/artifacts.mjs publish ./page.html --slug my-page --title "My Page"
node cli/artifacts.mjs publish ./site/ --slug demo --title "Demo"   # a folder is zipped
node cli/artifacts.mjs list
node cli/artifacts.mjs publish ./page-v2.html --slug my-page --note "new hero"  # new version
node cli/artifacts.mjs versions my-page
node cli/artifacts.mjs rollback my-page 1
node cli/artifacts.mjs grant my-page alice@example.com
node cli/artifacts.mjs views my-page   # total/unique + recent views log
node cli/artifacts.mjs users                     # directory with role + status
node cli/artifacts.mjs user-add bob@example.com  # invite
node cli/artifacts.mjs user-disable bob@example.com  # pause + revoke their tokens
node cli/artifacts.mjs user-enable bob@example.com

node cli/artifacts.mjs token-create "hermes-cloud" --owner alice@example.com --scopes read,publish
node cli/artifacts.mjs tokens
node cli/artifacts.mjs token-revoke <token-id>

token-* and user-* require an app session with the right platform/workspace role โ€” an API token can't mint or revoke tokens, or change who may sign in.

Remote MCP server (hosted)

rtfx.pro is a remote MCP server. Add it to Claude (claude.ai, Claude Desktop and mobile use the same flow: Customize โ†’ Connectors โ†’ + Add โ†’ Add custom connector) and ask Claude to publish, share and delete. Step by step with screenshots: rtfx.pro/guide.

  • Endpoint: https://mcp.rtfx.pro/mcp (Streamable HTTP)
  • Auth: OAuth 2.1 with discovery, dynamic client registration and client ID metadata documents (CIMD); nothing to paste. Scopes: rtfx:read, rtfx:publish, rtfx:manage.
  • Claude Code: claude mcp add --transport http rtfx https://mcp.rtfx.pro/mcp

The hosted server publishes content sent inside the tool call; it cannot read a path on your disk (use the local plugin below for that). Tools (REMOTE_TOOLS in src/mcp.ts):

ToolWhat it does
publishPublish an artifact from content carried in the request (one HTML page or PDF, or a small multi-file site) and return its stable URL; the same slug appends a new version.
create_upload_linkReserve the destination and return a single-use upload URL for a site too big for publish or containing images, video or other binary files.
list_artifactsList the artifacts the credential can manage (slug, title, URL, type, visibility, live version, size, last update), newest first and paginated.
artifact_detailsEverything known about one artifact: URL, full version history, who it is shared with (viewers and editors) and how often it has been opened.
artifact_statisticsAggregate numbers: versions, files, bytes and views, for one artifact or across everything the credential can reach.
share_artifactReplace who may open an artifact: restricted to named viewers and editors, or everyone in the workspace. Needs the manage scope.
rollback_artifactPoint an artifact's URL back at one of its earlier versions; non-destructive. Needs the publish scope.
delete_artifactPermanently delete an artifact: every version, file, access grant and share link. Requires confirm_slug; needs the manage scope.
doctorReport how this connection is authenticated and whether the instance answers; publishes nothing.

Claude Code plugins

This repository is a Claude Code marketplace with two plugins:

  • rtfx (listed in Anthropic's directory) is remote-only: a skill plus the hosted MCP server at https://mcp.rtfx.pro/mcp. /plugin install rtfx@rtfx, then /mcp to sign in. It publishes content Claude sends; it cannot read your disk. See plugins/rtfx.
  • rtfx-local is the full local tooling (below): publish a folder, build output or zip from disk by path. It is installed from this marketplace, not from the directory.
rtfx-local (local, stdio)

Installing rtfx-local makes publishing part of the conversation rather than a separate step:

/plugin marketplace add yogevgab/artifacts-server
/plugin install rtfx-local@rtfx

Then sign in from the session โ€” no token to copy, paste or store:

/rtfx-local:login

That runs an OAuth authorization-code flow with PKCE against the instance, on a loopback redirect, and writes a 0600 credential to ~/.config/rtfx/credentials.json (refresh tokens rotate; /rtfx-local:logout revokes both tokens and deletes it). To use an API token instead, enter it in the plugin's sensitive API token option (/plugin, rtfx, Configure); the MCP tools use it in preference to the stored sign-in. The plugin does not read RTFX_API_TOKEN from your shell, and the slash commands use the browser sign-in only. Self-hosting: set the plugin's rtfx endpoint option (MCP tools) and also export ARTIFACTS_URL=https://your-instance in the shell that starts Claude Code (slash commands); the endpoint must be https.

Skill publishing-to-rtfxLoads on its own when someone says "publish this" / "ship it".
/rtfx-local:publish [path] [slug]Publish or re-publish, then report the URL.
/rtfx-local:list ยท /rtfx-local:versions ยท /rtfx-local:rollbackInventory, history, and going back.
/rtfx-local:login ยท /rtfx-local:logoutBrowser sign-in, and revoking it.
/rtfx-local:setupCheck credentials and connectivity (prints a token's id, never the token).

The publisher (plugins/rtfx-local/scripts/rtfx.mjs) is dependency-free Node 18+, so it also works as a plain CLI on a machine that has never checked this repo out. It refuses to upload .env, *.pem, *.key and similar, and skips .git/node_modules, printing everything it left out.

This works today and needs nobody's approval โ€” any repository with a valid .claude-plugin/marketplace.json is a Claude Code marketplace. The plugin is not listed in Anthropic's community or official marketplace; what a submission to the first would need is written down in docs/ANTHROPIC_PLUGIN_SUBMISSION.md.

Details, testing and design notes: docs/CLAUDE_CODE.md. Release notes: plugins/rtfx-local/CHANGELOG.md.

Claude Desktop Extension

Download it from the current release or build it locally:

https://github.com/yogevgab/artifacts-server/releases/download/v1.2.0/rtfx.dxt
npm run dxt:pack
open dist/rtfx.dxt

That installs the same local MCP server without hand-editing claude_desktop_config.json. Because it runs on the user's machine, it can publish local paths/folders. Leave the optional API token blank when using the browser OAuth credential store; expose access management only when explicitly needed. Full details: docs/CLAUDE_DESKTOP.md.

Local MCP server (stdio alternative)

The hosted server above is the default. The plugin also ships a native local MCP server (plugins/rtfx-local/scripts/rtfx-mcp.mjs), so a client with no shell to run a command in โ€” Claude Desktop, or anything else that speaks MCP โ€” publishes through tool calls instead. Installing the plugin registers it; for a manual Claude Desktop setup, point claude_desktop_config.json at the script:

{
  "mcpServers": {
    "rtfx": {
      "command": "node",
      "args": ["/absolute/path/to/plugins/rtfx-local/scripts/rtfx-mcp.mjs"],
      "env": { "RTFX_API_TOKEN": "rtfx_โ€ฆ" }
    }
  }
}

Tools: publish (with a dry_run that uploads nothing), list_artifacts, get_versions, rollback, doctor, and update_access behind an opt-in env var. Same token, same scopes, same bundle filters โ€” it is a wrapper over the same libraries as the CLI, not a second implementation. Zero dependencies, no MCP SDK, Node 18+.

Tool schemas, client configuration and when to use the plugin instead: docs/MCP.md.

API tokens (server-to-server)

Automated publishers โ€” Hermes Cloud, CI, scripts โ€” authenticate with a hashed API token sent as Authorization: Bearer <token>, instead of a browser login:

curl -X POST "$ARTIFACTS_URL/api/machine/artifacts" \
  -H "Authorization: Bearer $RTFX_API_TOKEN" \
  -F "slug=my-page" -F "title=My Page" -F "file=@./page.html;type=text/html"
  • Only a SHA-256 hash of each token is stored; the plaintext is shown once, at creation.
  • Every token has an owner and so inherits that person's ownership rules โ€” an admin token manages everything, a user's token only their own artifacts.
  • Scopes (read, publish, manage) narrow a token below its owner's rights; they never widen anyone's. Default is read,publish, so a publishing integration can't delete.
  • Tokens are revocable (token-revoke), can carry an expiry, and are revoked automatically when their owner is removed from rtfx.pro.

Two surfaces, on purpose. /api/โ€ฆ is the dashboard's browser/session API: the app-owned rtfx_session identifies you and ordinary role checks decide what you may do. /api/machine/โ€ฆ is the same artifact surface for machines โ€” publish, list, versions, rollback, views, sharing, delete โ€” behind a stricter gate that requires a bearer token and refuses a browser session outright (requireApiToken in src/auth.ts). User management, token issuance and workspace membership are deliberately not mounted there: they require a signed-in app session with the right role, and refuse API tokens whatever the path.

Full request/response contract, error codes and rollback flow: docs/HERMES_CLOUD.md.

Permissions

The app decides who is signed in by verifying an emailed code or magic link and setting an rtfx_session cookie. The Worker decides who sees each artifact: restricted (only granted emails) or everyone (everyone in the artifact's workspace). Platform admins see metadata only, never content. New artifacts are private by default. A direct URL a viewer lacks access to returns 404.

Ownership. Every artifact belongs to the person/workspace that published it (artifacts.owner_email / artifacts.account_id). Instance admins (ADMIN_EMAILS / SUPER_ADMIN_EMAILS) manage everything; ordinary signed-in members manage the artifacts their workspace role allows โ€” their dashboard, /api/artifacts list, version previews and analytics are scoped to artifacts they own/manage. Attempts to read or change someone else's artifact return 404, so a slug they don't own is indistinguishable from one that doesn't exist. Being granted view access never confers management rights, and publishing to a slug someone else owns is refused (409 slug_taken) rather than adding a version to their artifact. Account/user management is admin-only, and API tokens are deliberately refused from those routes.

Artifacts with no owner (published before this model, or by a legacy service token with no email) are manageable by admins only. Run migrations/0005_owner_email.sql on an existing database; it backfills owners from created_by where that was a real email. API tokens live in migrations/0006_api_tokens.sql, and the local user/account tables in 0007 onward are additive.

Accounts / workspaces. An artifact also belongs to an account โ€” the workspace that owns it, and later the thing a plan is billed to (artifacts.account_id). Every person gets a personal workspace automatically; a team workspace can have several members with an account role of owner, admin, member or viewer. member and up manage the workspace's artifacts; a viewer can open them but not change them.

Four ideas are kept apart on purpose, and it is worth reading the row you care about twice:

AnswersComes from
Identitywho you arertfx_session + users
Accountwhose artifacts these areaccounts
Membershipwhat you may do in one workspaceaccount_members
Instance rolewhat you may do to this deploymentADMIN_EMAILS / SUPER_ADMIN_EMAILS

Being owner of a workspace is not being an admin of the instance, and there is no way to become one by writing to the database: instance privilege is re-derived from configuration on every request and is never read from a table. That is the property the test suite guards hardest.

This is entirely additive. account_id is nullable everywhere, owner_email is still checked first, and an artifact the backfill never adopted behaves exactly as it did before. Run migrations/0008_accounts.sql, 0009_account_links.sql and 0010_backfill_accounts.sql on an existing database โ€” 0008 and 0010 are safe to re-run, 0009 adds two columns and is not (check PRAGMA table_info(artifacts) first). None of them is strictly required: the Worker provisions the same rows on first use. See docs/ARCHITECTURE.md for the full model.

Versioning

Each publish to an existing slug creates a new immutable version and makes it live. On the free plan the five most recent versions are retained and older ones expire โ€” their bytes are removed but the history entry stays, so a version list never has holes in it. Paid plans keep every version. Previous versions are kept. Admins preview any version at /v/<slug>/<n>/; roll back from the dashboard or rollback <slug> <n>.

Views log

Each artifact records a view when a signed-in person loads an HTML page (assets, machine/ service-token fetches, and admin version previews aren't counted). The admin dashboard and views <slug> show total/unique counts and a recent log (time ยท viewer ยท version ยท country). Views are retained indefinitely; prune the artifact_views table if it grows large.

Development

npm install
npm run dev        # wrangler dev on http://localhost:8787 (DEV_LOGIN: no sign-in, you are admin)
npm test           # vitest (unit + integration via @cloudflare/vitest-pool-workers)
npm run typecheck
npm run validate:plugin  # structural check of the Claude Code plugin files
npm run check      # typecheck + tests + plugin validation

Locally there is no real email challenge. To simulate a specific viewer, send an X-Dev-Email header; to simulate a signed-out visitor (e.g. to see /gallery redirect to /login), send X-Dev-Anonymous: true. Both are honored only when DEV_LOGIN=true, which npm run dev sets โ€” never in production.

# once, seed the local DB:
npx wrangler d1 execute artifacts-meta --local --file schema.sql

Contributing

Issues and PRs welcome โ€” see CONTRIBUTING.md. Please run npm run check before opening a PR. Security reports: see SECURITY.md โ€” GitHub Security Advisories, never a public issue.

Self-hosting

Everything needed to run your own instance is in this repository; you supply your own Cloudflare account, R2/D1, mail path, session secret, optional Lemon Squeezy billing config, and your own legal values โ€” the /privacy and /terms pages ship as an operator template and say so on the page. See docs/SELF_HOSTING.md.

Open source, and where the line is

The source is MIT and public on purpose: an access-control product should let you read the code that enforces the access. The Worker, the plugin, the local and remote MCP servers, the CLI, the tests and the docs are all here, and the parts that run on your own machine are not held back.

The hosted rtfx.pro service is operated separately from this source. Its customer data, live account configuration, support and billing pipelines and commercial materials are not in this repository โ€” and the name, mark and domain are not part of the MIT grant, which is a copyright licence and does not license trademarks. Fork it and run it; please call it your own thing.

The full boundary โ€” what is intentionally public, what stays out, and why โ€” is in OPEN_SOURCE.md. The threat model, the plugin's credential handling and the local-vs-remote MCP boundary are in SECURITY.md.

License

MIT

Reviews

No reviews yet

Be the first to review this server!