Sasha MCP reference

editAppFile

Replace one exact passage in a source file of a Sasha App you manage

Replace exactly one occurrence of oldString with newString. oldString must match the current file exactly and occur exactly once, otherwise the edit is refused rather than guessed. Always readAppFile first and pass its version. The change is LIVE immediately. If this call returns an error, the change may still have landed. Call readAppFile before retrying. The result carries status: when status.ok is false the app is NOT usable until the listed diagnostics are fixed. Each names the package file, the line when known, the error code and a reason token. Fix the file and check again; the app is live as soon as it validates.

Arguments

ArgumentTypeRequiredDescription
appstringrequiredThe app id (lowercase kebab-case), as shown by open_app__<id> or listAppFiles.
pathstringrequiredPackage-relative path such as APP.md, index.html, styles.css, app.js, schema.sql, migrations/002-add-code.sql or actions/<id>.action.yaml.
oldStringstringrequiredNo description
newStringstringrequiredNo description
reasonstringrequiredOne line saying why, recorded in the audit log.
expectedVersionstringrequiredThe version returned by readAppFile or listAppFiles for the bytes you last saw.

Scopes

apps:invoke, apps:write

Annotations

  • Read only: no
  • Destructive: no

When to use

Use editAppFile for most changes to an app: it changes only the passage you name. To create a file or replace all of it, use writeAppFile.

The tool needs the same access as listAppFiles: the scopes apps:invoke and apps:write, an admin or staff user, and manage access on the app. There is no confirmation step for the source tools.

  1. Call readAppFile for the file. Keep its version.
  2. Call editAppFile with oldString copied exactly from the current text, newString, a one-line reason (1 to 100 characters, recorded in the audit log), and the version as expectedVersion.

Rules:

  • oldString must match the current file exactly and occur exactly once. If not, the edit is refused. It is never guessed. Include more of the surrounding text to make it unique.
  • newString can be empty, to remove the passage. It must not be the same as oldString.
  • expectedVersion is required.
  • The change is live at once. There is no draft and no undo.

The result has the new version of the file and status. An edit that passes the checks always lands, even when it breaks the app. Then status.ok is false and status.diagnostics says what to fix. When status.ok is true, the app is live at status.revision.

If the call returns an error, the change can still have landed. Call readAppFile before you retry.

Example

Add the billable column to schema.sql, after a migration added it:

{
  "app": "timesheet",
  "path": "schema.sql",
  "oldString": "  note TEXT\n);",
  "newString": "  note TEXT,\n  billable INTEGER NOT NULL DEFAULT 1\n);",
  "reason": "Match schema.sql to migration 002",
  "expectedVersion": "3f79bb7b435b05321651daefd374cdc681dc06faa65e374e38337b88ca046dea"
}

The structured result (structuredContent):

{
  "app": "timesheet",
  "path": "schema.sql",
  "version": "aaa9402664f1a41f40ebbc52c9993eb66aeb366602958fdfaa283b71e64db123",
  "status": {
    "ok": true,
    "revision": "de7d1b721a1e0632b7cf04edf5032c8ecffa9f9a08492152b926f1a5a7e765d7",
    "diagnostics": []
  }
}

The text part of the result says Edited schema.sql (version …). and App validates. Live revision ….

Refusals and what to do

The error result's text is the message. structuredContent.error holds code, message, retryable and diagnosticId.

  • APP_SOURCE_MATCH_INVALID: oldString does not occur in the current file, or occurs more than once. Call readAppFile, and include more surrounding text so that the passage occurs exactly once.
  • APP_SOURCE_CONFLICT: the file changed after you read it. Call readAppFile again, decide whether your change still applies to the new text, and retry with the new version.
  • APP_NOT_FOUND (app_not_found): there is no file at that path. To create a file, use writeAppFile without expectedVersion.
  • APP_INPUT_INVALID (app_input_invalid): the arguments do not match the schema, or newString is the same as oldString. Other examples: an empty oldString, a missing expectedVersion, an expectedVersion that is not 64 hex characters, or a reason that is empty, longer than 100 characters or has a control character.
  • APP_RESOURCE_LIMIT (app_resource_limit): the file would be larger than 1 MiB, or the package would go past 1 MiB in total.
  • APP_SOURCE_FILE_INVALID or APP_PATH_INVALID (app_path_invalid): the path is not one that these tools can change. Use a path from listAppFiles.
  • APP_ACCESS_DENIED (app_access_denied): this person does not have manage access on the app, or is not an admin or staff user. An app id that does not exist gets the same answer.
  • If the connection does not hold both apps:invoke and apps:write, the tool is not in your tool list, and a call to it returns MCP error -32602: Tool editAppFile not found. Read the permissions section of getDocs. The person must reconnect, or mint a new token, with apps:write. Only admin and staff can hold it.

Related

  • readAppFile gives the text to copy and the version.
  • writeAppFile creates a file or replaces all of it.
  • checkApp validates the package after a set of edits.
  • listAppFiles shows every file and the package status.
made with bernard

Cookie settings