Skip to main content
Glama

Propose a change

propose_change

Proposes edits to a tree, written out, for its editors to review and apply in OKForest: new pages, edits to pages (front-matter fields set or removed, and text in the body replaced), and pages moved or renamed, deprecated, or deleted. Links and index.md files follow a moved, new, or deleted page, and a page's files (those only it links to, in its folder or below) move or go with it. The edits are checked first: if a page would have errors, nothing is saved, and the errors come back to fix. Keep a change small, one purpose; each page can be in one edit of it. Read a page with get_concept before editing it. An editor's own proposal is in review at once; anyone else's is a request, which the editors are emailed about. Returns the change, its warnings, and its url, to give the person.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "title": "<title>",
      "edits": "<edits>"
    },
    "name": "propose_change"
  }
}

Input Schema

NameRequiredDescriptionDefault
treeNoThe tree's slug, as list_trees gives it (not its name). Required unless the Forest has one tree.
editsYesThe edits, in order.
titleYesWhat it does, in a few words: it becomes the commit's first line.

Output Schema

NameRequiredDescriptionDefault
byYesWho asked for it, by name.
idYesThe change's ID: pass it to get_change.
urlYesIts page in OKForest, where editors review and apply it.
aboutNoThe page it was asked about, when it was asked from one.
askedYesWhen it was asked for (ISO 8601).
pathsYesThe files it creates, edits, moves, or deletes.
stateYesWhere it is: `requested` (asked for, waiting for an editor), `drafting` (accepted, an editor writing its edits), `in-review` (edits written, waiting for an editor to apply them), or done: `applied` (committed), `declined`, or `withdrawn` by whoever asked.
titleYesWhat it does, in a few words: its commit's first line.
updatedYesWhen it last changed (ISO 8601).
findingsYesWhat the checks found: warnings to consider.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • changedInput schema / properties / edits / items / oneOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "kind": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "path": {
      -        "description": "A page's path in the tree, as get_concept gives it: `customers/acme-corp.md`.",
      -        "maxLength": 1024,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "text": {
      -        "description": "The whole page: its YAML front matter, with a `type` and a `title`, then its body in markdown.",
      -        "maxLength": 1000000,
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "kind",
      -      "path",
      -      "text"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "fields": {
      -        "additionalProperties": {},
      -        "description": "Front-matter fields to set, by key, each to its new value; null removes one. The rest of the front matter stays as written.",
      -        "propertyNames": {
      -          "type": "string"
      -        },
      -        "type": "object"
      -      },
      -      "kind": {
      -        "const": "edit",
      -        "type": "string"
      -      },
      -      "path": {
      -        "description": "A page's path in the tree, as get_concept gives it: `customers/acme-corp.md`.",
      -        "maxLength": 1024,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "replacements": {
      -        "description": "Changes to the page's body, in order.",
      -        "items": {
      -          "properties": {
      -            "new": {
      -              "description": "What replaces it; empty removes it.",
      -              "type": "string"
      -            },
      -            "old": {
      -              "description": "Text in the page's body, exactly as get_concept gives it, found exactly once: include enough around it.",
      -              "minLength": 1,
      -              "type": "string"
      -            }
      -          },
      -          "required": [
      -            "old",
      -            "new"
      -          ],
      -          "type": "object"
      -        },
      -        "type": "array"
      -      }
      -    },
      -    "required": [
      -      "kind",
      -      "path"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "files": {
      -        "description": "Whether its files move with it (true by default).",
      -        "type": "boolean"
      -      },
      -      "from": {
      -        "description": "A page's path in the tree, as get_concept gives it: `customers/acme-corp.md`.",
      -        "maxLength": 1024,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "kind": {
      -        "const": "move",
      -        "type": "string"
      -      },
      -      "to": {
      -        "description": "Its new path: a new folder, a new file name, or both.",
      -        "maxLength": 1024,
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "kind",
      -      "from",
      -      "to"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "kind": {
      -        "const": "deprecate",
      -        "type": "string"
      -      },
      -      "path": {
      -        "description": "A page's path in the tree, as get_concept gives it: `customers/acme-corp.md`.",
      -        "maxLength": 1024,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "successor": {
      -        "description": "The page that replaces it, if one: its page will say so.",
      -        "maxLength": 1024,
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "kind",
      -      "path"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "files": {
      -        "description": "Whether its files go too (true by default).",
      -        "type": "boolean"
      -      },
      -      "kind": {
      -        "const": "delete",
      -        "type": "string"
      -      },
      -      "path": {
      -        "description": "A page's path in the tree, as get_concept gives it: `customers/acme-corp.md`.",
      -        "maxLength": 1024,
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "kind",
      -      "path"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "kind": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "path": {
      +        "description": "A page's path in the tree, as get_concept gives it: `customers/acme-corp.md`.",
      +        "maxLength": 1024,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "text": {
      +        "description": "The whole page: its YAML front matter, with a `type` and a `title` (never `generated` or `verified`, which OKForest sets), then its body in markdown.",
      +        "maxLength": 1000000,
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "kind",
      +      "path",
      +      "text"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "fields": {
      +        "additionalProperties": {},
      +        "description": "Front-matter fields to set, by key, each to its new value; null removes one. The rest of the front matter stays as written. `generated` and `verified` aren't among them: OKForest sets them when the change is applied.",
      +        "propertyNames": {
      +          "type": "string"
      +        },
      +        "type": "object"
      +      },
      +      "kind": {
      +        "const": "edit",
      +        "type": "string"
      +      },
      +      "path": {
      +        "description": "A page's path in the tree, as get_concept gives it: `customers/acme-corp.md`.",
      +        "maxLength": 1024,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "replacements": {
      +        "description": "Changes to the page's body, in order.",
      +        "items": {
      +          "properties": {
      +            "new": {
      +              "description": "What replaces it; empty removes it.",
      +              "type": "string"
      +            },
      +            "old": {
      +              "description": "Text in the page's body, exactly as get_concept gives it, found exactly once: include enough around it.",
      +              "minLength": 1,
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "old",
      +            "new"
      +          ],
      +          "type": "object"
      +        },
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "kind",
      +      "path"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "files": {
      +        "description": "Whether its files move with it (true by default).",
      +        "type": "boolean"
      +      },
      +      "from": {
      +        "description": "A page's path in the tree, as get_concept gives it: `customers/acme-corp.md`.",
      +        "maxLength": 1024,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "kind": {
      +        "const": "move",
      +        "type": "string"
      +      },
      +      "to": {
      +        "description": "Its new path: a new folder, a new file name, or both.",
      +        "maxLength": 1024,
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "kind",
      +      "from",
      +      "to"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "kind": {
      +        "const": "deprecate",
      +        "type": "string"
      +      },
      +      "path": {
      +        "description": "A page's path in the tree, as get_concept gives it: `customers/acme-corp.md`.",
      +        "maxLength": 1024,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "successor": {
      +        "description": "The page that replaces it, if one: its page will say so.",
      +        "maxLength": 1024,
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "kind",
      +      "path"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "files": {
      +        "description": "Whether its files go too (true by default).",
      +        "type": "boolean"
      +      },
      +      "kind": {
      +        "const": "delete",
      +        "type": "string"
      +      },
      +      "path": {
      +        "description": "A page's path in the tree, as get_concept gives it: `customers/acme-corp.md`.",
      +        "maxLength": 1024,
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "kind",
      +      "path"
      +    ],
      +    "type": "object"
      +  }
      +]
    • changedInput schema / properties / title / maxLength
      Previous value: -200New value: +100
  2. Added

TDQS

A4.7/5.0
Behavior5/5

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

Annotations only say readOnly=false, destructive=false, idempotent=false, openWorld=false, which leaves the whole workflow unexplained. The description fills that gap with validation-before-save semantics ("if a page would have errors, nothing is saved, and the errors come back to fix"), review/email behavior for non-editors, and the side effects on links, index.md, and a page's files. It also returns a url, a usage detail that annotations cannot express.

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

Conciseness5/5

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

The description is dense but front-loaded: it opens with the operation, then covers side effects, validation, composition rules, and outcomes. Each sentence carries distinct information and none repeats the schema or annotations.

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 tool that writes changes into a knowledge tree and returns an output, the description covers prerequisite reading, validation, side effects, review status, and return value. With an output schema present and 100% parameter coverage, nothing material for correct invocation is missing.

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

Parameters4/5

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

Schema coverage is 100%, so all three top-level parameters and nested fields are already documented, which sets the baseline at 3. The description adds meaning the schema cannot encode: that each page may appear in only one edit, and how a proposal relates to review status, giving an agent a real constraint when composing the edits array.

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?

The description opens with a specific verb and resource ("Proposes edits to a tree") and then enumerates the exact operation kinds: create, edit, move/rename, deprecate, delete. That enumeration matches the schema's oneOf branches, so an agent can tell at a glance what the tool covers versus siblings like get_concept or list_changes.

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

Usage Guidelines4/5

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

The description gives concrete prerequisites and constraints: "Read a page with get_concept before editing it", "Keep a change small, one purpose", and "each page can be in one edit of it". It also distinguishes the outcome when an editor proposes versus someone else, which is close to routing against request_change, but it never names the alternative or states when to call one instead of the other.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources