Sasha MCP reference

Document write tools (writeDoc, editDoc)

Tool names: writeDoc, editDoc

Scopes: knowledge:read, knowledge:write

When to use

This family has two tools. writeDoc creates a document or replaces a whole document. editDoc replaces one exact passage. Use editDoc when you can: it changes the least.

The two tools are in the tool list only when all of these are true:

  • The instance has document writing turned on. It is off by default, and the instance's operator turns it on. Writing to a member home and writing to a shared project are two separate switches.
  • The person who connected is a member. An admin or staff connection never gets these tools, even with the knowledge:write scope. The tools are absent, not refused.
  • The connection holds knowledge:read and knowledge:write. A member's default grant includes both. A connection made before knowledge:write existed does not gain it: the person must reconnect, or mint a new token.

A member can write in two places:

  • Their own member home, when home writing is on.
  • An ordinary shared project where they hold a write grant, when shared-project writing is on. A read grant refuses the write. Another member's home answers as not found.

Every change is checked again against the person's current permissions. There is no confirmation step, no history and no undo. A replacement discards the old text.

The loop:

  1. Call readDoc for the document. Keep the version it returns.
  2. Call editDoc or writeDoc with that version as expectedVersion. The change is refused if the file changed after your read.
  3. To create a document, call writeDoc without expectedVersion. It is refused if a document already exists at that path.

Arguments that both tools take:

  • operationId: an id you make for this change, 8 to 64 characters of letters, digits, ., _ or -. A UUID is good. A retry with the same operationId and the same arguments returns the first result and does not write twice. The same operationId with different arguments is refused.
  • project: a project id from listProjects.
  • path: the path in the project. The file types are .md, .txt, .csv, .json, .xml, .yaml and .yml, up to 1 MiB.
  • reason: one line that says why, 1 to 100 characters after surrounding spaces are removed, with no control characters.

writeDoc also takes content (the complete new text) and an optional expectedVersion. editDoc also takes oldString, newString and a required expectedVersion. oldString must occur exactly once in the current file.

The result is JSON text with operationId, operation, path, bytes, created, reason, the new version, and project.

Example

A member creates a note in their own home with writeDoc:

{
  "operationId": "7c1e4b2a-9f3d-4e6a-8b10-5d2c7f9e0a41",
  "project": "member-14",
  "path": "notes/2026-10-02-client-call.md",
  "content": "# Client call, 2 October 2026\n\nThe client asked for the diagnostic at the standard price.\n",
  "reason": "Notes from the client call"
}
{
  "operationId": "7c1e4b2a-9f3d-4e6a-8b10-5d2c7f9e0a41",
  "operation": "writeDoc",
  "path": "notes/2026-10-02-client-call.md",
  "bytes": 90,
  "created": true,
  "reason": "Notes from the client call",
  "version": "AQ-example-opaque-version",
  "project": "member-14"
}

Refusals and what to do

A refusal is an error result with the text Error in <tool>: <code>:<reason>. For a code that a retry can fix, the text adds (recoverable: …) with the right way to retry.

  • version_conflict:stale_version: the file changed after your read. Call readDoc again, decide whether your change still applies to the new text, and retry with the new version and a new operationId. Never retry without the version.
  • version_conflict:target_exists: you called writeDoc without expectedVersion, and a document already exists at that path. Read it, and replace it only if that is what the person wants.
  • version_conflict:target_absent: you passed expectedVersion, but there is no document at that path.
  • invalid_input:edit_no_match or invalid_input:edit_not_unique: oldString does not occur in the file, or occurs more than once. Include more surrounding text.
  • idempotency_conflict:operation_id_reused: the operationId was used before with different arguments. Use a new operationId for a new change.
  • forbidden:home_writes_disabled: the target is a member home, but this instance has home writing turned off. Only shared-project writing is on. Write to a shared project where the person has a write grant, or ask the operator.
  • forbidden:not_a_member_home: the target is a shared project, but this instance has shared-project writing turned off. Only home writing is on. Write to the person's own home instead, or ask the operator.
  • payload_too_large:content_too_large: the new document would be larger than 1 MiB. Make it smaller, or split it into two documents.
  • invalid_input:no_change: the change would leave the document as it is, for example newString is the same as oldString. Do not send it.
  • forbidden:path_denied: the person does not have write permission on that project, for example only a read grant.
  • not_found:project_not_visible: the project does not exist, or this person cannot see it. Use a project from listProjects.
  • repository_busy:…: another change to the same file is in progress. Wait a short time, then retry with the same operationId and the same arguments.
  • invalid_input:arguments_invalid (<fields>): the arguments do not match the schema, for example an extra argument or an operationId with the wrong form. The named fields are wrong.
  • If writeDoc and editDoc are not in your tool list, a call returns MCP error -32602: Tool writeDoc not found. One of the conditions above is not true. Read the writing and permissions sections of getDocs. Do not tell the person that Sasha cannot write.

Related

  • writeDoc and editDoc are the two tools of this family.
  • readDoc gives the version to pass as expectedVersion.
  • listProjects and listDocs give the project ids and paths.
  • getDocs has the writing and permissions sections.
made with bernard

Cookie settings