Publish Markdown or HTML to a clean, shareable dochost.io link and hand the URL back to the user. Use when the user says "publish this", "share this as a lin...
---
name: dochost-publish
description: |
Publish Markdown or HTML to a clean, shareable dochost.io link and hand the URL
back to the user. Use when the user says "publish this", "share this as a link",
"put this on the web", "make a page from this", "turn this into a link", or in
Chinese "发布", "分享成链接", "做个网页", "生成链接" — for any document, report,
README, or HTML the assistant produced. Works on any agent that can make an HTTP
request (OpenClaw, Hermes, Claude, Cursor, ChatGPT, or a plain shell). Returns a
public dochost.io/d/... URL.
---
# Publish to dochost
Turn Markdown or HTML into a hosted web page at its own URL, in one call. The page
renders live (Markdown **and** HTML), so the recipient sees a real page, not a raw
`.md` blob. Free links last 7 days; permanent links, passwords, custom slugs and
branding removal follow the account's plan.
## One-time setup
The agent publishes **as a dochost user**, authenticated with an API key.
1. Sign in at <https://dochost.io>, open **Settings → API keys**, create a key.
2. Make it available to the agent as the environment variable `DOCHOST_API_KEY`.
That's the whole setup. Entitlements (link lifetime, password, custom slug,
branding) come from the account that owns the key, never from tool input.
## How to publish
Send one JSON-RPC `tools/call` to the dochost MCP endpoint with the key as a
Bearer token. No handshake or `initialize` call is needed (the server is stateless).
```bash
curl -sS -X POST https://dochost.io/api/mcp \
-H "Authorization: Bearer $DOCHOST_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "publish",
"arguments": {
"body": "# My report\n\nHello world.",
"format": "markdown"
}
}
}'
```
### Reading the result
The response is JSON-RPC. The tool payload is a JSON string inside
`result.content[0].text`. Parse it and read `url`:
```bash
# ...pipe the curl output through jq:
| jq -r '.result.content[0].text | fromjson | .url'
```
A success payload looks like:
```json
{ "ok": true, "slug": "q3-report", "url": "https://dochost.io/d/q3-report",
"editToken": "…", "expiresAt": "2026-06-22T12:00:00.000Z" }
```
**Give the user the `url`.** Mention `expiresAt` if it is set (free links expire;
`null` means permanent). Keep `editToken` only if the user may want to edit later.
## `publish` arguments
| Argument | Type | Notes |
|---|---|---|
| `body` | string (**required**) | The Markdown or HTML to publish. |
| `format` | `"markdown"` \| `"html"` | Auto-detected when omitted. Set it if the content is ambiguous. |
| `public` | boolean | List on dochost Explore. Default `false` (unlisted). |
| `customSlug` | string · paid | Choose the link path instead of a random slug. |
| `password` | string · paid | Gate the page behind a password. |
| `noBranding` | boolean · paid | Hide the dochost footer badge. |
## List previously published pages
```bash
curl -sS -X POST https://dochost.io/api/mcp \
-H "Authorization: Bearer $DOCHOST_API_KEY" \
-H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"list_my_pages","arguments":{"limit":10}}}'
```
Returns compact records (slug, url, title, createdAt, expiresAt) — never page bodies.
## Errors the user should hear about
The payload has `ok: false` and a plain-English `message` on failure. Common cases:
- `RATE_LIMITED` — too many publishes; the message says how long to wait.
- Quota / size limits — free plan caps page count and document size; the message
tells the user to delete a page or upgrade.
- Blocked URL — the content contained an unsafe link and was not published.
- Invalid / taken `customSlug` — pick a different slug (lowercase, numbers, hyphens).
Relay the `message` verbatim; it is written for end users.
## Notes
- Never put secrets, tokens, or private keys in `body` — published pages are public
URLs (a password only gates the rendered page, not the fact a URL exists).
- Anonymous publishing is disabled by design; a valid key is required.
- Native MCP clients can instead add the server as a tool — see the repo's
`clients/` guides. This skill uses plain HTTP so it works even where MCP isn't wired.
don't have the plugin yet? install it then click "run inline in claude" again.
restructured original content into implexa six-component format (intent, inputs, procedure, decision points, output contract, outcome signal), added explicit edge case handling for auth, rate limits, quota, oversized bodies, and custom slug conflicts, clarified request/response parsing, added http status code decision logic, and removed marketing language throughout.
turn markdown or html into a hosted web page at its own url, in one call. the page renders live (markdown and html), so the recipient sees a real page, not a raw .md blob. free links last 7 days; permanent links, passwords, custom slugs and branding removal follow the account's plan.
publish user-generated markdown or html to dochost.io, a document hosting service, and return a shareable public url. use this when the user says "publish this", "share this as a link", "put this on the web", "make a page from this", "turn this into a link", or equivalent in other languages. works for any document, report, readme, or html the assistant produced. the skill runs on any agent that can make http requests (openai, anthropic, cursor, or shell).
environment variable (required):
DOCHOST_API_KEY: api key from dochost.io account. obtain it by signing in at https://dochost.io, opening settings, api keys, and creating a new key. the key authenticates all requests and determines plan entitlements (link lifetime, password protection, custom slugs, branding removal).procedure inputs:
body (string, required): the markdown or html content to publish.format (string, optional): either "markdown" or "html". auto-detected when omitted; set explicitly if content is ambiguous (e.g., a markdown string that contains html tags).public (boolean, optional): list the page on dochost explore. default false (unlisted, private link).customSlug (string, optional, paid feature): custom url path (lowercase, numbers, hyphens only) instead of a random slug. requires paid plan.password (string, optional, paid feature): gate the page behind a password. requires paid plan.noBranding (boolean, optional, paid feature): hide the dochost footer badge. requires paid plan.external connection:
https://dochost.io/api/mcp (stateless, no handshake required).edge cases to handle:
message field.validate inputs: check that DOCHOST_API_KEY env var exists and is non-empty. if missing, stop and tell the user to set up the key first (see intent section for setup link).
prepare request body: construct a json-rpc 2.0 call with method tools/call and params {"name": "publish", "arguments": {...}}. include body (required) and format if provided or auto-detect. include public, customSlug, password, noBranding only if the user explicitly requested them.
send http request: post to https://dochost.io/api/mcp with headers:
Authorization: Bearer $DOCHOST_API_KEYContent-Type: application/jsonAccept: application/jsonparse response: extract the response body as json. check for http status code (200 ok, 401 auth error, 429 rate limit, 402/400 quota/validation error, 5xx server error).
extract payload: if status is 200, parse result.content[0].text as json (it is a json string, not raw json). if parse fails, inform user that dochost returned malformed response.
read success fields: from the parsed payload, extract:
url: the public dochost.io/d/... link.expiresAt: the expiration timestamp (null means permanent).editToken: the token for later edits (store if user may want to edit; do not expose to end user unless requested).slug: the generated or custom slug.read error fields: if ok is false, extract the message field (plain-english error text written for end users).
return to user: on success, hand back the url as the primary result. mention expiresAt if set (e.g., "this link expires on [date]"). on error, relay the message verbatim without paraphrasing.
if api key is missing or invalid:
DOCHOST_API_KEY env var. do not retry or fall back to unauthenticated publishing (it is disabled by design).if http status is 401 (unauthorized):
if http status is 429 (rate limited):
if http status is 402 or 400 with quota/validation error in message:
if http status is 5xx (server error):
if response parse fails or payload structure is unexpected:
if user requests a paid feature (customSlug, password, noBranding) but the account plan does not support it:
if body is very large (>10 MB):
if format is ambiguous (e.g., html-like markdown or markdown with html tags):
format to the suspected type explicitly.on success:
return object with fields:
ok: trueurl: string, the public dochost.io/d/{slug} link (e.g., "https://dochost.io/d/q3-report")slug: string, the generated or custom slugexpiresAt: string (iso 8601 timestamp) or null if permanenteditToken: string (only if user may edit later; not exposed to end user by default)hand the url to the user as the primary artifact. format as a clickable link if possible.
if expiresAt is not null, include in the message: "this link expires on [date]".
on error:
return object with fields:
ok: falsemessage: string, plain-english error description (user-facing, no technical jargon)relay the message verbatim. examples:
file location / artifact:
url.the user knows the skill worked when:
https://dochost.io/d/{slug} url.expiresAt is set, they know when the link will expire.the user knows the skill failed when: