Skip to main content
Glama

Update email template

lnkdrp_update_email_template
Idempotent

Changes an email template: any of name, description, format, align, subject, body and tags; a field left out stays as it is, description: null clears it, and tags replaces the whole tag list. The same checks as creating apply to the result (known tags, {{link.url}} present, no scripts in HTML, images only from this workspace's uploads); a tags list that declares a link-like custom tag is refused with details.code custom_tag_is_link, and a template whose tags are not sent keeps the ones it has. Tags are written {{entity.field}}, or {{entity.field|fallback}} for text used when the value is empty. Built-in tags, filled by LinkDrop for each recipient: contact.firstName: The first word of the contact's name. (e.g. Ken); contact.name: The contact's name: the name the team gave them, else the name they gave. (e.g. Ken Lee); contact.lastName: Everything after the first word of the contact's name. (e.g. Lee); contact.email: The contact's email address. (e.g. ken@example.com); contact.company: The domain of the contact's address; empty for a webmail address such as gmail.com. (e.g. acme.com); contact.note: The team's note on the contact, as written; it goes into the email exactly as it is. (e.g. Met at the October demo day.); contact.tags: The contact's tags, comma-separated. (e.g. Investor, Seed); contact.firstSeen: When LinkDrop first saw the contact, e.g. October 22, 2026. (e.g. October 22, 2026); contact.lastSeen: When the contact was last seen, e.g. October 22, 2026. (e.g. October 22, 2026); contact.visits: How many times the contact has viewed, as a number. (e.g. 3); link.url: The recipient's own LinkDrop link to the document or project; one link per person, reused on every render. (e.g. https://lnkdrp.com/s/example); link.password: The password of the recipient's own link; empty when the link has none. Filled when the email is sent and for a member signed in to the app; a connected agent sees [password]. (e.g. chris58); document.title: The document's title (document emails only). (e.g. Q3 investor update); project.name: The project's name (project emails only). (e.g. Series A data room); sender.name: The name of the member the email is from. (e.g. Chris); sender.firstName: The first word of the sender's name. (e.g. Chris); sender.email: The sender's LinkDrop account email (not necessarily the Gmail address the email goes out from). (e.g. chris@example.com); workspace.name: The workspace's name. (e.g. LinkDrop). {{link.url}} is one link per recipient: their own LinkDrop link to the one document or project the email is rendered for, reused on every render. A template's links (its own documents and projects) put several in one email, each wherever its {{link.}} is written: every recipient gets their own tracked link to each. A project is the other way: one link to all of its documents. {{link.url}} appears in every template without links; a template with links places at least one of them. Custom tags are {{custom.name}}, each declared in tags with a description of what it stands for, and hold words taken from lnkdrp_render_email's values; a custom tag whose name or description reads as a link (..._link, ..._url, an address) is refused as validation with details.code custom_tag_is_link. An HTML body shows images only from this workspace's uploads: an image is uploaded with lnkdrp_upload_email_asset and placed with the imgTag it returns (lnkdrp_list_email_assets lists those already uploaded). Any other image source (another site, data:) is refused as validation with details.code image_not_an_asset, on save, render and send; a javascript: URL or a is details.code html_not_allowed. The text version shows an image as [alt]. Each image is kept under 10 MB on every plan (big images make emails slow to open and more likely to be clipped or land in spam): an uploaded image over it in the body is swapped for a smaller copy on save. One email shows at most 10 images, 20 MB in all: over that, the save makes the images smaller, the largest first, until the email fits (reason email). imagesResized [{ name, from, to, assetId, note, reason }] lists each one. When it cannot fit, the save is refused as validation with details.code too_many_images or images_too_heavy, a sentence saying the limit and what to change, and details.limits. Emails already rendered from it keep the text they were rendered with. Each change that changes something is saved as the template's next version (template.version); lnkdrp_list_email_template_versions lists them. A template saved by someone else after this connection last read or saved it (or after baseVersion or baseUpdatedAt) is not overwritten: the call answers validation with details.code conflict, currentVersion and currentUpdatedAt, and nothing is saved. Returns the template, unusedTags and warnings: notes as { code, message } on a template that saved as sent. body_self_centred: the html body's outermost element centres itself with auto side margins (margin: 0 auto) while align is left, so the email still shows centred; the body is saved unchanged. link_unused: one of the template's links is not placed in the body, so that document goes out to no one. no_documents: the template has no links of its own, so each drop or email made from it takes its document from its own docId or projectId. visibility makes the template private to its owner or shares it with the team (not a document's visibility, lnkdrp_set_doc_visibility); it is sent with no other field (visibility with another field is validation) and moves no version. Making it private takes its owner or a workspace owner or admin, and an owner or admin making someone else's template private makes it private to that person; sharing a private template takes its owner; anyone else is forbidden. Another person's private template is not_found. projectIds files the template under projects: it is sent with no other field (projectIds with another field is validation), replaces the projects this person can see, moves no version and is not saved as a draft, so any member files a template whether or not they may publish it. Only the template's publishers change it live (its owner, workspace owners and admins, its chosen publishers, or everyone when it is set so). Anyone else's change is saved as their own draft, one per person, and the live template is unchanged: the result has saved: draft, draft { id, version, baseVersion, updatedAt, reviewUrl, publishers } and message; a publisher saves a draft with draft: true. The next update by the same person changes the same draft. On Free a non-publisher is forbidden with details.code publisher_required and upgradeUrl. lnkdrp_publish_email_template_draft publishes a draft.

Input Schema

NameRequiredDescriptionDefault
bodyNoThe body, with tags (up to 50,000 characters); contains {{link.url}} at least once, or, for a template with links, at least one {{link.<key>}}.
nameNoThe template's name, unique in the workspace (1-80 characters).
tagsNoTag declarations: every {{custom.x}} used, with its description; a built-in may be listed to override its description or required.
alignNoWhere an html email sits in the reader's window. left (the default): nothing is added around the body, so it shows flush left. center: the body is placed in a centred column at most 600px wide. The text version is unaffected.
draftNotrue: save the change as this person's draft even when they may publish.
linksNoThe template's documents and projects, each placed in the body by {{link.<key>}} wherever it should appear (as often as wanted). Every recipient gets their own tracked link to each, made with its settings, when the email is rendered; a send or render then needs no docId or projectId. With one, {{link.url}} also means it; with two or more, {{link.url}}, {{link.password}}, {{document.title}} and {{project.name}} are refused (link_tag_ambiguous). On an update the list replaces the template's documents.
formatNotext: a plain-text body (an HTML version is derived from it). html: an HTML body (a text version is derived from it).
draftIdNoThis person's open draft of the template to change; left out, their open draft if any.
subjectNoThe subject line, with tags (one line, up to 200 characters).
projectIdsNoThe projects the email template is filed under (up to 20 ids; [] for none). It replaces the projects this person can see; projects they cannot see stay as they are.
templateIdYesEmail template id (24 hex chars), from lnkdrp_list_email_templates.
visibilityNoprivate: only its owner sees the email template. team: everyone in the workspace sees it. Not a document's visibility (lnkdrp_set_doc_visibility).
baseVersionNoThe template's version as it was read. Left out, the version this connection last read or saved for the template is used, and none when it has not read it.
descriptionNoWhat the template is for (up to 500 characters); null clears it.
draftVersionNoThe draft's version as it was read. Left out, the version this connection last saved for the draft is used.
baseUpdatedAtNoThe template's updatedAt as it was read. Left out, the updatedAt this connection last read or saved for the template is used, and none when it has not read it.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed8 schema fields changed
    • addedInput schema / properties / baseVersion
      Added value: +{
      +  "description": "The template's version as it was read. Left out, the version this connection last read or saved for the template is used, and none when it has not read it.",
      +  "maximum": 9007199254740991,
      +  "minimum": 1,
      +  "type": "integer"
      +}
    • changedInput schema / properties / body / description
      Previous value: -"The body, with tags; contains {{link.url}} at least once (up to 50,000 characters)."New value: +"The body, with tags (up to 50,000 characters); contains {{link.url}} at least once, or, for a template with links, at least one {{link.<key>}}."
    • addedInput schema / properties / draft
      Added value: +{
      +  "description": "true: save the change as this person's draft even when they may publish.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / draftId
      Added value: +{
      +  "description": "This person's open draft of the template to change; left out, their open draft if any.",
      +  "pattern": "^[a-fA-F0-9]{24}$",
      +  "type": "string"
      +}
    • addedInput schema / properties / draftVersion
      Added value: +{
      +  "description": "The draft's version as it was read. Left out, the version this connection last saved for the draft is used.",
      +  "maximum": 9007199254740991,
      +  "minimum": 1,
      +  "type": "integer"
      +}
    • addedInput schema / properties / links
      Added value: +{
      +  "description": "The template's documents and projects, each placed in the body by {{link.<key>}} wherever it should appear (as often as wanted). Every recipient gets their own tracked link to each, made with its settings, when the email is rendered; a send or render then needs no docId or projectId. With one, {{link.url}} also means it; with two or more, {{link.url}}, {{link.password}}, {{document.title}} and {{project.name}} are refused (link_tag_ambiguous). On an update the list replaces the template's documents.",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "allowDownload": {
      +        "description": "Readers may download the PDF. Default false.",
      +        "type": "boolean"
      +      },
      +      "allowRevisionHistory": {
      +        "description": "Readers may open recent versions (Pro). Default false.",
      +        "type": "boolean"
      +      },
      +      "contactRole": {
      +        "description": "direct (default): the link is for that person; share: they may pass it on.",
      +        "enum": [
      +          "direct",
      +          "share"
      +        ],
      +        "type": "string"
      +      },
      +      "docId": {
      +        "description": "The document; exactly one of docId or projectId.",
      +        "pattern": "^[a-fA-F0-9]{24}$",
      +        "type": "string"
      +      },
      +      "expiresAfterDays": {
      +        "anyOf": [
      +          {
      +            "maximum": 365,
      +            "minimum": 1,
      +            "type": "integer"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "Days after it is made that each person's link stops working; null or left out: no expiry."
      +      },
      +      "key": {
      +        "description": "The tag that places it in the body: {{link.<key>}}. Not url or password. Left out: made from the document's title.",
      +        "pattern": "^[a-z][a-z0-9_]{0,39}$",
      +        "type": "string"
      +      },
      +      "password": {
      +        "anyOf": [
      +          {
      +            "maxLength": 128,
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "A password every person's link to it asks for, the same for everyone; null: none; left out: the one this key already has."
      +      },
      +      "projectId": {
      +        "description": "The project; exactly one of docId or projectId.",
      +        "pattern": "^[a-fA-F0-9]{24}$",
      +        "type": "string"
      +      }
      +    },
      +    "type": "object"
      +  },
      +  "maxItems": 10,
      +  "type": "array"
      +}
    • addedInput schema / properties / projectIds
      Added value: +{
      +  "description": "The projects the email template is filed under (up to 20 ids; [] for none). It replaces the projects this person can see; projects they cannot see stay as they are.",
      +  "items": {
      +    "pattern": "^[a-fA-F0-9]{24}$",
      +    "type": "string"
      +  },
      +  "maxItems": 20,
      +  "type": "array"
      +}
    • addedInput schema / properties / visibility
      Added value: +{
      +  "description": "private: only its owner sees the email template. team: everyone in the workspace sees it. Not a document's visibility (lnkdrp_set_doc_visibility).",
      +  "enum": [
      +    "private",
      +    "team"
      +  ],
      +  "type": "string"
      +}
  2. Changed1 schema field changed
    • addedInput schema / properties / baseUpdatedAt
      Added value: +{
      +  "description": "The template's updatedAt as it was read. Left out, the updatedAt this connection last read or saved for the template is used, and none when it has not read it.",
      +  "format": "date-time",
      +  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
      +  "type": "string"
      +}
  3. Added

TDQS

A4.5/5.0
Behavior5/5

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

With only generic annotations (readOnly false, destructive false, idempotent true), the description carries the real burden and does: optimistic-concurrency conflicts via baseVersion/baseUpdatedAt return details.code conflict with currentVersion/currentUpdatedAt and nothing saved, version bumping, draft fallback, publisher permissions, and per-error codes. The write profile it describes (mutating but reversible via versions, sets rather than increments) is consistent with the annotations.

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?

The lead sentence is well front-loaded, but the body then balloons into a full glossary of every built-in tag with examples — content that belongs to lnkdrp_list_email_tags — before returning to caller-relevant rules. The result is a single dense paragraph where image limits, tag syntax, drafts and conflicts are interleaved rather than grouped, making 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 16-parameter mutation with no output schema, the description still documents the return shape (template, unusedTags, warnings as { code, message }), names the warning codes, and covers draft results (saved: draft, draft { ... }). Very little an agent needs to call this correctly is missing.

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 100%, so 3 is the floor, but the description genuinely adds semantics the schema does not: omitted fields are left untouched, description: null clears, tags replaces the entire list, and visibility/projectIds must be sent alone or the call is a validation error. Those are the traps an agent would otherwise fall into.

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 opening clause names the specific verb and resource ('Changes an email template') and immediately enumerates the mutable fields, so it is distinguishable from lnkdrp_create_email_template and lnkdrp_update_from_source without opening a schema. It also discloses that omitted fields are preserved and that visibility/projectIds behave as separate single-field operations.

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?

It gives clear operational context: when a change becomes a version, when a non-publisher's change lands as a draft, and it points to lnkdrp_publish_email_template_draft and lnkdrp_list_email_template_versions for follow-ups. What it lacks is an explicit statement of when an agent should choose this over resetting via create or updating a draft directly.

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