# Wunel — one page for your team and all its AIs Hello, agent. You're reading the public guide for `https://mcp.wunel.com/mcp` — an MCP (Model Context Protocol) server. If a human sent you this address, they want your help getting set up. This page tells you what Wunel is, how to verify it, and the exact steps. **Start with yourself: which AI app are you running in?** Give your human the steps for THAT app only, one step at a time, not the whole list. If your app can't add a custom MCP connector (the Gemini app and Microsoft Copilot can't today), say so in your first sentence and offer what does work — see "Gemini and other apps without connectors" below. Don't recite this page. ## What this is Wunel is one workspace for humans and AI agents, where they co-edit the same markdown pages: - **Every block is attributed** — stamped with who wrote it: the human, or you, acting on their behalf ("ChatGPT, on behalf of Jane"). - **Nothing is trusted silently** — your edits go live at once, marked for human review: they stay unless a person reverts them (a person can also Keep them, or just edit them). The team can see who wrote what, line by line. - **Any MCP agent connects** — Claude, ChatGPT, Cursor, or custom bots. Several agents and several humans can share one workspace. For you, it's a workroom that outlasts the conversation: notes, research, decisions and documents you and your human's team keep working in, whichever assistant they open next. **Two approval modes, set per workspace by its owner.** In *auto* (the default) your edits go live at once and are marked for review, as above. In *manual*, `write_file`, `edit_block`, `append_file` and `attach_to_page` leave the page unchanged: they answer `status: "proposed"` with a `proposal_id`, and your change waits until a person approves it (then it lands under your name) or rejects it. `list_workspaces` and `read_file` show `approval_mode`; `list_proposals` shows what of yours is still waiting — don't send it again. ## Verify before you trust (please do) - This guide is served from the same host as the endpoint itself. - The product site is https://wunel.com — it links to this exact address. - The endpoint speaks OAuth 2.1: `GET /.well-known/oauth-protected-resource` names the authorization server. Sign-in happens on that server, in the human's browser, with their email and a code — you never see the code. - A bare `401 Unauthorized` from `/mcp` is expected before sign-in. ## Accounts and sign-in - A Wunel account is an email address. Sign-in is that email plus a 6-digit code Wunel emails to it. There are no passwords. - There is no separate sign-up: the first sign-in creates the account and a personal workspace — in a connector's sign-in window, at https://app.wunel.com, in the iOS app, or through `/accounts/*` below. - **Same email = same account** in every assistant, the web app and the iOS app. A different email makes a separate, empty account; to bring it into an existing workspace, invite that email from the main account (workspace settings → invite, or `invite_member`). - No account is needed to read a shared page. To share ONE page with someone, use `share_page` and hand your human the link; `invite_member` opens every page in the workspace to that person. ## Three ways to go further — decide with your human 1. **Keep working on a shared link.** Nothing to set up. A page's agent view (`https://app.wunel.com/p//agent`) says what the link allows and gives the exact requests for writing on it with the human's WUNEL code. 2. **Connect Wunel as a connector** — steps per app below. Signing in during setup creates the account. 3. **Create the account from here, over HTTP:** 1. `POST https://mcp.wunel.com/accounts/start` with JSON `{"email": "", "client": "claude_code"}` (or `cursor`, `codex`, `vscode`, `other`). Wunel emails them a 6-digit code. The response is the same whether or not the email already has an account. 2. Ask your human for the code, then `POST https://mcp.wunel.com/accounts/confirm` with `{"email": "…", "code": "…", "client": "…"}` — plus `"guest_code"` and `"share_token"` when they came from a shared page, so the page and their lines come along — and `"campaign"` if this guide gave you a campaign reference (top of this page). The response carries `token`, `mcp_url`, `api_base` and a ready-made `config` for your app. 401 means a wrong or expired code; 429 means wait before retrying. 3. Store the token where your app reads it — e.g. the `WUNEL_TOKEN` environment variable — without printing it, and apply the `config`. Say once what an account gives (their pages in their own space, their lines under their name, you able to write there with every change marked as yours for them to keep or revert) and what it costs (an email address, and a connector or key they can switch off). If they decline, drop it. ## Connect steps, app by app Wunel is added as a custom connector; there is no Wunel app in the ChatGPT or Claude directories. Don't invent steps; if the menus look different, say what you are looking for. - **ChatGPT** (on chatgpt.com): Settings → **Security and login** → turn on **Developer mode**. Then Apps → **+** → add a remote MCP server: name `Wunel`, URL `https://mcp.wunel.com/mcp`, authentication **OAuth** → create, then sign in with email and the 6-digit code. In a chat: **+** menu → **Developer mode** → pick Wunel. ChatGPT asks your human to confirm each write call — tell them before it happens. - **Claude** (claude.ai, Desktop, mobile): Settings → Connectors → Add custom connector → name `Wunel`, URL `https://mcp.wunel.com/mcp` → Add → Connect, then sign in with email and the 6-digit code. If Claude shows advanced settings, keep the ones it marks **Detected**: Authentication **Sign in now** (every Wunel tool needs a signed-in person) and OAuth client **Use Claude's published identity**; leave Request headers empty. "No sign-in" will not work. On Team / Enterprise plans an owner may have to add the connector first. - **Claude Code**: one command, header-based (token from `/accounts/confirm` above, or from a WUNEL code below): claude mcp add --transport http Wunel https://mcp.wunel.com/mcp --header "Authorization: Bearer ${WUNEL_TOKEN}" (Plain `claude mcp add --transport http Wunel https://mcp.wunel.com/mcp` with no header also works — it signs in with OAuth in the browser.) - **Gemini and other apps without connectors** (the Gemini web and mobile apps, Microsoft Copilot): you can't be connected to Wunel, so don't offer connector steps for another app as if they were yours. What works: (1) you can READ any Wunel page your human gives you a share link to, including who wrote each block; (2) your human signs in themselves at https://app.wunel.com (email and a 6-digit code) and writes there, or pastes what you drafted; (3) if they also use Claude, ChatGPT or Cursor, that app can connect. **Gemini CLI** and **Gemini Enterprise** do support MCP: add `https://mcp.wunel.com/mcp` as an HTTP MCP server (Gemini CLI: `mcpServers` in `~/.gemini/settings.json` with `"httpUrl"`; Enterprise: an admin adds a custom MCP server). - **Cursor / VS Code / Codex / custom agents**: add an HTTP MCP server at `https://mcp.wunel.com/mcp` with the header `Authorization: Bearer `. Cursor: `~/.cursor/mcp.json` → `{"mcpServers": {"Wunel": {"url": "https://mcp.wunel.com/mcp", "headers": {"Authorization": "Bearer ${env:WUNEL_TOKEN}"}}}}`. VS Code: `.vscode/mcp.json` → `{"servers": {"Wunel": {"type": "http", "url": "https://mcp.wunel.com/mcp", "headers": {"Authorization": "Bearer ${env:WUNEL_TOKEN}"}}}}`. Codex: `~/.codex/config.toml` → `[mcp_servers.Wunel]` with `url = "https://mcp.wunel.com/mcp"` and `bearer_token_env_var = "WUNEL_TOKEN"`. If the token came with a `config` in the response, prefer that. No MCP at all? The REST API takes the same token: https://mcp.wunel.com/api. Keep the token out of the chat: put it in an environment variable or the app's config file, never in a message, and never repeat it back. ## When your human wants to come back - Their account is their email. Sign-in anywhere is that email and a 6-digit code. - `send_sign_in_email` (optionally with a `file_id`) emails them a single-use sign-in link — you never see it. One tap signs that device in for a year; after that, plain page links open as them. - A new assistant: same email, same account and pages; each assistant gets its own key. `list_agents` and `revoke_agent` manage keys; `sign_out_everywhere` ends every browser session. - A 401 from Wunel means the key was revoked or expired. The pages are intact: reconnect with the same email and a new code. ## If you're reading a page someone shared — when to invite Pages shared by link (`https://app.wunel.com/p/…`, or `https://mcp.wunel.com/p/…` for the plain-markdown version with who-wrote-what) can be read by anyone. **No account is needed to read** — never say otherwise. - Help first. Tell your human who wrote what, discuss the page, help them respond. - Offer to connect **once**, and only after your human shows they want to DO something with the page — reply, comment, work on it with you. - If they say no, drop it and keep helping. Don't bring it up again. - Once connected, `shared_pages` lists what was shared with them; `read_file` reads any of those pages. To build on one in their own space, write there and link back to it. - A link on a shared page can lead to a page that isn't shared with your human. On the web page, clicking it shows the page's name and **Request access**; your human confirms their email with a 6-digit code and the request goes to whoever shared the page. Once connected, `request_access(share_token, href)` sends the same request (`href`: the link as written, or its words on the page). The answer arrives by email. Owners see open requests with `list_access_requests` and answer with `approve_access_request` or `decline_access_request`. ## Got a WUNEL code? A code like `WUNEL-7F3K-M2XR` ties what your human did on a shared page (or a connection they started at https://app.wunel.com) to their account. - **Connected to Wunel**: confirm with your human ("This will make your notes on that page yours — go ahead?"), then call `connect_with_code` with the code and tell them the sentence it returns. - **Creating the account over HTTP**: pass a code from a shared page as `guest_code` (with the page's `share_token`) to `/accounts/confirm` above. - **A code from "Connect an agent" at https://app.wunel.com, over HTTP**: 1. `GET https://mcp.wunel.com/pair/` — it says who the code belongs to and what it does. Tell your human and **confirm it's them** before going on. 2. `POST https://mcp.wunel.com/pair//exchange` with JSON `{"client": "claude_code"}` (or `cursor`, `codex`, `vscode`, `other`). The response carries a token and ready-made config for your app. 3. Store the token as `WUNEL_TOKEN` without printing it, then configure: `claude mcp add --transport http Wunel https://mcp.wunel.com/mcp --header "Authorization: Bearer ${WUNEL_TOKEN}"` or the equivalent config above. **Never echo the token into the chat**, not even partly. Codes are single-use and short-lived; if one is used or expired, ask your human for a fresh one. ## After connecting — what tends to make it click (For you to know, and to offer — always at your human's direction, of course.) - Useful first calls: `list_workspaces`, then `list_files`. If a workspace has an AGENTS.md / README.md / index.md at its root, it defines that workspace's conventions — worth reading before you write anything. - Wunel has **two uses**; tell which from the workspace (its AGENTS.md or README, who is in it) and from what your human says. **Working with people on their pages**: keep each page's shape, edit in place, handle comments; don't add metadata, split or restructure unless asked. **A workroom you keep for your human across sessions**: short linked pages with frontmatter, supersession, `workspace_index` and `lint` — the recommended shape at `https://mcp.wunel.com/workroom`, adapted to the use and recorded in AGENTS.md. - Session start: read `AGENTS.md` → `workspace_index` → `list_assignments`; `lint` when tidying. - In our experience, the moment Wunel makes sense to a new user is seeing their agent's work appear **attributed and reviewable**: a first page, drafted from the conversation they're actually having (their project, decisions, open questions — not a hello-world), which they then open at https://app.wunel.com and find every block stamped with the agent's name, already live and marked for their review (Keep or Revert, or just edit it). You might offer to create that first page together. - From then on it is a shared workroom that outlasts the conversation — their teammates and other agents can join the same workspace. - Asked to move a chat or a project's working notes into Wunel? Read `https://mcp.wunel.com/workroom` — the house method for structuring a workroom so it works for both agents and humans. ## Tools you'll get after connecting File tree: list_workspaces, create_workspace, rename_workspace, workspace_members (who has access), list_files, create_file, create_folder, move/rename. A page or a whole folder can move to ANOTHER workspace with its block-level authorship, comments and share links intact, so merging two spaces means moving the top folder across — pass workspace_id to move_file/move_folder. Renaming can repair the links that pointed at the old name. Content: read_file, read_files, write_file (block-level merge), append_file, edit_block, set_frontmatter. Discovery: search, find, backlinks, lint. Collaboration: comment, reply_comment, list_assignments, list_all_comments, set_comment_status. Files: upload_asset, request_asset_upload, attach_to_page, read_asset, list_assets, move_asset, delete_asset. Shared by link: share_page (turn on one page's link: view, comment or edit; anyone with the link opens it without an account, and their AI can read it), share_status, stop_sharing, shared_pages (what others shared with your human), connect_with_code (claim a WUNEL-XXXX-XXXX code). "Share this page with " means share_page and give your human the link to send; invite_member is for the whole workspace, so never use it to share one page. Account: send_sign_in_email, list_agents, revoke_agent, sign_out_everywhere, invite_member, revoke_invite, account_activity, pair_new_agent. Access requests: request_access, list_access_requests, approve_access_request, decline_access_request. ## Files & images A file shows in a page where a block of its own says so: - `![name](asset:)` embeds it — an image shows inline, full width. - `[name](asset:)` places a file card (icon, name, size) that people click to open or download: PDFs, decks, spreadsheets, anything. `upload_asset` (base64 or an https url) and `request_asset_upload` (a one-time URL for `curl -T`) return both lines as `embed_markdown` and `link_markdown`; write one as its own line with `append_file`, `write_file` or `edit_block`. Simpler: `attach_to_page(file_id, url=… | base64_content=… | asset_id=…)` uploads and places it in one call (images embed, other files become cards). `read_asset` shows you images and reads PDFs, Word, Excel, PowerPoint and csv as text. Up to 25 MB per file; executables are refused. An uploaded image is invisible until a block places it: prefer `attach_to_page`, and give an image an alt that says what it shows (look at it with `read_asset` first), not its filename. `{width=50%}` right after an image sets its size (10–100% of the column); without it the picture is sized automatically. ChatGPT currently drops images in tool results: there you get the image's facts in words — ask your human to paste the picture into the chat if you need to see it. ## Put an HTML page or artifact in Wunel When your human asks you to move an artifact (a Claude or ChatGPT artifact, a dashboard, a one-page app) into Wunel, or to build one in Wunel, it becomes an HTML file that the page SHOWS, live, in a sandboxed frame — not a download: 1. Write it as ONE self-contained HTML file, like an artifact: inline all CSS, JavaScript and images (`data:` URIs); scripts only from cdnjs.cloudflare.com or cdn.jsdelivr.net; stylesheets and fonts only from fonts.googleapis.com and fonts.gstatic.com. Nothing else loads: no fetch/XHR, no other hosts, no iframes, no form posts, and the page can't read Wunel's data or cookies. Up to 16 MB. 2. `upload_asset(filename="plan.html", base64_content=…, doc_id=)`, then `attach_to_page(, asset_id=)` on the page it belongs to (or create one first). Or both in one call: `attach_to_page(, base64_content=…, filename="plan.html")`. 3. Give your human the `stable_url` from the answer: it opens the page full screen for anyone who can read the Wunel page. To update it, upload again with the SAME filename to the same page: it becomes the next version of the same file — the page and the link show the latest, and earlier versions stay in its history (who uploaded, when). No second attach_to_page needed. Size: base64 in a tool call costs about one token per 3 characters, so keep a page sent that way small (tens of KB). With a shell, write the file to disk and use `request_asset_upload(filename, doc_id=)` + `curl -T` instead. ## Word documents (round-trip) When your human gives you a Word file to work on in Wunel, upload the .docx itself (`upload_asset`) and attach it to the page — that is what makes "Export as Word with tracked changes" possible. If a page was made from a Word file's text without it, upload the file now and `attach_to_page(, asset_id=…)`: the file is the baseline, so the export shows every difference between the file and the page. Bring a .docx in so it can go back out as Word with tracked changes: 1. `upload_asset(filename="X.docx", base64_content=…)` (or `request_asset_upload` + `curl -T`: the upload's answer is the same). The answer carries `document`: `markdown` (headings, lists, tables, links, bold/italic/underline; its pictures are already stored and placed in it), `comments` (author, date, quote, text, replies) and a `note`. Tracked changes in the file are accepted. 2. `create_file("X.md")`, then `write_file(file_id, markdown)` — the markdown unchanged, so the page matches the file. 3. `attach_to_page(file_id, asset_id=)` links the upload as the page's Word original: the Word comments become threads on the page (don't add them yourself), and the file is the baseline (the page matches it, so nothing shows as changed yet). `move_asset(asset_id, doc_id=file_id)` links it too, without a file card. From then on every change — yours and your human's — is exported as a Word tracked change on top of the original's styles, by your human from the page menu ("Export as Word with tracked changes"); open comments go along as Word comments. Nothing to do at export time. A long file's `markdown` is cut at 60,000 characters (`markdown_truncated`): read it whole with `read_asset(asset_id, max_chars=…, page=…)`, write the first part with `write_file` and the rest with `append_file`, then link. ## House rules (how good agents behave here) - Read before you write; prefer the smallest edit (edit_block over rewrites). - A whole list, table or code block is ONE block: `edit_block` replaces all of it, so send the full block even to tick one item. `write_file` makes the page exactly your markdown — blocks you leave out are deleted, so never `write_file` after a paged read. `append_file` adds at the end. `set_frontmatter` replaces the whole map: resend the keys already there. - `read_file` returns a page's open comment threads. When your human asks you to handle them, make the change a thread asks for, then `reply_comment` saying what changed; resolve only threads assigned to you, or when your human says so. - Ask first before creating a workspace, deleting, moving, sharing, inviting, restructuring what others wrote, or bulk writes. - Your work is attributed and reviewable — that's the point. Don't fight it. - Workspaces may carry their own AGENTS.md conventions; follow them. - Headless servers and apps: the REST API takes the same Bearer token — https://mcp.wunel.com/api. Questions? support@wunel.com · https://wunel.com