← WebMCP Directory

Tool tree

copresence-canvas.vercel.app

Productivity & BusinessTools verified
Website
An infinite canvas where a human and an AI agent edit the same live in-browser scene at the same time, over WebMCP.
Explore capabilities
    get_sceneAnswer

    Read the live canvas: every sticky note with its id and text, plus edges, regions, annotations and overall bounds, as structured JSON. Call this first — you cannot act on the board until you have seen it. This state lives only in the page; no server has it. Every note and edge carries `seat` (which participant last touched it) and `mine` (true when it was you or the human you sit beside), so you can tell your own work from a peer's without diffing snapshots. Re-read this after any pause: other people and their agents are editing the same board and nothing notifies you when they do.

    View tool JSON
    {
      "name": "get_scene",
      "kind": "answer",
      "impl": "imperative",
      "description": "Read the live canvas: every sticky note with its id and text, plus edges, regions, annotations and overall bounds, as structured JSON. Call this first — you cannot act on the board until you have seen it. This state lives only in the page; no server has it. Every note and edge carries `seat` (which participant last touched it) and `mine` (true when it was you or the human you sit beside), so you can tell your own work from a peer's without diffing snapshots. Re-read this after any pause: other people and their agents are editing the same board and nothing notifies you when they do.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      }
    }
    what_changedAnswer

    Find out what happened on this board while you were not looking. Pass the `asOf` or `cursor` you were given last time as `since`, and you get back every change made in between — who made it, what it was, and which notes it touched — instead of having to keep an old get_scene and diff it by hand. Anything marked `mine: false` was another participant or their agent: it is their work, not a stale copy of yours, so read it before you rearrange or undo it. Call this after any pause, and after any call that took longer than you expected. Calling it with no `since` gives you a starting cursor rather than the whole session.

    View tool JSON
    {
      "name": "what_changed",
      "kind": "answer",
      "impl": "imperative",
      "description": "Find out what happened on this board while you were not looking. Pass the `asOf` or `cursor` you were given last time as `since`, and you get back every change made in between — who made it, what it was, and which notes it touched — instead of having to keep an old get_scene and diff it by hand. Anything marked `mine: false` was another participant or their agent: it is their work, not a stale copy of yours, so read it before you rearrange or undo it. Call this after any pause, and after any call that took longer than you expected. Calling it with no `since` gives you a starting cursor rather than the whole session.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "since": {
            "type": "number",
            "description": "The cursor from a previous what_changed, or `asOf` from get_scene."
          }
        },
        "additionalProperties": false
      }
    }
    get_board_contextAnswer

    Find out who you are and who else is on this board. Returns your own seat name, what your human currently has selected — which is what they mean by "these" — the seat name and held notes of every other person connected, whether each of them has an agent of their own, and the rule that governs a whole-board change. Call this before your first change on any board you have not seen: without it you cannot tell your own work from a peer's, and you cannot interpret a refusal, which names a seat ("Ochre declined") rather than describing one. It also reports whether this tab is in the background, which is the usual reason a call takes far longer than you expect.

    View tool JSON
    {
      "name": "get_board_context",
      "kind": "answer",
      "impl": "imperative",
      "description": "Find out who you are and who else is on this board. Returns your own seat name, what your human currently has selected — which is what they mean by \"these\" — the seat name and held notes of every other person connected, whether each of them has an agent of their own, and the rule that governs a whole-board change. Call this before your first change on any board you have not seen: without it you cannot tell your own work from a peer's, and you cannot interpret a refusal, which names a seat (\"Ochre declined\") rather than describing one. It also reports whether this tab is in the background, which is the usual reason a call takes far longer than you expect.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      }
    }
    get_human_activityAnswer

    See what the human has been doing on the canvas alongside you: which notes they have added, edited or moved recently, and which notes they are physically holding right now. You are both working on this board at the same time — check this before rearranging an area, and never move a note the human is currently holding. Other people, each with an agent of their own, may also be on this board; anything they or their agents have hold of is reported here and is not yours to move.

    View tool JSON
    {
      "name": "get_human_activity",
      "kind": "answer",
      "impl": "imperative",
      "description": "See what the human has been doing on the canvas alongside you: which notes they have added, edited or moved recently, and which notes they are physically holding right now. You are both working on this board at the same time — check this before rearranging an area, and never move a note the human is currently holding. Other people, each with an agent of their own, may also be on this board; anything they or their agents have hold of is reported here and is not yours to move.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "sinceSeconds": {
            "type": "number",
            "description": "How far back to look, in seconds. Defaults to 120."
          }
        },
        "additionalProperties": false
      }
    }
    arrange_regionAction

    Physically reposition a set of notes into a spatial layout. You choose WHAT belongs together and the shape it should take; the page computes where each note goes and animates a labelled agent cursor to move them. Use "cluster" for affinity groups, "timeline_horizontal" for anything sequenced or dated, "grid" for a matrix or even survey, "hierarchy" for parent/child structure. Pass a label to title the group.

    View tool JSON
    {
      "name": "arrange_region",
      "kind": "act",
      "impl": "imperative",
      "description": "Physically reposition a set of notes into a spatial layout. You choose WHAT belongs together and the shape it should take; the page computes where each note goes and animates a labelled agent cursor to move them. Use \"cluster\" for affinity groups, \"timeline_horizontal\" for anything sequenced or dated, \"grid\" for a matrix or even survey, \"hierarchy\" for parent/child structure. Pass a label to title the group.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "nodeIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Ids of the notes to arrange, from get_scene."
          },
          "layout": {
            "type": "string",
            "enum": [
              "cluster",
              "timeline_horizontal",
              "grid",
              "hierarchy"
            ],
            "description": "The spatial shape to impose on the group."
          },
          "label": {
            "type": "string",
            "description": "Optional title for the group, shown on the canvas."
          },
          "basedOn": {
            "type": "number",
            "description": "The `asOf` you were given by the get_scene this plan is based on. Cite it and the page will refuse this call outright rather than let it overwrite anything another participant changed while you were deciding. Omitting it is allowed and skips the check; you are then writing blind."
          }
        },
        "required": [
          "nodeIds",
          "layout"
        ],
        "additionalProperties": false
      }
    }
    find_and_linkAnswer

    Draw labelled connections between notes you judge to be related. Read the note text with get_scene, decide the pairs yourself, and state the criterion you used (e.g. "cause and effect", "evidence supports hypothesis"). The agent cursor draws each edge.

    View tool JSON
    {
      "name": "find_and_link",
      "kind": "answer",
      "impl": "imperative",
      "description": "Draw labelled connections between notes you judge to be related. Read the note text with get_scene, decide the pairs yourself, and state the criterion you used (e.g. \"cause and effect\", \"evidence supports hypothesis\"). The agent cursor draws each edge.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "criterion": {
            "type": "string",
            "description": "The relationship you are asserting, in a few words."
          },
          "links": {
            "type": "array",
            "description": "The pairs to connect.",
            "items": {
              "type": "object",
              "properties": {
                "from": {
                  "type": "string",
                  "description": "Source note id."
                },
                "to": {
                  "type": "string",
                  "description": "Target note id."
                },
                "label": {
                  "type": "string",
                  "description": "Short label for this specific edge."
                }
              },
              "required": [
                "from",
                "to",
                "label"
              ],
              "additionalProperties": false
            }
          },
          "basedOn": {
            "type": "number",
            "description": "The `asOf` you were given by the get_scene this plan is based on. Cite it and the page will refuse this call outright rather than let it overwrite anything another participant changed while you were deciding. Omitting it is allowed and skips the check; you are then writing blind."
          }
        },
        "required": [
          "criterion",
          "links"
        ],
        "additionalProperties": false
      }
    }
    annotate_sceneAction

    Attach a floating comment to the canvas without moving anything — an observation, a question, a gap you noticed. Anchor it to a note with nodeId, or leave nodeId out to pin it above the whole board. Cheap, non-destructive, and safe to use while the human works.

    View tool JSON
    {
      "name": "annotate_scene",
      "kind": "act",
      "impl": "imperative",
      "description": "Attach a floating comment to the canvas without moving anything — an observation, a question, a gap you noticed. Anchor it to a note with nodeId, or leave nodeId out to pin it above the whole board. Cheap, non-destructive, and safe to use while the human works.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The comment to leave on the canvas."
          },
          "nodeId": {
            "type": "string",
            "description": "Optional note id to anchor the comment to."
          }
        },
        "required": [
          "text"
        ],
        "additionalProperties": false
      }
    }
    summarize_clusterAction

    Collapse a group of notes into a single labelled summary note in the same place on the canvas. The originals gather to the centre and are replaced; edges to the outside world are rewired to the summary. Use this to reduce a solved area of the board to one idea.

    View tool JSON
    {
      "name": "summarize_cluster",
      "kind": "act",
      "impl": "imperative",
      "description": "Collapse a group of notes into a single labelled summary note in the same place on the canvas. The originals gather to the centre and are replaced; edges to the outside world are rewired to the summary. Use this to reduce a solved area of the board to one idea.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "nodeIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Ids of the notes to collapse."
          },
          "summary": {
            "type": "string",
            "description": "The text of the resulting summary note."
          },
          "basedOn": {
            "type": "number",
            "description": "The `asOf` you were given by the get_scene this plan is based on. Cite it and the page will refuse this call outright rather than let it overwrite anything another participant changed while you were deciding. Omitting it is allowed and skips the check; you are then writing blind."
          }
        },
        "required": [
          "nodeIds",
          "summary"
        ],
        "additionalProperties": false
      }
    }
    add_notesAction

    Write new sticky notes onto the canvas — missing evidence, open questions, next steps. Notes appear in the agent colour so the human can see exactly what you contributed. This call is NOT idempotent, and it is paced by an animation, so it can take tens of seconds in a background tab. Never send it again because it seems slow — it has not been dropped. If you do repeat yourself, text you wrote in the last minute is refused rather than written twice, and comes back under `alreadyPresent`.

    View tool JSON
    {
      "name": "add_notes",
      "kind": "act",
      "impl": "imperative",
      "description": "Write new sticky notes onto the canvas — missing evidence, open questions, next steps. Notes appear in the agent colour so the human can see exactly what you contributed. This call is NOT idempotent, and it is paced by an animation, so it can take tens of seconds in a background tab. Never send it again because it seems slow — it has not been dropped. If you do repeat yourself, text you wrote in the last minute is refused rather than written twice, and comes back under `alreadyPresent`.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "texts": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "One string per note. Keep each under ~80 characters."
          },
          "near": {
            "type": "string",
            "description": "Optional note id to place them beside."
          }
        },
        "required": [
          "texts"
        ],
        "additionalProperties": false
      }
    }
    reorganize_boardAction

    Restructure the WHOLE board into named groups at once. This is the one destructive action: it moves every note you list, so the human is asked to approve it first and may decline. Give a short rationale — they will read it before deciding. Prefer arrange_region for anything smaller than a full restructure.

    View tool JSON
    {
      "name": "reorganize_board",
      "kind": "act",
      "impl": "imperative",
      "description": "Restructure the WHOLE board into named groups at once. This is the one destructive action: it moves every note you list, so the human is asked to approve it first and may decline. Give a short rationale — they will read it before deciding. Prefer arrange_region for anything smaller than a full restructure.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "rationale": {
            "type": "string",
            "description": "One sentence on why this structure is better. Shown to the human."
          },
          "groups": {
            "type": "array",
            "description": "The groups to build, laid out left to right.",
            "items": {
              "type": "object",
              "properties": {
                "label": {
                  "type": "string",
                  "description": "Group title shown on the canvas."
                },
                "nodeIds": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "layout": {
                  "type": "string",
                  "enum": [
                    "cluster",
                    "timeline_horizontal",
                    "grid",
                    "hierarchy"
                  ]
                }
              },
              "required": [
                "label",
                "nodeIds"
              ],
              "additionalProperties": false
            }
          },
          "basedOn": {
            "type": "number",
            "description": "The `asOf` you were given by the get_scene this plan is based on. Cite it and the page will refuse this call outright rather than let it overwrite anything another participant changed while you were deciding. Omitting it is allowed and skips the check; you are then writing blind."
          }
        },
        "required": [
          "rationale",
          "groups"
        ],
        "additionalProperties": false
      }
    }
    undo_last_agent_actionAction

    Revert the most recent change you made to the canvas, restoring the board to how it looked before. Use this when the human says your last move was wrong.

    View tool JSON
    {
      "name": "undo_last_agent_action",
      "kind": "act",
      "impl": "imperative",
      "description": "Revert the most recent change you made to the canvas, restoring the board to how it looked before. Use this when the human says your last move was wrong.",
      "inputSchema": {
        "type": "object",
        "properties": {},
        "additionalProperties": false
      }
    }