2026-05-19 00:30:20 +02:00
import Link from 'next/link' ;
import { CodeBlock } from '@/components/code-block' ;
const PROMPT_EXAMPLE = ` Create an MCP server that searches our Notion workspace.
Tools : search_pages , get_page_content .
Auth : NOTION_API_KEY. ` ;
const OUTPUT_EXAMPLE = ` > Generating spec... OK (2 tools)
> Static checks OK
> Building image bmm - mcp - notion OK 17.2 s
> Deploying container OK
> Live at https : //notion-x9.mcp.buildmymcpserver.com
> First request : 401 → token → 200 OK ` ;
const INSTALL_SNIPPET = ` {
"mcpServers" : {
"notion" : {
"url" : "https://notion-x9.mcp.buildmymcpserver.com/mcp" ,
"auth" : "oauth2"
}
}
} ` ;
const EXAMPLES : { title : string ; desc : string } [ ] = [
{ title : 'Postgres reader' , desc : 'Read-only access to your tables with schema introspection.' } ,
{ title : 'Salesforce' , desc : 'Query opportunities, accounts and leads from Claude.' } ,
{ title : 'Notion' , desc : 'Search pages, read content, append blocks.' } ,
{ title : 'GitHub' , desc : 'List issues, search code, post comments — scoped to one repo.' } ,
{ title : 'Stripe' , desc : 'Look up charges, customers, refunds (read-only by default).' } ,
{ title : 'Custom REST' , desc : 'Wrap any HTTP API behind one prompt-defined tool surface.' } ,
] ;
2026-05-21 00:37:06 +02:00
const MARKETPLACE_POINTS : { t : string ; d : string } [ ] = [
{
t : 'Fork and own' ,
d : 'Start from a server someone already shipped. Fork it, paste your own credentials, deploy — no prompt required.' ,
} ,
{
t : 'Secrets never travel' ,
d : "A template carries the spec and generated code, never the author's API keys. You add your own on fork." ,
} ,
{
t : 'Ranked by real usage' ,
d : 'Templates rise on fork count and active deploys — not vanity stars. The useful ones surface themselves.' ,
} ,
] ;
2026-05-19 00:30:20 +02:00
const FAQ : { q : string ; a : string } [ ] = [
{
q : 'What is MCP?' ,
a : 'Model Context Protocol — an open standard from Anthropic for connecting AI assistants to external tools, data and APIs over a transport like Streamable HTTP.' ,
} ,
{
q : 'Do I need to write code?' ,
a : 'No. You describe the tool in natural language. We generate the TypeScript server, run static checks, build a Docker image and deploy it to a public OAuth-protected URL.' ,
} ,
{
q : 'Which clients work?' ,
a : 'Claude Desktop, Cursor, ChatGPT Custom Connectors, VS Code Copilot, Continue.dev — anything that speaks the MCP spec.' ,
} ,
{
q : 'How is auth handled?' ,
a : 'Every generated server is an OAuth 2.1 Resource Server. Our control plane is the Authorization Server (PKCE + Dynamic Client Registration + Resource Indicators per RFC 8707).' ,
} ,
{
q : 'Can I self-host?' ,
a : 'Yes. The runner is a plain Docker container; the control plane is open to BYO Postgres + Redis. See the self-hosting guide in docs.' ,
} ,
{
q : 'What about secrets?' ,
a : 'AES-256-GCM at rest in Postgres, injected as environment variables into the runtime container. Never logged, never echoed back.' ,
} ,
{
q : 'Cold starts?' ,
a : 'No cold starts. Containers stay warm. Sub-50ms tool-call overhead on average for in-region requests.' ,
} ,
{
q : 'Rate limits?' ,
a : 'Default 100 requests/min/IP per tool. Configurable per server. Quota enforced at the Traefik layer before hitting your container.' ,
} ,
{
q : 'How fast is generation?' ,
a : 'Spec → image → live URL typically completes in 45-90 seconds.' ,
} ,
{
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.' ,
} ,
{
q : 'What if I cancel?' ,
a : 'You can export the full TypeScript source of every server you built. No vendor lock-in.' ,
} ,
{
q : 'Custom domain?' ,
a : 'Pro plan and above. Add a CNAME, we provision Let’ s Encrypt automatically.' ,
} ,
] ;
const TIERS = [
{ name : 'Hobby' , price : '€0' , tag : 'Forever free' , features : [ '1 server' , '100k calls/mo' , 'BMM subdomain' , 'Community support' ] } ,
{ name : 'Pro' , price : '€49' , tag : '/ month' , features : [ '5 servers' , '1M calls/mo' , 'Custom domain' , 'Priority build queue' , 'Email support' ] } ,
{ name : 'Team' , price : '€149' , tag : '/ month' , features : [ '25 servers' , '10M calls/mo' , 'RBAC + audit log' , 'SLA 99.9%' , 'Slack support' ] } ,
{ name : 'Enterprise' , price : '€499+' , tag : '/ month' , features : [ 'Unlimited' , 'BYOC' , 'SSO / SAML' , 'Dedicated cluster' , 'Customer success' ] } ,
] ;
export default function Landing() {
return (
< >
{ /* Hero */ }
< section className = "relative border-b border-[--color-border]" >
< div className = "mx-auto grid max-w-6xl gap-12 px-6 py-20 md:grid-cols-[1.05fr_1fr] md:items-center md:py-28" >
< div >
< span className = "mono inline-block rounded-full border border-[--color-border] bg-[--color-bg-elevated] px-2.5 py-0.5 text-[11px] tracking-wide text-[--color-fg-muted]" >
feat(marketplace): default-on share in wizard + owner unshare anytime
Goal: maximize template volume without a dark pattern and without leaking data.
Wizard Done-page Share panel:
- 'Share as template in the marketplace (recommended)' checkbox, default ON,
rendered inline in the build-success flow where every user lands.
- Honest copy — corrected a draft that claimed 'only abstracted code pattern is
shared'. That is false: the FULL generated code becomes publicly viewable on
the template detail page (by design, for pre-fork audit). The panel now says:
'Your secrets stay private ... but your generated code becomes publicly
viewable so others can audit it before forking. Unshare anytime.'
- When checked: inline minimal form — short description (prefilled from the
spec), category select, optional per-secret credential hints. One 'Publish to
marketplace' click. Not auto-published silently — that would be a consent dark
pattern; one visible deliberate click keeps it clean.
- Forked servers don't show the panel (re-publishing a fork is an edge case).
Owner unshare/reshare:
- GET /v1/servers/:id/template — owner lookup, drives the Publish tab UI.
- PATCH /v1/templates/:slug/visibility { shared } — owner-only toggle between
public and hidden. 403 for non-owners, 409 if an admin took it down (owner
cannot resurrect an admin takedown). Audit-logged as template.unshare /
template.reshare.
- Server-detail Publish tab now detects an existing template and shows the
shared status (public/hidden/takedown badge), fork count, a marketplace link
and an Unshare/Re-share button — instead of the publish form.
Why this is safe to default ON:
- Secrets are architecturally bound to mcp_servers, never copied into templates.
Publish reads tools_schema + generated_code only; the secrets table is never
touched. Data leak is structurally impossible, not policy-dependent.
- Publish re-scans the generated code for banned patterns AND hardcoded
credentials (sovereign-audit hardening) before it can reach the marketplace.
- The user sees a visible, pre-ticked checkbox and reads one honest sentence
before publishing. Privacy-conscious users untick; everyone else contributes
volume. Informed consent, GDPR-clean.
Verified end-to-end via API:
GET server/:id/template -> null (unpublished)
POST /v1/templates -> published, slug share-test-server
GET server/:id/template -> status public
PATCH visibility {shared:false} -> hidden, drops out of public list
PATCH visibility {shared:true} -> public again
UI: Publish tab renders the shared-status panel with View + Unshare (screenshot
confirmed).
Also: hero badge date set to 2026-05-20. Changed 'MCP spec 2025-11-25' to
'updated 2026-05-20' — claiming an MCP spec dated today would be factually wrong
(no such spec release exists); 'updated' is accurate and gives the requested
fresh date. The real spec date is still cited correctly in /docs.
2026-05-20 17:04:46 +02:00
v0 . 1 — updated 2026 - 05 - 20
2026-05-19 00:30:20 +02:00
< / span >
< h1 className = "mt-6 text-balance text-[44px] font-semibold leading-[1.05] tracking-tight md:text-[56px]" >
Describe your tool .
< br / >
We host the server .
< br / >
< span className = "text-[--color-fg-muted]" > AI uses it . < / span >
< / h1 >
< p className = "mt-5 max-w-md text-[15px] leading-relaxed text-[--color-fg-muted]" >
From prompt to production MCP server in 60 seconds . OAuth 2.1 , Streamable HTTP , ready
for Claude , Cursor and ChatGPT .
< / p >
< div className = "mt-7 flex flex-wrap items-center gap-3" >
< Link
href = "/login"
className = "inline-flex h-9 items-center justify-center rounded-md bg-[--color-accent] px-4 text-[13px] font-medium text-white transition-colors duration-200 hover:bg-[#5557e8]"
>
Start building free
< / Link >
< Link
href = "/docs"
className = "inline-flex h-9 items-center justify-center rounded-md border border-[--color-border] bg-[--color-bg-elevated] px-4 text-[13px] text-[--color-fg-muted] transition-colors hover:text-[--color-fg]"
>
Read the docs
< / Link >
< / div >
< div className = "mt-10 flex flex-wrap gap-x-6 gap-y-2 text-[12px] text-[--color-fg-subtle]" >
< span className = "inline-flex items-center gap-1.5" >
< span className = "size-1.5 rounded-full bg-emerald-400" / > OAuth 2.1 + PKCE
< / span >
< span className = "inline-flex items-center gap-1.5" >
< span className = "size-1.5 rounded-full bg-emerald-400" / > Streamable HTTP
< / span >
< span className = "inline-flex items-center gap-1.5" >
< span className = "size-1.5 rounded-full bg-emerald-400" / > AES - 256 secrets
< / span >
< span className = "inline-flex items-center gap-1.5" >
< span className = "size-1.5 rounded-full bg-emerald-400" / > Per - server isolation
< / span >
< / div >
< / div >
< div className = "relative" >
< div className = "absolute -inset-px rounded-lg border border-[--color-border-strong]" / >
< div className = "space-y-3" >
< CodeBlock label = "prompt.txt" code = { PROMPT_EXAMPLE } / >
< CodeBlock label = "build.log" code = { OUTPUT_EXAMPLE } / >
< CodeBlock label = "claude_desktop_config.json" code = { INSTALL_SNIPPET } / >
< / div >
< / div >
< / div >
< / section >
{ /* How it works */ }
< section id = "how" className = "border-b border-[--color-border] py-20" >
< div className = "mx-auto max-w-6xl px-6" >
< div className = "mb-12 max-w-2xl" >
< h2 className = "text-[28px] font-semibold tracking-tight" > How it works < / h2 >
< p className = "mt-2 text-[14px] text-[--color-fg-muted]" >
Three steps . No JSON to write , no Docker to manage .
< / p >
< / div >
< div className = "grid gap-6 md:grid-cols-3" >
{ [
{ n : '01' , t : 'Describe your tool' , d : 'A sentence is enough. List your secrets and which APIs to call.' } ,
{ n : '02' , t : 'We generate, check, deploy' , d : 'Claude writes the spec. We render TypeScript, run static checks, build a container, deploy to your subdomain.' } ,
{ n : '03' , t : 'Install in your client' , d : 'Copy the snippet into Claude Desktop, Cursor or ChatGPT. OAuth flow on first use.' } ,
] . map ( ( s ) = > (
< div key = { s . n } className = "panel p-5" >
< div className = "mono text-[11px] tracking-widest text-[--color-fg-subtle]" > { s . n } < / div >
< h3 className = "mt-4 text-[15px] font-semibold tracking-tight" > { s . t } < / h3 >
< p className = "mt-2 text-[13px] leading-relaxed text-[--color-fg-muted]" > { s . d } < / p >
< / div >
) ) }
< / div >
< / div >
< / section >
{ /* Works with */ }
< section className = "border-b border-[--color-border] py-16" >
< div className = "mx-auto max-w-6xl px-6" >
< h2 className = "text-center text-[13px] uppercase tracking-[0.18em] text-[--color-fg-subtle]" >
Works with the clients you already use
< / h2 >
< div className = "mt-8 flex flex-wrap items-center justify-center gap-x-12 gap-y-4 text-[14px] text-[--color-fg-muted]" >
{ [ 'Claude Desktop' , 'Cursor' , 'ChatGPT' , 'VS Code Copilot' , 'Continue.dev' ] . map ( ( t ) = > (
< span key = { t } className = "inline-flex items-center gap-2" >
< span className = "size-1.5 rounded-full bg-[--color-fg-subtle]" / >
{ t }
< / span >
) ) }
< / div >
< / div >
< / section >
{ /* Examples */ }
< section className = "border-b border-[--color-border] py-20" >
< div className = "mx-auto max-w-6xl px-6" >
< div className = "mb-10 max-w-2xl" >
< h2 className = "text-[28px] font-semibold tracking-tight" > Built for the work you actually have < / h2 >
< p className = "mt-2 text-[14px] text-[--color-fg-muted]" >
Anything with an HTTP API or a database , in minutes .
< / p >
< / div >
< div className = "grid gap-3 md:grid-cols-3" >
{ EXAMPLES . map ( ( e ) = > (
< div key = { e . title } className = "panel p-4 transition-colors hover:border-[--color-border-strong]" >
< div className = "text-[13px] font-semibold tracking-tight" > { e . title } < / div >
< p className = "mt-1 text-[12.5px] leading-relaxed text-[--color-fg-muted]" > { e . desc } < / p >
< / div >
) ) }
< / div >
< / div >
< / section >
2026-05-21 00:37:06 +02:00
{ /* Marketplace */ }
< section className = "border-b border-[--color-border] py-20" >
< div className = "mx-auto max-w-6xl px-6" >
< div className = "mb-10 flex flex-wrap items-end justify-between gap-4" >
< div className = "max-w-2xl" >
< h2 className = "text-[28px] font-semibold tracking-tight" >
Start from a template , ship in seconds
< / h2 >
< p className = "mt-2 text-[14px] text-[--color-fg-muted]" >
The marketplace is a library of working MCP servers the community already built .
Fork one to skip the prompt — or publish your own and let others build on it .
< / p >
< / div >
< Link
href = "/templates"
className = "inline-flex h-9 shrink-0 items-center justify-center rounded-md border border-[--color-border] bg-[--color-bg-elevated] px-4 text-[13px] text-[--color-fg-muted] transition-colors hover:text-[--color-fg]"
>
Browse the marketplace →
< / Link >
< / div >
< div className = "grid gap-3 md:grid-cols-3" >
{ MARKETPLACE_POINTS . map ( ( p ) = > (
< div key = { p . t } className = "panel p-5" >
< h3 className = "text-[15px] font-semibold tracking-tight" > { p . t } < / h3 >
< p className = "mt-2 text-[13px] leading-relaxed text-[--color-fg-muted]" > { p . d } < / p >
< / div >
) ) }
< / div >
< / div >
< / section >
2026-05-19 00:30:20 +02:00
{ /* Pricing */ }
< section id = "pricing" className = "border-b border-[--color-border] py-20" >
< div className = "mx-auto max-w-6xl px-6" >
< div className = "mb-10 max-w-2xl" >
< h2 className = "text-[28px] font-semibold tracking-tight" > Pricing < / h2 >
< p className = "mt-2 text-[14px] text-[--color-fg-muted]" >
Pay for tool calls , not for boilerplate .
< / p >
< / div >
< div className = "grid gap-3 md:grid-cols-4" >
{ TIERS . map ( ( t , i ) = > (
< div
key = { t . name }
className = { ` panel p-5 ${ i === 1 ? 'border-[--color-accent]/40' : '' } ` }
>
< div className = "text-[12px] uppercase tracking-wider text-[--color-fg-subtle]" > { t . name } < / div >
< div className = "mt-2 flex items-baseline gap-1" >
< span className = "text-[26px] font-semibold tracking-tight" > { t . price } < / span >
< span className = "text-[12px] text-[--color-fg-subtle]" > { t . tag } < / span >
< / div >
< ul className = "mt-4 space-y-1.5 text-[12.5px] text-[--color-fg-muted]" >
{ t . features . map ( ( f ) = > (
< li key = { f } > — { f } < / li >
) ) }
< / ul >
< / div >
) ) }
< / div >
< / div >
< / section >
{ /* FAQ */ }
< section className = "py-20" >
< div className = "mx-auto max-w-6xl px-6" >
< h2 className = "text-[28px] font-semibold tracking-tight" > FAQ < / h2 >
< div className = "mt-8 grid gap-x-12 gap-y-6 md:grid-cols-2" >
{ FAQ . map ( ( f ) = > (
< div key = { f . q } >
< h3 className = "text-[14px] font-semibold tracking-tight" > { f . q } < / h3 >
< p className = "mt-1.5 text-[13px] leading-relaxed text-[--color-fg-muted]" > { f . a } < / p >
< / div >
) ) }
< / div >
< / div >
< / section >
< / >
) ;
}