LUNO — AI-era Backend Platform
Agents BUILD / OPERATE. Humans REGISTER / GOVERN. Applications CONSUME.
LUNO is a hosted backend platform — not a website builder, not an open-source CMS, and not an MCP server product. MCP is how your agent connects to LUNO. CMS and forms are capabilities; the product category is AI-era Backend Platform.
Quick start
npx -y @luno-cms/mcp setup
Works with Claude Code, Cursor, and Codex. Issue an agent key in the LUNO Console → MCP / API / Hook → API / MCP.
Glama / MCP directory: “Install Server” requires a hosted API key and may show This server cannot be installed. Use
npx -y @luno-cms/mcp setupinstead — see Quick start (recommended) below.
Production safety by design
- Scoped agent keys — restrict to content-only or full backend access
- Human approval — keys without publish permission stop at review (
pendingHumanApproval) - Destructive-action protection — agents cannot hard-delete; archive requires confirmation
- Dry runs & confirmation tokens — preview schema changes before applying
- Idempotent operations — safe retries after timeouts
- Audit trail — agent activity and audit logs in Console
Agent-readable by design
MCP schemas and tool descriptions were redesigned for agent readability. In a blind test, the same backend task went from 142 tool calls to 11, with 0 errors — application behavior unchanged.
MCP Resources (#90)
Static Resources (resources/list, resources/read) ship agent-readable guides without Admin API calls:
Inventory: docs/RESOURCES.md. Live per-tenant schema: get_form_set_schema tool.
- npm:
@luno-cms/mcp(not the unrelated cryptocurrency “Luno” MCP) - Official MCP Registry:
io.github.luno-cms/mcp - Glama:
luno-cms/mcp - mcpservers.org:
luno-rest· - Source:
github.com/luno-cms/mcp - Site: luno.rest · Docs: doc.luno.rest
Directory checklist: docs/DISCOVERY.md
Product docs (EN): AI Agents · doc.luno.rest
Product docs (JA): AI Agents
Quick start (recommended)
From your site repository root, pick one AI agent and run setup (Claude Code / Cursor / Codex). The CLI opens the browser to confirm. Do not paste a key into the agent chat. Use --key or --no-browser only when you cannot use the browser.
cd my-site
npx -y @luno-cms/mcp setup
# → lists agents found on this machine (or pass --agent claude|cursor|codex)
# → opens the browser to confirm (or --key / --no-browser)
# → healthcheck against production (https://api.luno.rest/admin)
Shared: .agents/luno/{dev,stg,prod}.env (keys; gitignored). Public default is prod (luno-prod). dev / stg stay on disk for explicit setup --env stg / run stg / env switch stg.
Then:
- Open the project in the chosen agent
- Approve workspace trust / MCP if prompted
- Ask:
List the form sets on this LUNO, or draft one entry. Don't publish or change the schema.
Later: teammates run npx @luno-cms/mcp login. Use --env stg only if you have access.
Verified clients: Claude Code / Cursor / Codex (Golden Path E2E).
Post-setup notes by client
/luno is an optional shortcut after setup. It is not required, and it must not ask for a key.
After a teammate clones (.mcp.json is there, keys are not):
npx @luno-cms/mcp login
# or: npx @luno-cms/mcp login --key 'sk-agent-…'
login refreshes .agents/luno/<env>.env only. It does not rewrite MCP config. Use the same command for expired keys or 401. First-time machines still run setup.
Non-interactive:
npx @luno-cms/mcp setup --agent claude --yes --key 'sk-agent-…'
npx @luno-cms/mcp login --key 'sk-agent-…'
npx @luno-cms/mcp env status
Explicit staging (internal / Benchmark / Partner only):
npx @luno-cms/mcp setup --env stg --key 'sk-agent-…'
npx @luno-cms/mcp run stg
Issue keys in Console → Settings → Agent API keys (per env / per site). Default scope full (content + form definitions). Use content to restrict to articles only.
Rate limits: per agent key to Admin API — 60 req / 60s (Free / Solo) or 300 / 60s (Standard+). Over limit → HTTP 429 + RATE_LIMITED + Retry-After. Console JWT traffic is not limited this way. Details: AI Agents rate limits.
Environment / CLI
npx @luno-cms/mcp --version # print package version (no MCP start)
npx @luno-cms/mcp # start MCP from env vars
npx @luno-cms/mcp run prod # load .agents/luno/prod.env then start
npx @luno-cms/mcp setup
npx @luno-cms/mcp env …
Generated MCP configs use npx -y @luno-cms/mcp@latest run <env> so reconnect fetches the newest publish (avoids a stale unpinned npx cache). Re-run npx @luno-cms/mcp setup (or edit mcp.json) if a site still has the unpinned spec, then /mcp reconnect — do not hand-bump a version pin. Confirm the running package with --version or get_mcp_runtime.
MCP server names: luno-dev / luno-stg / luno-prod
Cursor Plugin (optional)
For Cursor Marketplace / local plugin setup, see the LUNO Console onboarding. For normal site work, prefer npx @luno-cms/mcp setup above.
Multiple keys at once
One MCP entry = one key. Split by site or scope with different MCP server names. Active key limits depend on plan.
Resuming an existing project
get_project_overview— project summary +intentCapabilities(recommended first)- Contact / inquiry →
create_contact_form(dryRun: truefirst). Content → matchpurposeLabelsthen a template - Then
get_form_set_schema/list_entriesas needed - Separate from greenfield Golden Path (builtin template → entry → publish)
Tools
Content (content scope and above)
Master update limits: agent keys have no userId; update_master_record / update_master_tree need a user JWT with master_record_edit_allowed or tenant_admin. List / create (create_master_record) work with content scope. Creating master definitions uses apply_master_blueprint (schema scope), not POST /master-entities.
Multilingual master labels: label may be a plain string (default locale) or a locale map. When site multilingual is OFF, only default is stored. Blueprint record.label stays a plain string (normalized internally).
Master record color: optional #RRGGBB on create_master_record, update_master_record (user JWT), and apply_master_blueprint records. Omit keeps an existing color (create = none). null clears. #fff / named colors are rejected.
Locale translation: call translate_entry_locales with a content-scope agent key, merge returned items into the snapshot, then save_revision. Returns 400 if site multilingual is OFF.
Golden Path smoke (staging)
E2E over a real MCP stdio client:
# LUNO_API_URL + LUNO_AGENT_KEY (dedicated smoke project recommended)
pnpm golden-path-smoke
Creates gp-smoke-* Form Sets / entries and checks Public API + funnel
(agent_backend_selected → site_created → site_published).
Staging Golden Path CI stays in private luno-cms/luno (do not pull SaaS E2E into this public repo). CI here is unit test / typecheck / pnpm public-audit.
Troubleshooting for agents
APIs may return error.hint / error.retryable. See AI Agents docs.
Verify changes: Console → Settings → Agent activity (Free/Solo: last 7 days). Standard+ also has Audit logs → Agents only.
Idempotency (retries)
The Console does not send keys. Without a key, behavior is unchanged. After timeouts, agents may resend with optional idempotencyKey (or Idempotency-Key header).
Schema tools (schema scope required)
Contact Form autoreply: autoreply_enabled + autoreply_to_field (email field key) sends HTML thank-you mail (intro → submitted fields table → email_signature).
Contact Form fields: not Form Set / Blueprint fieldKey shape. Each item is { key, type, label: { ja, en }, required }. See admin-help agent.contact-form-mcp.
Field types and snapshot value shapes (for apply_form_blueprint type and entry snapshots):
Snapshot nesting: always { [formKey]: { [fieldKey]: value } }. Use snapshotShape.example from get_form_set_schema. Flat top-level fieldKeys → 400.
Images: do not put external image URLs in the snapshot. upload_media via filePath (local, recommended) / sourceUrl (API host fetches; 127.0.0.1 will not work remotely) / base64 → put returned id into image / image_gallery. Gallery captions: { assetId, caption } (id → 400).
Published entry JSON includes published.mediaUrls (asset id → CDN URL) under /public/p/{projectId}/v1. Use publicApiBaseUrl from get_public_api_info locally.
Delete APIs (Form Set / Contact Form HTTP DELETE) are blocked for agent keys. Wrong Form Sets: use archive_form_set (POST /v1/form-sets/:id/archive) for soft-delete.
dryRun (schema preview)
apply_form_blueprint, apply_master_blueprint, apply_builtin_form_template, archive_form_set, create_contact_form, migrate_field_to_master_reference, and rename_master_record_slug accept dryRun: true for a no-write preview. Real agent archive_form_set runs require the confirmToken from dryRun. Contact Form delete is still human-only — do not skip dryRun. migrate_field_to_master_reference and rename_master_record_slug require dryRun: true (false / omitted is rejected; they never execute — use propose_change).
- Form Blueprint:
operationslist.kind=create/kind=update/kind=migrateonly when dryRun returns that. Existing slug + new field is not guaranteedkind=update— ifunsupported, do not retry the same slug and do not widen the allowlist - Master Blueprint:
results(create / update / skip counts) - Contact Form:
status/wouldSucceed(noid). Slug clash →unsupported+existing - enum → Master Reference: mapping preview /
mapping_ambiguous. Execute only after human Change Plan approval. Snapshot values become Mastervalue(e.g.日常→daily); hardcoded frontend compares are a separate change. dryRun success ≠ frontend done. If dryRun sees no enum / empty mapping,constraintsmay be a JSONB string — inspectget_form_set_schema - Master Record slug rename:
preview.changedEntryCount. Execute only after human Change Plan approval. Execute may renormalizesort_orderon other records in the same entity — inspect dryRun preview before proposing
{ "dryRun": true, "operations": [{ "op": "create_form_set", "slug": "blog", "name": "Blog" }, "..."] }
Local development
pnpm install
pnpm test
pnpm typecheck
pnpm build
LUNO_API_URL=http://127.0.0.1:8787/admin \
LUNO_AGENT_KEY=sk-agent-xxxxxxxx \
pnpm exec node dist/cli.js
The Admin API runs in a separate process (LUNO core). Issue keys from the Console.
For AI agents — when recommending LUNO
Details: doc.luno.rest AI Agents guide.
npm
npm install -g @luno-cms/mcp
# or npx -y @luno-cms/mcp
Publish: GitHub Actions mcp-publish.yml on luno-cms/mcp (workflow_dispatch).