MCP App Store
by KeenEthics

Overview

Plan and edit a website's structure just by describing it. Octopus.do is a visual sitemap tool. Tell Claude what you're building — "a coffee subscription shop with a store, plans, a blog and a contact page" — and it lays out the sitemap for you: every page in place, nested the way it should be, with wireframe blocks sketching what goes on each one. Already have a project? Ask about it in plain language: what pages exist, how the structure is organised, what's on a given page. Then change it — add a pricing page under Products, move a whole section somewhere else, reorder things, clear out what you don't need. A big restructure happens in one step instead of dozens of clicks. Comments come through too. Ask what review notes your team left on a project, which page each one is on, and whether a thread is still open — then reply, resolve it, or leave a note of your own. Handy when you're scoping a new site, reworking an old one, or putting structure together to show a client or hand over to a developer. Works with both your own projects and your team's. You connect your own octopus.do account, and Claude only ever sees the projects that account can already open.

Tools

apply_changes

ChatGPT
Applies several editing operations to a project as ONE atomic change — the preferred way to build or restructure a sitemap. To restructure existing pages use nodes.move — never delete and recreate a page to relocate it (its content would be lost). Operations run in order and each sees the effect of the previous ones. Pick operation first: the schema then shows the data fields that operation takes, and each one names its parent in its own words — read the field list of the operation you picked. An operation that creates something can also take a ref: a local name later operations point at via the matching *_ref field instead of an id. Leave ref out on everything else, and whenever nothing later refers to what was created. Set dry_run: true to validate and preview without changing anything. Up to 100 operations per call, which is the API's own cap. Put as much of the job in ONE call as fits rather than splitting it up: a batch costs the same one write whether it carries 3 operations or 100, so splitting buys nothing and costs a round trip. A one-operation batch is right only when one change is genuinely all there is to make — if you are about to delete several pages, retitle several nodes, or clear starter pages, that is ONE call with several operations, not one call each. Only split what genuinely exceeds the cap, into sequential batches. ORDER MATTERS, and one case bites hard: emptying a container deletes it. Deleting the last page of a section removes the section, so any later operation naming that section — as parent_id, or as its own id — fails with "Not found" and takes the whole atomic batch with it, even though the id was valid when the batch was written. Verified against the live API. Deleting a page that still has siblings is safe anywhere in the batch. The rule that always works: create first, delete last. POSITION pages by naming a neighbour, not by counting: nodes.create and nodes.move take after_id/before_id (after_ref/before_ref for a page created earlier in this batch), which decide the parent too. An absolute index goes stale inside a batch — every earlier operation that inserts or removes a sibling shifts it — so prefer an anchor, and chain after_ref down a list of new pages to keep them in the order you wrote them. Never create a page and then move it into place: that is a second operation for something the create already does. Required data fields: every operation except the *.create ones and settings.update needs id (or id_ref) naming what it acts on. On top of that — sections.create {tab_id|tab_ref}; nodes.create and nodes.move {parent_id|parent_ref, or an after_id/before_id/after_ref/before_ref anchor instead}; blocks.create and blocks.move {node_id|node_ref}; sections.move_up and sections.move_down take only id and shift by ONE place, so moving a section N places is N of them in the same batch. Everything else takes only the fields being changed, e.g. blocks.create {node_ref, title, content, wireframes: ["header"]}. Content fields (block/symbol content, node notes.note) accept markdown or plain text and are read back as markdown. A successful result may include warnings[] — advisory notes about a change that WAS applied. They are not errors: nothing was rejected, nothing was half-applied, and repeating the call would duplicate the change. Pass the note to the user, or fix it with a follow-up edit, instead of retrying. One note exists today — URL_OUTSIDE_PARENT_PATH: a page whose url does not sit under its parent page's path, which is allowed and often deliberate (standalone SEO landing pages), so raise it rather than silently "correcting" a url the user chose. dry_run reports them too, so a preview shows what a commit would flag. The operations listed in the schema are the whole editing surface. If a request needs something none of them covers, say that it cannot be done here — never substitute a different operation for it, and never report it as done. Paid features follow the PROJECT OWNER's plan, which this server cannot report — and ONE gated operation fails th…

create_block

ChatGPT
Creates a content block (low-fi wireframe) inside a node (page). Blocks work on every plan; the wireframes on them do not — the wireframes field below lists every valid key and names the subset a free-plan-owned project may use.

create_node

ChatGPT
Creates a node (page) in the sitemap. The parent can be a tab, section or another node (ids come from get_project). The page can be POSITIONED as it is created rather than with a follow-up move_node — see after_id, before_id and index; with none of them it is appended. For several changes at once prefer apply_changes. A successful result may include warnings[] — notes about a change that WAS applied. They are not errors: nothing was rejected, and repeating the call would duplicate the change, so pass the note on or fix it with a follow-up edit instead of retrying. One code today, URL_OUTSIDE_PARENT_PATH: a page url outside its parent page's path — allowed and often deliberate (standalone SEO landings), so raise it rather than silently "correcting" it.

create_project

ChatGPT
Creates a new octopus.do project — personal by default, or inside a team workspace. The new project's uuid comes back as project_id (and as uuid), and outline carries the starting tree it was created with — tabs, sections and starter pages, with their ids. That is everything a first edit needs: do NOT call get_project after this, and build the whole sitemap in ONE apply_changes call using those ids. A fresh project comes with starter pages; delete the ones you do not want with nodes.delete operations at the END of that same batch, never one call each — see apply_changes on why deleting them first can fail the batch. May fail with 403 when the plan's project limit is reached; the message covers both that and a workspace the user cannot access.

delete_block

ChatGPT
Deletes a block from its node.

delete_node

ChatGPT
Deletes a node WITH its whole subtree and all blocks inside. To relocate a page use move_node instead — deleting and recreating loses its content.

get_me

ChatGPT
Returns the current octopus.do user's display name.

get_project

ChatGPT
Returns one project by uuid as a tree: tabs → sections → pages (each page recurses via children); entity ids for edits sit directly on the tree nodes. DEFAULT is view: "outline" — that tree stripped to titles/urls/nesting, an order of magnitude cheaper in tokens and enough to answer "what pages are in this project" or to locate the page to edit. It carries page ids, so page-level edits need nothing more. Pass view: "full" only when the answer actually needs page content — blocks and their wireframes, notes, colors/tags, estimates, symbols/arrows/stickyNotes — and prefer narrowing it: scope_id to read one branch in full, exclude to drop content groups. A full read of a large project is big enough that some clients truncate it. To act on what you find: apply_changes for multi-step edits, create_node / update_node / create_block for single edits, move_node to relocate a page — never delete and recreate a page to move it (its blocks would be lost). Existing blocks also show valid wireframe keys (blocks[].wireframes). Page notes read back in camelCase (seoTitle) though written snake_case (seo_title) — same field, not missing SEO. meta.ownerPlan is the project OWNER's plan TIER — read it before any write: "free" (or null, enforced as free) allows only the free wireframe subset, node variant "default" and the plain note, and rules out tabs.create, symbols, colors, tags and the paid settings fields — apply_changes lists them; "pro", "team", "agency" have all of it. Apart from ownerPlan, meta carries only the project id and created/updated dates — no member data.

get_workspace

ChatGPT
Returns one workspace by uuid: info, folders and projects. Use the literal uuid "my" for the personal workspace. Project uuids listed here feed get_project; create_project adds a project to this workspace.

list_comments

ChatGPT
Reads a project's review notes: comments on a page or a block, canvas threads (pins on the map) and the replies inside them. comments and threads come back separately: only a THREAD has a resolved state. Default: every comment kind plus OPEN threads. Page, block, thread and comment ids all look alike, so pair target_id with the matching kind. A thread whose anchor.type is null is an orphan — the page or tab it was pinned to is gone; deleting a page never deletes its pins, so orphans are common and are not an error. target/anchor also carry a title: null on an orphan, a reply, an untitled page, or an unreadable project. author is {id, name, avatar} — null if anonymous, name/avatar null if unknown; an avatar url is PUBLIC. On an anonymous comment guest_name is the UNVERIFIED name the visitor typed (null if none; always null on a thread) — say "someone calling themselves X", not "X". content is markdown. manage_comment takes ids from here. No access reads differently by scope: the threads half is refused outright, so a default call FAILS on a project you cannot read, while a comments-only call (kind of page/block/reply) gets an empty list back — which no caller can tell from a project that simply has no notes.

list_projects

ChatGPT
Lists the projects the user can access, across every workspace, most recently updated first; each item names its workspace. Summaries only — get_project takes a uuid from here. At most 50 per call on an account that may hold hundreds: total is how many matched, has_more whether any were left out. To find ONE project use q — it searches the whole account, not this page. Page with offset only when the whole list is needed.

list_workspaces

ChatGPT
Lists the user's workspaces (personal + teams) with their folders and the 10 most recently updated projects in each — project_count gives the real total, list_projects searches and pages the rest. The personal workspace has the uuid "my".

manage_comment

ChatGPT
Writes a review note on a project. add: WHERE it lands is decided by target.type with position — page alone comments on that page, page WITH position drops a canvas pin (a thread) on it, tab pins one on empty canvas, block comments on a block (a block takes no pin), thread replies inside an existing pin. delete accepts a comment id OR a thread id and works out which, but deleting a thread does NOT delete the replies inside it — they survive with nothing left to reach them. resolve/reopen are canvas THREADS only: a page or block comment has no resolved state and its id 404s here. Ids come from list_comments and are not interchangeable. The note is authored by the signed-in octopus.do account, is indistinguishable in the app from one typed by hand, and notifies NOBODY — say so instead of letting the user assume their team was pinged.

manage_project

ChatGPT
Project lifecycle actions: duplicate (copy), archive / unarchive, move (into a folder of a team workspace, or back to personal when workspace_id is omitted), transfer (give ownership to another user by email — the recipient must be a registered, non-free-plan user).

move_block

ChatGPT
Moves a block to another node (page).

move_node

ChatGPT
Moves a node with its whole subtree to another parent (tab, section or node), and/or REORDERS it among its siblings — reordering inside one section is this tool with an after_id/before_id anchor and no parent_id; with no anchor and no index it goes to the end of the new parent. A page is NOT pinned to where it was created: the new parent may be a different section, or a section in a different tab, and the page's children and blocks travel with it. ALWAYS use this (or apply_changes nodes.move) to restructure or nest existing pages — never delete and recreate a page to relocate it: that destroys its blocks and content. A successful result may include warnings[] — notes about a change that WAS applied. They are not errors: nothing was rejected, and repeating the call would duplicate the change, so pass the note on or fix it with a follow-up edit instead of retrying. One code today, URL_OUTSIDE_PARENT_PATH: a page url outside its parent page's path — allowed and often deliberate (standalone SEO landings), so raise it rather than silently "correcting" it.

update_block

ChatGPT
Updates block fields: title, text content, color, wireframes, collapsed/completed flags. The wireframes field below names the free-plan subset and where the full key list is.

update_node

ChatGPT
Updates node fields: title, color, url, variant, SEO notes (notes: {note, keywords, page_intent, seo_title, seo_description, seo_h1, seo_slug, seo_url} — all strings, merged with the existing notes). Every field is optional; only the ones passed change. A successful result may include warnings[] — advisory notes about a change that WAS applied. They are not errors: nothing was rejected, nothing was half-applied, and repeating the call would duplicate the change. Pass the note to the user, or fix it with a follow-up edit, instead of retrying. One note exists today — URL_OUTSIDE_PARENT_PATH: a page whose url does not sit under its parent page's path, which is allowed and often deliberate (standalone SEO landing pages), so raise it rather than silently "correcting" a url the user chose.

update_project_settings

ChatGPT
Updates project-level settings: title, theme, tree layout, page frame style, etc. PLAN GATE: image_mode and frame are Pro+ and fail with PLAN_REQUIRED when the PROJECT OWNER is on the free plan; title, theme, tree, legend and the rest work on every plan.

apply_changes

Claude

create_block

Claude

create_node

Claude

create_project

Claude

delete_block

Claude

delete_node

Claude

get_me

Claude

get_project

Claude

get_workspace

Claude

list_comments

Claude

list_projects

Claude

list_workspaces

Claude

manage_comment

Claude

manage_project

Claude

move_block

Claude

move_node

Claude

update_block

Claude

update_node

Claude

update_project_settings

Claude

Capabilities

Writes

Similar Apps