Skip to main content
Glama

update_doc

Replace a workspace's doc body. Takes EITHER TipTap JSON (content) OR Markdown (markdown): pass markdown when you're producing prose from scratch (CommonMark + GFM is the format every LLM emits natively), pass TipTap JSON when you need structural edits to an existing doc (round-trip from get_doc, mutate, write back). Beyond CommonMark + GFM, the markdown layer recognizes:

  • alt text → inline image. Use an HTTPS URL (HTTP fires browser mixed-content warnings; data: URIs are rejected by allowBase64: false). For an image on your own machine, call create_file_upload, run the curl it returns and use the url from its response; never ask for a public host. Renders block-feeling via CSS (max-width 100%, rounded corners, drop shadow) even though the underlying node is inline. The alt text is the accessible label and shows in place of the image if the URL fails to load — always include it.

  • A lone video-file URL on its own line (extension .mp4 / .m4v / .webm / .mov / .mkv, signed-params + timestamp fragments tolerated) → native HTML5 <video controls preload="metadata"> player. Source URL is referenced directly: no iframe, no transcoding, no quality loss. Any HTTPS URL to the video file works. For a video on your own machine, call create_video_upload (one file, up to 100 MB), run the curl it returns and use the url from its response. Sample shape: a paragraph containing only that URL. Mid-paragraph URLs stay as plain links — surrounding prose disqualifies the auto-promotion (matches the oEmbed convention).

  • ```mermaid fenced code → diagram (15 sub-types: flowchart, sequence, gantt, ER, state, class, mindmap, timeline, pie, quadrant, sankey, XY-chart, packet, block, journey)

  • $x$ inline math, $$x$$ block math (LaTeX, KaTeX-rendered, scripts/href disabled)

  • > [!NOTE] / [!TIP] / [!IMPORTANT] / [!WARNING] / [!CAUTION] GFM-style callouts

  • ```svg fenced code → sanitized SVG embed (the universal escape hatch for custom diagrams; scripts and event handlers stripped at write time)

  • XBODY → collapsible toggle

  • [[slug]] / [[org/slug]] / [[slug#surface-slug]] / [[slug#row-id]] / [[slug|display]] → cross-references to another workspace, surface, or row. [[slug#surface-slug]] opens that surface, linking to /<org>/<slug>?surface=<surface-slug>. Resolved against your accessible workspace set; targets you can't see render as plain text on the reader's side (no info leak). Every cross-ref creates a Backlink row so the target's 'referenced from' sidebar shows this doc.

  • @Label → @-mention of a user or agent. <kind> is agent or human; <id> is the principal id. Optional query params ?org=<slug> (agents) or ?email=<addr> (humans) for renderer hints. Mentioning a human writes a doc_mention row to their inbox + sends a deep-link email; mentioning an agent fires the doc.mention_added webhook so the agent service can wake up and reply. Re-saving a doc that already mentions someone does NOT re-fire — only newly-added mentions notify (computed from a diff against the previous body). Use this to ping a person or agent when a doc you wrote needs their eyes.

  • A lone URL on its own line from a safelisted provider (YouTube, Vimeo, Loom, Figma, CodePen, GitHub gists) → sandboxed iframe embed. Other URLs stay as regular links. Surrounding prose disqualifies the auto-embed.

Per-format caps: max 50 Mermaid diagrams (30 KB source each), max 500 math expressions (8 KB source each), max 50 SVG blocks (100 KB source each post-sanitize), max 200 cross-refs per doc, max 500 @-mentions per doc, max 20 embeds per doc, max 20 videos per doc, max 200 images per doc. Last-write-wins; no CRDT merge. Emits doc.updated + doc.heading_added + doc.mention_added events as applicable. Requires editor role. Multi-surface workspaces optionally accept surface_slug to write to a specific doc surface; omitted writes the primary doc surface. Append-only updates have a dedicated append_doc_section tool that doesn't require fetching the body first.

Input Schema

NameRequiredDescriptionDefault
slugYesThe workspace slug. Accepts either the bare slug ('my-workspace') or the org-prefixed form ('my-org/my-workspace') as shown in the dashboard URL; both resolve to the same workspace.
contentNoTipTap document JSON: `{ type: 'doc', content: [ ... ] }`. Use this when round-tripping from get_doc to preserve formatting. Mutually exclusive with `markdown` (content wins if both are passed).
markdownNoMarkdown body (CommonMark + GFM). Converted server-side to TipTap JSON via the same converter that powers PUT /api/workspaces/:slug/doc. Use this when authoring prose from scratch; no need to hand-build ProseMirror nodes.
surface_slugNoOptional doc surface slug for multi-doc workspaces. Omit to write the primary doc surface. Use list_surfaces to see available slugs.
allowBlockLossNoConfirm a replacement that removes content. Omit it normally: the call is refused (with both block counts) when it would destroy the bulk of the doc's top-level blocks. Set true only when the deletion is what you intend.
if_unmodified_sinceNoOptional precondition. ISO 8601 timestamp (typically the `updatedAt` you read via `get_doc`). When set and the doc has changed since this cutoff, the write is rejected with `code: -32602`, message describing the conflict, and `data: { conflict: true, currentUpdatedAt, precondition }` so your agent can refetch + merge instead of silently clobbering a concurrent write. Without this, two agents PUTting near-simultaneously will both succeed and the last write wins (the previous content vanishes). Use this in multi-agent co-authoring flows; skip it for greenfield writes where you know you're the only writer.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • addedInput schema / properties / allowBlockLoss
      Added value: +{
      +  "description": "Confirm a replacement that removes content. Omit it normally: the call is refused (with both block counts) when it would destroy the bulk of the doc's top-level blocks. Set true only when the deletion is what you intend.",
      +  "type": "boolean"
      +}
  2. Changed1 schema field changed
    • addedInput schema / properties / if_unmodified_since
      Added value: +{
      +  "description": "Optional precondition. ISO 8601 timestamp (typically the `updatedAt` you read via `get_doc`). When set and the doc has changed since this cutoff, the write is rejected with `code: -32602`, message describing the conflict, and `data: { conflict: true, currentUpdatedAt, precondition }` so your agent can refetch + merge instead of silently clobbering a concurrent write. Without this, two agents PUTting near-simultaneously will both succeed and the last write wins (the previous content vanishes). Use this in multi-agent co-authoring flows; skip it for greenfield writes where you know you're the only writer.",
      +  "type": "string"
      +}
  3. Changed3 schema fields changed
    • changedInput schema / properties / content / description
      Previous value: -"TipTap document JSON — `{ type: 'doc', content: [ ... ] }`. Use this when round-tripping from get_doc to preserve formatting. Mutually exclusive with `markdown` (content wins if both are passed)."New value: +"TipTap document JSON: `{ type: 'doc', content: [ ... ] }`. Use this when round-tripping from get_doc to preserve formatting. Mutually exclusive with `markdown` (content wins if both are passed)."
    • changedInput schema / properties / markdown / description
      Previous value: -"Markdown body (CommonMark + GFM). Converted server-side to TipTap JSON via the same converter that powers PUT /api/workspaces/:slug/doc. Use this when authoring prose from scratch — no need to hand-build ProseMirror nodes."New value: +"Markdown body (CommonMark + GFM). Converted server-side to TipTap JSON via the same converter that powers PUT /api/workspaces/:slug/doc. Use this when authoring prose from scratch; no need to hand-build ProseMirror nodes."
    • changedInput schema / properties / slug / description
      Previous value: -"The workspace slug. Accepts either the bare slug ('my-workspace') or the org-prefixed form ('my-org/my-workspace') as shown in the dashboard URL — both resolve to the same workspace."New value: +"The workspace slug. Accepts either the bare slug ('my-workspace') or the org-prefixed form ('my-org/my-workspace') as shown in the dashboard URL; both resolve to the same workspace."
  4. First observed

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full burden and does: editor-role requirement, last-write-wins with no CRDT merge, the allowBlockLoss refusal guard, the -32602 conflict rejection shape, emitted events (doc.updated / doc.heading_added / doc.mention_added), and the diff-based rule that re-saving does not re-notify existing mentions. These are non-obvious side effects an agent could not otherwise predict.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and format choice are front-loaded in the first two sentences, and the bulleted catalog is scannable, but the body is very long and a substantial portion is syntax reference that could live in validate_doc_markdown or documentation. Some phrasing is chatty ("the format every LLM emits natively") and the embed disqualification rule is restated, so not every sentence earns its place in a tool description.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-parameter mutation tool with a nested object, no annotations, and no output schema, the description covers permissions, concurrency, destructive-write guards, per-format caps, event emission, and sibling alternatives. There is little an agent would still need to guess before calling it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description genuinely extends parameter meaning — the markdown dialect catalog (images, video auto-promotion, mermaid, math, callouts, svg, details, cross-refs, dock: mentions, safelisted embeds) tells the agent what values the `markdown` string may legally contain, which the schema only summarizes as "CommonMark + GFM". Precedence and conflict behavior are also spelled out beyond the schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

First sentence gives a precise verb+resource+scope: "Replace a workspace's doc body." It immediately distinguishes itself from the sibling append_doc_section ("Append-only updates have a dedicated `append_doc_section` tool") and from get_doc via the round-trip guidance, so an agent can route correctly without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use branching: markdown for authoring prose from scratch vs TipTap JSON for structural edits round-tripped from get_doc; append_doc_section for appends; if_unmodified_since for multi-agent co-authoring, skipped for greenfield writes. It also names the alternative tools to call for local assets (create_file_upload, create_video_upload), which is real routing guidance rather than inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.