lobby
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@lobbypublish a landing page for launch.example.com with a hero and pricing section"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Lobby
A hotel for landing pages. One process, many domains — each site is a single markdown file.
acme.com → sites/acme.com.md
otherbrand.io → sites/otherbrand.io.mdThe request's Host decides which file is the site, the same way a reverse
proxy picks a backend by hostname. There is no database: publishing is writing
a file, backing up is copying a folder, and the source a human edits is the
source a language model reads.
Point a wildcard at it and there is no per-site setup left at all. Adding a customer is one file — no DNS record, no config entry, no redeploy:
curl -X POST https://lobby.example.com/mcp \
-H "Authorization: Bearer $LOBBY_API_TOKEN" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{
"name":"write_site",
"arguments":{"host":"newcustomer.example.com","content":"---\ntitle: Hello\n---\n\n::hero\n# Live.\n::"}}}'That call takes about 150 ms, and the site is serving when it returns.
Why it is like this
Files, not a database. A database buys transactions and indexes that a hundred landing pages never need, and costs the thing that makes the format worth using. The one real risk files carry — two writers clobbering — is handled where it lives: writes are atomic and versioned, so a stale save is refused rather than quietly winning.
Rendered on the server, no client JavaScript. Not minimalism for its own sake. The point is that crawlers and language models read the page, so the page has to exist without running anything.
Agents and people share one store. An agent writing over MCP and a human clicking in
/adminedit the same file, so neither works from a private copy of the truth.
Related MCP server: Aigist MCP
The format
Optional frontmatter, then blocks. Anything outside a block is ordinary
markdown, so a plain .md file renders fine with no directives at all.
---
title: "Acme — industrial rope"
description: "Rope since 1904."
footer: "© Acme"
---
::hero{eyebrow="since 1904"}
# Rope that **holds**.
## Braided in Gothenburg, tested to failure, sold by the metre.
[See the catalogue](/site.md){.primary} [Call us](tel:+46000000){.ghost}
::
::two-column{image="https://example.com/rope.jpg" imageAlt="Coiled rope" reverse=true}
## Made to be trusted
Every batch is pull-tested and stamped.
::
::cta
## Need a quote?
[Email us](mailto:hi@example.com){.primary}
::Directive | What it is |
| The opening statement, with call-to-action links |
| Text beside an image. |
| A boxed invitation, centred |
| Everything else |
| Sticky header. |
| Grid of icon, title and body. |
| A row of numbers with labels |
| A pull quote. |
| Tiers as cards. |
| Question and answer pairs, rendered as native |
| Link row plus a |
| A card for every site this hotel serves. |
Blocks that hold several records take them as markdown lists, so the file still reads as prose:
::features{columns=3 title="What it does"}
- icon: ⚖️
title: The rules are kept for you
body: It objects *before* you publish, not after.
- icon: 🔁
title: Shift swaps without a middleman
body: Staff post and take shifts in the app.
::
::pricing{title="Prices"}
- name: Standard
price: 59 kr
period: /person/month
features: Everything in Small; Forecasting; Payroll export
cta: Try it free
href: mailto:hi@example.com
featured: true
::
::faq{title="Common questions"}
- q: How long is the contract?
a: There isn't one. Monthly, cancel whenever.
::::faq renders native <details> rather than a scripted accordion: it opens
without JavaScript, the answers are findable with the browser's own search, and
screen readers already know what it is.
::sites is a directive rather than a built-in page so a landing page opts in —
a customer's site should not list its neighbours just because they share a
container. Signed in as admin, each card gains an edit link and a delete
button.
A link written [Label](/where){.primary} becomes a button (.primary,
.ghost). An unknown directive still renders its words — a typo in a block
name costs you the layout, never the content.
GET /site.md serves the source verbatim. That is the point of the format,
not a debug hatch.
Running it
npm install && npm start # http://localhost:8080
docker build -t lobby . && docker run -p 8080:8080 lobbyVariable | Default | Meaning |
|
| Port to listen on |
|
| Where the markdown files live |
| (unset) | Optional catch-all site. Unset means an unknown hostname gets a 404 |
| (unset) | Bearer token for |
| (unset) | Password for |
|
| Admin username |
| (unset) | Hostnames routed here, so the admin can show which sites are live |
Themes
Set theme: in frontmatter. Each theme is a palette, a typeface pairing and
one signature detail you can recognise at a glance — without that, themes are
the same page in different colours and an agent picking one is guessing.
Theme | Signature |
| None — the neutral baseline |
| Drop cap on the first paragraph after a heading |
| Heavy rules above every block, no rounded corners |
| Pill buttons and a tinted hero |
| Dark by default, glowing hairline under the hero |
Admin
/admin is the human half of the same job: a list of every site, click one to
edit its markdown, save. Agents write over MCP, people click here, and both go
through the same store — an agent's change shows up in the editor immediately.
Set LOBBY_ADMIN_PASSWORD to turn it on. Signed in, every site also carries an
Edit this page button, so you can go from reading a page to fixing its
typo without finding it in a list.
The list marks a site live when a hostname is actually routed here, and warns when a routed hostname has no file — a visitor gets the default site and nothing looks broken, which makes it the hardest failure to notice. That comparison is why the container is told its own domains.
Writes are atomic and versioned. When an agent saves a site while you have it open, saving refuses with a conflict rather than silently discarding their work; your text stays in the editor so you can decide.
MCP — letting an agent run the hotel
POST /mcp speaks JSON-RPC 2.0 with a bearer token, the same shape as
AgentHotel's own endpoint. Five tools, because a site is a file:
list_sites, read_site, write_site, delete_site, list_themes.
{
"mcpServers": {
"lobby": {
"url": "https://lobby.example.com/mcp",
"headers": { "Authorization": "Bearer YOUR_TOKEN" }
}
}
}Writing a site publishes it, so the endpoint stays closed until
LOBBY_API_TOKEN is set — a world-writable CMS is not a default anyone should
get by accident. write_site replaces the whole file rather than merging, so
read before you edit.
Files in the image's /seed are copied into SITES_DIR only when a name is
missing, so a redeploy never overwrites a site you have edited.
SEO
The pages are server-rendered with no client JavaScript, which is the part
that matters most: a crawler or a language model gets the words on the first
request without running anything. On top of that each site emits a canonical
URL, Open Graph and Twitter card tags, robots.txt and a sitemap.xml, and
returns a real 404 for anything that is not its one page.
Frontmatter carries the rest:
Key | Effect |
|
|
| meta description, |
| the |
|
|
| keeps a site out of search results |
Notes
The hostname reaches the filesystem, so it is validated rather than trusted: lowercased, port stripped, restricted to what a domain may contain. A
Hostof../../etc/passwdgets the default site, not a file read.www.example.comfalls back toexample.com.md, so one file serves both.An unknown hostname gets a real 404. Behind a wildcard route every possible subdomain reaches this process, so a silent fallback would render a page for every mistyped link and never a mistake. Set
DEFAULT_SITEto opt into a catch-all.No client-side JavaScript. The page renders on arrival, which is what makes it readable by crawlers and language models.
Running it on AgentHotel
Lobby is built to be checked in as a guest of
AgentHotel: pick the Git App
runtime, give it this repository, port 8080, and a health check path of
/healthz. Set DOMAIN_ALIASES to *.example.com and the panel writes the
wildcard route for you; it also passes AGENTHOTEL_DOMAINS in, which is what
lets the admin tell a live site from an unrouted one.
Nothing here depends on it — Lobby is an ordinary container with two environment variables and a volume.
Credits
The ::directive{attr} format follows
markdownweb, so content moves
between them.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Create, edit, preview, publish, and manage web pages from MCP-capable AI clients.
Create, publish and track sales funnels and Sites with custom domains from any MCP agent.
Agent-first web hosting: deploy sites, apps, databases and domains over MCP.
Hosted MCP for creating, checking, deploying, and hosting static sites for AI agents.
Related MCP Servers
- AlicenseAqualityAmaintenanceEnables MCP clients to read, search, create, update, and share collaborative documentation pages on the AgentDocs platform.192211MIT
- AlicenseNot gradedqualityCmaintenancePublish and manage shareable HTML/Markdown pages with access control and comments via MCP clients.MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to deploy HTML pages and manage them (list, archive, move, rename) in a versioned library via MCP tools.67MIT
- AlicenseNot gradedqualityBmaintenanceEnables publishing sanitized static HTML pages from an MCP agent and receiving shareable URLs, with tools for updating, listing, publishing, and deleting pages.43MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/magnusfroste/lobby'
If you have feedback or need assistance with the MCP directory API, please join our Discord server