Skip to main content
Glama

Edit source

edit_source
Destructive

Change the source of a form or a workflow, on its draft. Nothing goes live until publish.

dry_run defaults to true: the first call previews the change and returns diagnostics without committing. Read them, fix your ops, then call again with dry_run: false.

ops is an ordered array of { kind: "edit", anchor, action, text? }: action is replace | insertBefore | insertAfter | delete; anchor is { id } (a field key or block id; prefer it), { find, replaceWith } (an exact substring and what replaces it; no action or text) or { find } (an exact substring, for delete only); text is required for replace, insertBefore and insertAfter. Ids are made by Paperform: never invent one.

Workflows are supported too: call get_help with topic "workflow" first, read the workflow's #source (it ends with a read-only ::: outputs block: each step's saved example output, trimmed; edits to it are ignored), and send only edit ops (path may be omitted): anchor a trigger, step or component on its #id ({ id: "step-1" }; a quoted id such as #"step 1" is anchored with the unquoted string). A rule is written on the step it runs into (after, when, on): change it by replacing that step. Indentation is cosmetic. A dry run returns { diff } — the node and rule ids added, removed and changed — and no save; a commit saves the draft and returns Stepper's validation issues as diagnostics with the line of the node they concern in the source as re-fetched. A committed edit can delete a step or trigger. Confirm with the user before calling this. For a workflow, expected is { version: , version_id: <version_id> } with the values #source's metadata reported; the edit is refused if the workflow changed since. Some of what the editor fills in on setup is filled in here too, from the app's static definition, and only by edit_source and create (update no longer writes a workflow's steps). A step whose params the edit writes (a new step, one moved to another app or action, or one with a param added, changed or removed) gets the declared default of each field it leaves out that has a plain default: text, number, true/false and date fields, multiple-value text fields and single or multiple dropdowns the app's #schema lists. Fields resolve_parameters lists that the #schema does not (computed from the values chosen so far), and object and reference fields, are never filled: write their defaults yourself. When the workflow is published, Stepper checks each step's fields and marks every HTML field (an email body) whose param makes no choice with options { encodeHTML: true }, so the answers a reference inserts are HTML-escaped however the step was written; a publish is refused if a step's fields cannot be checked. A param that says options { encodeHTML: false } keeps answers raw: write that only to insert trusted HTML on purpose, and the dry run warns about it on a field the app's #schema declares html. Plain-text fields get answers as they are. The dry run refuses a required param left out of a step whose params the edit writes, and a trigger type other than the one fetch on the app lists for that trigger. It checks each reference ({{step.path}} in a param, and each when condition) against the referenced step's example: against a loaded sample or test run, a path the example does not offer is a warning naming the closest one it does; against the app's own example, which lists only some keys, only a key nested deeper than the example puts it is noted; a step with no example is not checked. A path in the older list form, with an index between list levels, is warned about with the path Stepper now resolves it as. A commit stores an example on each trigger or step it adds or moves to another app, operation, trigger or connection, without running anything: a trigger gets its first recent item loaded through its connection (or, when there is none, the trigger's example as the editor builds it, else its app's own example), an action its app's own example when the app declares one. Diagnostics with code workflow_example say what was stored, and warn about each step a later step or rule reads that still has no example, with the call that stores one (load_trigger_samples or test_action, with workflow and node); publishing over MCP is refused until each has one. A step nothing reads needs none.

Forms: call get_help with topic "forms" first, read the form's #source (or #outline for its ids), and send only edit ops, anchored on field keys or block ids in that text (path may be omitted). The edit goes to the form's draft; a committed edit returns preview: { url, expires_at }, a five-minute link that renders the draft in a browser; give it to the person after each committed edit, since the form's live link shows the published version until publish puts the draft live. A committed edit can delete a field. Confirm with the user before calling this. For a form, expected is { version: "" } with the version string fetch reported in its metadata (e.g. "abc123:4" or "live:4"), passed back unchanged; the commit is refused if the form changed since.

Example: edit_source({ id: "12:form:abc123", ops: [{ kind: "edit", anchor: { id: "7ep7s" }, action: "insertAfter", text: "@email "Work email"" }] }) → { "dry_run": true, "diagnostics": [] }

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": {
      "id": "<id>",
      "ops": "<ops>"
    },
    "name": "edit_source"
  }
}

Input Schema

NameRequiredDescriptionDefault
idYesA form id or a workflow id, exactly as search, list or fetch returned it.
opsYesOrdered edit ops ({ kind: "edit", … }): forms and workflows take no other kind. action is replace | insertBefore | insertAfter | delete.
dry_runNoPreview without committing. Defaults to true.
messageNoOptional change note.
expectedNoFor a form, { version: "<version>" }, the version string from fetch's metadata, unchanged; for a workflow, { version: <v>, version_id: <id> }; refuses the commit if it changed since.

Output Schema

NameRequiredDescriptionDefault
idNo
diffNo
dry_runNo
committedNo
diagnosticsNo
applied_with_repairsNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observed

TDQS

A4.7/5.0
Behavior5/5

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

Beyond the destructiveHint=true annotation, it discloses the draft-vs-live model, the dry-run default and what a dry run returns ({ diff } and no save), that a committed edit can delete a step/field/trigger, that a five-minute preview link is returned for forms, version-conflict refusal, and the encodeHTML escaping behavior on publish. This is exactly the destructive/mutating context the annotations alone cannot convey.

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

Conciseness3/5

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

The material is front-loaded with the dry-run workflow first, which is good, but the body is a very dense wall of text with repeated instructions ('Confirm with the user before calling this' appears twice) and long multi-clause sentences about example storage that are hard to scan. Much of the value survives, but it is not tightly edited.

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 complex nested-op mutation tool with an output schema and full schema coverage, the description covers the missing pieces: draft semantics, dry-run/commit cycle, version pinning, validation diagnostics, and per-node example requirements. An agent has enough to call it correctly and interpret refusals.

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 the baseline is 3, but the description adds genuine meaning: the anchor forms for workflow nodes (quoted #"step 1" anchored with the unquoted string), that path may be omitted, that a rule is edited by replacing the step it runs into, and the differing expected shape for forms vs workflows. It stops short of fully re-explaining every op field, which the schema already covers well.

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 first sentence names a specific verb and resource ('Change the source of a form or a workflow, on its draft') and immediately bounds it ('Nothing goes live until publish'), which separates it from publish/update siblings. It also explicitly states that update no longer writes a workflow's steps, further sharpening the boundary.

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?

It gives explicit sequencing: call get_help with topic 'workflow' or 'forms' first, read #source/#outline, send only edit ops, read dry-run diagnostics, then re-call with dry_run: false. It also names required prerequisites (expected version/version_id) and an explicit confirmation step with the user, and points to load_trigger_samples/test_action when an example is missing.

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