plsreadme
The plsreadme server lets you share, manage, and track markdown documents as permanent, beautifully rendered web pages directly from your AI editor or agent.
Share documents: Upload local markdown files or plain text as permanent shareable URLs (
plsrd.me/v/xxx); plain text is auto-formatted into clean markdown via AI conversionUpdate & delete: Replace content or permanently remove shared documents using their ID or file path; admin tokens are resolved automatically from the local
.plsreadmerecordTrack shared links: List all documents tracked locally with their IDs, titles, URLs, and source file paths
Version control: Access full revision timelines, restore previous snapshots (archive-first, non-destructive), and manage revision history
Collaboration: Enable inline paragraph comments with review modes (Current draft vs. Timeline)
Authentication: Clerk-based user ownership, dashboard access, and legacy anonymous link claiming
Raw access: Download original markdown from any shared link
Rendering: Mobile-responsive pages with clean typography and dark mode support
MCP compatibility: Works with Claude, Cursor, VS Code, and other AI editors
Rate limits: Upload (30/hr), update/restore (60/hr), AI convert (10/hr)
Integrates with Clerk for user authentication, managing document ownership, and facilitating the claiming of legacy anonymous links.
Supports document ownership and user identity management through GitHub-based authentication.
Supports document ownership and user identity management through Google-based authentication.
Converts Markdown text or files into shareable, rendered web pages with features like dark mode, version history, and inline commenting.
The Problem
You wrote a README, a PRD, meeting notes, or an API doc in markdown. Now you need to share it with someone who doesn't have a markdown renderer, doesn't use GitHub, or just needs a clean link they can open in a browser.
plsreadme turns any markdown into a permanent, beautifully rendered web page in one step. No accounts. No sign-ups. No friction.
✨ Features
Instant sharing — Paste markdown or upload a file, get a
plsrd.melinkBeautiful rendering — Clean typography, dark mode, mobile-responsive
Inline comments — Readers can click any paragraph and leave feedback
Review mode (current vs timeline) — Multi-version docs default to Current draft feedback with one-click access to full Timeline history
AI auto-formatting — Throw raw text at it; it comes out as clean markdown
MCP server — Share docs directly from Claude, Cursor, VS Code, or any MCP client
OpenClaw skill — Available on ClawHub for AI agent workflows
Short links — Every doc gets a compact
plsrd.me/v/xxxURLRaw access — Download the original
.mdfile from any shared linkVersion timeline + safe restore —
/v/:id/versions+/v/:id/history+ archive-first restore API for fast rollbackClerk auth foundation — GitHub/Google sign-in wiring + Clerk-hosted email fallback + backend auth verification utilities
Ownership model (Phase 2) — docs can be linked to a Clerk user (
owner_user_id) while preserving anonymous flowsMy Links dashboard (Phase 3) — authenticated
/my-linkspage with search/sort/pagination and quick copy/open actionsLegacy link claiming (Phase 4) — signed-in users can claim older anonymous links by proving the original
admin_tokenZero config website demo — No account or API key needed to try it in the browser
🚀 Quick Start
Web
Go to plsreadme.com, paste your markdown, click share.
Auth Paths And Rollout State
Recommendation order:
Try in browser first — fastest demo path, no MCP setup required.
Use hosted remote MCP with browser login when client support is verified.
Use API key / local MCP fallback when interactive login is unavailable.
Current rollout state:
Journey | Status today | Ownership rule | Source tag |
Anonymous website demo | Available now via browser-verified demo flow |
|
|
Signed-in website create | Available now | doc is created with the signed-in Clerk user as owner |
|
Hosted remote MCP with browser login | Available now in supported clients | creates owned docs for the signed-in user after browser login |
|
Hosted remote MCP with API key | Available now as the compatibility fallback | creates owned docs for the API key owner |
|
Local npm MCP with API key | Available now and recommended for local stdio setups | creates owned docs for the API key owner |
|
Local npm MCP anonymous fallback | Still available only with explicit opt-in | remains anonymous unless later claimed/saved |
|
Hosted remote MCP rollout notes:
https://plsreadme.com/mcphttps://plsreadme.com/sse
Those hosted remote MCP routes are live behind OAuth-protected browser login in code, including /authorize, /oauth/token, and /oauth/register.
Operational notes:
D1
doc_create_eventsis the canonical create-attribution table across web, hosted MCP, and local MCP flows.docs.raw_view_counttracks every render hit, whiledocs.view_countis reserved for likely-human reads.See
docs/runbooks/auth-surface-monitoring.mdfor the production query set and response steps.access tokens last about
1 hourrefresh tokens last about
30 daysreconnecting the same client replaces the older grant
signing out of the website does not revoke an existing editor grant by itself
this repo is now wired to a dedicated Cloudflare Workers KV binding named
OAUTH_KV
When browser login is not available in your client, create a personal API key from /my-links and use either the hosted remote header fallback or the local npx -y plsreadme-mcp package.
Website demo trust model today:
anonymous website creates on
/api/create-linkrequire a short-lived browser verification grantsigned-in website creates skip that grant and stay friction-light
post-create UI now branches into
Save to my account,Connect your editor, andCopy link
API
curl -X POST https://plsreadme.com/api/render \
-H "Content-Type: application/json" \
-d '{"markdown": "# Hello World\n\nThis is my doc."}'{
"id": "abc123def456",
"url": "https://plsreadme.com/v/abc123def456",
"raw_url": "https://plsreadme.com/v/abc123def456/raw",
"admin_token": "sk_..."
}Save the admin_token — you'll need it to edit or delete:
# Update
curl -X PUT https://plsreadme.com/v/abc123def456 \
-H "Authorization: Bearer sk_..." \
-H "Content-Type: application/json" \
-d '{"markdown": "# Updated content"}'
# Delete
curl -X DELETE https://plsreadme.com/v/abc123def456 \
-H "Authorization: Bearer sk_..."Version timeline + safe restore
Use the timeline endpoint to review revision context during AI iteration cycles:
curl https://plsreadme.com/v/abc123def456/versions{
"id": "abc123def456",
"current_version": 5,
"total_versions": 5,
"versions": [
{ "version": 5, "is_current": true, "raw_url": "https://plsreadme.com/v/abc123def456/raw" },
{ "version": 4, "is_current": false, "raw_url": "https://plsreadme.com/v/abc123def456/raw?version=4" }
]
}If an AI edit regresses the doc, restore a prior snapshot (archive-first, non-destructive):
curl -X POST https://plsreadme.com/v/abc123def456/restore \
-H "Authorization: Bearer sk_..." \
-H "Content-Type: application/json" \
-d '{"version": 4}'Restore is rate-limited similarly to updates (currently 60/hour per actor key) to reduce abuse.
For docs owned by an authenticated Clerk user, update/delete/restore also require that owner session (to prevent cross-user mutation), while anonymous docs continue to work with admin_token only.
Review mode usage notes (Current draft first, Timeline on demand)
The document viewer now exposes comment review controls:
Current draft — shows only comments tied to the latest doc version (default when a doc has multiple versions).
Timeline — shows the full cross-version comment history.
You can fetch the same modes directly from the API:
# Latest-version comments only
curl "https://plsreadme.com/api/comments/abc123def456?view=current"
# Full timeline comments (default API behavior)
curl "https://plsreadme.com/api/comments/abc123def456?view=all"Viewer links persist the mode in the URL for shareable review context:
https://plsreadme.com/v/abc123def456?view=currenthttps://plsreadme.com/v/abc123def456?view=timeline
To claim a legacy anonymous link into your signed-in account:
curl -X POST https://plsreadme.com/api/auth/claim-link \
-H "Authorization: Bearer <clerk-session-jwt>" \
-H "Content-Type: application/json" \
-d '{"id":"abc123def456","adminToken":"sk_..."}'MCP (AI Editors)
Current recommendation today:
use hosted remote MCP with browser login when your client supports it cleanly
use personal API key fallback when remote auth is unavailable or awkward in that client
use the local
plsreadme-mcppackage withPLSREADME_API_KEYfor the safest stdio path
Connect your editor to plsreadme and share docs with natural language:
"Share this README as a plsreadme link" "Turn my PRD into a shareable page" "Make these meeting notes into a readable link"
MCP/agent auto-review loop with /versions
For iterative AI writing flows (draft → critique → revise), agents can consume /v/:id/versions as the source of truth:
Keep the canonical readable URL (
/v/:id) for humans.Poll
/v/:id/versionsbetween iterations.Compare
current_versionto the last reviewed version.If changed, fetch
raw_urlfor the newest version and run review checks.If quality regresses, optionally trigger
/v/:id/restorewith admin token + owner session.
This gives automation deterministic revision tracking without scraping HTML.
See docs/ai-iteration-versioning.md for a full playbook.
🔌 MCP Setup
Client compatibility matrix
Current as of April 5, 2026:
Client | Recommended path | Browser login support | API key fallback | Notes |
Claude Code | hosted remote MCP first | verified live | yes | best supported remote flow; local stdio with |
Cursor | hosted remote MCP first | documented, but build-dependent in practice | yes | use headers if your build does not surface the OAuth prompt |
VS Code | hosted remote MCP when available | configuration exists, rollout varies by build | yes |
|
Windsurf | hosted remote MCP when available | documented remote support | yes | use |
Claude Desktop | local npm MCP | no verified remote browser flow here | yes | prefer stdio + |
Raw HTTP / scripts | hosted remote header mode | no | yes | send |
Hosted Remote Login (supported clients)
Claude Code:
claude mcp add --transport http plsreadme https://plsreadme.com/mcpCursor:
{
"mcpServers": {
"plsreadme": {
"url": "https://plsreadme.com/mcp"
}
}
}VS Code:
{
"servers": {
"plsreadme": {
"type": "http",
"url": "https://plsreadme.com/mcp"
}
}
}Windsurf:
{
"mcpServers": {
"plsreadme": {
"serverUrl": "https://plsreadme.com/mcp"
}
}
}Lifecycle notes:
access token TTL is about
1 hourrefresh token TTL is about
30 daysreconnecting the same client replaces the older grant
sign out ends the website session but does not automatically revoke an existing editor grant
use
GET /api/auth/mcp-grantsandDELETE /api/auth/mcp-grants/:grantIdto audit or revoke hosted editor grants
If your client supports browser login, prefer this path. It is the cleanest setup and keeps owned docs tied to your website account automatically.
Hosted Remote API Key fallback
Create a personal API key from https://plsreadme.com/my-links first, then use one of these:
Claude Code:
claude mcp add --transport http \
--header "Authorization: Bearer $PLSREADME_API_KEY" \
plsreadme-api https://plsreadme.com/mcpCursor:
{
"mcpServers": {
"plsreadme-api": {
"url": "https://plsreadme.com/mcp",
"headers": {
"Authorization": "Bearer ${env:PLSREADME_API_KEY}"
}
}
}
}VS Code:
{
"inputs": [
{
"type": "promptString",
"id": "plsreadme-api-key",
"description": "plsreadme personal API key",
"password": true
}
],
"servers": {
"plsreadme-api": {
"type": "http",
"url": "https://plsreadme.com/mcp",
"headers": {
"Authorization": "Bearer ${input:plsreadme-api-key}"
}
}
}
}Windsurf:
{
"mcpServers": {
"plsreadme-api": {
"serverUrl": "https://plsreadme.com/mcp",
"headers": {
"Authorization": "Bearer ${env:PLSREADME_API_KEY}"
}
}
}
}Raw remote endpoint users:
curl -i https://plsreadme.com/mcp \
-H "Authorization: Bearer $PLSREADME_API_KEY"Local npm fallback
Claude Code:
claude mcp add --transport stdio \
--env PLSREADME_API_KEY=$PLSREADME_API_KEY \
plsreadme -- npx -y plsreadme-mcpCursor:
Add to ~/.cursor/mcp.json:
{
"mcpServers": {
"plsreadme": {
"command": "npx",
"args": ["-y", "plsreadme-mcp"],
"env": {
"PLSREADME_API_KEY": "${env:PLSREADME_API_KEY}"
}
}
}
}VS Code:
Add to .vscode/mcp.json:
{
"inputs": [
{
"type": "promptString",
"id": "plsreadme-api-key",
"description": "plsreadme personal API key",
"password": true
}
],
"servers": {
"plsreadme": {
"command": "npx",
"args": ["-y", "plsreadme-mcp"],
"env": {
"PLSREADME_API_KEY": "${input:plsreadme-api-key}"
}
}
}
}Claude Desktop:
Add to claude_desktop_config.json:
{
"mcpServers": {
"plsreadme": {
"command": "npx",
"args": ["-y", "plsreadme-mcp"],
"env": {
"PLSREADME_API_KEY": "<paste-your-personal-api-key>"
}
}
}
}Windsurf:
Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"plsreadme": {
"command": "npx",
"args": ["-y", "plsreadme-mcp"],
"env": {
"PLSREADME_API_KEY": "${env:PLSREADME_API_KEY}"
}
}
}
}Notes:
local stdio now expects
PLSREADME_API_KEYby default so new docs are ownedexplicit legacy anonymous mode still exists with
PLSREADME_ALLOW_ANONYMOUS=1create your key from https://plsreadme.com/my-links
Migrating existing anonymous MCP setups
If you already used plsreadme-mcp anonymously:
Create a personal API key from
/my-links.Add
PLSREADME_API_KEYto your MCP client config.Keep
PLSREADME_ALLOW_ANONYMOUS=1only as a temporary compatibility crutch for old workflows.Claim older anonymous links later with
/api/auth/claim-linkif you still have theiradmin_token.
The migration rule is simple:
new automated/editor creates should be owned by default
anonymous local MCP is now legacy-only and explicit
the website demo path remains zero-setup even while editor auth gets stricter
add-mcp
npx add-mcp plsreadme-mcpOpenClaw
clawhub install plsreadmeDocker (for MCP registries / listing checks)
Build and run the stdio MCP server in a clean container:
docker build -t plsreadme-mcp:local .
docker run --rm -i plsreadme-mcp:localThe containerized server uses stdio (no ports, no env vars required).
🛠 MCP Tools
Tool | What it does |
| Share a local file by path → returns shareable link. Re-sharing updates the same link. |
| Share markdown or plain text directly → returns shareable link |
| Update an existing doc with new content (by ID or file path) |
| Delete a shared doc permanently (by ID or file path) |
| List all documents you've shared from this project |
Prompts:
share-document— Guided flow to share content as a readable linkrefactor-and-share— Uses your AI model to refactor raw text into polished markdown, then shares it
Plain text input? No problem — the MCP auto-structures it into markdown, or you can use the refactor-and-share prompt to leverage your AI's reasoning for a polished result.
.plsreadme Record File
The MCP server tracks your shared documents in a .plsreadme JSON file in your project root. This stores document IDs, URLs, and admin tokens needed for editing and deleting.
⚠️ Add .plsreadme to your .gitignore — it contains admin tokens. The tool will warn you if it's missing.
🏗 Architecture
Built on Cloudflare's edge stack for speed everywhere:
┌─────────────┐ ┌──────────────────┐ ┌─────────┐
│ Web / API │────▶│ Cloudflare │────▶│ R2 │
│ MCP Client │ │ Workers (Hono) │ │ (docs) │
└─────────────┘ └──────────────────┘ └─────────┘
│
┌──────┴──────┐
│ D1 │
│ (metadata) │
└─────────────┘Hono — Lightweight web framework on Workers
Cloudflare D1 — SQLite at the edge for metadata, comments, analytics
Cloudflare R2 — Object storage for markdown documents
Durable Objects — Stateful MCP server endpoint
Workers AI — Optional fallback for text-to-markdown conversion
📁 Project Structure
plsreadme/
├── worker/
│ ├── index.ts # Main worker entry
│ ├── auth.ts # Clerk JWT verification utilities/middleware
│ ├── routes/
│ │ ├── auth.ts # Auth config/session/protected identity endpoints
│ │ ├── docs.ts # Document creation & rendering
│ │ ├── comments.ts # Inline commenting system
│ │ ├── convert.ts # AI text→markdown conversion
│ │ ├── analytics.ts # View tracking
│ │ ├── links.ts # Short link handling
│ │ └── waitlist.ts # Waitlist & notifications
│ ├── mcp-agent.ts # Remote MCP server (Durable Object)
│ └── types.ts # TypeScript types
├── packages/
│ └── mcp/ # npm package: plsreadme-mcp
│ └── src/index.ts # MCP server (stdio transport)
├── public/ # Static assets & landing pages
├── db/
│ └── schema.sql # D1 database schema
├── docs/
│ ├── ai-iteration-versioning.md # Version timeline/restore patterns for human + agent loops
│ ├── auth-clerk.md # Auth setup + environment checklist
│ └── runbooks/
│ └── legacy-link-claim-rollout.md
├── skill/
│ └── plsreadme/ # OpenClaw agent skill
└── wrangler.jsonc # Cloudflare Workers config🔧 Development
# Install dependencies
npm install
# Run locally
npm run dev
# Deploy
npm run deploy
# Bootstrap schema (fresh local DB)
npm run db:migrate:local
# Audit unapplied migrations (remote + local)
npm run db:migrations:status
# Apply migration files explicitly
npm run db:migrations:apply # remote
npm run db:migrations:apply:local # localOwnership phase migration notes:
wrangler.jsoncpointsmigrations_dirtodb/migrations, so migration status is auditable with explicit list/apply commands.Apply
db/migrations/004_owner_user_id.sqlin existing environments before relying on ownership filters.Apply
db/migrations/007_doc_attribution_telemetry.sqlbefore relying ondoc_create_eventsorraw_view_count.Legacy rows are intentionally backfilled as
owner_user_id = NULL(anonymous/public behavior preserved).Write routes still run a safe ownership schema ensure step (duplicate-column tolerant) for mixed-env rollout safety.
See
docs/migrations.mdfor the explicit audit/apply workflow.
MCP package release
plsreadme-mcp is published from packages/mcp by pushing an mcp-v* tag (see .github/workflows/publish-mcp.yml).
cd packages/mcp
npm version patch # or minor/major
cd ../..
git add packages/mcp/package.json packages/mcp/package-lock.json
VERSION=$(node -p "require('./packages/mcp/package.json').version")
git commit -m "chore(mcp): release v${VERSION}"
git tag "mcp-v${VERSION}"
# push commit + tag from your machine to trigger npm publish workflowEnvironment Variables
Start from .env.example and set values in your local/dev/prod environment.
Cloudflare tip: non-sensitive values can live in
vars; sensitive values should be set withwrangler secret put.
Variable | Required | Description |
| No | OpenAI key for |
| No | Waitlist signup notifications |
| No | New link creation notifications |
| No | Email notifications |
| No | Email recipient for notifications |
| For auth | Clerk publishable key for frontend auth wiring (social + email fallback) |
| For auth | Clerk JWT issuer used by worker verification |
| Optional | Expected audience claim for Clerk JWTs |
| Optional | Clerk-hosted sign-in URL hint (default |
| Optional | Clerk-hosted sign-up URL hint (default |
| Optional | Reserved for future server-side Clerk integrations |
If OAuth credentials are not configured yet, users can still click Sign in / Use email instead and complete auth through the Clerk-hosted email flow immediately.
Frontend auth shell notes:
/app.htmland/my-linksusepublic/clerk-auth-shell.js(Clerk-native browser SDK wiring).Authenticated frontend API calls should read bearer tokens through
window.plsreadmeGetAuthToken().
The core sharing functionality still requires zero configuration. Clerk auth, AI conversion, and notifications are opt-in.
For the full auth setup checklist, see docs/auth-clerk.md.
For rollout + smoke checks, see docs/runbooks/mcp-auth-rollout-checklist.md.
📊 Limits
Limit | Value |
Max document size | 200 KB |
Upload rate limit | 30/hour per actor key |
Update/restore rate limit | 60/hour per actor key |
AI convert rate limit | 10/hour per IP |
Link lifetime | Permanent |
🤝 Contributing
Feature ideas? Bug reports? Open an issue.
PRs welcome for bug fixes and improvements.
📄 License
MIT — do whatever you want with it.
Appeared in Searches
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/FacundoLucci/plsreadme'
If you have feedback or need assistance with the MCP directory API, please join our Discord server