aft.page

Agents first

MCP for aft.page

Any MCP-capable agent can publish small software to a live *.aft.page URL — no account, no repository setup.

Agents: prefer https://aft.page/mcp.md or llms.txt — same content, machine-friendly. HTML below is for humans configuring a host.

What it is

aft.page hosts small software — one-pagers, prototypes, agent-built HTML, static SPAs — at a shareable HTTPS URL in seconds. The name comes from the aft of a ship: the back of the vessel — take what you built and put it out into the world.

Prefer the MCP tools below. If MCP is unavailable, call the HTTP API directly.

Quick start

Local package lives at apps/mcp ((@aft.page/mcp). Transport: stdio. Node 20+.

cd apps/mcp
npm install
npm start

MCP host config

Add a server named aft-page. Point args at the absolute path of apps/mcp/src/index.ts:

{
  "mcpServers": {
    "aft-page": {
      "command": "npx",
      "args": [
        "tsx",
        "/ABSOLUTE/PATH/TO/aft.page/apps/mcp/src/index.ts"
      ]
    }
  }
}

Optional env: AFT_API_BASE (default https://api.aft.page). Reload the host, then ask:

Deploy this HTML to aft.page

The agent should call deploy_html and return a live URL.

Tools

deploy_html

Publish a single HTML document (inline CSS/JS fine) to https://{slug}.aft.page. Use for one-file pages.

Input Type Required Notes
html string yes Full document; prefer <!DOCTYPE html>…</html>
preferred_slug string no Hint like about-me. Pattern ^[a-z0-9](?:[a-z0-9-]{0,46}[a-z0-9])?$. Never overwrites — collision gets a suffix (about-me-mist.

Returns text + structured content:

Live: https://{slug}.aft.page
Manage/claim: https://aft.page/preview?url=…
slug: …
deploy: dep_…
files: 1

deploy_files

Publish multiple static files as one site. Use for multi-file pages or SPA build output. Always include index.html.

Input Type Required Notes
files array yes 1–50 items
files[].path string yes Relative path, e.g. index.html, assets/app.js
files[].content string yes UTF-8, or base64 if encoding set
files[].encoding utf8 | base64 no Default utf8
preferred_slug string no Same rules as deploy_html

Limits: 50 files · 2 MB each · 5 MB total. Paths: no .., no leading /, no \.

aft_health

Ping the deploy API. No inputs. Returns ok and the API base.

Prompt: deploy_to_aft

Optional prompt that steers the agent:

  • Prefer deploy_html for one document.
  • Prefer deploy_files for multi-file / SPA.
  • Pass preferred_slug when sensible.
  • Return the live HTTPS URL as the deliverable.
  • Do not invent account or repository setup steps.

Arg: html_or_files (optional context string).

HTTP API (no MCP)

Base: https://api.aft.page. CORS: * on deploy + site GET.

GET /health

{ "ok": true }

POST /v1/deploy

Query: optional ?slug=preferred-name. Optional header X-Aft-Client: mcp|web|extension|curl|cli (metrics). Three body shapes:

A) Raw HTML

POST /v1/deploy?slug=hello
Content-Type: text/html; charset=utf-8

<!DOCTYPE html><html><body><h1>Hi</h1></body></html>

B) JSON files (agents)

POST /v1/deploy
Content-Type: application/json

{
  "files": [
    { "path": "index.html", "content": "<h1>App</h1>" },
    { "path": "style.css", "content": "body{margin:0}" }
  ]
}

C) Multipart — fields file0 + file0_path, …

Success (200)

{
  "ok": true,
  "slug": "hello",
  "deployId": "dep_…",
  "url": "https://hello.aft.page",
  "files": 1,
  "bytes": 42
}

Errors include no_files, too_many_files, file_too_large, payload_too_large, bad_path, reserved_slug, slug_exhausted, internal. Invalid ?slug= patterns are ignored (random unique slug); only reserved names return reserved_slug.

Serving

URL Behavior
https://{slug}.aft.page/ Primary — index.html
https://{slug}.aft.page/{path} Static asset
https://api.aft.page/s/{slug}/ Path fallback

If the requested object is missing, the Worker soft-falls back to that deploy’s index.html (SPA-style). Content-Type follows the file extension when the upload type is missing or application/octet-stream (so CSS is text/css).

Slugs

  1. Prefer valid ?slug= / preferred_slug when provided.
  2. Else allocate a random unique slug.
  3. Clients (paste UI, extension, agents) may derive a hint from <title> / <h1> and pass it as ?slug= — the Worker does not parse HTML for a name.
  4. Never overwrite — append a short word suffix on collision.
  5. Reserved: www, api, app, admin, docs, status, …

Preview shell

https://aft.page/preview?url=https://{slug}.aft.page

Live iframe, indented source, copy link, download HTML, claim / visibility stubs. Only *.aft.page URLs allowed in url=. Optional from= (chat URL) enables “Back to chat”.

Limits (today)

Limit Value
Files per deploy 50
Per-file size 2 MB
Total payload 5 MB
Auth None (anonymous)
Overwrite Never
Custom domains / private invite Later

Examples

Minimal HTML via curl

curl -sS -X POST "https://api.aft.page/v1/deploy?slug=curl-smoke" \
  -H "content-type: text/html; charset=utf-8" \
  --data-binary @index.html

Agent rule of thumb

  1. Prefer MCP deploy_html or deploy_files.
  2. Return the live https://{slug}.aft.page URL.
  3. Optionally link the preview shell.
  4. Do not invent auth steps that do not exist yet.

Troubleshoot

Symptom Fix
MCP tools missing Reload host; check absolute path; Node 20+
reserved_slug Change title / slug
Size errors Stay under 2 MB / file, 5 MB total
Unstyled CSS Ensure path ends in .css; re-deploy
Site 404 Wait for DNS; try /s/{slug}/ on API host