From 7eb323e8f8ea9a36632cb6efae568e678884b610 Mon Sep 17 00:00:00 2001 From: Marco Sadjadi Date: Sun, 31 May 2026 13:33:41 +0200 Subject: [PATCH] fix(pricing): every tier claim now true or honest; build real priority queue Audited all tiers vs code. BUILT priority build queue (both enqueue sites set BullMQ priority by plan, enterprise>team>pro>hobby). Made honest what is not built and cannot be built remotely: Custom domain -> coming soon; Team RBAC -> Audit log + RBAC coming soon; dropped Team 99.9 SLA; reworded FAQ rate-limit, cold-start sub-50ms, 30-day-retention and auto-TLS claims to reality; quota FAQ no longer promises unbuilt overage billing; JSON-LD offers aligned, Team price 149->199. Verified-true kept: server limits 1/5/25/inf and daily caps 5/40/50 enforced, faster paid Claude analysis, source export. Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/api/src/lib/queue.ts | 9 ++++ apps/api/src/routes/servers.ts | 52 +++++++++++++---------- apps/web/app/(marketing)/pricing/page.tsx | 12 +++--- apps/web/lib/seo.ts | 14 +++--- 4 files changed, 52 insertions(+), 35 deletions(-) diff --git a/apps/api/src/lib/queue.ts b/apps/api/src/lib/queue.ts index 8cda5f1..17d1b58 100644 --- a/apps/api/src/lib/queue.ts +++ b/apps/api/src/lib/queue.ts @@ -1,6 +1,15 @@ +import type { Plan } from '@bmm/llm'; import { Queue } from 'bullmq'; import { getRedis } from './redis.js'; +// BullMQ priority: LOWER number = processed sooner. Paid tiers jump ahead of +// free in the shared build queue — this is what makes the "priority build +// queue" plan claim actually true. +const PLAN_PRIORITY: Record = { enterprise: 1, team: 2, pro: 3, hobby: 4 }; +export function buildPriority(plan: Plan): number { + return PLAN_PRIORITY[plan] ?? 4; +} + export interface BuildJobData { buildId: string; serverId: string; diff --git a/apps/api/src/routes/servers.ts b/apps/api/src/routes/servers.ts index dd76073..58cc81c 100644 --- a/apps/api/src/routes/servers.ts +++ b/apps/api/src/routes/servers.ts @@ -37,7 +37,7 @@ import { encryptSecret } from '../lib/crypto.js'; import { stopContainer } from '../lib/docker.js'; import { SERVER_LIMITS, getOrgBilling } from '../lib/plan.js'; import { cacheSpec, loadSpec, overwriteSpec } from '../lib/preview-cache.js'; -import { getBuildQueue } from '../lib/queue.js'; +import { buildPriority, getBuildQueue } from '../lib/queue.js'; import { BUILD_DAILY_LIMIT, PREVIEW_DAILY_LIMIT, checkDailyLimit } from '../lib/rate-limit.js'; import { buildChannel, getSubscriber } from '../lib/redis.js'; import { requireAuth } from '../plugins/session.js'; @@ -525,17 +525,21 @@ export async function serverRoutes(app: FastifyInstance): Promise { .returning(); if (!build) return reply.code(500).send({ error: 'build_create_failed' }); - await getBuildQueue().add('generate', { - buildId: build.id, - serverId: server.id, - orgId: user.orgId, - prompt, - version: 1, - slug, - serverName: name, - secrets: secretValues, - previewId, - }); + await getBuildQueue().add( + 'generate', + { + buildId: build.id, + serverId: server.id, + orgId: user.orgId, + prompt, + version: 1, + slug, + serverName: name, + secrets: secretValues, + previewId, + }, + { priority: buildPriority(plan) }, + ); await audit({ orgId: user.orgId, @@ -631,16 +635,20 @@ export async function serverRoutes(app: FastifyInstance): Promise { .set({ status: 'queued', updatedAt: new Date() }) .where(eq(mcpServers.id, server.id)); - await getBuildQueue().add('generate', { - buildId: build.id, - serverId: server.id, - orgId: user.orgId, - prompt: parsed.data.prompt, - version: nextVersion, - slug: server.slug, - serverName: server.name, - secrets: parsed.data.secrets, - }); + await getBuildQueue().add( + 'generate', + { + buildId: build.id, + serverId: server.id, + orgId: user.orgId, + prompt: parsed.data.prompt, + version: nextVersion, + slug: server.slug, + serverName: server.name, + secrets: parsed.data.secrets, + }, + { priority: buildPriority(billing.plan) }, + ); await audit({ orgId: user.orgId, diff --git a/apps/web/app/(marketing)/pricing/page.tsx b/apps/web/app/(marketing)/pricing/page.tsx index 581dd4d..ec06ffe 100644 --- a/apps/web/app/(marketing)/pricing/page.tsx +++ b/apps/web/app/(marketing)/pricing/page.tsx @@ -37,9 +37,9 @@ const TIERS = [ '5 MCP servers', '1M tool calls / month', '40 prompt analyses / day', - 'Custom domain', 'Priority build queue', - 'Email support, 1 business-day SLA', + 'Custom domain · coming soon', + 'Email support, 1 business-day response', ], cta: 'Start Pro', href: '/settings/billing?tier=pro_monthly', @@ -49,15 +49,15 @@ const TIERS = [ name: 'Team', price: '€199', tag: '/ month', - description: 'For teams with RBAC, audit, and 99.9% SLA needs.', + description: 'For teams that need an audit trail and room to scale.', model: 'Claude AI', modelDetail: "Anthropic's flagship quality", features: [ '25 MCP servers', '10M tool calls / month', '50 prompt analyses / day', - 'RBAC + extended audit log', - '99.9% uptime SLA', + 'Audit log', + 'RBAC · coming soon', 'Shared Slack channel support', ], cta: 'Start Team', @@ -89,7 +89,7 @@ const FAQ = [ }, { q: 'What happens if I exceed my quota?', - a: 'Hobby: 429 with a hint to upgrade. Pro/Team: overage at €0.02 per 1000 calls, billed the following month. Soft caps configurable.', + a: 'Daily build and analysis limits return a 429 with a clear upgrade hint. Monthly tool-call volumes are generous soft limits — we reach out before anything is capped.', }, { q: 'Annual billing?', diff --git a/apps/web/lib/seo.ts b/apps/web/lib/seo.ts index 85acc9a..ae807a5 100644 --- a/apps/web/lib/seo.ts +++ b/apps/web/lib/seo.ts @@ -61,11 +61,11 @@ export const FAQ: FaqItem[] = [ }, { q: 'Cold starts?', - a: 'No cold starts. Containers stay warm. Sub-50ms tool-call overhead on average for in-region requests.', + a: 'No cold starts — each server runs in a container that stays warm (auto-restarts on failure), so there is no spin-up delay on a tool call.', }, { q: 'Rate limits?', - a: 'Default 100 requests/min/IP per tool. Configurable per server. Quota enforced at the proxy layer before hitting your container.', + a: 'Every request is gated by OAuth 2.1 before it reaches your container. Configurable per-server rate limiting is on the roadmap.', }, { q: 'How fast is generation?', @@ -73,7 +73,7 @@ export const FAQ: FaqItem[] = [ }, { q: 'Logs and metrics?', - a: 'Live log streaming to the dashboard, structured tool-call metrics (P50/P95/P99 latency, error rate, per-tool throughput) — all retained for 30 days.', + a: 'Live build-log streaming to the dashboard, plus structured tool-call metrics — latency, error rate and per-tool throughput — viewable per server.', }, { q: 'What if I cancel?', @@ -81,7 +81,7 @@ export const FAQ: FaqItem[] = [ }, { q: 'Custom domain?', - a: 'Pro plan and above. Add a CNAME, we provision a TLS certificate automatically.', + a: 'On the roadmap. Today every server is reachable at a buildmymcpserver.com URL with TLS; bring-your-own-domain support is coming.', }, ]; @@ -107,12 +107,12 @@ const OFFERS = [ name: 'Pro', price: '49', description: - '5 servers, 1M tool calls/month, custom domain, priority build queue, email support.', + '5 servers, 1M tool calls/month, faster Claude analysis, priority build queue, email support.', }, { name: 'Team', - price: '149', - description: '25 servers, 10M tool calls/month, RBAC + audit log, 99.9% SLA, Slack support.', + price: '199', + description: '25 servers, 10M tool calls/month, audit log, shared Slack support.', }, { name: 'Enterprise',