---
name: kite
description: Publish pages and files to Kite (kite.new) and get shareable links; read who opened them and what they said.
---

# Kite skill

Use Kite when the user wants to share something you made (a page, dashboard, report, document) with other people as a link.

## Setup
If your host supports MCP with OAuth, add https://kite.new/api/mcp as a server and let the user sign in. Otherwise the user creates an API key at https://kite.new/settings (Connect); ask them to paste it once, store it as KITE_API_KEY, never print it back.

## Publish
POST https://kite.new/api/mcp with the MCP Streamable HTTP protocol, or call the REST-like JSON-RPC:
- One document of HTML or Markdown: tools/call publish_page { title, content } -> url
- Anything else: request_upload_url { files: [{ filename, source_url }] } -> url, in one call
- Or, with no URL and no way to PUT (an image you generated): request_upload_url { files: [{ filename, size, mime }] } -> re-encode to web size, base64, upload_chunk { page_id, path, chunk_index, total_chunks, data } in pieces of ≤100,000 chars -> finalize_upload { page_id } -> url
- Or, if you can PUT: request_upload_url { files: [{ filename, size, mime }] } -> PUT each file's bytes to its own upload_url with the returned headers -> finalize_upload { page_id } -> url

Use the second or third whenever the page is not a single blob of text: an HTML page with its images, CSS and JS; a built site or exported folder; or one file on its own (PDF, image, xlsx, docx, pptx, and source files like .py or .json, which get a syntax-highlighted viewer). Pass every file in one call — index.html becomes the page and the rest are served beside it, so `<img src="photo.jpg">` resolves. Several images and no HTML become a gallery: one page, every photo in order, a rail of thumbnails, and download-all as a zip. Do not inline images as base64 data URIs.

**Prefer `source_url`.** Give a file the URL its bytes live at and Kite downloads them and publishes the page in that single call. It is the only route open to a caller that cannot make an arbitrary HTTP PUT — which is most of them, and an image you generated is bytes you are holding a reference to, not bytes you can send. Only use `size` when you really can PUT. Either way you get a `warning` naming anything the page asks for that never arrived — read it before handing over the link, and never publish a page that describes an image it does not contain.

## After publishing
- Tell the user the url on its own line.
- Offer to restrict it: set_audience { page, audience: "code" | "email_gate" | "restricted", emails, code }. With "code" the page opens only for someone who types the code; tell the user the code alongside the link.
- If the user dislikes the name in the link, it can be changed in the page's share panel, and every link already sent keeps working.
- Later, get_views and get_comments to report who opened it and what they said; reply_comment to answer. get_comments tells you what part of the page a pinned comment is about.

## Finding and removing
- search_pages { query } searches inside pages, not just titles — use it when the user describes a page rather than names it.
- delete_page { page } moves a page to Trash; the link stops working and it can be restored in the app for 30 days.

## Vocabulary
Say "page" and "link". Do not mention MCP, slugs or tokens to the user.
