# MCP: DocPin for AI apps

DocPin is a remote [Model Context Protocol](https://modelcontextprotocol.io) server. Once it's connected, an AI app like Claude or ChatGPT can publish pages, update them, manage who can open them, and push data to them.

- **Server URL:** `https://mcp.docpin.app/mcp` (streamable HTTP)
- **Auth:** OAuth. The person signs in to DocPin and picks one workspace; the app then acts in that workspace with their rights.

## Connect

**Claude:** Customize → Connectors → Add → Add custom connector. Name it DocPin, paste the server URL, then Connect and sign in.

**ChatGPT:** chatgpt.com/plugins → Add → Add custom MCP server. Name it DocPin, keep OAuth, paste the server URL, create it, then Connect DocPin. In a chat, type `@DocPin`.

**Other MCP clients:** add a remote server with the URL above. The client discovers OAuth through the server's `/.well-known` documents and registers itself.

## Tools

Pages are referred to by `slug` (plus `board` if the page is in one) or by `id` from `list_pages`.

| Tool | What it does |
| --- | --- |
| `publish_page` | Publishes HTML (`html`) or several files (`files`: `[{path, content}]` with an `index.html`) and returns the links. **Reusing a `slug` publishes a new version behind the same link.** Optional `title`, `board`, `unlisted`, `access`. |
| `list_pages` | Pages with their links and slugs, newest first. Optional `board`. |
| `rename_page` | New title and/or slug. Old links redirect, and the short link never changes. |
| `move_page` | Moves a page into or out of a board. |
| `archive_page` | Hides a page from the page list without deleting it (`archived: false` brings it back). |
| `delete_page` | Deletes a page. Only when the person explicitly asks. |
| `set_access` | Who can open a page or board: `public`, `password`, `people` (emails and `@domains`), or `inherit`. Private pages need Pro. |
| `list_versions` / `restore_version` | Version history, and putting an earlier version live again. |
| `get_page_views` | How often a page was opened, and by whom on people-only pages. |
| `get_page_data` | A page's [data](/docs/page-data.md): the JSON object it reads with `docpin.data()`. |
| `set_page_data` | Updates a page's data without republishing. Merges by default (`null` removes a key); `replace: true` replaces everything. |
| `list_boards` / `create_board` / `update_board` / `delete_board` | Boards: landing pages that group related pages. |

The server also returns instructions on connect that summarise how published pages run. They're the same rules as [How pages run](/docs/page-runtime.md).

## Building pages with an AI app

For a page that's interactive or updated over time, a model should:
1. **Write the page to read from page data.** Lay out the HTML, then fill values from `docpin.data()`, or `docpin.onData()` for pages left open. Always handle empty data.
2. **Publish it** with `publish_page` and a clear `slug`.
3. **Fill in the data** with `set_page_data`. Use `get_page_data` first when changing an existing page's data, so no keys are lost.
4. **Update later** with `set_page_data` alone. Republish only when the layout changes, with `publish_page` and the same slug.
5. **Keep shareable state in the URL** (`history.replaceState`) and personal state in `localStorage`.

**Example conversation:**

> **Person:** Make me a dashboard of this week's support tickets and publish it to DocPin.
> **Model:** *(writes HTML that renders from `docpin.onData`, calls `publish_page` with slug `support`, then `set_page_data` with `{ "open": 42, "closed": 118, "asOf": "…" }`)* It's live at acme.docpin.it/support.
> **Person** *(the next day):* Update it: 37 open, 131 closed.
> **Model:** *(calls `set_page_data` with `{ "open": 37, "closed": 131, "asOf": "…" }`)* Updated. Anyone with it open will see the new numbers within a minute.

## Notes for app builders

- Tool results include structured content (`structuredContent`) alongside the text, for example links and ids from `publish_page`.
- Errors come back as tool results with `isError: true` and a plain-English message to show the person, such as an upgrade prompt for Pro features.
- `set_page_data` and publishing are each rate limited to about 30 a minute per workspace.
