Skip to main content
Glama

Edit document

edit

Replace an exact-match substring in an existing document body and validate the whole document before writing, enabling precise changes without frontmatter access.

Instructions

Surgical, exact-match string replacement of an existing document's frontmatter-stripped body across the whole-body domains (type is one of req, uc, tsk, qa, prb, gol, rsk, dec, sop, feat, vcr, sysrs, txt; adr is not supported -- an explicit pre-dispatch ValueError, unlike update's inherited KeyError). Read the current body via the corresponding get_<d>(id, raw=True) first -- the read-before-edit step is a client convention, not server-enforced. Use edit for a surgical string replacement within an existing body; use the generic update tool for a whole-body or line-range replacement instead. The YAML frontmatter is never addressable (body only). The edit is 2-fold: stage 1 requires old_str to match the on-disk body byte-exactly -- uniquely, unless replace_all is true, in which case every exact occurrence is rewritten -- and stage 2 validates the edited body as a whole document; the document is written to disk only if both stages pass, and nothing is written on any failure (the file stays byte-unchanged). An empty new_str is a pure deletion (legal iff stage 2 validates). Matching is pure byte-exact with no line-ending normalization (an old_str containing \n will not match a CRLF body), no BOM handling, and no fuzzy/regex fallback. A document that exists but fails to parse returns a ParseFailureResult (error/path/id) instead of raising the domain's not-found error -- its error text is byte-identical to the domain's list_<d> failed row's error for the same file (identical field path and cause, including the trailing pydantic documentation line; ADR 9080b37c-82b3-4f63-81f1-79641d0bf14c) -- and a truly-absent id still raises the domain's not-found error. A stage-2 content-validation failure on the post-edit result returns a non-raising ValidateResult (valid=False, errors=[{message}]) with the message capped at 300 chars as the generic validate tool caps it, instead of raising AssertionError/pydantic.ValidationError (ADR b8c9bfea-6dcf-4158-bfc5-4ec17abb842f, GitHub issue #170 -- case 4 of the ADR 519d1206 non-raising-structured-result workaround chain). Stage-1's not-found/multiple-matches guards and every caller-usage ValueError (invalid id shape, unknown or adr type, identical input, empty old_str) still raise. An invalid id (path-injection attempt or wrong format for type) is a ValueError raised before any file access. Returns the updated frontmatter only (no body; updated bumped) on success; use the corresponding get_<d> tool to fetch the full document afterward. The optional language parameter (default 'en', feat-197-i18n) selects the language variant to edit: omitted/'en' = the flat default-language document, exactly the default behavior; a non-default ISO 639-1-shaped lowercase two-letter code (e.g. 'de') = that language's variant at docs//{language}/ (found by id-scan of that subdirectory), matched against and written to that file ONLY -- the EN file's content and updated timestamp stay untouched -- with the stage-2 validation going through that language's heading-mapping table. Every whole-body type except feat supports a non-default language; for feat (always English) a non-default language raises a ValueError, as does a malformed language or one with no packaged heading-mapping table -- all raised before any file access.

Input Schema

NameRequiredDescriptionDefault
idYes
typeYes
new_strYes
old_strYes
languageNoen
replace_allNo

Output Schema

NameRequiredDescriptionDefault
resultYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed4 schema fields changedv0.38.0
    • addedInput schema / properties / language
      Added value: +{
      +  "default": "en",
      +  "title": "Language",
      +  "type": "string"
      +}
    • changedInput schema / properties / type / enum
      Previous value: -[
      -  "req",
      -  "uc",
      -  "tsk",
      -  "qa",
      -  "prb",
      -  "gol",
      -  "rsk",
      -  "dec",
      -  "sop",
      -  "feat",
      -  "vcr",
      -  "sysrs"
      -]New value: +[
      +  "req",
      +  "uc",
      +  "tsk",
      +  "qa",
      +  "prb",
      +  "gol",
      +  "rsk",
      +  "dec",
      +  "sop",
      +  "feat",
      +  "vcr",
      +  "sysrs",
      +  "txt"
      +]
    • addedOutput schema / $defs / TxtFrontmatter
      Added value: +{
      +  "description": "Free-Form Text (TXT) frontmatter: `MarkdownFrontmatter` narrowed for the ``txt`` document type.\n\nParameters\n----------\ntype:\n    Fixed discriminator, always ``\"txt\"``. Narrows the base's mandatory,\n    default-less ``str`` field to a ``Literal[\"txt\"] = \"txt\"``, so a document\n    omitting ``type`` entirely still parses as a free-form text document.\nstatus:\n    One of ``\"draft\"``, ``\"progress\"``, ``\"done\"``. Narrows the base's\n    free-form ``str = \"draft\"`` default to this closed three-value set.\n    Blank/absent still defaults to ``\"draft\"`` (inherited from the base's\n    ``_default_blank_status_to_draft`` validator, which runs before this\n    one).\nversion:\n    The ``models.md`` schema major.minor.patch version this document's\n    frontmatter was written with. DO NOT CHANGE!\n\nAll other fields (``id``, ``created``, ``updated``, ``version``,\n``classification``) are inherited unchanged from\n:class:`MarkdownFrontmatter`.",
      +  "properties": {
      +    "classification": {
      +      "anyOf": [
      +        {
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "default": null,
      +      "title": "Classification"
      +    },
      +    "created": {
      +      "anyOf": [
      +        {
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "default": null,
      +      "pattern": "^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}\\.\\d{3}(?:Z|[+-]\\d{2}:\\d{2})$",
      +      "title": "Created"
      +    },
      +    "id": {
      +      "anyOf": [
      +        {
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "default": null,
      +      "title": "Id"
      +    },
      +    "status": {
      +      "default": "draft",
      +      "enum": [
      +        "done",
      +        "draft",
      +        "progress"
      +      ],
      +      "title": "Status",
      +      "type": "string"
      +    },
      +    "type": {
      +      "const": "txt",
      +      "default": "txt",
      +      "title": "Type",
      +      "type": "string"
      +    },
      +    "updated": {
      +      "anyOf": [
      +        {
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "default": null,
      +      "pattern": "^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}\\.\\d{3}(?:Z|[+-]\\d{2}:\\d{2})$",
      +      "title": "Updated"
      +    },
      +    "version": {
      +      "default": "1.0.0",
      +      "title": "Version",
      +      "type": "string"
      +    }
      +  },
      +  "title": "TxtFrontmatter",
      +  "type": "object"
      +}
    • changedOutput schema / properties / result / anyOf
      Previous value: -[
      -  {
      -    "$ref": "#/$defs/ReqFrontmatter"
      -  },
      -  {
      -    "$ref": "#/$defs/UcFrontmatter"
      -  },
      -  {
      -    "$ref": "#/$defs/TskFrontmatter"
      -  },
      -  {
      -    "$ref": "#/$defs/QaFrontmatter"
      -  },
      -  {
      -    "$ref": "#/$defs/PrbFrontmatter"
      -  },
      -  {
      -    "$ref": "#/$defs/GolFrontmatter"
      -  },
      -  {
      -    "$ref": "#/$defs/RskFrontmatter"
      -  },
      -  {
      -    "$ref": "#/$defs/DecFrontmatter"
      -  },
      -  {
      -    "$ref": "#/$defs/FeatFrontmatter"
      -  },
      -  {
      -    "$ref": "#/$defs/SopFrontmatter"
      -  },
      -  {
      -    "$ref": "#/$defs/VcrFrontmatter"
      -  },
      -  {
      -    "$ref": "#/$defs/SysrsFrontmatter"
      -  },
      -  {
      -    "$ref": "#/$defs/ParseFailureResult"
      -  },
      -  {
      -    "$ref": "#/$defs/ValidateResult"
      -  }
      -]New value: +[
      +  {
      +    "$ref": "#/$defs/ReqFrontmatter"
      +  },
      +  {
      +    "$ref": "#/$defs/UcFrontmatter"
      +  },
      +  {
      +    "$ref": "#/$defs/TskFrontmatter"
      +  },
      +  {
      +    "$ref": "#/$defs/QaFrontmatter"
      +  },
      +  {
      +    "$ref": "#/$defs/PrbFrontmatter"
      +  },
      +  {
      +    "$ref": "#/$defs/GolFrontmatter"
      +  },
      +  {
      +    "$ref": "#/$defs/RskFrontmatter"
      +  },
      +  {
      +    "$ref": "#/$defs/DecFrontmatter"
      +  },
      +  {
      +    "$ref": "#/$defs/FeatFrontmatter"
      +  },
      +  {
      +    "$ref": "#/$defs/SopFrontmatter"
      +  },
      +  {
      +    "$ref": "#/$defs/VcrFrontmatter"
      +  },
      +  {
      +    "$ref": "#/$defs/SysrsFrontmatter"
      +  },
      +  {
      +    "$ref": "#/$defs/TxtFrontmatter"
      +  },
      +  {
      +    "$ref": "#/$defs/ParseFailureResult"
      +  },
      +  {
      +    "$ref": "#/$defs/ValidateResult"
      +  }
      +]
  2. Changed12 schema fields changedv0.37.0
    • addedOutput schema / $defs / DecFrontmatter / properties / status / enum
      Added value: +[
      +  "accepted",
      +  "deprecated",
      +  "draft",
      +  "proposed",
      +  "rejected",
      +  "superseded"
      +]
    • addedOutput schema / $defs / FeatFrontmatter / properties / status / enum
      Added value: +[
      +  "done",
      +  "planning",
      +  "progress",
      +  "review"
      +]
    • addedOutput schema / $defs / GolFrontmatter / properties / status / enum
      Added value: +[
      +  "accepted",
      +  "deprecated",
      +  "draft",
      +  "implemented",
      +  "proposed",
      +  "rejected",
      +  "superseded"
      +]
    • addedOutput schema / $defs / PrbFrontmatter / properties / status / enum
      Added value: +[
      +  "active",
      +  "cancelled",
      +  "draft",
      +  "resolved"
      +]
    • addedOutput schema / $defs / QaFrontmatter / properties / status / enum
      Added value: +[
      +  "active",
      +  "cancelled",
      +  "done",
      +  "draft"
      +]
    • addedOutput schema / $defs / ReqFrontmatter / properties / status / enum
      Added value: +[
      +  "accepted",
      +  "deprecated",
      +  "draft",
      +  "implemented",
      +  "proposed",
      +  "rejected",
      +  "superseded"
      +]
    • addedOutput schema / $defs / RskFrontmatter / properties / status / enum
      Added value: +[
      +  "accepted",
      +  "closed",
      +  "dropped",
      +  "mitigating",
      +  "occurred",
      +  "open"
      +]
    • addedOutput schema / $defs / SopFrontmatter / properties / status / enum
      Added value: +[
      +  "active",
      +  "approved",
      +  "draft",
      +  "retired",
      +  "review"
      +]
    • addedOutput schema / $defs / SysrsFrontmatter / properties / status / enum
      Added value: +[
      +  "active",
      +  "approved",
      +  "draft",
      +  "retired",
      +  "review"
      +]
    • addedOutput schema / $defs / TskFrontmatter / properties / status / enum
      Added value: +[
      +  "active",
      +  "cancelled",
      +  "done",
      +  "draft"
      +]
    • addedOutput schema / $defs / UcFrontmatter / properties / status / enum
      Added value: +[
      +  "accepted",
      +  "deprecated",
      +  "draft",
      +  "proposed",
      +  "superseded"
      +]
    • addedOutput schema / $defs / VcrFrontmatter / properties / status / enum
      Added value: +[
      +  "approved",
      +  "complete",
      +  "draft",
      +  "progress"
      +]
  3. First observedv0.36.0

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: two-stage execution, atomicity ("nothing is written on any failure (the file stays byte-unchanged)"), byte-exact matching with no line-ending/BOM/fuzzy fallback, and which failures raise versus return structured results (`ParseFailureResult`, non-raising `ValidateResult`). Return-shape behavior (frontmatter only, no body, `updated` bumped) is also disclosed.

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

Conciseness2/5

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

It is front-loaded with the strongest sentence, but the remainder is one massive run-on paragraph dense with internal references (ADR UUIDs, GitHub issue #170, ADR chain citations) that do not help an agent select or invoke the tool. Length and embedding of critical facts mid-paragraph (e.g. the `language` scope rules) make it hard to scan.

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 six-parameter mutation tool with no annotations, everything an agent needs is present: preconditions, matching semantics, failure modes and their exact result shapes, atomicity guarantee, return value, and language-variant scoping. With an output schema present, it correctly does not re-describe the success payload beyond noting no body is returned.

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

Parameters5/5

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

Schema coverage is 0% and the description fully compensates for all six parameters: `old_str` (byte-exact, must be unique unless `replace_all`), `new_str` (empty = pure deletion, legal only if stage 2 validates), `replace_all`, `id` (invalid shape/path injection = pre-dispatch `ValueError`), `type` (`adr` unsupported, enum-consistent), and `language` (default 'en' = flat file, non-default = docs/<type>/{language}/ only, `feat` raises). No parameter is left undocumented.

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?

"Surgical, exact-match string replacement of an existing document's frontmatter-stripped body" names a specific verb (replace), the resource (document body), and the exact matching contract. The scope restriction ('body only', frontmatter never addressable) and the explicit contrast with `update` lets an agent distinguish it from the ~100 siblings without opening a 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?

Explicitly routes between siblings: "Use `edit` for a surgical string replacement within an existing body; use the generic `update` tool for a whole-body or line-range replacement instead." It also states the read-before-edit convention and flags that it is a client convention, not server-enforced, plus the `adr` exclusion which tells the agent when this tool is unavailable.

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

Deploy Server

Other Tools