DocPin
Publique páginas HTML, relatórios e dashboards da sua IA em um link próprio e escolha quem pode abri-los.
Servidor MCP hospedado
npx add-mcp 'https://mcp.docpin.app/mcp'Instala no Claude Code, Codex, Cursor e outros
Documentação
MCP: DocPin for AI apps
DocPin is a remote Model Context Protocol server. Connected to Claude, ChatGPT or another MCP client, an AI app can publish pages, update them, choose who can open them, and push data to them.
At a glance
| Server URL | https://mcp.docpin.app/mcp (streamable HTTP) |
|---|---|
| Auth | OAuth. The person signs in to DocPin and picks a default workspace. One connection can use every workspace they can publish to, with their rights in each |
| Scopes | publish for pages, data and entries; settings for workspace settings, granted when "Workspace settings" is ticked on connect. setup_docpin works without it |
| Results | Text for the model, plus structuredContent with links and ids. Errors come back with isError: true and a message to show the person |
| Instructions | Sent on connect: how published pages run, the same rules as How pages run |
Connect
| Client | Steps |
|---|---|
| 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. In a chat, type @DocPin |
| Other clients | Add a remote server with the URL. The client discovers OAuth through the server's /.well-known documents and registers itself |
Tools
Pages are referred to by slug (plus board if it's in one) or by id from list_pages.
Every tool acts in the default workspace unless you pass workspace (a workspace slug); list_workspaces lists the ones the person can publish to. Connections made before 11 November 2026 cover one workspace: disconnecting and connecting again upgrades them.
Publish and manage pages
| Tool | Key arguments | What it does |
|---|---|---|
publish_page | html or files ([{path, content, encoding?}] with an index.html; encoding: "base64" for binary files); optional slug, title, board, unlisted, access, draft | Publishes and returns the links. Reusing a slug adds a version behind the same link. A draft returns url: null and a previewUrl that lasts about an hour |
create_upload_link | Same options as publish_page | For agents that can run shell commands: a one-time link (15 minutes). curl -F file=@page.html <uploadUrl> publishes the file and prints the links as JSON. Faster, and works up to 25 MB, .zip included |
set_draft | draft, and access (plus listed) when sharing | draft: false shares a draft: the AI asks the person who should open it. draft: true makes a page a draft again |
list_pages | optional board | Pages with links and slugs, newest first |
rename_page | new_title and/or new_slug | Old links redirect; the short link never changes |
move_page | to_board (empty string for the top level), optional listed, unlisted | Into or out of a board, and whether it shows in listings. The old link redirects |
archive_page | archived | Hides it from the page list without deleting it |
delete_page | the page | Deletes it. Only when the person explicitly asks |
set_access | access (kind: team, public, password, people, inherit) | Who can open a page or, with only board, a whole board |
list_versions / restore_version | version_id | Version history, and putting an earlier version live |
get_page_views | the page | How often it was opened, and who opened it when signed in. Teammates' visits aren't counted |
Data and entries
| Tool | Key arguments | What it does |
|---|---|---|
get_page_data | the page | The page's data: the JSON object it reads with docpin.data() |
set_page_data | data, optional replace: true | Merges data in (null removes a key), or replaces everything. No new version |
set_page_entries | on: true or false | Lets viewers save entries (votes, RSVPs, answers), or stops new ones |
get_page_entries | optional collection | What viewers saved: totals, collections and the newest entries, with emails |
Workspaces and boards
| Tool | What it does |
|---|---|
list_workspaces | The workspaces the person can publish to, with their slugs, links, plan and role, and which is the default |
list_boards / create_board / update_board / delete_board | Boards: landing pages that group related pages |
Workspace settings
Most of these need the workspace owner. A logo works on Free; the rest of branding, custom domains and more teammates need Pro. They use the settings scope; a connection without it must be disconnected and connected again. ChatGPT doesn't show setup_docpin or get_billing_link.
| Tool | What it does |
|---|---|
setup_docpin | A guided setup: who sees new pages, existing work, branding, domain, team and Pro. Read-only |
get_workspace_settings | Plan, defaults, branding, custom domains and their DNS status, members and invites, and billing, in one call |
update_defaults | What new pages start as (new_pages: draft, team, link or listed), and how link and listed pages are protected (access, Pro) |
set_branding_image | slot (logo, logo-dark, icon or image) from an https url or base64, or remove: true |
set_board_template | template: default, clean, or custom with Mustache html (branding). Add board for one board, with inherit to undo; dark for dark mode |
add_custom_domain / check_custom_domain / remove_custom_domain | Connect a domain like docs.acme.com. Adding returns the CNAME record to set |
invite_member / remove_member | Invite someone by email, or remove them or cancel their invite |
get_billing_link | To upgrade, a Stripe checkout link (interval: month or year); the person pays on Stripe. Already on Pro, the app's billing page |
Deleting the workspace or account, and creating API keys, stay in the app.
How a model should build pages
| Page | Build it like this |
|---|---|
| Static (a report, a proposal) | publish_page with a clear slug. Republish with the same slug to update |
| Updated over time (a dashboard) | Render from docpin.data() or docpin.onData(), with an empty state. publish_page, then set_page_data. Later updates are set_page_data alone. Call get_page_data before replacing data |
| Collecting from viewers (a poll, RSVPs) | Use docpin.shared and docpin.mine, save from a click handler, and show entries with textContent. publish_page, then set_page_entries with on: true. Read results with get_page_entries |
| Interactive (tabs, filters) | Keep shareable state in the URL with history.replaceState, and personal state in localStorage |
Person: Make me a dashboard of this week's support tickets and publish it to DocPin.
Model: (writes HTML that renders from
docpin.onData, callspublish_pagewith slugsupport, thenset_page_datawith{ "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_datawith{ "open": 37, "closed": 131, "asOf": "…" }) Updated. Anyone with it open will see the new numbers within a minute.
Limits
publish_page and set_page_data are each limited to about 30 calls a minute per workspace.