Schema migrations: - users.is_admin boolean - users.password_hash text (scrypt N=16384, 16-byte salt) - users.last_login_at timestamp - organizations.suspended + suspended_reason - admin_settings table (DB-stored prompt override + future settings) Auth (@bmm/auth): - hashPassword + verifyPassword via node:crypto scrypt (no extra dep) - loginWithPassword: scrypt-verifies, issues 30-day session, updates last_login_at - seedAdmin: idempotent upsert keyed on email; creates org + membership on first run - AuthedUser now carries isAdmin flag API: - POST /v1/auth/admin/login (email + password) — 300ms throttle on failure - requireAdmin preHandler — 401 if no session, 403 if non-admin - Bootstrap: api on boot calls seedAdmin(ADMIN_EMAIL, ADMIN_PASSWORD, ADMIN_NAME) if env present. Idempotent. Admin API routes (all gated by requireAdmin): - GET /v1/admin/overview (totals, trends 7d, server-status breakdown, builds 24h, recent activity) - GET /v1/admin/users (search, per-row org + plan + serverCount) - PATCH /v1/admin/users/:id (isAdmin, name) - DELETE /v1/admin/users/:id (self-delete blocked) - GET /v1/admin/orgs (member + server counts) - PATCH /v1/admin/orgs/:id (plan, quota, suspended; cascades to mcp_servers.status=paused on suspend) - GET /v1/admin/servers (cross-org with status filter) - POST /v1/admin/servers/:id/rebuild (re-queues build using last prompt) - DELETE /v1/admin/servers/:id - GET /v1/admin/builds (status filter, error messages, prompt previews) - GET /v1/admin/builds/:id/logs - GET /v1/admin/audit (system-wide with user email join) - GET /v1/admin/system (DB ping, Redis ping, BullMQ queue depth, docker ps count) - GET /v1/admin/prompt (builtin + override + updatedAt) - PATCH /v1/admin/prompt (value: string | null) — saves DB override or drops it UI (apps/web/app/admin/*): - /admin/login — password form, separate from /login magic-link - AdminLayout — Linear-style sidebar (8 nav items), bottom panel with user email + 'user view' shortcut + logout, client-side requireAdmin guard with redirect - /admin — overview dashboard with 4 metric cards, 2 panels (status + 24h builds), recent activity table linking to full audit - /admin/users — search + admin toggle + delete (self-delete blocked) - /admin/orgs — plan/quota/suspend actions via prompts - /admin/servers — cross-org table with rebuild + delete actions, status filter - /admin/builds — every build cross-fleet with error vs prompt preview - /admin/audit — system-wide log + CSV export + filter dropdowns - /admin/system — auto-refreshing 5s health probes for Postgres, Redis, queue, Docker - /admin/prompt — live editor for the LLM system prompt with built-in baseline, override-state badge, drop-override action, diff preview, save-as-override End-to-end verified: login as marco.frangiskatos@gmail.com + Melusa112233.*, every admin page returns 200, admin login + overview tested via screenshot, docker probe returns true count of running MCP containers. |
||
|---|---|---|
| apps | ||
| packages | ||
| scripts | ||
| .env.example | ||
| .gitignore | ||
| biome.json | ||
| BuildMyMCPServer_MASTER_PROMPT.md | ||
| CHOICES.md | ||
| docker-compose.yml | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| tsconfig.base.json | ||
| turbo.json | ||
BuildMyMCPServer
Describe your tool. We host the server. AI uses it.
Prompt-to-production MCP servers with OAuth 2.1 and Streamable HTTP. Production-grade infrastructure for hosting Model Context Protocol servers your AI clients (Claude Desktop, Cursor, ChatGPT) can install with a copy-paste snippet.
Quick start
# 1. Install
pnpm install
# 2. Copy env. Defaults work for local dev. Set ANTHROPIC_API_KEY if you want real generation.
cp .env.example .env
# 3. Boot everything
pnpm dev
pnpm dev will:
- Load
.env. docker compose up -d --waitpostgres + redis.- Push the Drizzle schema (
drizzle-kit push --force). - Start the full stack in parallel: web (Next.js, :3000), api (Fastify, :4000), generator (BullMQ worker).
Then open:
- Dashboard: http://localhost:3000
- API: http://localhost:4000/health
Click Start building, enter your email, copy the magic-link URL printed to the
api terminal output, paste it in your browser. You land on /dashboard. Click
New server, paste a prompt, and watch the build stream live over WebSocket.
If ANTHROPIC_API_KEY is unset, the generator returns a deterministic mock spec
(an echo and a now tool) so the full end-to-end flow stays demoable.
If Docker is unavailable, the build will fail at the deploy step with a clear error.
Otherwise: a fresh container is launched on a host port from
RUNNER_PORT_RANGE_START…RUNNER_PORT_RANGE_END, the server is marked live, and the
dashboard renders install snippets for Claude Desktop, Cursor and ChatGPT.
Architecture
See BuildMyMCPServer_MASTER_PROMPT.md for the full specification and CHOICES.md
for decisions made during this Sprints 1–3 build.
apps/
web/ Next.js 15 dashboard + marketing landing
api/ Fastify control plane (auth, server CRUD, OAuth 2.1 AS, JWKS, WS stream)
generator/ BullMQ worker — Claude → spec → render → docker build → local deploy
runner-template/ Hosted MCP server template (Streamable HTTP + OAuth 2.1 RS)
packages/
db/ Drizzle schema + client
auth/ Magic-link + session
types/ Shared Zod contracts
Scripts
| Command | Effect |
|---|---|
pnpm dev |
Bootstrap + parallel dev for web, api, generator |
pnpm dev:no-docker |
Skip docker-compose (assumes postgres + redis already up) |
pnpm build |
Turbo build all apps |
pnpm typecheck |
Turbo typecheck all apps |
pnpm lint |
Biome check |
pnpm lint:fix |
Biome check --write |
pnpm db:push |
Push schema to postgres (drizzle-kit) |
pnpm db:generate |
Generate SQL migration files |
pnpm db:migrate |
Apply pending migrations |
pnpm stop |
docker compose down |
Acceptance check
After pnpm dev is up:
http://localhost:3000renders the landing page.http://localhost:4000/healthreturns{ "ok": true }.- Sign in via magic link (URL printed in the api terminal).
- New Server → paste prompt → live WebSocket stream
queued → generating → building → deploying → live. - If Docker is running, a container is launched and
http://localhost:<port>/mcpresponds 401 + WWW-Authenticate without a token, 200 with a valid token issued by/oauth/token. - Install snippets render with copy buttons for Claude Desktop, Cursor, ChatGPT.
Repo conventions
- TypeScript strict, zero
any(Biome lintsnoExplicitAnyas error). - ESM-only, Node 20 LTS.
- Conventional commits.
- Tailwind v4 (
@import 'tailwindcss'). - Geist + Geist Mono.