Ephemeral Pages exposes a hosted Model Context Protocol server
for agents. It is a first-party adapter of the existing POST /api/pages API: same
validation, anonymous rate limits, and public /p/:id URLs. It is not a new product surface — no
accounts, listing, or page editing.
The server speaks MCP 2026-07-28 only. Older 2025-era clients are not supported.
Production URL:
https://ephemeral.schalkneethling.com/mcp
This endpoint uses the MCP 2026-07-28 Streamable HTTP transport in buffered JSON mode. Despite
the transport's name, the specification permits either a single JSON response or a request-scoped
SSE stream; this deployment returns one application/json response for each normal request and
does not send mid-call progress or logging notifications. No API key, OAuth, or GitHub OIDC is
required or accepted. Clients that only speak 2025-era MCP will fail.
Each client has its own config file and field names. Use the official docs for the client you run; the snippets below are the minimum working shapes for this URL.
codex mcp add ephemeral-pages --url https://ephemeral.schalkneethling.com/mcpOr add a table to ~/.codex/config.toml (or a trusted project's .codex/config.toml):
[mcp_servers.ephemeral-pages]
url = "https://ephemeral.schalkneethling.com/mcp"Do not set a bearer token. Codex connects without credentials when none are configured.
Project file .cursor/mcp.json, or ~/.cursor/mcp.json for every workspace:
{
"mcpServers": {
"ephemeral-pages": {
"url": "https://ephemeral.schalkneethling.com/mcp"
}
}
}claude mcp add --transport http ephemeral-pages https://ephemeral.schalkneethling.com/mcpJSON in .mcp.json or ~/.claude.json must include "type": "http". A url with no type is
read as stdio and skipped:
{
"mcpServers": {
"ephemeral-pages": {
"type": "http",
"url": "https://ephemeral.schalkneethling.com/mcp"
}
}
}OpenCode MCP docs (current). OpenCode v2
nests the same remote entry under mcp.servers and uses disabled instead of enabled.
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"ephemeral-pages": {
"type": "remote",
"url": "https://ephemeral.schalkneethling.com/mcp"
}
}
}If the client starts an OAuth flow against this public server, set oauth to false on the
remote entry.
Pi does not ship MCP. Install the community pi-mcp extension, which negotiates MCP 2026-07-28:
pi install git:github.com/dmmulroy/pi-mcp@acd1428863dd6ce8ee30371b30f0958e8fb8fbe2That commit is intentionally pinned because Pi extensions run with full system access. To update
it, review the target commit and dependency changes, run the extension's checks, then replace the
full SHA above and run the same pi install command. Pi does not move pinned Git sources during
normal updates.
Then add ~/.pi/agent/mcp.json or a project .pi/mcp.json:
{
"mcp": {
"ephemeral-pages": {
"type": "remote",
"url": "https://ephemeral.schalkneethling.com/mcp"
}
}
}The extension defaults to lazy startup. Open /mcp, select ephemeral-pages, and connect it.
- VS Code / Copilot:
workspace
.vscode/mcp.jsonuses"type": "http"andurlunderservers. - Model Context Protocol lists other clients.
Look for a remote, HTTP, or Streamable HTTP server. Streamable HTTP is the specification's formal
transport name even when a server chooses its permitted buffered JSON response mode. Point it at
the production URL. Do not invent an API key, OAuth client, or stdio command for this service.
The official Inspector CLI
defaults to the 2025 era. Use ephemeral-pages-inspector.json
so it negotiates 2026-07-28:
npx @modelcontextprotocol/inspector --cli \
--config ephemeral-pages-inspector.json \
--server ephemeral-pages \
--stored-auth-only \
--format json \
--method tools/listClients discover what this server can do from the protocol, not from this page. After
connect they receive server instructions, then tools/list
(name, description, input schema, and output schema) and prompts/list. The
model uses those descriptions and schemas to call tools. Both tools advertise
the same output: id, createdAt, expiresAt, and url. Error results omit
structuredContent.
publish-html-page is a prompt:
a user-invoked starter (slash command or menu item), not a help or usage catalog. Prompts
are usually named for the workflow they start (git-commit, draft-email), not help or
usage — those would collide with client commands and duplicate the tool descriptions.
| Name | Kind | Purpose |
|---|---|---|
create_page |
tool | Publish a full HTML document and return id, createdAt, expiresAt, and url |
get_page |
tool | Return metadata for a known page id (never the HTML) |
publish-html-page |
prompt | User-invoked starter: read a file path, then publish it with create_page |
create_page arguments:
html(required): a complete, self-contained HTML page. Typical form is a doctype plushtml,head, andbody. Fragments, Markdown, and a barebodyare not a page.expirationHours(optional):1,3,5,7,12(default),24,72,120, or168.idempotencyKey(optional): 1–200 printable ASCII characters; same key and payload replay the original page.
publish-html-page arguments:
path(required): a workspace HTML file the agent should read, then send tocreate_page. Do not paste HTML into the prompt.
There is no encoding argument. Large CI reports should keep using the REST API with
encoding: "br+base64".
- Netlify buffered request body is about 6 MB.
- Raw HTML is limited to 20 MiB; Brotli-compressed HTML to 2 MiB (same as REST).
- Uploads: 10 per 10 minutes per client IP.
/mcpalso has the same 120 requests per minute edge limit as/api/*.
- Published URLs are public. Never upload secrets, credentials, private source, or sensitive data.
- Uploaded pages are sandboxed. Declarative scripts, stylesheets, and fonts may load only from the
approved CDNs.
fetch, XHR, and WebSocket are blocked. /mcpis unauthenticated. IncomingAuthorizationis ignored so a leftover client token cannot be treated as GitHub OIDC. Repository OIDC stays on the REST API for GitHub Actions. Later auth, if any, should follow MCP 2026-07-28 authorization (CIMD), not Actions OIDC.- Admin delete, page HTML content, and abuse reporting are not MCP tools.
An MCP Apps preview (confirm the
published HTML in the client after create_page) is tracked as a later exploration:
issue #14. No preview UI exists
today.