post-engineer-mcp
by Ryan-Carloso
README.md
# Post Engineer
[](https://github.com/Ryan-Carloso/post-engineer/actions/workflows/ci.yml)
[](LICENSE)
[](https://www.npmjs.com/package/post-engineer-mcp)
[π§π·π΅πΉ Leia em PortuguΓͺs](README.pt-BR.md)
Create AI video personas that generate and publish short videos on autopilot.
Give a persona a niche and a voice; Post Engineer writes the script, generates the
voiceover, assembles the video, and publishes it to your social accounts on a
schedule. Manage everything from the web dashboard, drive it programmatically
through the API, or let your AI agent run it through the MCP server β all from
this one monorepo.
Post Engineer is open source under the [Apache License, Version 2.0](LICENSE).
Self-host the whole platform on your own VPS following
[docs/SELF_HOSTING.md](docs/SELF_HOSTING.md), or use the hosted version and
buy tokens. Lip sync (LongCat) runs on [Modal.com](https://modal.com):
Modal's Starter plan includes $30/month in compute credits (see
[modal.com/pricing](https://modal.com/pricing)). We are not Modal: this
free-credit offer is theirs and can end at any time. Light self-hosted usage
can fit inside the free credits while it lasts β usage beyond that is billed
by Modal.
> Prefer the hosted version? The same platform runs at
> [post-engineer.com](https://post-engineer.com) β you can skip the local
> setup and connect the MCP server straight to your account (see
> [MCP server](#mcp-server)).
## What it does
- **AI personas** β persistent characters with a voice, face, language, and niche.
Optional lip-synced intro clips for a human-like presenter, plus a persona
image library for face consistency across videos.
- **Automatic video generation** β topic in, HD short video out: script (LLM),
voiceover (TTS), subtitles, stock footage, and background music, assembled
into a finished video.
- **Scheduling & publishing** β queue posts for YouTube, Instagram, LinkedIn,
and Bluesky; track upcoming and past posts with per-account status.
- **Dashboard** β personas, posts history, connected social accounts, API keys,
and token billing in one Next.js app.
- **Agent control** β an MCP server ([`apps/mcp/`](apps/mcp/)) exposes the same
capabilities to AI agents (Claude, Cursor, Codex, OpenCode): create personas,
generate videos, check status, and schedule posts.
## Repository layout
This is a pnpm/Nx monorepo β web, engine, and MCP live together:
```text
apps/web/ Next.js 15 dashboard + API routes (TypeScript)
apps/engine/ Python/FastAPI video-generation engine
apps/mcp/ MCP server for AI agents (npm package: post-engineer-mcp)
```
The web app owns authentication, personas, scheduling, OAuth, billing, and the
API. It calls the engine over HTTP (authenticated with a shared secret,
`MONEYPRINT_API_SECRET`) for video generation, TTS, and publishing. The MCP
server talks to the web API with a user API key. Postgres (via Supabase) is
the system of record: personas, schedules, OAuth tokens (encrypted at rest),
API keys, and token balances.
## Prerequisites
- **Node.js** 20+ and **pnpm** 10 (`npm install -g pnpm` or via corepack)
- **Python** 3.11β3.12 and **uv** (`curl -LsSf astral.sh/uv/install.sh | sh`)
- **ffmpeg** on `PATH` (the engine shells out to it via moviepy)
- A **Supabase** project (hosted at [supabase.com](https://supabase.com), or
self-hosted) with a Postgres database
- API keys for the external services you plan to use (see the table below)
## Local setup from scratch
### 1. Install dependencies
```bash
git clone https://github.com/Ryan-Carloso/post-engineer.git
cd post-engineer
pnpm install
```
### 2. Set up Supabase
1. Create a project at [supabase.com](https://supabase.com) (or point at your
self-hosted instance).
2. In the Supabase SQL editor, apply the database scripts. The persona image
library script lives in this repo: [`supabase/migrations/002_persona-images.sql`](supabase/migrations/002_persona-images.sql)
(manual-apply by design).
> **Need help?** If you are setting up a fresh project and need the current
> schema snapshot, reach out:
> **Email:** [madebyryandev@gmail.com](mailto:madebyryandev@gmail.com) Β·
> **WhatsApp:** [+351 962 248 268](https://wa.me/351962248268)
### 3. Create the three env files (never commit these)
There are exactly three env files by design β copy each from its example and
fill in your own values:
```bash
cp apps/web/.env.example apps/web/.env
cp apps/engine/.env.example apps/engine/.env
cp apps/engine/config.example.toml apps/engine/config.toml
```
| File | Purpose | Key variables |
|---|---|---|
| `apps/web/.env` | Web app + API routes | `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_ANON_KEY`, `SUPABASE_SERVICE_ROLE_KEY` (server-only), `TOKEN_ENCRYPTION_KEY` (generate: `openssl rand -base64 32`), `MONEYPRINT_API_SECRET`, `MONEYPRINT_API_URL`, OAuth client ids/secrets + redirect URIs, Stripe keys, `MCP_OAUTH_PRIVATE_KEY_PEM` |
| `apps/engine/.env` | Engine runtime | `MONEYPRINT_API_SECRET` (must be **identical** to the web value), `SUPABASE_URL` + `SUPABASE_SERVICE_ROLE_KEY` (for the in-process fill scheduler), mandatory `R2_ACCOUNT_ID` + `R2_ACCESS_KEY_ID` + `R2_SECRET_ACCESS_KEY` (final-video archive), optional `DISCORD_WEBHOOK_URL`, optional `POSTHOG_API_KEY` (error tracking, analytics funnel, AI observability traces) |
| `apps/engine/config.toml` | Engine behavior config | LLM/TTS/stock-footage provider keys (OpenAI-compatible, Pexels, Pixabay, β¦), `listen_port` (default `8080`) |
The app fails fast on missing variables (no silent fallbacks) β see
`apps/web/.env.example` for the full documented list.
### 4. Register OAuth apps (for social publishing)
To connect YouTube, Instagram, or LinkedIn accounts you need OAuth apps whose
**redirect URIs exactly match** the values in `apps/web/.env`:
- **Google / YouTube** β [Google Cloud Console](https://console.cloud.google.com):
create an OAuth 2.0 Client ID, add the authorized redirect URIs from
`GOOGLE_REDIRECT_URI` / `GOOGLE_REDIRECT_URI_LOCAL`, and fill in
`GOOGLE_CLIENT_ID` / `GOOGLE_CLIENT_SECRET`.
- **Instagram** β [Meta for Developers](https://developers.facebook.com): a
Business app with the Instagram product (`instagram_business_basic` and
`instagram_business_content_publish` permissions); set `INSTAGRAM_CLIENT_ID` /
`INSTAGRAM_CLIENT_SECRET` and register `INSTAGRAM_REDIRECT_URI`.
- **LinkedIn** β [LinkedIn Developers](https://developer.linkedin.com): create
an app, register `LINKEDIN_REDIRECT_URI`, and set `LINKEDIN_CLIENT_ID` /
`LINKEDIN_CLIENT_SECRET`.
- **Threads** β [Meta for Developers](https://developers.facebook.com/docs/threads):
create an app with the Threads use case (`threads_basic`,
`threads_content_publish` and `threads_manage_insights` permissions), register
`THREADS_REDIRECT_URI`, and set `THREADS_CLIENT_ID` / `THREADS_CLIENT_SECRET`.
- **Bluesky** uses an app password entered in the dashboard (encrypted at
rest) β no OAuth app registration needed.
### 5. Stripe setup (token billing)
1. Create a [Stripe](https://stripe.com) account and get the secret +
publishable keys (`STRIPE_SECRET_KEY`, `NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY`).
2. Create the token-pack products and put the price IDs in
`STRIPE_PRICE_PACK_10` / `_50` / `_100`.
3. Add a webhook endpoint pointing at `/api/billing/webhook` and store the
signing secret in `STRIPE_WEBHOOK_SECRET`. The webhook handler verifies the
signature and is idempotent.
### 6. Generate the self-managed secrets
These are yours to create β nothing to register:
```bash
# Web <-> engine shared secret (identical in both .env files)
openssl rand -hex 32
# OAuth token encryption key (AES-256-GCM)
openssl rand -base64 32
# MCP OAuth signing key (PEM, \n-escaped into MCP_OAUTH_PRIVATE_KEY_PEM)
openssl ecparam -genkey -name prime256v1 -noout | openssl pkcs8 -topk8 -nocrypt
```
## Running
```bash
pnpm dev:web # dashboard at http://localhost:3434
pnpm dev:engine # video engine API at http://127.0.0.1:8080 (see /docs there)
```
Useful commands (all verified against `package.json` / `project.json`):
```bash
pnpm test # all tests (web + engine + MCP, via Nx)
pnpm lint # ESLint (web + MCP) + ruff (engine)
pnpm typecheck # tsc --noEmit (web + MCP) + engine checks
pnpm build # production build of the web app
pnpm graph # Nx project graph
```
Per-app details: [apps/web/README.md](apps/web/README.md),
[apps/engine/README.md](apps/engine/README.md),
[apps/mcp/README.md](apps/mcp/README.md).
## MCP server
The MCP server ([`apps/mcp/`](apps/mcp/), npm package
[`post-engineer-mcp`](https://www.npmjs.com/package/post-engineer-mcp)) lets AI
agents create personas, generate videos, check generation status, and schedule
posts on your account. You don't need to clone this repo to use it against the
hosted platform:
```json
{
"mcpServers": {
"post-engineer": {
"type": "local",
"command": ["npx", "-y", "post-engineer-mcp@latest"],
"environment": {
"POST_ENGINEER_API_KEY": "<MY_API_KEY>"
}
}
}
}
```
Generate `<MY_API_KEY>` at
[post-engineer.com/api-keys](https://post-engineer.com/api-keys). The
`@latest` tag matters: `npx` reuses its cached copy without checking for
updates. To point the
server at your own self-hosted instance instead, set
`POST_ENGINEER_API_URL` (see [apps/mcp/README.md](apps/mcp/README.md) for the
full tool list, OpenCode timeout tips, and local development).
## External services you must key yourself
| Service | Required? | What for | Where to get it |
|---|---|---|---|
| Supabase | **Yes** | Postgres, auth, storage | [supabase.com](https://supabase.com) or self-hosted |
| Google OAuth app | For YouTube publishing | OAuth client id/secret | Google Cloud Console |
| Instagram (Meta) app | For Instagram publishing | OAuth client id/secret | developers.facebook.com |
| LinkedIn app | For LinkedIn publishing | OAuth client id/secret | developer.linkedin.com |
| Stripe | For token billing | Secret/publishable keys, price IDs, webhook secret | stripe.com |
| LLM provider key **or** Ollama | For script generation | OpenAI-compatible key, or run Ollama locally | Your provider / ollama.com |
| Pexels / Pixabay / Coverr / TwelveLabs | For stock footage | API keys | Respective developer portals |
| `MONEYPRINT_API_SECRET` | **Yes** | Web β engine auth | Generate yourself (`openssl rand -hex 32`) |
| `TOKEN_ENCRYPTION_KEY` | **Yes** | Encrypts OAuth tokens at rest | Generate yourself (`openssl rand -base64 32`) |
| `MCP_OAUTH_PRIVATE_KEY_PEM` | For MCP server OAuth | Signs MCP tokens | Generate yourself (EC key, see above) |
| PostHog | Optional | Error tracking + product analytics | `NEXT_PUBLIC_POSTHOG_KEY` (browser), `POSTHOG_API_KEY` (server), `NEXT_PUBLIC_POSTHOG_HOST` β see `apps/web/.env.example` |
| Discord webhook | Optional | Fill-schedule notifications | Discord channel settings |
| `ZAI_API_KEY` | CI only | AI code-review workflow | Not a runtime dependency |
## Support & Contact
Questions, get in touch:
- **Email:** [madebyryandev@gmail.com](mailto:madebyryandev@gmail.com)
- **WhatsApp:** [+351 962 248 268](https://wa.me/351962248268)
## License
Licensed under the [Apache License, Version 2.0](LICENSE) β see
[CONTRIBUTING.md](CONTRIBUTING.md) and [SECURITY.md](SECURITY.md).
## Credits
Video engine derived from [MoneyPrinterTurbo](https://github.com/harry0703/MoneyPrinterTurbo)
(MIT Β© 2024 Harry), extended with persona lip-sync, background-music catalog,
batch queue, scheduling, and publishing.
This server cannot be deployed
Maintenance
ActivityActive
ResponsivenessResponsive