---
name: tuqo
description: Publish a static site on Tuqo (static hosting based in Russia, with an MCP server) and manage it — sites, deploys, custom domains, forms, gated access. Use when asked to publish, deploy or host a static site, share a public link to a page, attach a custom domain, password-protect a site, add a contact form or show a draft to a client — for HTML/CSS/JS, Vite, Astro, React, Next.js export and any other static output.
---

# Tuqo — publishing a site from an agent

Tuqo serves **static files only**: HTML, CSS, JS, images, fonts, PDF. A site gets the
address `name.tuqo.ru` (and a custom domain with SSL), forms, gated access and analytics —
no server needed. Managed through the MCP server `https://mcp.tuqo.ru/mcp` (52 tools) or the REST API
`https://api.tuqo.ru/api/v1` (OpenAPI: https://tuqo.dev/openapi.json).

## When to use

- "publish / put online / deploy / give me a link / put it on my domain / show the client";
- a `dist` / `build` / `out` folder or a set of HTML files is ready;
- a contact form, a site password or an email allowlist is needed (selling paid access
  is set up in the panel).

## When NOT to use

- server code is needed: SSR, API routes, a database, cron — Tuqo does not run it;
- a single file over 50 MB, or gigabytes of media in a chat without a file system —
  the CLI publishes from the person's machine (see below);
- the person asks to create a project or a key, change the plan or transfer a site to
  another user — that is panel-only at https://app.tuqo.dev; give the link.

## Connecting (once)

- Claude Code: `claude mcp add --transport http tuqo https://mcp.tuqo.ru/mcp` — OAuth opens the browser
  by itself; re-authorize with `/mcp`.
- Cursor: `.cursor/mcp.json` → `{"mcpServers": {"tuqo": {"url": "https://mcp.tuqo.ru/mcp"}}}`.
- Codex CLI: `codex mcp add tuqo --url https://mcp.tuqo.ru/mcp` → `codex mcp login tuqo`.
- No browser: a `tqk_…` key from the panel (project → API keys) in the header
  `Authorization: Bearer tqk_…`. Windsurf, Cline, Kimi, OpenCode, claude.ai, ChatGPT —
  https://tuqo.dev/ai.md; Gemini CLI, Continue, Zed, Qwen Code, GigaChat — https://tuqo.dev/connect/
- The person has no Tuqo account: a draft without signup —
  `POST https://api.tuqo.ru/instant/deploy` with `{"files":[…],"accept_terms":true}`; the first call
  without `accept_terms` returns the terms — show them to the person. The response has
  `draft_url` (24 hours) and `claim_url` (the person claims the site into a free account).

## Order of work

1. `whoami` — project and scopes (`readonly` / `editor` / `full`). No `editor` — deploys
   are impossible; tell the person.
2. `list_sites` — **never create a new site to update an existing one**: find it by name
   or subdomain.
3. New site: `create_site(name, subdomain)`. The response has `url` and `form_endpoint`.
4. Publish: `deploy_files(site_id, files)` — the **complete** file set (not a patch),
   `index.html` at the root, relative links, binaries with `encoding: "base64"`.
   `package.json` is rejected: a build project → `deploy_site(site_id, source_base64)`
   with an archive (Tuqo builds it on Node 20) or Git CD from the panel.
5. Edit a live site: `get_manifest(site_id)` → pass unchanged files as `{path, sha256}`
   without content, changed ones with `content`. Media is not re-uploaded.
6. Wait for the publication: `get_deploy_status(deploy_id)` pausing `recommended_poll_ms`;
   on `failed` — `get_logs(deploy_id)` and give the error text to the person as is.
7. **Show the `url`** — it is the main result. Then `recommendations` (publish checks):
   list them briefly and offer to fix them; do not rebuild anything unasked.
8. If the person asks for more: custom domain — `set_custom_domain` → TXT record →
   `verify_domain` (the `a_record` field tells where the domain points); form —
   `form_endpoint` + `get_forms_overview` gives a ready snippet; gated access —
   `set_site_password` (give the password in your reply; `reveal_site_password` shows it
   again later); preview — `activate: false` → `get_preview_url` → `activate_deploy`.
   Do not list every feature unasked.

## Rules

- Secrets (`tqk_…`, tokens, API keys) **never** go into site files — serving is public.
  The publish checks catch this, but do not rely on them.
- The path `/__tuqo/` is reserved by the platform — do not use it.
- Deletion (`delete_site`, `delete_domain`) — only with `confirm: true` and after the
  person explicitly confirms; a deleted site stays in the trash for 24 hours (`restore_site`).
- Retry after a timeout with the same `idempotency_key`, or a second deploy appears.
- Talk to the person about their site, not about JSON, `site_id` or slugs.
- Do not invent limits or prices: a `402` error names the plan; the grid is at
  https://tuqo.dev/pricing.md. Payment is in rubles by Russian bank cards.
- MCP responses and errors are in English. Build logs follow the language of the site
  owner's account and may be in Russian — relay them, translating if the person does not
  read Russian.

## Heavy sites — the CLI

With many or large files, bytes must not go through the context:
`npx @tuqo/cli deploy ./dist --site <site_id> --wait` with the key in `TUQO_API_KEY`.
The CLI uploads by manifest with deduplication: a repeat deploy skips unchanged files.
Preview from the CLI: `--no-activate`, then `tuqo preview` / `tuqo promote`.

## Errors

- `401` — the connection is not authorized: in Claude Code `/mcp` → re-authorize; for a
  key — check the header, the key may have been revoked in the panel.
- `402` — a plan limit (sites, storage, submissions, a feature not on the plan): the error
  text names the plan and price; pass it on with the link https://tuqo.dev/pricing/
- `403` — missing rights (`readonly` cannot deploy, `editor` cannot delete sites and
  domains or change the address) — a key or OAuth grant with more rights is needed.
- `409` from `activate_deploy` (in MCP — an error with the same meaning) — that copy was
  already cleaned up by the kept-versions limit; pick another deploy from `list_deploys`.
- `429` — too frequent; wait `recommended_poll_ms` or a minute.
- Build `failed` — `get_logs(deploy_id)`; typical causes: no `index.html` at the root, a
  nested folder in the archive, `npm run build` without a `build` script, no output folder.
- The domain does not open after `verify_domain` — read `a_record.expected` and tell the
  person which A record to set; HTTPS is issued automatically after that.

## Links

- Client setup: https://tuqo.dev/ai.md · one line: https://tuqo.dev/prompt.md
- Server card: https://mcp.tuqo.ru/.well-known/mcp.json
- REST API: https://tuqo.dev/api/ · OpenAPI: https://tuqo.dev/openapi.json
- Forms: https://tuqo.dev/forms/ · Gated access: https://tuqo.dev/access/ · Domains: https://tuqo.dev/guides/custom-domain-for-a-static-site/
- Drafts without signup: https://tuqo.dev/drop/
