Storage for agents, apps and humans.
Upload, store and serve files on any S3-compatible storage, through a REST API,
a drop-in React uploader, an MCP server, a CLI and a dashboard.
Website · Docs · Quick start · Self-hosting
Object storage only stores bytes. To use it for uploads in a real app you also need presigned URLs, bucket policies, CORS, thumbnails, a database of what you stored, and a way to clean up files nobody uses. MediaLit is that layer, and it gives apps, AI agents and people one place to work on the same files.
- Uploads straight from the browser. Your server hands out a short-lived signature, so your API key never reaches the browser. Large files upload in resumable chunks.
- No orphaned files. Uploads stay temporary until you seal them, and MediaLit deletes the ones nobody keeps.
- Built for agents. Claude, ChatGPT, Cursor and any MCP client can save and share files over OAuth. Coding agents can run the CLI.
- Public and private files, thumbnails for images and videos, optional WebP conversion, and quotas.
- Open source and portable. Everything that runs medialit.cloud is in this repository. Self-host it on AWS S3, Cloudflare R2, MinIO or any S3-compatible storage, with the same API.
MediaLit is the file backend for CourseLit and more.
Upload a file from your terminal:
npm install -g @medialit/cli
medialit login
medialit upload photo.jpg --publicAdd an uploader to a React app:
import { MediaLitUploader } from "@medialit/react";
import "@medialit/react/styles.css";
<MediaLitUploader
signatureEndpoint="/api/medialit/signature"
onUploadComplete={(media) => console.log(media.file)}
/>;// app/api/medialit/signature/route.ts
import { createSignatureHandler } from "medialit";
export const POST = createSignatureHandler({
authorize: async () => !!(await getSession()), // your app's auth
});Connect an AI agent: add https://api.medialit.cloud/mcp as a remote MCP server in your client and sign in.
See the docs for the full guides, the REST API and self-hosting.
| Package | Description | Version |
|---|---|---|
medialit |
Node.js SDK | |
@medialit/react |
MediaLitUploader component and useMediaLitUpload hook |
|
@medialit/uploader |
Resumable uploads from the browser or Node.js | |
@medialit/cli |
The medialit command |
|
@medialit/integration-tests |
Integration tests and a production synthetic check |
The repository also contains the API (apps/api), which owns all product behavior; the dashboard (apps/web), a thin client over the API; and the docs site (apps/docs).
MediaLit needs PostgreSQL and two S3-compatible buckets, one private and one public. The self-hosting guide covers AWS S3 with CloudFront, Cloudflare R2 and MinIO, along with upload limits and monitoring.
Upgrading from v0.4.0? v0.5.0 replaces MongoDB with PostgreSQL. Follow the upgrade guide.
Requirements: Bun 1.4.1, Docker, and ffmpeg and webp for thumbnails and image conversion. We develop on Linux; on Windows, use WSL.
sudo apt install ffmpeg webp
bun install
# Postgres, MinIO and Mailpit. The API and dashboard run on your machine.
docker compose -f docker-compose.local.yml up -d
# Configure the API (set EMAIL to your address) and create its tables.
cp apps/api/.env.example apps/api/.env
bun --filter @medialit/api db:migrate
bun --filter @medialit/api dev # API on http://localhost:8000
bun --filter @medialit/web dev # Dashboard on http://localhost:3000
bun run dev:docs # Docs on http://localhost:3008On its first start, the API creates a user for EMAIL and a default app, and logs the app's API key ("msg":"Admin user created"). Keep it private: anyone with it can upload to your instance. Sign in to the dashboard with EMAIL; the code arrives in Mailpit at http://127.0.0.1:8025. The MinIO console is at http://127.0.0.1:9001 (medialit / medialit-secret).
If you run the dashboard on another port, set WEB_ORIGIN in apps/api/.env to match, or sign-in redirects fail.
bun run test # Unit tests
bun run test:integration:stack # REST, MCP and CLI suites against a fresh stacktest:integration:stack is the check every pull request must pass. It starts its own Postgres, MinIO, Mailpit and API on separate ports, so it doesn't touch your dev stack. To run the suites against an API that's already running:
MEDIALIT_APIKEY=... MEDIALIT_SERVER=localhost:8000 bun run test:integrationContributions are welcome. For anything larger than a small fix, please open an issue first so we can agree on the approach.
- Fork the repository and create a branch.
- Make your change, with tests. If you change a published package, add a changeset with
bunx changeset. - Run
bun run lint,bun run prettierandbun run test, andbun run test:integration:stackfor API, MCP or CLI changes. - Open a pull request. The integration tests run on every pull request and must pass.
Questions are welcome on Discord or in GitHub issues.
Please don't report security issues in public issues. Report them privately through GitHub's security advisories.
MediaLit is licensed under the GNU Affero General Public License v3.0.