# Edith MCP Tools

This contract defines Edith's primitive MCP operations. `tools/list` and this document are sufficient to use the available workflows.

Contract version: `2.1.1`. Updated: `2026-10-26`.

## Core Model

- Owner draft edits are mutable accepted working state. Saved versions are immutable checkpoints.
- Share links are pinned to saved document revisions. Review links show current accepted review state.
- Named sharing uses get_document_share_target then share_document and ALWAYS emails. Show email_preview (full subject, body and recipients, no CC/BCC), disclose any generated-link placeholder and obtain explicit final sending authorisation. Workspace access, including organisation admins, uses internal links with existing roles and no review quota. Others use external review links. Recipient access changes require a fresh check. Reuse request_id for replays; only failed deliveries may be explicitly retried with expected_attempt. Public review links are a separate unnamed utility; create_share_link stays pinned and read-only.
- Workspace and reviewer-token proposal tools read and update one shared proposal head per document. Reviewer-token tools cannot create links or edit the accepted draft directly.
- Proposal updates require the accepted draft version and shared proposal version returned by a proposal read.
- Proposed changes are independently attributed source hunks. Apply non-overlapping selections atomically; choose one alternative when hunks overlap. Discussions can attach to the same visible proposed-change groups used by the browser UI.

## Asset revision references

Workspace asset links and images without rev follow the latest asset revision, even in saved Markdown or a pinned document share. To freeze bytes, explicitly author ?rev=N in the Markdown destination, for example ![Diagram](assets/diagram.png?rev=3). N is one canonical positive decimal integer (1, 2, 3, ...); empty, zero, negative, leading-zero, duplicate, malformed and unavailable selectors never fall back to latest. Asset delivery and preview URLs return HTTP 404 for invalid or missing revisions. This parameter selects an asset revision, not a document revision. Save, share and export preserve authored Markdown; they do not automatically add pins. Relative paths resolve from the document folder; /paths resolve from the workspace root. Preserve other query parameters with &, and put fragments after the query, for example assets/report.pdf?rev=3&download=1#page=2. Use list_workspace_asset_revisions to find revision_number values and list_document_references to verify revision_mode, requested_revision, current_revision, resolved_revision and revision_available. Discovery checks metadata and routes, not stored bytes or external URLs. Public review/share asset routes expose only authored pinned revisions and the current revision of floating references; changing rev cannot expose other history. A pin grants no new access and does not survive a broken file path.

Selector range: `1..2147483647`, matching stored asset revision numbers. Out-of-range selectors are invalid.

```markdown
![Latest diagram](assets/diagram.png)
![Pinned diagram](assets/diagram.png?rev=3)
[Report](/reports/report.pdf?rev=2#page=2)
```

## Connection

- MCP endpoint: `https://edithmd.com/mcp`
- OAuth discovery: `https://edithmd.com/.well-known/oauth-authorization-server`
- Protected resource metadata: `https://edithmd.com/.well-known/oauth-protected-resource/mcp`
- Scope selection: OAuth without `scope` grants full account access (`mcp:*`). Explain that default before OAuth; request explicit scopes only if the user prefers narrower access.
- Verify setup with MCP `tools/list`. Edith exposes MCP tools, not MCP resources, so `resources/list` is not required.
- `tools.listChanged` is false. Reconnect after Edith deploys a new tool contract, and re-authorise when changing between `mcp:*` and narrower scopes. `tools/list` is not scope-filtered; `tools/call` enforces scopes.

## OAuth Scope Consent

OAuth without a requested scope grants full account access (`mcp:*`). Explain that default before OAuth starts. If the user prefers narrower access, request and explain explicit scopes before OAuth starts.

Common scope bundles:

- **Read-only owner setup**: `mcp:documents:read mcp:reviews:read mcp:shares:read mcp:contacts:read` - Read owner documents, review state, share links, and contacts without making changes.
- **Owner drafting/versioning**: `mcp:documents:read mcp:documents:write` - Read documents and create or update drafts, files, folders, assets, and saved versions.
- **Owner review workflow**: `mcp:documents:read mcp:reviews:read mcp:reviews:write` - Read documents and manage review links, shared proposals, replies, and comment resolution.
- **Owner share workflow**: `mcp:documents:read mcp:shares:read mcp:shares:write` - Check named recipients, send authorised document-sharing emails, and manage pinned read-only links. Sharing requires current document edit access.
- **Reviewer feedback**: `mcp:reviewer:read mcp:reviewer:write` - Read assigned reviews and submit comments, replies, and shared proposal contributions.
- **Organisation admin**: `mcp:admin:read mcp:admin:write` - List manageable organisations and workspaces, inspect members and invites, create or rename workspaces, invite or remove members, and change roles.
- **Full account access**: `mcp:*` - Use every current Edith MCP tool so the agent can act on the user's behalf. Only for trusted AI assistants.

## `list_documents`

**List documents**

Owner read. List the current user's documents; set archived=true for archived documents. Draft edits and saved versions are separate document states.

```json
{
  "properties": {
    "archived": {
      "description": "List archived documents instead of active documents.",
      "type": "boolean"
    }
  },
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `list_workspaces`

**List workspaces**

Owner read. List workspaces visible to the current user before creating or moving workspace files, assets, or Markdown documents.

```json
{
  "properties": {},
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `list_organisations`

**List organisations**

Admin read. List organisations the current user can manage before using organisation or workspace administration tools.

```json
{
  "properties": {},
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `get_organisation_settings`

**Get organisation settings**

Admin read. Get organisation members and open invites for a manageable organisation before inviting, revoking, changing roles, or removing members.

```json
{
  "properties": {
    "organisation_id": {
      "description": "Organisation UUID.",
      "type": "string"
    }
  },
  "required": [
    "organisation_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `update_organisation`

**Update organisation**

Admin write. Rename a manageable organisation only after the user confirms the organisation and new name.

```json
{
  "properties": {
    "name": {
      "description": "Organisation name.",
      "type": "string"
    },
    "organisation_id": {
      "description": "Organisation UUID.",
      "type": "string"
    }
  },
  "required": [
    "organisation_id",
    "name"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `invite_organisation_member`

**Invite organisation member**

Admin external write. Invite a member with optional pending workspace roles. ALWAYS sends email; show the complete email, subject and recipients and obtain explicit final sending authorisation. Access starts on acceptance.

```json
{
  "properties": {
    "email": {
      "description": "Invitee email address.",
      "type": "string"
    },
    "organisation_id": {
      "description": "Organisation UUID.",
      "type": "string"
    },
    "role": {
      "description": "Organisation admins already access all workspaces.",
      "enum": [
        "member",
        "admin"
      ],
      "type": "string"
    },
    "workspaces": {
      "description": "Pending workspace assignments for members. Empty for organisation admins. Only workspaces in this organisation are allowed.",
      "items": {
        "properties": {
          "role": {
            "enum": [
              "viewer",
              "reviewer",
              "editor",
              "admin"
            ],
            "type": "string"
          },
          "workspace_id": {
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "workspace_id",
          "role"
        ],
        "type": "object"
      },
      "maxItems": 200,
      "type": "array"
    }
  },
  "required": [
    "organisation_id",
    "email",
    "role"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": true,
  "readOnlyHint": false
}
```

## `update_organisation_invite`

**Update organisation invite**

Admin write. Replace a pending invitation's organisation role and workspace assignments after checking current settings. Keeps the link valid and sends no email. Existing memberships are preserved on acceptance.

```json
{
  "properties": {
    "invite_id": {
      "description": "Invite UUID.",
      "type": "string"
    },
    "organisation_id": {
      "description": "Organisation UUID.",
      "type": "string"
    },
    "role": {
      "description": "Organisation role. Admins already access all workspaces.",
      "enum": [
        "member",
        "admin"
      ],
      "type": "string"
    },
    "workspaces": {
      "description": "Pending workspace assignments for members. Empty for organisation admins. Only workspaces in this organisation are allowed.",
      "items": {
        "properties": {
          "role": {
            "enum": [
              "viewer",
              "reviewer",
              "editor",
              "admin"
            ],
            "type": "string"
          },
          "workspace_id": {
            "format": "uuid",
            "type": "string"
          }
        },
        "required": [
          "workspace_id",
          "role"
        ],
        "type": "object"
      },
      "maxItems": 200,
      "type": "array"
    }
  },
  "required": [
    "organisation_id",
    "invite_id",
    "role",
    "workspaces"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `revoke_organisation_invite`

**Revoke organisation invite**

Admin destructive write. Revoke an open organisation invite so the invitee can no longer accept it.

```json
{
  "properties": {
    "invite_id": {
      "description": "Invite UUID.",
      "type": "string"
    },
    "organisation_id": {
      "description": "Organisation UUID.",
      "type": "string"
    }
  },
  "required": [
    "organisation_id",
    "invite_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `update_organisation_member`

**Update organisation member**

Admin destructive write. Change a member's organisation role; confirm user and role because this can reduce access.

```json
{
  "properties": {
    "organisation_id": {
      "description": "Organisation UUID.",
      "type": "string"
    },
    "role": {
      "description": "Organisation role: member or admin.",
      "type": "string"
    },
    "user_id": {
      "description": "Member user UUID.",
      "type": "string"
    }
  },
  "required": [
    "organisation_id",
    "user_id",
    "role"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `remove_organisation_member`

**Remove organisation member**

Admin destructive write. Remove a member from a manageable organisation after explicit confirmation.

```json
{
  "properties": {
    "organisation_id": {
      "description": "Organisation UUID.",
      "type": "string"
    },
    "user_id": {
      "description": "Member user UUID.",
      "type": "string"
    }
  },
  "required": [
    "organisation_id",
    "user_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `list_organisation_workspaces`

**List organisation workspaces**

Admin read. List workspaces in a manageable organisation before creating workspaces or changing workspace membership.

```json
{
  "properties": {
    "organisation_id": {
      "description": "Organisation UUID.",
      "type": "string"
    }
  },
  "required": [
    "organisation_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `create_workspace`

**Create workspace**

Admin write. Create a workspace inside a manageable organisation after confirming the organisation and workspace name.

```json
{
  "properties": {
    "name": {
      "description": "Workspace name.",
      "type": "string"
    },
    "organisation_id": {
      "description": "Organisation UUID.",
      "type": "string"
    }
  },
  "required": [
    "organisation_id",
    "name"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `get_workspace_settings`

**Get workspace settings**

Admin read. Get workspace settings, members, and eligible organisation members before changing workspace access.

```json
{
  "properties": {
    "workspace_id": {
      "description": "Workspace UUID.",
      "type": "string"
    }
  },
  "required": [
    "workspace_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `update_workspace`

**Update workspace**

Admin write. Rename a workspace the current user can administer after confirming the workspace and new name.

```json
{
  "properties": {
    "name": {
      "description": "Workspace name.",
      "type": "string"
    },
    "workspace_id": {
      "description": "Workspace UUID.",
      "type": "string"
    }
  },
  "required": [
    "workspace_id",
    "name"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `add_workspace_member`

**Add workspace member**

Admin write. Add an organisation member to a workspace with a confirmed workspace role.

```json
{
  "properties": {
    "role": {
      "description": "Workspace role: viewer, reviewer, editor, or admin.",
      "type": "string"
    },
    "user_id": {
      "description": "Member user UUID.",
      "type": "string"
    },
    "workspace_id": {
      "description": "Workspace UUID.",
      "type": "string"
    }
  },
  "required": [
    "workspace_id",
    "user_id",
    "role"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `update_workspace_member`

**Update workspace member**

Admin destructive write. Change a workspace member role; confirm user, workspace, and role because this can reduce access.

```json
{
  "properties": {
    "role": {
      "description": "Workspace role: viewer, reviewer, editor, or admin.",
      "type": "string"
    },
    "user_id": {
      "description": "Member user UUID.",
      "type": "string"
    },
    "workspace_id": {
      "description": "Workspace UUID.",
      "type": "string"
    }
  },
  "required": [
    "workspace_id",
    "user_id",
    "role"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `remove_workspace_member`

**Remove workspace member**

Admin destructive write. Remove a member from a workspace after explicit confirmation.

```json
{
  "properties": {
    "user_id": {
      "description": "Member user UUID.",
      "type": "string"
    },
    "workspace_id": {
      "description": "Workspace UUID.",
      "type": "string"
    }
  },
  "required": [
    "workspace_id",
    "user_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `list_workspace_files`

**List workspace files**

Workspace read. Browse one workspace folder with pagination so agents can inspect direct child files/folders without loading a huge nested tree.

```json
{
  "properties": {
    "cursor": {
      "description": "Opaque next_cursor from a previous response.",
      "type": "string"
    },
    "include_all_folders": {
      "description": "Also return all folders in the workspace for move-target pickers; omit for normal browsing.",
      "type": "boolean"
    },
    "include_archived": {
      "description": "Include archived Markdown documents in results.",
      "type": "boolean"
    },
    "kind": {
      "description": "Optional file kind filter: folder, markdown, or asset.",
      "type": "string"
    },
    "limit": {
      "description": "Maximum direct child entries to return, 1-200. Defaults to 100.",
      "type": "integer"
    },
    "parent_id": {
      "description": "Optional folder UUID.",
      "type": "string"
    },
    "workspace_id": {
      "description": "Workspace UUID.",
      "type": "string"
    }
  },
  "required": [
    "workspace_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `list_workspace_asset_revisions`

**List workspace asset revisions**

Workspace read. List immutable asset revisions, newest first, 50 per page. Use before_revision for older history. Returns uploader, checksum, messages, restored-from provenance and authenticated original-file download URLs. To pin bytes in authored Markdown, append ?rev=N to the asset path using a returned revision_number; omit rev to follow latest, even in saved/shared documents. N must be one canonical positive decimal integer; invalid or missing pins never fall back. This does not grant public access.

```json
{
  "properties": {
    "before_revision": {
      "description": "Optional exclusive revision cursor for older history.",
      "minimum": 1,
      "type": "integer"
    },
    "file_id": {
      "description": "Existing asset UUID.",
      "type": "string"
    },
    "workspace_id": {
      "description": "Current workspace UUID.",
      "type": "string"
    }
  },
  "required": [
    "workspace_id",
    "file_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `get_workspace_asset_preview`

**Get workspace asset preview**

Workspace read. Resolve a read-only asset preview and original download URL for current or an exact revision. Returned URLs pin the resolved revision with ?rev=N and require workspace access. Its revision_number JSON argument selects an asset revision; authored Markdown instead uses ?rev=N on the asset path, with omitted rev following latest. Invalid or missing pins never fall back. Office/spreadsheet preparation populates a derived cache; pending/running/failed/limited states are explicit. Image, text, PDF and browser-supported audio/video use read-only viewers.

```json
{
  "properties": {
    "file_id": {
      "description": "Asset UUID.",
      "type": "string"
    },
    "revision_number": {
      "description": "Optional exact asset revision. Omit to resolve current; returned URLs pin that resolved revision.",
      "minimum": 1,
      "type": "integer"
    },
    "workspace_id": {
      "description": "Current workspace UUID.",
      "type": "string"
    }
  },
  "required": [
    "workspace_id",
    "file_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `restore_workspace_asset_revision`

**Restore workspace asset revision**

Workspace write. Restore an asset revision as a new current revision with a restored-from back-reference. Requires expected_revision; stale requests fail. Reuse request_id for retries to return the original result. Existing history and workspace filename remain intact.

```json
{
  "properties": {
    "expected_revision": {
      "description": "Expected current revision.",
      "minimum": 1,
      "type": "integer"
    },
    "file_id": {
      "description": "Existing asset UUID.",
      "type": "string"
    },
    "message": {
      "description": "Optional version message.",
      "maxLength": 2000,
      "type": "string"
    },
    "request_id": {
      "description": "New operation UUID; reuse for retries.",
      "type": "string"
    },
    "revision_number": {
      "description": "Revision to restore.",
      "minimum": 1,
      "type": "integer"
    },
    "workspace_id": {
      "description": "Current workspace UUID.",
      "type": "string"
    }
  },
  "required": [
    "workspace_id",
    "file_id",
    "revision_number",
    "expected_revision",
    "request_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `search_workspace_files`

**Search workspace files**

Workspace read. Search a workspace-wide flat file index with pagination and filters so agents can discover exact file/document IDs without loading folder trees. Use for large or batch discovery; combine kind, path_prefix, query, and cursor pagination as needed.

```json
{
  "properties": {
    "cursor": {
      "description": "Opaque next_cursor from a previous response.",
      "type": "string"
    },
    "include_archived": {
      "description": "Include archived Markdown documents in results.",
      "type": "boolean"
    },
    "kind": {
      "description": "Optional file kind filter: folder, markdown, or asset.",
      "type": "string"
    },
    "limit": {
      "description": "Maximum matching entries to return, 1-200. Defaults to 100.",
      "type": "integer"
    },
    "path_prefix": {
      "description": "Optional workspace path prefix such as /Help Desk.",
      "type": "string"
    },
    "query": {
      "description": "Optional case-insensitive search over file names and paths.",
      "type": "string"
    },
    "workspace_id": {
      "description": "Workspace UUID.",
      "type": "string"
    }
  },
  "required": [
    "workspace_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `list_document_references`

**List document references**

Owner read. List links and images in an owned document draft, including Markdown tables. Resolve relative paths against the document folder and leading-slash paths against the workspace root. Return resolved_path, canonical rendered_url, file_exists and rendered_link_valid. Asset references also return revision_mode (latest, pinned or invalid), requested_revision when validly pinned, current_revision, resolved_revision when available and revision_available. Author ?rev=N in Markdown to pin an asset revision; omit rev to follow latest, including in saved/shared Markdown. N must be one canonical positive decimal integer; invalid_revision and revision_not_found are explicit unresolved reasons with no latest fallback. Resolved asset metadata describes the selected bytes. An unavailable pin can retain its canonical rendered_url for an explicit HTTP 404. Metadata and route checks do not validate HTTP delivery or stored bytes; external URLs are listed separately and not validated.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `get_document_details`

**Get document details**

Workspace read. Get metadata for explicit documents before edits, saves/publishes, review links, or share workflows. Returns file/path, version, archived, draft, and has_draft_changes_since_latest state; does not return Markdown.

```json
{
  "properties": {
    "document_ids": {
      "description": "Document UUIDs to inspect; max 100. For batch edits or publishing, inspect all target documents and check has_draft_changes_since_latest before update_document_draft or save_document_version.",
      "items": {
        "type": "string"
      },
      "type": "array"
    }
  },
  "required": [
    "document_ids"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `get_document`

**Get document**

Workspace read. Return the mutable accepted draft Markdown and metadata for an accessible document. Draft edits are separate from saved versions and shared proposals.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `create_document`

**Create document**

Owner write. Create an Edith Markdown document draft. Markdown content may be empty. Optional file_name must have no extension or a .md extension. This does not save an immutable version or create review/share links. Asset links/images in authored Markdown follow latest unless explicitly pinned with ?rev=N, for example ![Diagram](assets/diagram.png?rev=3). N is one canonical positive asset revision_number; missing/invalid pins never fall back. Saving/sharing does not automatically pin assets. Use list_workspace_asset_revisions to choose a revision and list_document_references to verify it.

```json
{
  "properties": {
    "file_name": {
      "description": "Optional Markdown document file name. Use no extension or a .md extension. Defaults from first H1 or Untitled document.",
      "type": "string"
    },
    "markdown": {
      "description": "Draft Markdown. May be empty.",
      "type": "string"
    },
    "parent_id": {
      "description": "Optional target folder UUID.",
      "type": "string"
    },
    "workspace_id": {
      "description": "Optional target workspace UUID. Defaults to personal workspace.",
      "type": "string"
    }
  },
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `update_document_draft`

**Update document draft**

Workspace destructive write. Replace the accepted draft with exactly the supplied Markdown without saving/publishing a version. expected_version is the required live draft counter. Stale writes fail unless the user explicitly asks to force. Attribution difficulty does not veto a valid current-version replacement; affected older suggestions may move to history. Asset links/images in authored Markdown follow latest unless explicitly pinned with ?rev=N, for example ![Diagram](assets/diagram.png?rev=3). N is one canonical positive asset revision_number; missing/invalid pins never fall back. Saving/sharing does not automatically pin assets. Use list_workspace_asset_revisions to choose a revision and list_document_references to verify it.

```json
{
  "additionalProperties": false,
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    },
    "expected_version": {
      "description": "Required current draft_version from get_document.",
      "minimum": 1,
      "type": "integer"
    },
    "force": {
      "description": "When true, ignore expected_version.",
      "type": "boolean"
    },
    "markdown": {
      "description": "Draft Markdown.",
      "type": "string"
    }
  },
  "required": [
    "document_id",
    "markdown",
    "expected_version"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `edit_document_draft`

**Edit document draft**

Workspace destructive write. Edit the accepted draft without saving a version. Apply targeted Markdown replacements atomically. Supply the live counter(s) from a fresh read and one or more start/end line-column ranges in that exact source. Lines and columns are 1-based; columns count Unicode code points (a tab counts as one), not bytes, UTF-16 units or visual width. End positions are excluded. All ranges refer to the same LF-normalised base. expected_source and replacement_source are required, including empty strings for insertion/deletion. Overlapping edits, stale counters and expected-text mismatches fail without document mutation. Asset links/images in authored Markdown follow latest unless explicitly pinned with ?rev=N, for example ![Diagram](assets/diagram.png?rev=3). N is one canonical positive asset revision_number; missing/invalid pins never fall back. Saving/sharing does not automatically pin assets. Use list_workspace_asset_revisions to choose a revision and list_document_references to verify it.

```json
{
  "additionalProperties": false,
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    },
    "edits": {
      "description": "Atomic replacements with 1-based code-point line/column ranges in the same source base; end positions are excluded.",
      "items": {
        "additionalProperties": false,
        "properties": {
          "end": {
            "additionalProperties": false,
            "properties": {
              "column": {
                "minimum": 1,
                "type": "integer"
              },
              "line": {
                "minimum": 1,
                "type": "integer"
              }
            },
            "required": [
              "line",
              "column"
            ],
            "type": "object"
          },
          "expected_source": {
            "type": "string"
          },
          "replacement_source": {
            "type": "string"
          },
          "start": {
            "additionalProperties": false,
            "properties": {
              "column": {
                "minimum": 1,
                "type": "integer"
              },
              "line": {
                "minimum": 1,
                "type": "integer"
              }
            },
            "required": [
              "line",
              "column"
            ],
            "type": "object"
          }
        },
        "required": [
          "start",
          "end",
          "expected_source",
          "replacement_source"
        ],
        "type": "object"
      },
      "maxItems": 500,
      "minItems": 1,
      "type": "array"
    },
    "expected_version": {
      "description": "Current accepted draft_version returned by get_document.",
      "minimum": 1,
      "type": "integer"
    }
  },
  "required": [
    "edits",
    "document_id",
    "expected_version"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `discard_document_draft`

**Discard document draft**

Owner destructive write. Restore the mutable draft to the latest saved version and drop unsaved draft changes; no new version is saved.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `save_document_version`

**Save document version**

Workspace write. Save/publish the current draft as a new immutable version checkpoint with an optional message. This publishes all current draft changes; use get_document_details first when publishing many documents or when unrelated pending draft changes would matter.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    },
    "message": {
      "description": "Optional Git-style multiline checkpoint message; max 2,000 characters.",
      "type": "string"
    }
  },
  "required": [
    "document_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `list_document_versions`

**List document versions**

Owner read. List immutable saved versions for a document; these are separate from the current mutable draft.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `export_document_draft`

**Export document draft**

Owner read. Return the current mutable draft Markdown for a document; this may differ from the latest saved version.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `export_document_version`

**Export document version**

Owner read. Return Markdown for one immutable saved document version selected by revision_number.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    },
    "revision_number": {
      "description": "Saved version number.",
      "type": "integer"
    }
  },
  "required": [
    "document_id",
    "revision_number"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `archive_document`

**Archive document**

Owner destructive write. Archive an owned document and remove it from active document workflows without deleting it.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `unarchive_document`

**Unarchive document**

Owner write. Restore an archived owned document to active document workflows.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `delete_document`

**Delete document**

Owner destructive write. Permanently delete an owned document only after confirming its current file name.

```json
{
  "properties": {
    "confirm_file_name": {
      "description": "Current document file name, required to confirm deletion.",
      "type": "string"
    },
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id",
    "confirm_file_name"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `create_workspace_folder`

**Create workspace folder**

Owner write. Create a folder in a workspace; list workspaces/files first so the folder target is explicit.

```json
{
  "properties": {
    "name": {
      "description": "Folder name.",
      "type": "string"
    },
    "parent_id": {
      "description": "Optional parent folder UUID.",
      "type": "string"
    },
    "workspace_id": {
      "description": "Workspace UUID.",
      "type": "string"
    }
  },
  "required": [
    "workspace_id",
    "name"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `rename_workspace_file`

**Rename workspace file**

Owner write. Rename a workspace file, folder, asset, or Markdown document file after confirming the file_id and new name.

```json
{
  "properties": {
    "document_id": {
      "description": "Optional document UUID when renaming a Markdown document file.",
      "type": "string"
    },
    "file_id": {
      "description": "Workspace file UUID.",
      "type": "string"
    },
    "name": {
      "description": "New file or folder name.",
      "type": "string"
    },
    "workspace_id": {
      "description": "Workspace UUID.",
      "type": "string"
    }
  },
  "required": [
    "workspace_id",
    "file_id",
    "name"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `move_workspace_file`

**Move workspace file**

Owner write. Move a workspace file, folder, asset, or Markdown document file after confirming source and destination IDs.

```json
{
  "properties": {
    "destination_parent_id": {
      "description": "Optional destination folder UUID. Omit to move to destination workspace root.",
      "type": "string"
    },
    "destination_workspace_id": {
      "description": "Optional destination workspace UUID. Defaults to source workspace.",
      "type": "string"
    },
    "file_id": {
      "description": "Workspace file UUID.",
      "type": "string"
    },
    "workspace_id": {
      "description": "Source workspace UUID.",
      "type": "string"
    }
  },
  "required": [
    "workspace_id",
    "file_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `start_workspace_file_upload`

**Start workspace file upload**

Workspace write. Start an upload with exact total size and SHA-256, subject to overall plan storage and provider limits, with no separate Edith per-file asset cap. For upload_protocol=multipart, use create_workspace_file_upload_part for each 1-based part_number; PUT the exact slice at offset (part_number-1)*part_size, then complete_workspace_file_upload and poll get_workspace_file_upload until completed. Resume by listing uploaded_parts. For single, PUT exact bytes to upload_url with upload_headers, then complete. Never log signed URLs or send Edith authentication to storage. target_file_id plus expected_revision creates an immutable asset version; omission creates a separate file. New text .md uploads become documents.

```json
{
  "properties": {
    "byte_size": {
      "description": "Exact total byte size. No separate Edith per-file asset cap: overall plan storage and the object storage provider's limits apply.",
      "minimum": 0,
      "type": "integer"
    },
    "checksum_sha256": {
      "description": "Lowercase SHA-256 of the exact bytes. A replacement matching current bytes succeeds without a redundant revision.",
      "type": "string"
    },
    "content_type": {
      "description": "MIME type for the upload Content-Type header.",
      "type": "string"
    },
    "expected_revision": {
      "description": "Required with target_file_id. Current asset revision; concurrent changes cause a conflict.",
      "minimum": 1,
      "type": "integer"
    },
    "file_name": {
      "description": "Upload filename. New text .md uploads become Markdown documents; other files become assets. A replacement retains the target asset's workspace filename.",
      "type": "string"
    },
    "message": {
      "description": "Optional version message.",
      "maxLength": 2000,
      "type": "string"
    },
    "multipart": {
      "description": "Request resumable multipart transport for an asset, including small files. Automatically used above 16 MiB. Markdown imports and empty files use single transport.",
      "type": "boolean"
    },
    "parent_id": {
      "description": "Optional parent folder for a new file.",
      "type": "string"
    },
    "target_file_id": {
      "description": "Optional existing asset UUID to upload a new version. Omit to create a separate file; matching names or hashes never silently replace.",
      "type": "string"
    },
    "workspace_id": {
      "description": "Workspace UUID.",
      "type": "string"
    }
  },
  "required": [
    "workspace_id",
    "file_name",
    "content_type",
    "byte_size",
    "checksum_sha256"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `get_workspace_file_upload`

**Get workspace file upload**

Owner read. Read an owned upload's status and a bounded page of uploaded_parts for resuming. Follow next_part using after_part. queued/processing means background sealing and verification are not finished: poll using poll_after_ms until completed or failed. Completed asset results return the original revision receipt; never claim the file was published while processing.

```json
{
  "properties": {
    "after_part": {
      "description": "Exclusive uploaded part-number cursor from next_part. Omit for the first page.",
      "maximum": 10000,
      "minimum": 0,
      "type": "integer"
    },
    "upload_session_id": {
      "description": "Owned upload session UUID.",
      "type": "string"
    }
  },
  "required": [
    "upload_session_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `create_workspace_file_upload_part`

**Create workspace file upload part**

Workspace write. Create a short-lived signed PUT target for one 1-based part_number of an owned multipart session. Upload exactly the corresponding original-byte slice using the returned method, URL and headers including Content-Length. Retry this part independently; get_workspace_file_upload lists accepted part numbers. URLs are temporary write credentials: never log/share them or attach Edith authentication.

```json
{
  "properties": {
    "part_number": {
      "description": "1-based part number, no greater than this session's part_count.",
      "maximum": 10000,
      "minimum": 1,
      "type": "integer"
    },
    "upload_session_id": {
      "description": "Owned multipart upload session UUID.",
      "type": "string"
    }
  },
  "required": [
    "upload_session_id",
    "part_number"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `complete_workspace_file_upload`

**Complete workspace file upload**

Workspace write. Queue multipart sealing and streaming size/SHA-256/type/SVG verification, returning queued/processing before publication. Poll get_workspace_file_upload until completed or failed. Single uploads complete synchronously. Asset completion is retry-safe: reuse upload_session_id for the original revision receipt, even after later updates. unchanged=true means matching current bytes created no revision. Markdown imports retain pending-only completion.

```json
{
  "properties": {
    "upload_session_id": {
      "description": "Workspace file upload session UUID.",
      "type": "string"
    }
  },
  "required": [
    "upload_session_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `abort_workspace_file_upload`

**Abort workspace file upload**

Owner write. Abort a pending workspace file upload and delete its uploaded object if present; this does not delete completed workspace files.

```json
{
  "properties": {
    "upload_session_id": {
      "description": "Workspace file upload session UUID.",
      "type": "string"
    }
  },
  "required": [
    "upload_session_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `delete_workspace_file`

**Delete workspace file**

Owner destructive write. Delete a workspace file, folder, asset, or Markdown document file after confirming its exact current name; this can remove nested files.

```json
{
  "properties": {
    "confirm_file_name": {
      "description": "Current file, folder, asset, or document file name, required to confirm deletion.",
      "type": "string"
    },
    "file_id": {
      "description": "Workspace file UUID.",
      "type": "string"
    },
    "workspace_id": {
      "description": "Workspace UUID.",
      "type": "string"
    }
  },
  "required": [
    "workspace_id",
    "file_id",
    "confirm_file_name"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `create_share_link`

**Create share link**

Owner write. Create a read-only public share link pinned to the latest or selected saved version; this does not create a review/comment workflow.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    },
    "revision_number": {
      "description": "Optional saved version number. Defaults to latest saved version.",
      "type": "integer"
    }
  },
  "required": [
    "document_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `list_share_links`

**List share links**

Owner read. List read-only share links for a document, including the saved revision number each link is pinned to.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `revoke_share_link`

**Revoke share link**

Owner destructive write. Revoke a read-only share link by URL or sh_ token so it can no longer be used.

```json
{
  "properties": {
    "share_token": {
      "description": "Share token beginning sh_.",
      "type": "string"
    },
    "share_url": {
      "description": "Full share URL.",
      "type": "string"
    }
  },
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `list_contacts`

**List contacts**

Owner read. List saved reviewer contacts for review-link workflows; contacts are distinct from review identities.

```json
{
  "properties": {
    "query": {
      "description": "Optional search query.",
      "type": "string"
    }
  },
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `upsert_contact`

**Upsert contact**

Owner write. Create or update a saved reviewer contact by email for future review-link workflows.

```json
{
  "properties": {
    "email": {
      "description": "Contact email address.",
      "type": "string"
    },
    "name": {
      "description": "Optional contact name.",
      "type": "string"
    }
  },
  "required": [
    "email"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `update_contact`

**Update contact**

Owner write. Update a saved reviewer contact by ID after confirming the new email and optional name.

```json
{
  "properties": {
    "contact_id": {
      "description": "Contact UUID.",
      "type": "string"
    },
    "email": {
      "description": "Contact email address.",
      "type": "string"
    },
    "name": {
      "description": "Optional contact name.",
      "type": "string"
    }
  },
  "required": [
    "contact_id",
    "email"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `archive_contact`

**Archive contact**

Owner destructive write. Archive a saved reviewer contact by ID; use only after explicit confirmation.

```json
{
  "properties": {
    "contact_id": {
      "description": "Contact UUID.",
      "type": "string"
    }
  },
  "required": [
    "contact_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `get_document_share_target`

**Get document share target**

Workspace read. Check a named recipient's relationship and effective access to the document's current workspace. Requires sender edit access. Returns destination_type, capabilities, email_purpose and expected_target. No token, link or email is created; unrelated account details are not exposed.

```json
{
  "additionalProperties": false,
  "properties": {
    "document_id": {
      "description": "Document UUID in the sender's current accessible workspace.",
      "type": "string"
    },
    "recipient_email": {
      "description": "Named recipient's email address.",
      "type": "string"
    }
  },
  "required": [
    "document_id",
    "recipient_email"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `share_document`

**Share document**

Workspace external write. ALWAYS SENDS EMAIL to recipient_email. Before calling, show the complete email, subject and recipients and obtain explicit final sending authorisation. First call get_document_share_target and use its expected_target. Existing workspace access uses an internal document link with no role change or review quota; others receive an external review link. Reuse request_id on double clicks, replays and retries. Retry only email_status=failed with the returned attempt as expected_attempt; sending/uncertain must not be automatically resent. Changed recipient access requires a fresh preflight and renewed authorisation.

```json
{
  "additionalProperties": false,
  "properties": {
    "document_id": {
      "description": "Document UUID in the sender's current accessible workspace.",
      "type": "string"
    },
    "expected_attempt": {
      "description": "0 initially. Explicit failed-delivery retry uses returned attempt; never retry sending/uncertain automatically.",
      "minimum": 0,
      "type": "integer"
    },
    "expected_target": {
      "description": "Exact expected_target from get_document_share_target, checked before obtaining final email sending authorisation.",
      "type": "string"
    },
    "recipient_email": {
      "description": "Named recipient's email address.",
      "type": "string"
    },
    "request_id": {
      "description": "New UUID for one authorised email; reuse on replays and failed-delivery retries.",
      "type": "string"
    }
  },
  "required": [
    "document_id",
    "recipient_email",
    "expected_target",
    "request_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": true,
  "readOnlyHint": false
}
```

## `create_public_review_link`

**Create public review link**

Workspace write. Create an unnamed public rw_ review link after saving the draft. Shows the current review state, not a pinned revision. Sends no email. Named recipients must use share_document.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `get_review_status`

**Get review status**

Owner read. List document-scoped review links and active/revoked status for an owned document; review links are distinct from share links.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `revoke_review_link`

**Revoke review link**

Owner destructive write. Revoke a document-scoped rw_ review link so reviewers can no longer use it.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    },
    "review_link_id": {
      "description": "Review link UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id",
    "review_link_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `get_final_markdown`

**Get final markdown**

Owner read. Return the latest saved Markdown version for an owned document, not the mutable draft.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `get_document_proposal`

**Get document proposal**

Workspace read. Return the shared proposal head for a document visible with workspace read capability. The response includes shared-head Markdown, current accepted draft and proposal versions, safe attribution, and source-hunk state and ranges. Reading leaves the accepted draft, proposal, and saved versions unchanged.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `update_document_proposal`

**Update document proposal**

Workspace write. Replace the one shared suggested draft with exactly the submitted Markdown, using both required current counters. Preserve clear earlier attribution; ambiguous attribution becomes a larger rewrite by this submitter, with earlier changes kept in history. Attribution difficulty does not veto current-version source. Stale writes fail without mutation. The accepted draft and saved versions remain unchanged. Asset links/images in authored Markdown follow latest unless explicitly pinned with ?rev=N, for example ![Diagram](assets/diagram.png?rev=3). N is one canonical positive asset revision_number; missing/invalid pins never fall back. Saving/sharing does not automatically pin assets. Use list_workspace_asset_revisions to choose a revision and list_document_references to verify it.

```json
{
  "additionalProperties": false,
  "properties": {
    "document_id": {
      "description": "Document UUID in an accessible workspace.",
      "type": "string"
    },
    "expected_draft_version": {
      "description": "Current accepted document draft version returned by a proposal read.",
      "type": "integer"
    },
    "expected_proposal_version": {
      "description": "Current shared proposal version returned by a proposal read.",
      "type": "integer"
    },
    "proposed_markdown": {
      "description": "Complete proposed Markdown based on the shared proposal head.",
      "type": "string"
    }
  },
  "required": [
    "document_id",
    "proposed_markdown",
    "expected_draft_version",
    "expected_proposal_version"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `edit_document_proposal`

**Edit document proposal**

Workspace write. Edit the one shared suggested draft as this workspace user; accepted source and saved versions remain unchanged. Apply targeted Markdown replacements atomically. Supply the live counter(s) from a fresh read and one or more start/end line-column ranges in that exact source. Lines and columns are 1-based; columns count Unicode code points (a tab counts as one), not bytes, UTF-16 units or visual width. End positions are excluded. All ranges refer to the same LF-normalised base. expected_source and replacement_source are required, including empty strings for insertion/deletion. Overlapping edits, stale counters and expected-text mismatches fail without document mutation. Asset links/images in authored Markdown follow latest unless explicitly pinned with ?rev=N, for example ![Diagram](assets/diagram.png?rev=3). N is one canonical positive asset revision_number; missing/invalid pins never fall back. Saving/sharing does not automatically pin assets. Use list_workspace_asset_revisions to choose a revision and list_document_references to verify it.

```json
{
  "additionalProperties": false,
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    },
    "edits": {
      "description": "Atomic replacements with 1-based code-point line/column ranges in the same source base; end positions are excluded.",
      "items": {
        "additionalProperties": false,
        "properties": {
          "end": {
            "additionalProperties": false,
            "properties": {
              "column": {
                "minimum": 1,
                "type": "integer"
              },
              "line": {
                "minimum": 1,
                "type": "integer"
              }
            },
            "required": [
              "line",
              "column"
            ],
            "type": "object"
          },
          "expected_source": {
            "type": "string"
          },
          "replacement_source": {
            "type": "string"
          },
          "start": {
            "additionalProperties": false,
            "properties": {
              "column": {
                "minimum": 1,
                "type": "integer"
              },
              "line": {
                "minimum": 1,
                "type": "integer"
              }
            },
            "required": [
              "line",
              "column"
            ],
            "type": "object"
          }
        },
        "required": [
          "start",
          "end",
          "expected_source",
          "replacement_source"
        ],
        "type": "object"
      },
      "maxItems": 500,
      "minItems": 1,
      "type": "array"
    },
    "expected_draft_version": {
      "description": "Current accepted_draft_version from get_document_proposal or get_review_proposal.",
      "minimum": 1,
      "type": "integer"
    },
    "expected_proposal_version": {
      "description": "Current proposal_version from that same shared suggested-draft read.",
      "minimum": 0,
      "type": "integer"
    }
  },
  "required": [
    "edits",
    "document_id",
    "expected_draft_version",
    "expected_proposal_version"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `apply_proposed_changes`

**Apply proposed changes**

Workspace destructive write. Atomically apply selected pending changes from the one shared suggested draft to the accepted draft. Other current changes remain in the suggested draft with their authorship. Superseded, rejected and applied changes are history and cannot be applied again. Both current concurrency versions are required. Saved versions remain unchanged until save_document_version runs.

```json
{
  "additionalProperties": false,
  "properties": {
    "document_id": {
      "description": "Document UUID in an editable workspace.",
      "type": "string"
    },
    "expected_draft_version": {
      "description": "Current accepted document draft version returned by a proposal read.",
      "type": "integer"
    },
    "expected_proposal_version": {
      "description": "Current shared proposal version returned by a proposal read.",
      "type": "integer"
    },
    "proposed_change_ids": {
      "description": "Proposed change UUIDs to decide atomically. Select pending changes currently represented in the shared suggested draft.",
      "items": {
        "type": "string"
      },
      "minItems": 1,
      "type": "array",
      "uniqueItems": true
    }
  },
  "required": [
    "document_id",
    "proposed_change_ids",
    "expected_draft_version",
    "expected_proposal_version"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `reject_proposed_changes`

**Reject proposed changes**

Workspace destructive write. Atomically reject selected pending changes from the one shared suggested draft, restoring accepted wording for those changes and preserving all other current changes and authorship. Historical alternatives are not revived. Both current concurrency versions are required. The accepted draft and saved versions remain unchanged; the proposal version advances once.

```json
{
  "additionalProperties": false,
  "properties": {
    "document_id": {
      "description": "Document UUID in an editable workspace.",
      "type": "string"
    },
    "expected_draft_version": {
      "description": "Current accepted document draft version returned by a proposal read.",
      "type": "integer"
    },
    "expected_proposal_version": {
      "description": "Current shared proposal version returned by a proposal read.",
      "type": "integer"
    },
    "proposed_change_ids": {
      "description": "Proposed change UUIDs to decide atomically.",
      "items": {
        "type": "string"
      },
      "minItems": 1,
      "type": "array",
      "uniqueItems": true
    }
  },
  "required": [
    "document_id",
    "proposed_change_ids",
    "expected_draft_version",
    "expected_proposal_version"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": true,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `list_comment_threads`

**List comment threads**

Owner read. Return visible comment threads for an owned document with explicit safe thread, source-selector, author-display, and comment fields.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `create_document_comment`

**Create document comment**

Owner write. Create a whole-document discussion thread without changing the accepted draft, shared proposal, or saved versions.

```json
{
  "properties": {
    "body": {
      "description": "Comment body.",
      "type": "string"
    },
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id",
    "body"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `create_content_comment`

**Create content comment**

Owner write. Create a content-anchored discussion thread from an immutable source snapshot byte range without changing document content.

```json
{
  "properties": {
    "body": {
      "description": "Comment body.",
      "type": "string"
    },
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    },
    "source_end_byte": {
      "description": "Exclusive UTF-8 byte end in the exact LF-normalised snapshot Markdown.",
      "type": "integer"
    },
    "source_snapshot_id": {
      "description": "Immutable source snapshot UUID returned with the Markdown.",
      "type": "string"
    },
    "source_start_byte": {
      "description": "Zero-based UTF-8 byte start in the exact LF-normalised snapshot Markdown.",
      "type": "integer"
    }
  },
  "required": [
    "document_id",
    "source_snapshot_id",
    "source_start_byte",
    "source_end_byte",
    "body"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `create_proposed_change_comment`

**Create proposed change comment**

Owner write. Create or extend the discussion attached to a pending proposed change. Edith attaches the discussion to the same visible proposed-change group used by the browser UI.

```json
{
  "additionalProperties": false,
  "properties": {
    "body": {
      "description": "Comment body.",
      "type": "string"
    },
    "document_id": {
      "description": "Document UUID in an accessible workspace.",
      "type": "string"
    },
    "proposed_change_id": {
      "description": "Pending proposed change UUID returned by get_document_proposal.",
      "type": "string"
    }
  },
  "required": [
    "document_id",
    "proposed_change_id",
    "body"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `reply_comment_thread`

**Reply comment thread**

Owner write. Reply to an existing comment thread on an owned document without saving a document version.

```json
{
  "properties": {
    "body": {
      "description": "Reply body.",
      "type": "string"
    },
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    },
    "thread_id": {
      "description": "Comment thread UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id",
    "thread_id",
    "body"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `resolve_comment_thread`

**Resolve comment thread**

Owner write. Resolve a comment thread on an owned document without changing draft content or saving a version.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    },
    "thread_id": {
      "description": "Comment thread UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id",
    "thread_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `reopen_comment_thread`

**Reopen comment thread**

Owner write. Reopen a resolved comment thread on an owned document when more discussion is needed.

```json
{
  "properties": {
    "document_id": {
      "description": "Document UUID.",
      "type": "string"
    },
    "thread_id": {
      "description": "Comment thread UUID.",
      "type": "string"
    }
  },
  "required": [
    "document_id",
    "thread_id"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `get_review_document`

**Get review document**

Reviewer-token read. Return the current accepted review document and safe reviewer context for an active rw_ token. The response excludes token hashes, contact details, and internal identity records.

```json
{
  "properties": {
    "review_token": {
      "description": "Review token beginning rw_.",
      "type": "string"
    }
  },
  "required": [
    "review_token"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `get_review_proposal`

**Get review proposal**

Reviewer-token read. Return the document's shared proposal head through an active review token. The response includes shared-head Markdown, current accepted draft and proposal versions, safe attribution, and source-hunk state and ranges. Reading leaves all document state unchanged.

```json
{
  "properties": {
    "review_token": {
      "description": "Review token beginning rw_.",
      "type": "string"
    }
  },
  "required": [
    "review_token"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `update_review_proposal`

**Update review proposal**

Reviewer-token write. Replace the shared suggested draft with exactly this signed-in review identity's submitted Markdown. Both current counters and proposed_markdown are required. Preserve clear attribution; ambiguous sections become a larger rewrite by this reviewer with older contributions kept in history. Stale writes fail without mutation; the accepted draft and saved versions remain unchanged. Preserve authored asset ?rev=N selectors; omitted rev follows latest and invalid/missing pins never fall back. Reviewer tokens do not grant workspace asset-history enumeration or owner-only list_document_references access.

```json
{
  "additionalProperties": false,
  "properties": {
    "expected_draft_version": {
      "description": "Current accepted document draft version returned by a proposal read.",
      "type": "integer"
    },
    "expected_proposal_version": {
      "description": "Current shared proposal version returned by a proposal read.",
      "type": "integer"
    },
    "proposed_markdown": {
      "description": "Complete proposed Markdown based on the shared proposal head.",
      "type": "string"
    },
    "review_token": {
      "description": "Active review token beginning rw_.",
      "type": "string"
    }
  },
  "required": [
    "review_token",
    "proposed_markdown",
    "expected_draft_version",
    "expected_proposal_version"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `edit_review_proposal`

**Edit review proposal**

Reviewer-token write. Edit the same shared suggested draft as this signed-in review identity through an active review link. Accepted source and saved versions remain unchanged. Apply targeted Markdown replacements atomically. Supply the live counter(s) from a fresh read and one or more start/end line-column ranges in that exact source. Lines and columns are 1-based; columns count Unicode code points (a tab counts as one), not bytes, UTF-16 units or visual width. End positions are excluded. All ranges refer to the same LF-normalised base. expected_source and replacement_source are required, including empty strings for insertion/deletion. Overlapping edits, stale counters and expected-text mismatches fail without document mutation. Preserve authored asset ?rev=N selectors; omitted rev follows latest and invalid/missing pins never fall back. Reviewer tokens do not grant workspace asset-history enumeration or owner-only list_document_references access.

```json
{
  "additionalProperties": false,
  "properties": {
    "edits": {
      "description": "Atomic replacements with 1-based code-point line/column ranges in the same source base; end positions are excluded.",
      "items": {
        "additionalProperties": false,
        "properties": {
          "end": {
            "additionalProperties": false,
            "properties": {
              "column": {
                "minimum": 1,
                "type": "integer"
              },
              "line": {
                "minimum": 1,
                "type": "integer"
              }
            },
            "required": [
              "line",
              "column"
            ],
            "type": "object"
          },
          "expected_source": {
            "type": "string"
          },
          "replacement_source": {
            "type": "string"
          },
          "start": {
            "additionalProperties": false,
            "properties": {
              "column": {
                "minimum": 1,
                "type": "integer"
              },
              "line": {
                "minimum": 1,
                "type": "integer"
              }
            },
            "required": [
              "line",
              "column"
            ],
            "type": "object"
          }
        },
        "required": [
          "start",
          "end",
          "expected_source",
          "replacement_source"
        ],
        "type": "object"
      },
      "maxItems": 500,
      "minItems": 1,
      "type": "array"
    },
    "expected_draft_version": {
      "description": "Current accepted_draft_version from get_document_proposal or get_review_proposal.",
      "minimum": 1,
      "type": "integer"
    },
    "expected_proposal_version": {
      "description": "Current proposal_version from that same shared suggested-draft read.",
      "minimum": 0,
      "type": "integer"
    },
    "review_token": {
      "description": "Active rw_ review token.",
      "type": "string"
    }
  },
  "required": [
    "edits",
    "review_token",
    "expected_draft_version",
    "expected_proposal_version"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `list_review_comment_threads`

**List review comment threads**

Reviewer-token read. List comment threads visible through an rw_ review token before replying or adding feedback.

```json
{
  "properties": {
    "review_token": {
      "description": "Review token beginning rw_.",
      "type": "string"
    }
  },
  "required": [
    "review_token"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": true,
  "openWorldHint": false,
  "readOnlyHint": true
}
```

## `create_review_document_comment`

**Create review document comment**

Reviewer-token write. Create a whole-document comment through an rw_ token for questions or general feedback, not as a substitute for proposed edits.

```json
{
  "properties": {
    "body": {
      "description": "Comment body.",
      "type": "string"
    },
    "review_token": {
      "description": "Review token beginning rw_.",
      "type": "string"
    }
  },
  "required": [
    "review_token",
    "body"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `create_review_content_comment`

**Create review content comment**

Reviewer-token write. Create a content-anchored discussion from an immutable source snapshot byte range through an active rw_ token without changing document content.

```json
{
  "properties": {
    "body": {
      "description": "Comment body.",
      "type": "string"
    },
    "review_token": {
      "description": "Review token beginning rw_.",
      "type": "string"
    },
    "source_end_byte": {
      "description": "Exclusive UTF-8 byte end in the exact LF-normalised snapshot Markdown.",
      "type": "integer"
    },
    "source_snapshot_id": {
      "description": "Immutable source snapshot UUID returned with the review Markdown.",
      "type": "string"
    },
    "source_start_byte": {
      "description": "Zero-based UTF-8 byte start in the exact LF-normalised snapshot Markdown.",
      "type": "integer"
    }
  },
  "required": [
    "review_token",
    "source_snapshot_id",
    "source_start_byte",
    "source_end_byte",
    "body"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `create_review_proposed_change_comment`

**Create review proposed change comment**

Reviewer-token write. Create or extend the discussion attached to a pending proposed change through an active rw_ token. Edith attaches the discussion to the same visible proposed-change group used by the browser UI.

```json
{
  "additionalProperties": false,
  "properties": {
    "body": {
      "description": "Comment body.",
      "type": "string"
    },
    "proposed_change_id": {
      "description": "Pending proposed change UUID returned by get_review_proposal.",
      "type": "string"
    },
    "review_token": {
      "description": "Active review token beginning rw_.",
      "type": "string"
    }
  },
  "required": [
    "review_token",
    "proposed_change_id",
    "body"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

## `reply_review_comment_thread`

**Reply review comment thread**

Reviewer-token write. Reply to an existing comment thread visible through an rw_ review token.

```json
{
  "properties": {
    "body": {
      "description": "Reply body.",
      "type": "string"
    },
    "review_token": {
      "description": "Review token beginning rw_.",
      "type": "string"
    },
    "thread_id": {
      "description": "Comment thread UUID.",
      "type": "string"
    }
  },
  "required": [
    "review_token",
    "thread_id",
    "body"
  ],
  "type": "object"
}
```

Annotations:

```json
{
  "destructiveHint": false,
  "idempotentHint": false,
  "openWorldHint": false,
  "readOnlyHint": false
}
```

