list_documents
Scope:documents:read (step-up) · Kind: read-only · Annotations: readOnlyHint: true, destructiveHint: false, openWorldHint: false
List the documents and pages you can reach. Narrow to one conversation (conversation_id), one pod (pod_id), or a library section (scope:mine= ones you own,shared= shared with you,pod= every pod you belong to,org= shared with the whole workspace); with none of these, everything you can reach is merged. Each row carriesscopeand yourrole(owner | editor | commenter | viewer) — a viewer can read but not edit or comment. Optionalqueryfilters by title/content. Returns metadata only; use read_document for content.
Parameters
Pass at most one ofscope, conversation_id and pod_id.
'mine' | 'shared' | 'pod' | 'org'
A library section.
mine = artifacts you own; shared = artifacts
explicitly shared with you; pod = every pod you belong to; org =
artifacts shared with the whole workspace.string
Only artifacts linked to this conversation.
string
Only artifacts in this pod.
string
Case-insensitive substring filter over title and body, applied to the rows
already read. It is a funnel, not a ranked search; use
search_knowledge for retrieval.string
The
next_cursor from the previous page of the same listing. Opaque and
bound to the arguments that produced it: passing it with a different
scope, pod_id, query or include_archived is refused.boolean
default:"false"
Include archived artifacts.
number
default:"50"
Rows to return, 1 to 50. Clamped.
Returns
array
string | null
Where the next page starts. A string on the paged listings (
mine,
shared, org, pod_id) while more rows exist; null when the listing
is exhausted, and always null on the merged listing, scope: "pod" and
conversation_id, which cannot page.boolean
true when more rows exist than were returned: on a paged listing that is
the same as next_cursor being a string; on the merged listings it means
narrow with pod_id or scope (or an org-wide listing stopped after 50
pods).No documents found.
Completion checklist
- On
mine,shared,organdpod_id, follownext_cursoruntil it isnullbefore concluding a document does not exist;queryfilters each page, so a page can be short without being the last. - On the merged listing and
scope: "pod",truncated: trueis inconclusive. Narrow withpod_id,conversation_idor a pagedscopeand list again. - A row’s
conversation_idandpod_idare the ids the other tools take;list_conversationsturns a room or pod name into them. - The task is done when a read-back shows it: after any write, call
read_documentand check the content, not only the tool’s success.
Permissions and side effects
- Needs
documents:read. - Rows you have no role on are dropped, never surfaced.
- A
conversation_idorpod_idyou cannot reach fails withArtifact not found, the same as a made-up id. - Reads only. Recorded in the agent activity history.
Errors
Example
Requestread_document
Scope:documents:read (step-up) · Kind: read-only · Annotations: readOnlyHint: true, destructiveHint: false, openWorldHint: false
Read a document as markdown (an HTML page returns its source). ALWAYS returnsversion— the token edit_document’s expected_version and replace_all writes are checked against. Long documents window: passoffsetto continue past 24000 characters.
Parameters
string
required
The artifact id.
number
default:"0"
Character offset to start from. Minimum 0.
number
default:"24000"
Characters to return, 1 to 24,000. Clamped.
Returns
string
string
'document' | 'html_app' | 'table'
string
The requested slice. For an
html_app this is the page’s HTML source.number
The document’s current version. Pass it as
expected_version to
edit_document.number
Total length of the full text.
number
The offset that was applied.
boolean
true when text remains after this slice. Call again with
offset = offset + window.boolean
object
Present when the artifact is linked to a conversation:
{ "conversation_id": "<id>" }.Permissions and side effects
- Needs
documents:readand at least theviewerrole on the artifact. - Reads only. Recorded in the agent activity history.
Errors
Limitations
- Comment marks and other editor-only annotations are not part of the markdown.
- For a
table, the returned text is whatever markdown projection the table exposes; tables cannot be edited through MCP. - Reading a page here returns raw HTML.
read_pageis the page-specific tool and returns the sameversion.
Example
Requestcreate_document
Scope:documents:write (step-up) · Kind: write · Annotations: readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false
Create a new collaborative document, optionally filled with your markdown. Either in a conversation (conversation_id— its card is posted to the room) or in the person’s library with ascope:user(private to them, the default),pod(needspod_id), ororg(every workspace member can edit). The caller becomes its owner. Returns . Passidempotency_keyto make retries safe: a repeat with the same key within 10 minutes returns the original document instead of creating a twin.
Parameters
Pass eitherconversation_id or scope (with pod_id when the
scope is pod), never both.
string
required
The document’s title. Must be non-empty.
string
Create inside this conversation. A document card is posted to the room.
'user' | 'pod' | 'org'
default:"user"
Where the document lives when no
conversation_id is given. user is
private to the caller; pod needs pod_id; org is editable by every
workspace member. No card is posted anywhere; the document gets its own
chat.string
Required with
scope: "pod".string
Initial body. Written verbatim, up to 60,000 characters. Whitespace-only
content is treated as empty.
string
Any string you choose. A second call with the same key within 10 minutes
returns the original document (
deduplicated: true) instead of creating
another. Keyed on the key only, never the title, so two deliberate creates
with one title both succeed.Returns
string
string
number
0 for an empty document; otherwise the version after the initial fill.
On a deduplicated retry this is present only when the retry filled in
missing content.boolean
Present and
true when an idempotency_key matched a recent create.boolean
Present and
true when a deduplicated retry found the original empty and
filled it with content_markdown.Created "<title>" (document_id: <id>, version <n>). or, on a
retry, Document already created: "<title>" (document_id: <id>). Returning the original instead of creating a duplicate — ….
Permissions and side effects
- Needs
documents:write. - With
conversation_id: you must be able to participate in that conversation. The gate runs inside the same transaction as the insert. - With
scope: "pod": you must be a member of the pod. - The caller becomes the owner. The initial fill is a checkpointed write
attributed to you via the host, and appears in
get_document_versions. - With
conversation_id, a card lands in the room. With ascope, nothing is posted anywhere.
Errors
Example
Requestedit_document
Scope:documents:write (step-up) · Kind: write, destructive · Annotations: readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false
Write verbatim markdown into a document while humans may be editing it live. Modes:append(add at the end),replace_section(replace the region an EXACTsection_excerptfrom read_document resolves to — a stale excerpt fails loudly with candidates, it can never clobber),replace_all(whole body; conflicts ifexpected_versionmoved),fill_empty(only if nobody typed yet). Human edits made mid-write are KEPT and reported inkept_blocks, never overwritten. Every write is checkpointed and undoable.dry_runresolves the target and writes nothing.
Parameters
string
required
'append' | 'replace_section' | 'replace_all' | 'fill_empty'
required
What to do with
content_markdown.string
required
The markdown to write, verbatim. Up to 60,000 characters; longer content
stops early with
stop_reason: "cap".string
replace_section only, and required there. An exact passage quoted from
read_document. It is matched whitespace-insensitively and resolved to
the contiguous blocks it covers; those blocks are replaced.number
The
version a prior read_document returned. Required for
replace_all, where a mismatch is a hard conflict. On other modes it is
optional and only reports drift.boolean
default:"false"
Resolve the target and version checks, write nothing.
How expected_version is tiered
Returns
On success:number
The document’s version after the write.
number
boolean
Present when the write did not complete.
'cap' | 'anchor_gone'
Why it stopped.
cap: the 60,000-character budget was hit; continue with
another call. anchor_gone: someone removed the section being written
into; do not re-add it.string
What the agent should do about the early stop.
boolean
Present when
expected_version no longer matched (non-replace_all modes).number
How many blocks changed since
expected_version, when known.object
Present when a person edited blocks while this write ran. Their edits are
kept next to yours:
{ "count": n, "excerpts": ["…"] }.dry_run:
Wrote <n> characters (<mode>); the document is now at version <v>. followed by
Stopped early (<reason>). and/or Kept <n> block(s) a person edited while you were writing — their text stands next to yours. when applicable.
Permissions and side effects
- Needs
documents:writeand theeditororownerrole. - Checkpoints the document before writing; the checkpoint appears in
get_document_versionsand is undoable in the app. - Takes a short write lease. Concurrent agent writers queue briefly, then
receive
write_conflictwith a retry hint. - Attributed to you via the host on version rows and cursors.
- Works only on
documentartifacts; pages and tables are refused with a message naming the right tool.
Errors
A failed
replace_section is never degraded into an append.
Recovering from refusals
Retrying without duplicating: a result with
stopped_early: true wrote part
of the content, so re-read and append only what is missing rather than the
whole payload again. A call that timed out with no result may still have
landed; read before retrying. A version_conflict on replace_section is
not a stale excerpt: the excerpt still resolves, so the retry is the same
call with the fresh version.
Example
Requestget_document_versions
Scope:documents:read (step-up) · Kind: read-only · Annotations: readOnlyHint: true, destructiveHint: false, openWorldHint: false
Recent versions of a document, newest first — automatic checkpoints (every agent write checkpoints before touching it, so this is the undo history) and named versions a person saved (pinned: true, with theirlabel; never pruned). Metadata only; restoring and naming stay human acts in the app.
Parameters
string
required
Returns
array
The 20 most recent rows, newest first.
No versions yet.
Permissions and side effects
- Needs
documents:readand any role on the artifact. - Reads only. Recorded in the agent activity history.
Errors
Limitations
- Only the 20 most recent rows are returned; there is no paging.
- Automatic checkpoints are pruned over time in the app; named versions are not.
- There is no MCP tool to restore, name or diff versions.
Example
Requestinstruction is a free-form label set by whatever produced the row; the
values shown are illustrative.