Skip to main content
Glama

Replace template content

replace-template-content
Destructive

Replaces the ENTIRE content of a draft template from an HTML string in a single destructive write.

Use this tool ONLY when:

  • You are authoring the initial content of an empty, freshly created template (e.g. after create-template-from-scratch), or

  • The user has explicitly asked to discard the current content and rewrite the whole template.

This is the right tool for laying down a large body of content at once (e.g. a whole NDA). It writes the whole template body in one go; there is no way to edit an individual node.

Do NOT use this tool to edit a template that already has content. Overwriting throws the existing content away. If the template already has content, this tool refuses to run unless you pass replace_existing_content=true to confirm the destructive overwrite. Read the current content with get-template-html first, so anything worth keeping can be carried over into the new HTML.

Overwriting an existing body cannot be undone, so ask the user to confirm it before passing replace_existing_content=true.

Only allowed on unpublished (draft) templates. Once a template is published its content can no longer be changed with this tool.

Use the same data-* attribute conventions as get-template-html. UUIDs present on nodes (e.g. data-uuid on a paragraph or heading) are preserved; nodes without a UUID are assigned one automatically. The returned HTML reflects the stored result, with every addressable node carrying a data-uuid you can use in subsequent operations.

Each data-uuid identifies exactly one node, so no two nodes may carry the same one. When you copy an existing node to build a similar one, drop its data-uuid (a fresh one is assigned on write) - reusing it is rejected and nothing is written at all. A cross-reference is the one exception: it carries the uuid of the clause it points at rather than one of its own, so that uuid appears twice by design.

Numbering follows the source. A block the source numbers becomes an ordered list node; a block it does not keeps the tag it had - an stays an , prose stays a . A source that numbers nothing gets no list node at all: a contract written entirely as headings and paragraphs is a correct result.

Headings go three levels deep, to . An or deeper is rejected and nothing is written, so carry a hierarchy past three levels with nested list nodes rather than with a deeper heading.

The numbers themselves are ALWAYS computed by fynk, never typed into the text. HTML whose text starts with a clause marker ("1. Confidentiality", "2)", "(a)", "iv.", "§ 5") is rejected and nothing is written. Where the source numbers a clause, wrap it in an ordered list node instead:

<div data-list data-kind="ordered" data-numbering-type="continue"><p>Confidentiality.</p></div>
<div data-list data-kind="ordered" data-numbering-type="continue"><p>Term.</p></div>

Nest another such <div data-list> inside a clause to create sub-clauses (1.1, 1.2). fynk computes the numbers (1., 2., 1.1., …) automatically and returns them as read-only data-number attributes, which are ignored on input.

To cross-reference a clause, give that clause a data-uuid of your own - any uuid you generate, as long as it appears on exactly one node - and point the reference at it:

<div data-list data-kind="ordered" data-uuid="11111111-1111-4111-8111-111111111111">
    <p>Confidentiality.</p></div>
…
<p>As set out in <span data-section-ref data-uuid="11111111-1111-4111-8111-111111111111"></span>,
notices are written.</p>

which renders the clause's computed number ("1.") in place of the reference, following it wherever the clause moves rather than hardcoding it. Both go in the same call: there is no need to write the body first and read the uuids back. A cross-reference carrying no data-uuid points at nothing and is rejected, so drop the reference where you have no clause to name.

A list node decides how its own number is rendered, so any scheme a source document uses is computed rather than typed:

  • data-numbering-style: decimal (default), upper-roman, lower-roman, upper-alpha, lower-alpha.

  • data-delimiter-style: dot (default, "1."), parenthesis ("1)"), double-parenthesis ("(1)"), section-mark ("§ 1").

  • data-numbering-type: continue (default) carries on from the preceding list node, restart begins a new count at 1.

  • data-show-nested-order-representation: true (default) prefixes a nested clause with its parent's number ("10.1."), false numbers it on its own ("1.", "(a)"). Leave it on where the clause continues the parent's count (1.1., 1.2.), turn it off where the clause has a style of its own that reads wrong with the parent in front of it ("X.1.", "1.(a)").

A heading never carries a number, so a section the source numbers is a list node holding its clauses as nested list nodes - not an followed by clauses. One list node is one number: its own text is its first paragraph, so every clause of its own beside that paragraph needs its own nested :

<div data-list data-kind="ordered" data-numbering-style="upper-roman" data-numbering-type="restart">
    <p>Subject of the lease</p>
    <div data-list data-kind="ordered" data-numbering-type="restart" data-show-nested-order-representation="false"><p>The lessor lets the premises.</p></div>
    <div data-list data-kind="ordered" data-numbering-type="continue" data-show-nested-order-representation="false"><p>The premises comprise.</p></div>
</div>

which fynk numbers I., 1., 2., with the next such section continuing at II. Writing those two clauses as plain inside the section instead numbers the section I. and leaves both clauses with no number at all.

Where the source's section titles carry no number, the section stays an with its prose as plain beneath it. A list node placed beside such a heading numbers the prose rather than the section, so every section reads "1." and its title ends up written twice.

The opposite mistake numbers prose that has no number of its own. Text belonging to a clause stays a plain beside the list node's own first paragraph:

<div data-list data-kind="ordered" data-numbering-type="continue">
    <p>Purpose</p>
    <p>The parties wish to explore a potential business relationship. Each may disclose confidential
    information to the other in the course of it.</p>
</div>

which fynk numbers 1., with the prose under it unnumbered. Nesting that paragraph in a of its own numbers it as well, leaving the section with a clause that is only its own body text.

To insert a dynamic field (a fill-in placeholder), reference it inline by its ref_uuid:

<span data-dynamic-field data-ref-uuid="<dynamic field ref_uuid>"></span>

Discover the available fields and their ref_uuids with get-template-info (include=["dynamic_fields"]), or create a new one with create-template-dynamic-field (which returns its ref_uuid). Referencing a ref_uuid that does not belong to the template is rejected.

Signatures are always placed as a signature container holding one or more signature blocks - even a single block needs one:

<div data-signatures data-align="left"><span data-signature-block data-ref-uuid="<signature block ref_uuid>"></span><span data-signature-block data-ref-uuid="<another ref_uuid>"></span></div>

Each inside the container points at one signature block by its ref_uuid; data-align is optional on the container (left, center, right, or justify; default left). A block placed outside a container, as , is legacy: it is still accepted so existing content can be written back unchanged, but it is stored as a container holding that one block.

Discover signature blocks and their ref_uuids with get-template-info (include=["signature_blocks"]), or create one with create-template-signature-block (which returns its ref_uuid). Referencing a ref_uuid that does not belong to the template (in either form) is rejected.

To reference a contracting party, point at it by ref_uuid and choose what is rendered with data-format:

<span data-party data-ref-uuid="<party ref_uuid>" data-format="name"></span>       (the party's entity/company name)
<span data-party data-ref-uuid="<party ref_uuid>" data-format="reference"></span>  (the party's reference name)

Other formats are "address" and "address:inline". A data-format is required and must be one of name/reference/address/address:inline. Discover parties and their ref_uuids with get-template-info, or create one with create-template-party. A ref_uuid not on the template, or a missing/invalid data-format, is rejected.

Images (<img data-image>), dynamic tables (<div data-dynamic-table>) and signing vote blocks (<span data-signing-vote-block>) cannot be created here — there is no way to author one through this tool. They can only be preserved: copy the tag exactly as get-template-html returned it, including its data-uuid / data-ref-uuid / data-table-uuid, and the underlying image or table is kept. Omitting the tag removes it from the template.

A block's layout cannot be authored here either. The margins, indent and line height a block is laid out with are kept per block and matched by data-uuid on a block of the same kind, so a block you copy over with the data-uuid it came with keeps the spacing it had. A block you write fresh is laid out the way the editor lays out a new block, and so is one you rewrite as a different kind of block - a paragraph turned heading. A style stating a margin, an indent or a line height is ignored; the text formatting inside the block - bold, colour, font, size, highlight - is not.

A block's alignment is authored here, as data-text-align on the paragraph, heading or list node carrying it - left, center, right or justify:

<h1 data-text-align="center">Mutual Non-Disclosure Agreement</h1>

A text-align style is not read, and any other value of the attribute counts as stating no alignment: a block you write fresh is then aligned left, and one you copy over with the data-uuid it came with keeps the alignment it already had - state data-text-align="left" to align such a block left again.

When you are laying down content derived from a source document (e.g. a PDF), create the parties, dynamic fields and signature blocks first, so this single write can reference them. Weaving them in afterwards costs a second, destructive rewrite of the whole body.

The response carries a warnings list alongside the stored HTML: advisory notes on what the template is still missing to behave as a template rather than as a flat copy of its source text - dynamic fields or signature blocks that exist but are placed nowhere, a body naming its parties as fixed text. The write succeeded either way, but act on them before reporting the template as finished.

Only available for templates with a prosemirror_data content type.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
htmlYesFull HTML of the template content. Use the same data-* attribute conventions as get-template-html. Replaces the entire document
template_uuidYesUUID of the unpublished template whose content should be replaced
replace_existing_contentNoRequired confirmation (true) to overwrite a template that already has content. Omit (or false) for empty templates. Defaults to false.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
htmlNoThe stored template content serialised back to HTML. Addressable nodes carry a data-uuid attribute usable in subsequent operations.
warningsNoAdvisory notes on what the stored template is still missing to work as a template: dynamic fields or signature blocks that exist but are placed nowhere, a body naming its parties as fixed text. The write succeeded; act on these before reporting the template as finished.

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observed

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only declare destructiveHint=true and readOnlyHint=false; the description adds far more — refusal unless replace_existing_content=true, draft-only (unpublished) restriction, non-undoable overwrite requiring user confirmation, UUID preservation/rejection rules, automatic number computation, rejected-input conditions, and the warnings list in the response.

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

Conciseness4/5

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

Front-loads the destructive warning and the when-to-use rules before any format detail, and uses bullets, code samples and short paragraphs rather than a wall of prose. It is nevertheless extremely long (roughly 1,500 words) with section-level formatting rules that border on product documentation, so it is not maximally economical.

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 destructive, complex HTML-authoring mutation, nothing an agent needs is missing: prerequisites (draft + prosemirror_data content type), confirmation flow, reference-resolution rules, unsupported elements (images, dynamic tables, vote blocks must be copied verbatim), and the advisory warnings returned alongside the HTML. The output schema covers return structure, so the description need not explain it further.

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 description coverage is 100%, so the baseline is 3. The description goes well beyond the schema's one-line html description by spelling out the full data-* convention contract, the semantics of data-uuid reuse, and the confirm-to-overwrite behaviour of replace_existing_content. It is diffuse (spread through an authoring guide rather than focused per parameter), which keeps it from a 5.

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?

States a specific verb and resource — replaces the ENTIRE content of a draft template from an HTML string in a single destructive write — and explicitly distinguishes itself from node-level editing ('there is no way to edit an individual node'). An agent can tell this apart from get-template-html, create-template-from-scratch and the create/update-*-party field tools 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?

Gives an explicit 'Use this tool ONLY when' with two bullets, a matching 'Do NOT use this tool to edit a template that already has content', and names the alternative workflow (read with get-template-html first). It also routes creation of dependent entities to create-template-party / create-template-dynamic-field / create-template-signature-block and warns to do so before this write.

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