Tool reference

update_article

Update Article. Update an article's title, subtitle, markdown body, imageUrl (remote images fetched to S3 and appended), or Substack settings (audience, comments, SEO, slug, social title, publishAt).

GroupAccessMCP name
ArticlesIrreversibleupdate_article
This tool changes data in a way that cannot be undone. Confirm with the writer before calling it.

Description

The description the MCP server sends to the model, word for word. Its rules apply to every call.

Update an article's title, subtitle, markdown body, imageUrl (remote images fetched to S3 and appended), or Substack settings (audience, comments, SEO, slug, social title, publishAt). This saves locally only — it does not push to Substack. Pass baseVersion from get_article; a version conflict means you must re-read the article. Images in bodyMarkdown are fetched to S3. Body markdown supports the same Substack-safe formats as create_article (headings, bold/italic/strike/code, lists, quotes, pullquotes, callouts, paywall, links, images). BEFORE calling this tool, you MUST call get_article for the same articleId and base the update on that fresh copy — the user may have edited the article in WriteStack. Never update from a stale draft you wrote earlier in the conversation. Replaces the article's current content and settings with the values you pass; there is no undo through this integration.

Arguments

ArgumentTypeRequiredDescription
articleIdstringYes
audiencestringNo
baseVersionintegerNocontentVersion from get_article. Pass it to avoid overwriting newer edits.
bodyMarkdownstringNoGitHub-flavored Markdown body. Supported and synced to Substack: headings #–######, bold, italic, strikethrough, inline code, links, images ![alt](url), bullet and numbered lists, > blockquotes, :::pullquote ... :::, :::callout ... :::, and a paid-only split with a standalone :::paywall::: line (content after it is behind the Substack paywall). Voice and video embeds are not supported.
commentPermissionsstringNo
imageUrlstring[]NoOptional image URLs to insert into the article. WriteStack fetches each URL, stores the image on S3, and appends it to the markdown body. For an image that has no public URL (a local file, a private Google Drive file), call create_article_image_upload first, upload the file, and pass the imageUrl it returned. Markdown/HTML images already in bodyMarkdown are ingested the same way. Max 20. Pass full https:// URLs. Invalid or unreachable URLs are skipped. Images are uploaded to Substack when the article is opened or saved with the Chrome extension, and again when pushing the draft. Max items 20.
publishAtstring | nullNo
seoDescriptionstring | nullNo
seoTitlestring | nullNo
slugstring | nullNo
socialTitlestring | nullNo
subtitlestring | nullNo
titlestringNo

Example call

The smallest valid request: required arguments only, with placeholder values.

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "update_article",
    "arguments": {
      "articleId": "…"
    }
  }
}

Result

The result has structuredContent that matches this schema. The same data is also in content as JSON text.

FieldTypeRequiredDescription
articleIdstringYes
contentVersionnumberNo
imagesobject[]No
images[].s3UrlstringYes
images[].sourceUrlstringNo
messagestringYes
statusstringYes

Annotations

HintValue
readOnlyHintfalse
destructiveHinttrue
openWorldHinttrue

The full input and output JSON Schemas for every tool are in /mcp-tools.json.

On this page