Skip to main content
Glama
mrlo

artifact-inbox

by mrlo

artifact-inbox

A self-hosted inbox for everything your AI agents produce. Agents push finished documents (PDF, markdown, HTML, text) over MCP or REST; you read, sort and mark them done in one clean web UI.

The inbox

Why

I run several agents: a chat bot, a coding agent, a research agent, scheduled jobs. Each one produces real work (reports, comparisons, drafts, summaries), and each one leaves it somewhere different: a chat thread, a desktop app, a file on a server. A 10-page report scrolling past in a chat bubble doesn't get read. A week later nobody (me included) can find it.

What I wanted was a single place where every artifact from every agent lands, so there is one thing to check instead of five, and a proper reading interface instead of whatever each bot's UI happens to offer: a real PDF viewer, rendered markdown, categories, an unread/done state, and a layout that works on a phone. Agents write; I read when I have time; nothing is lost in scrollback.

So: one small container, one bearer token, and a skill that teaches any agent when to push something and when to just answer in chat.

Related MCP server: DraftRelay

Features

  • Agent-friendly: MCP (streamable HTTP) at /mcp, REST at /api/push, and /install, a page an agent can follow to configure itself (plus a ready-made skill, /install/SKILL.md).

  • Per-agent tokens with one-click setup: in the UI, Agents → Add agent gives you a single-use install link. Hand it to the agent ("install this: https://your-host/install?claim=..."); it swaps the link for its own token, and the inbox then labels everything it pushes with that name. Revoke one agent later without touching the others.

  • Reads well: PDFs in the browser's viewer, sanitised markdown, sandboxed interactive HTML (a pushed checklist keeps its ticks), plain text. Dark mode and phone layout.

  • Triage: unread/done, categories with counts, "mark all done" per category, source agent and summary on every item.

  • Small: Python, SQLite, one container, ~256 MB.

Markdown

PDF

Interactive HTML

Phone

Agents

Quick start

cp .env.example .env            # set INBOX_API_TOKEN (openssl rand -hex 32), INBOX_BASE_URL, INBOX_UI_PASSWORD
mkdir -p data && sudo chown 1000:1000 data
docker compose up -d            # pulls ghcr.io/mrlo/artifact-inbox (amd64/arm64); UI on http://127.0.0.1:8000

To build from source instead: docker compose up -d --build. Pin a release with image: ghcr.io/mrlo/artifact-inbox:0.2.0.

Push something:

curl -sS -X POST http://127.0.0.1:8000/api/push \
  -H "Authorization: Bearer $INBOX_API_TOKEN" \
  -F file=@report.pdf -F title="Report title" -F category=research -F source_agent=me -F summary="One line."

Connect an agent over MCP (Claude Code example):

claude mcp add --transport http artifact-inbox http://127.0.0.1:8000/mcp --header "Authorization: Bearer $INBOX_API_TOKEN"

Security: read this before exposing it

Two layers, both optional to combine:

  • /mcp and /api/* always require a bearer token: either the admin token (INBOX_API_TOKEN) or a per-agent token.

  • Per-agent tokens come from single-use claim links (/install?claim=..., valid 60 minutes by default). Opening the link doesn't use it up (so chat link previews can't burn it); the agent redeems it once with POST /api/claim. Only SHA-256 hashes of tokens and claims are stored, and the server stamps each item with the agent's registered name.

  • The web UI is protected by built-in HTTP basic auth when INBOX_UI_PASSWORD is set (user INBOX_UI_USER, default admin). If you leave it empty, the UI is open and you must put it behind your own auth (SSO proxy, VPN/Tailscale). The default compose file binds to 127.0.0.1 for that reason.

Basic auth has no lockout or rate limiting, so use a long password and serve it over HTTPS (or keep it private). See docs/DEPLOYMENT.md for the model and a Traefik example (examples/compose.traefik.yml).

What the app does enforce:

  • Constant-time token compare; fails closed if INBOX_API_TOKEN is unset.

  • PDFs recognised by %PDF- magic bytes, not file names; binary non-PDF content rejected (415); 50 MB cap (413).

  • Files stored under random ids; user-supplied names never touch the disk.

  • Markdown rendered with raw HTML disabled, then sanitised (nh3). HTML items run in <iframe sandbox="allow-scripts"> with a CSP that blocks network access; /raw/<id> sends CSP: sandbox. All files carry X-Content-Type-Options: nosniff.

  • push_artifact(url=...) fetches only public addresses (non-global IPs refused, redirects re-checked, size capped).

  • UI POSTs reject cross-origin Origin headers.

Known limitations: one human user (no multi-user, no per-agent permissions beyond on/off), DNS-rebinding race on URL fetch (resolve-then-connect), UI lists only the newest 500 items, no rate limiting on failed token or password attempts.

Configuration

Variable

Purpose

INBOX_API_TOKEN

Bearer token for /mcp and /api/* (required)

INBOX_UI_PASSWORD

Enables basic auth on the web UI (empty = no UI auth; rely on your proxy)

INBOX_UI_USER

Basic-auth user (default admin)

INBOX_CLAIM_TTL_MIN

Minutes an install link stays valid (default 60)

INBOX_BASE_URL

Public URL, used in returned links and the /install page (default http://localhost:8000)

INBOX_DATA_DIR

Data directory inside the container (default /data)

Data lives in ./data (inbox.db and files/). Back it up. Rotate the token: new value in .env, docker compose up -d, update each agent.

Docs

Try it with demo data

INBOX_API_TOKEN=... python3 scripts/seed_demo.py http://127.0.0.1:8000

Adds seven fictional items (markdown, a PDF, an interactive HTML checklist, text). The screenshots above were taken this way.

Development

python3 -m venv .venv && .venv/bin/pip install -r requirements.txt pytest && .venv/bin/python -m pytest -q tests

License

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Open-source, self-hosted Inbox-as-a-Service API for AI agents. It enables agents to manage email inboxes, send/receive emails, search messages, and wait for replies via REST or MCP.
    30
    Apache 2.0
  • A
    license
    Not graded
    quality
    D
    maintenance
    A delivery outbox MCP server that enables AI agents to save polished artifacts like emails, summaries, or updates for human review and copying, supporting local and hosted modes.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    A self-hosted push inbox for AI agents that enables agents to send updates and ask questions, waiting for user answers before continuing.
    1
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server that lets AI agents manage an Agent Inbox queue via natural language. It supports listing pending items, adding new URLs with notes, and marking items as reviewed or deleted.
    18 npm
    4
    MIT