Marco Sadjadi 0c6d738a6b
All checks were successful
Deploy to Production / deploy (push) Successful in 1m27s
feat(preview): SSE-streamed generation, no CF 100s edge cap
Architectural fix for "spec_too_large" / preview_timeout — the sync
endpoint had to fit the whole model run into Cloudflare's ~100s edge
window, which made the system fragile against any prompt that produced
a verbose spec. The new streaming path pipes Anthropic's token deltas
as Server-Sent Events; every chunk resets CF's idle timer and a 15s
keepalive comment guarantees activity even during slow first-token
windows.

@bmm/llm: new streamSpecFromAnthropic() exposes the SDK's .stream()
flow with the same typed-error contract as generateSpec — same
SpecTruncatedError / SpecValidationError / SpecTimeoutError raised from
the relevant moment.

API: POST /v1/servers/preview/stream returns text/event-stream with
events 'text' (deltas), 'spec' (final success payload, same shape as
the sync endpoint), 'error' (typed). Anthropic-only — GLM/hobby falls
back to the sync route via 409 streaming_unavailable.

Frontend: apiSseStream() handles the POST + ReadableStream + SSE
parser. The wizard's analyze() prefers the stream and only uses the
sync endpoint on the explicit 409 fallback.

nginx (api.buildmymcpserver.com): the /v1/builds/ location block (which
already had proxy_buffering off + 600s read timeout for the WS build
stream) now also matches /v1/servers/preview/stream so the SSE
response isn't buffered.
2026-05-28 21:11:05 +02:00

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:

  1. Load .env.
  2. docker compose up -d --wait postgres + redis.
  3. Push the Drizzle schema (drizzle-kit push --force).
  4. Start the full stack in parallel: web (Next.js, :3000), api (Fastify, :4000), generator (BullMQ worker).

Then open:

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 13 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:3000 renders the landing page.
  • http://localhost:4000/health returns { "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>/mcp responds 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 lints noExplicitAny as error).
  • ESM-only, Node 20 LTS.
  • Conventional commits.
  • Tailwind v4 (@import 'tailwindcss').
  • Geist + Geist Mono.
Description
No description provided
Readme 54 MiB
Languages
TypeScript 96.2%
Shell 1.9%
JavaScript 0.7%
Dockerfile 0.6%
CSS 0.6%