Skip to content
CytSoftwarePublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

publ

CI PRs welcome

Give your agent a "publish this" button. It returns a link.

publ is a hosting layer for AI-generated artifacts. An agent calls a single MCP tool to publish an HTML page, Markdown doc, or file — and instantly gets a shareable link that opens in any browser. Re-publishing keeps the same link and versions the content. A web dashboard manages your artifacts, usage, and MCP connection.

A Cyt Software product — sibling-in-spirit to GitShare (share private repos via link), but for agent output. Open source and self-hostable.

📄 Full spec, decisions, and roadmap: PRD.md


How it works

   ┌─────────┐  publish_artifact(...)   ┌──────────────┐
   │  Agent  │ ───────────────────────▶ │  publ        │  stores content + version
   │ (MCP)   │ ◀─────────────────────── │  /mcp        │  returns https://<slug>.…
   └─────────┘     { url: "…" }          └──────────────┘
                                                │ serves
   ┌───────────┐    opens the link             ▼
   │ Anyone    │ ──────────────────▶  <slug>.<usercontent-domain>
   └───────────┘                       (own origin · strict CSP · no cookies)
  1. Your agent publishes an artifact over MCP and gets back a link.
  2. You send the link to anyone — it opens in their browser.
  3. The agent can update it (same link, new version), list, fetch, revoke, or delete.

What works today

The publish → serve loop runs end-to-end on a local stack. MCP tools:

Tool Does
publish_artifact Publish inline HTML / Markdown / text → returns the share URL
update_artifact New version, same URL (old versions stay at /v/<n>)
list_artifacts Your artifacts with URLs + view counts
get_artifact Fetch content + metadata (latest or a specific version)
revoke_link Disable the public link (visitors get 410); content retained
delete_artifact Permanently delete the artifact and purge its bytes
  • Markdown renders to a clean, themed reader page.
  • Each artifact is served from its own origin with a strict CSP and no cookies (so artifact JS can't touch your session — see PRD §8).
  • Per-account bearer-token auth; every tool is scoped to the calling user (no cross-account access).

Deferred to Phase 2 and rejected loudly until then: password-protected links, expires_at enforcement, and large-file (presigned) uploads.

Architecture

Agent      ──Bearer token──▶  FastAPI app  ── /mcp   FastMCP (streamable HTTP)
Dashboard  ──session───────▶               ── /api   REST API
Recipient  ────────────────▶  <slug>.<usercontent-domain>  ── serve layer (strict CSP, no cookies)

One FastAPI deployable, dispatched by Host. Storage is behind an interface — local filesystem for dev, Backblaze B2 in Phase 2, swapped via one env var.

Stack: FastAPI + uv (Python 3.12) · async SQLAlchemy + Alembic · PostgreSQL · FastMCP v3 · Next.js 15 + pnpm + Tailwind + Radix · Docker → Dokploy.

Quick start

# Minimal backend/.env for local dev (USERCONTENT_DOMAIN=localhost enables *.localhost serving).
# See .env.example for the full list of variables.
cat > backend/.env <<'ENV'
ENV=development
USERCONTENT_DOMAIN=localhost
DATABASE_URL=postgresql+asyncpg://pubspace:pubspace@localhost:5433/pubspace
STORAGE_BACKEND=local
SESSION_SECRET=dev-secret-not-for-prod
ENV

docker compose up -d db                      # Postgres (host port 5433, dev override)
cd backend
uv sync
uv run alembic upgrade head
uv run python -m app.scripts.seed you@example.com   # prints an API token + connect command
uv run uvicorn app.main:app --reload --port 8000

Connect your agent and publish. Claude Code:

claude mcp add --transport http publ http://localhost:8000/mcp/ \
  --header "Authorization: Bearer <token-from-seed>"

OpenCode (~/.config/opencode/opencode.json):

{ "mcp": { "publ": {
  "type": "remote",
  "url": "http://localhost:8000/mcp/",
  "enabled": true,
  "headers": { "Authorization": "Bearer <token-from-seed>" }
} } }

Then ask your agent to publish_artifact(title="Test", type="html", content="<h1>It works</h1>"). It returns http://<slug>.localhost:8000 — open it in any browser.

Run the dashboard too:

cd frontend
corepack enable          # one-time (uses the pinned pnpm)
pnpm install
pnpm dev                 # http://localhost:3000

Local only: dev uses local-filesystem storage and serves artifacts under *.localhost. Nothing is exposed to the public internet. Backblaze B2 + a dedicated usercontent domain land in Phase 2. To run a real deployment, see SELF_HOSTING.md.

Project structure

publ/
├─ PRD.md                  # product spec, decisions, roadmap
├─ docker-compose.yml      # db + backend + frontend (override exposes db on 5433)
├─ backend/                # FastAPI (uv)
│  └─ app/
│     ├─ main.py           # app factory: host-routes usercontent, mounts /mcp + /api
│     ├─ mcp/              # FastMCP server + DB-backed bearer-token auth
│     ├─ services/         # publishing logic (create/version/serve, ownership checks)
│     ├─ storage/          # Storage interface + LocalStorage (B2 in Phase 2)
│     ├─ serve/            # usercontent serve layer (CSP, no cookies)
│     ├─ models/ · api/    # ORM models · REST routes
│     └─ scripts/seed.py   # mint a user + API token
└─ frontend/               # Next.js 15 + pnpm + Tailwind + Radix

Status & roadmap

  • Phase 0 — Scaffold ✅ monorepo, CI, migrations, MCP mounted.
  • Phase 1 — Publish loop ✅ publish/update/list/get/revoke/delete, versioning, Markdown rendering, local storage, token auth + ownership. (dashboard UI still stubbed)
  • Phase 2 — B2 storage + large files, dedicated usercontent domain, dashboard auth (magic link) + token management UI, password/expiry, OAuth connector, billing.

See PRD.md §11 for detail.

Contributing & security

Contributions welcome — see CONTRIBUTING.md and our CODE_OF_CONDUCT.md. Found a vulnerability? Please follow SECURITY.md (don't open a public issue).

License

To be finalized. The hosted publ.sh service is intended as the commercial offering; this repository is the open core.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages