Canvas Searching
Locate rendered text in original Cell coordinates.
HEAD a63778ecanvas_search searches the active Canvas or current Slide page's rendered
Cells. It is read-only, works on source-backed projections, and does not move the
camera or change interaction. Source files, read rulers, style notes, and sampled
maps are not search content.
Query and position
{ "query": "Hello", "viewport": [0, 0, 100, 50] }在 full-access local MCP 中可增加 canvasId 指定目标 Canvas;省略时使用
当前 active Canvas。list action 返回短持久化 ID;只有需要跨 Canvas 时才使用它。
query is literal and case-sensitive by default. Set ignoreCase: true for
Unicode case folding; set regex: true for RE2 syntax.
Lookaround and backreferences are unsupported. Each match must consume non-empty
text at complete grapheme boundaries; zero-length regex matches are skipped.
Actual LF separates a two-dimensional template. Rows match at the same Cell x
on consecutive Canvas rows; widths may differ. Spaces are literal, and content
after each row's match is unconstrained. Every template row must contain a
non-whitespace character; empty/blank rows and other control characters are rejected.
{ "query": "Hello \\w+\nWelcome", "regex": true, "ignoreCase": true }This finds Hello Alice above Welcome, not merely two nearby strings.
Queries are limited to 4096 UTF-16 units and 64 rows.
Omit viewport to search all content. A supplied rectangle uses the same Cell
coordinates as reading, but search always uses original
precision regardless of read's sampling sampleSize. The complete template must fit
inside it. Boundary-clipped glyphs do not match.
Sparse rows and limits
Literal matching joins only gaps shorter than the longest template row.
Regex matching uses each finite stored row envelope, clipped by the input
viewport: missing internal Cells are spaces, and ^/$ refer to that envelope's
edges, not storage spans or the template's origin. Unstored exterior space is
not searchable. Envelopes over 16384 Cells are rejected, never split silently.
A shared scan/time budget returns search_limit with no partial results. Narrow
viewport and retry. RE2JS avoids backtracking;
the budget also bounds sparse expansion and repeated template checks.
Results and continuation
{
"canvasId": "cv-7k3m9a1b2c",
"matches": [{ "origin": [10, 20], "bounds": [10, 20, 5, 1], "content": "Hello" }],
"next": null
}Results are ordered by the match's y, then x, with non-overlapping matches.
Each item contains only origin, exact bounds, and the matched content.
There is no surrounding preview, padding, ruler, border, or style note. bounds
is a Cell rectangle that can be passed directly to canvas_read when
the agent needs context or styles.
Search is intentionally a locator, not a context reader. The agent decides when more context is worth a separate read.
Each call returns at most 20 matches. Non-null next is the last returned match's
origin [x,y]; pass it as after with identical
query, regex, ignoreCase, and viewport to continue
strictly after that position. Confirm the canvasId still belongs to the same
Canvas. Calls observe
current content, not a shared snapshot; restart after an edit if consistency matters.
Empty results have matches: [] and next: null.