I wanted to see how far an AI agent could get building a real, deployed full-stack app against Magic Cloud using nothing but MCP tool calls — no hand-written code. Here's what came out of one session.
The Stack
-
Backend: Hyperlambda, generated entirely via the
generate-hyperlambdaMCP tool (never hand-written — the platform enforces this) -
Database: SQLite,
crmdatabase, singlecontactstable -
Frontend: Vanilla HTML/CSS/JS SPA served from
/etc/www/ - Auth: Magic Auth (built-in RBAC/JWT)
- Orchestrator: Claude, via the Magic MCP connector (~105 tools across 14 namespaces)
What Got Built
-
Schema: a
contactstable (name, email, phone, company, notes) viaexecute-sql -
CRUD API: four separate Hyperlambda endpoints —
create,read(paged/sorted/filtered),update,delete— each generated as its owngenerate-hyperlambdacall and auto-exposed as an MCP tool the moment it's saved -
Frontend: login-gated SPA, JWT stored in
localStorage, auto-refreshing the ticket every 10 minutes, classic/corporate visual theme - Seed data: 10 example contacts inserted directly via SQL
Total build time: minutes, not hours.
Two Bugs Worth Knowing About
1. GET/DELETE requests can't carry a Content-Type header.
Hyperlambda's HTTP layer throws if you decorate a GET or DELETE request with a content-type header. You cannot decorate an HTTP GET or DELETE request with content type of headers.
This bit both the MCP invoke-http tool (which defaults to application/json unless you override with an empty headers object) and would have bitten the frontend if I hadn't special-cased it — app.js only attaches Content-Type on POST/PUT.
2. Relative asset paths break without a trailing slash.
/etc/www/crm-contacts/index.html serves at /crm-contacts/. But if a user hits /crm-contacts (no trailing slash), the browser resolves <link href="style.css"> against domain root, not the folder — instant 404. Fix: use absolute paths (/crm-contacts/style.css) in every asset reference. Easy to miss, annoying to debug from a screenshot of a 404.
The Interesting Part
The Hyperlambda generator refuses to be hand-debugged — the platform's own tooling actively pushes you toward invoke-http and the OpenAPI spec instead of trying to read/patch the generated .hl files directly. That constraint, combined with checking log_entries in the magic SQLite database for the actual exception text, was faster for root-causing both bugs above than staring at HTTP status codes would have been.
Takeaway
Framework-enforced constraints (no hand-written Hyperlambda, RBAC at execution time, generator-only codegen) slow down the "just let me fix this one line" instinct — but they're also what made a zero-manual-code CRM buildable in a single sitting without the usual pile of copy-pasted, unreviewed AI-generated backend code.
You can watch me going through the whole process below ...
Top comments (0)