Skip to main content
Glama

Review articles and short posts before scheduling

preview_publishing_plan
Read-onlyIdempotent

Show exact proposed schedule_note and schedule_article calls for the writer to review in ChatGPT. No scheduling occurs. Include full inline content (not draftId), explicit dates with UTC offsets, time zones, selected account identifiers (never implicit multi-account defaults), and explicit subscriber-email/audience/SEO choices for articles. Each note needs clientRequestId. For unsupported advanced options, review in the conversation instead. The panel sends user approval or requested changes back to the conversation; execute scheduling only after that approval. Voice selection comes from open_publishing_studio. Article scheduling is personal-account only.

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": {
      "voice": "<voice>",
      "calls": "<calls>"
    },
    "name": "preview_publishing_plan"
  }
}

Input Schema

NameRequiredDescriptionDefault
callsYes
voiceYes

Output Schema

NameRequiredDescriptionDefault
viewYes
accountNameYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / calls / items / oneOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "arguments": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "clientRequestId": {
      -            "description": "Optional but recommended: your own id for this note, 8 to 80 letters, numbers, hyphens or underscores. Use a new one for each note and the same one when retrying it (for example after a timeout or a rate-limit pause): the retry returns the original result and schedules nothing again. Reusing it with different text, platforms or time is refused.",
      -            "pattern": "^[A-Za-z0-9_-]{8,80}$",
      -            "type": "string"
      -          },
      -          "content": {
      -            "description": "Used only when creating a new note draft.",
      -            "type": "string"
      -          },
      -          "firstReply": {
      -            "description": "Optional first reply for supported destinations. An invalid reply is omitted per platform without cancelling the root post.",
      -            "type": "string"
      -          },
      -          "imageUrls": {
      -            "description": "Optional image URLs or image data URIs to attach to the scheduled note.",
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "instagramDestinations": {
      -            "description": "Instagram destinations with accountId returned by list_instagram_destinations and optional independent caption. Each account receives its own delivery receipt.",
      -            "items": {
      -              "additionalProperties": false,
      -              "properties": {
      -                "accountId": {
      -                  "type": "string"
      -                },
      -                "caption": {
      -                  "maxLength": 2200,
      -                  "type": "string"
      -                },
      -                "label": {
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "accountId"
      -              ],
      -              "type": "object"
      -            },
      -            "maxItems": 5,
      -            "minItems": 1,
      -            "type": "array"
      -          },
      -          "linkedInAccountId": {
      -            "description": "Optional LinkedIn account id for a connected LinkedIn destination. Absence of both this field and linkedInOrganizationUrn selects the configured default.",
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "linkedInOrganizationUrn": {
      -            "description": "Optional LinkedIn Company Page URN for a connected LinkedIn destination. Requires linkedInAccountId.",
      -            "minLength": 1,
      -            "pattern": "^urn:li:organization:[^\\s]+$",
      -            "type": "string"
      -          },
      -          "platformVersions": {
      -            "additionalProperties": {
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "description": "Optional platform-specific text keyed by platform, e.g. { \"BLUESKY\": \"...\" }. Each supplied version must fit its limit (Bluesky 300, Threads 500, LinkedIn 3000, X 25000) or nothing is scheduled. Saved as the draft’s platform-specific version.",
      -            "type": "object"
      -          },
      -          "platforms": {
      -            "items": {
      -              "enum": [
      -                "SUBSTACK",
      -                "LINKEDIN",
      -                "X",
      -                "BLUESKY",
      -                "THREADS",
      -                "INSTAGRAM",
      -                "FACEBOOK",
      -                "TIKTOK",
      -                "PINTEREST"
      -              ],
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "publication": {
      -            "description": "Substack publication name, handle, or URL selected by the user. Optional when exactly one active Substack publication is connected: Narrareach uses it when its session is ready and says which one was used in substackPublicationSelection.message (source \"sole_connection\"); if the session needs a sync or the profile cannot be verified, nothing is scheduled and the result says what to fix. In a team workspace with one publication, or when a writer who is also a team member omits workspace, nothing is scheduled until the writer confirms it (requiresPublicationChoice: true, publicationChoiceReason: \"confirmation_required\"). Notes publish from the profile signed in to that connection, including publications sharing one login. Unverified or mismatched profile identity returns action_required without publishing. Notes are profile-level: when it is missing and all of the writer’s publications are signed in to one Substack profile, no choice is needed and the note posts from that profile. Only when the publications span two or more Substack profiles does the writer choose a profile: Narrareach uses the one they chose most recently (and says so in substackPublicationSelection.message), or, with no previous choice, nothing is scheduled and the result has requiresPublicationChoice: true, choiceScope: \"profile\" and publicationChoices (one per profile); ask the user, then call again with substackConnectionId set to the chosen publicationChoices[].substackConnectionId. An ambiguous publication value also returns publicationChoices.",
      -            "type": "string"
      -          },
      -          "scheduledFor": {
      -            "description": "Local wall-clock publishing date/time interpreted in timezone, including DST (e.g. \"2026-07-01T14:30:00\" means 2:30 PM). A Z or explicit UTC offset represents an absolute instant instead.",
      -            "type": "string"
      -          },
      -          "socialAccountIds": {
      -            "additionalProperties": {
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "description": "Optional account to post to on Threads, Facebook, TikTok, Pinterest or X, keyed by platform, e.g. { \"THREADS\": \"<accountId>\" }, with accountId values from list_social_accounts. Omit a platform to use its only account or its default. Required for a platform where list_social_accounts reports accountChoiceRequired; ask the writer which account rather than picking one.",
      -            "type": "object"
      -          },
      -          "substackConnectionId": {
      -            "deprecated": true,
      -            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      -            "type": "string"
      -          },
      -          "threadsTopicTag": {
      -            "description": "Optional Threads topic tag. Threads must be selected; maximum 50 characters.",
      -            "type": "string"
      -          },
      -          "timezone": {
      -            "description": "IANA timezone the scheduledFor time above is expressed in (e.g. \"Europe/London\"). Defaults to the writer's saved timezone, else UTC.",
      -            "type": "string"
      -          },
      -          "videoUrls": {
      -            "description": "Optional video URLs or video data URIs to attach to the scheduled note.",
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "workspace": {
      -            "description": "Authorized team workspace name or id for team scheduling. Absence selects the authenticated user’s personal account.",
      -            "type": "string"
      -          },
      -          "writer": {
      -            "description": "Authorized team writer name, handle, or id. \"me\" selects the linked team voice. Required when a team workspace has multiple writers.",
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "scheduledFor",
      -          "platforms",
      -          "timezone",
      -          "content",
      -          "clientRequestId"
      -        ],
      -        "type": "object"
      -      },
      -      "tool": {
      -        "const": "schedule_note",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "tool",
      -      "arguments"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "arguments": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "addSearchMetadata": {
      -            "description": "Generate SEO titles, descriptions, and a Substack slug for supported article destinations. SEO metadata is generated automatically on Revenue Writer, Full Agentic Mode, and Teams & Agencies, and for trials or other accounts with article SEO access. Set this option to false to turn it off. X does not support separate article SEO settings.",
      -            "type": "boolean"
      -          },
      -          "contentHtml": {
      -            "description": "Required when creating a new draft. Supports public <img> or <video> elements and {{media:N}} placeholders resolved from media entries. Video articles require Substack as the sole platform. Native Substack paywall markup is <hr data-type=\"paywall\"> at the selected paragraph boundary, or a single {{NARRAREACH_PAYWALL}} token; paywallMarker supports custom tokens. A Substack Freewall (free and paid subscribers keep reading) is <hr data-type=\"paywall\" data-access=\"subscribers\">, or set freewall to true. Native subscribe block markup is <div data-type=\"button\" data-kind=\"subscribeCaption\" data-text=\"Subscribe\" data-caption=\"Your caption\"></div> with HTML-escaped attribute values. data-kind=\"subscribe\" represents a button without caption. Ordinary links remain links. Audience sections use a div with data-dynamic-content=\"true\" and data-dynamic-audiences=\"paid_sub\", containing data-dynamic-content-match=\"true\" and data-dynamic-content-else=\"true\" divs. Supported audience conditions: non_sub, free_sub, paid_sub, founding_sub (comma-separated). Keep both branches. Subscriber-tag targeting must be published in Substack.",
      -            "type": "string"
      -          },
      -          "coverImage": {
      -            "description": "Optional cover image for a newly created draft, placed at the top of the published body. Supports public HTTPS URLs, data URIs, or base64 image bytes. URL ingestion depends on source-host access. For an image attached in ChatGPT, use coverFile instead. For a saved draft (draftId), attach the cover first with update_draft.",
      -            "properties": {
      -              "data": {
      -                "description": "Data URI or raw base64 image bytes.",
      -                "type": "string"
      -              },
      -              "mimeType": {
      -                "description": "Required for raw base64. Example: image/png.",
      -                "type": "string"
      -              },
      -              "sourceType": {
      -                "enum": [
      -                  "url",
      -                  "data_uri",
      -                  "base64"
      -                ],
      -                "type": "string"
      -              },
      -              "url": {
      -                "description": "Public HTTPS image URL.",
      -                "type": "string"
      -              }
      -            },
      -            "type": "object"
      -          },
      -          "freewall": {
      -            "description": "Make the article's single wall divider (or paywallMarker) a Substack Freewall: everyone sees the content above it; free and paid subscribers keep reading below it. Requires SUBSTACK and a publication with Substack Freewalls. For a new draft (title and contentHtml) it sets the Freewall. A saved draft (draftId) keeps the wall already in its body: a Freewall there is scheduled as a Freewall with or without this field, and true only confirms it. Never combine with isPaidContent. Default false.",
      -            "type": "boolean"
      -          },
      -          "isPaidContent": {
      -            "description": "Whether the Substack article is paid-only. Default false. Do not combine with freewall.",
      -            "type": "boolean"
      -          },
      -          "linkedinAuthorUrn": {
      -            "description": "LinkedIn personal profile or Company Page author URN belonging to the connected LinkedIn Articles account.",
      -            "type": "string"
      -          },
      -          "linkedinNewsletterUrn": {
      -            "description": "LinkedIn newsletter URN belonging to the connected LinkedIn Articles account. Required when linkedinPublicationType is newsletter.",
      -            "type": "string"
      -          },
      -          "linkedinPublicationType": {
      -            "description": "LinkedIn destination type. Defaults to an individual article; newsletter represents a user-selected newsletter destination.",
      -            "enum": [
      -              "article",
      -              "newsletter"
      -            ],
      -            "type": "string"
      -          },
      -          "linkedinShareCommentary": {
      -            "description": "Optional LinkedIn share text used when publishing a LinkedIn article.",
      -            "type": "string"
      -          },
      -          "media": {
      -            "description": "Optional inline images or Substack article videos for a newly created draft. Replaces {{media:N}} placeholders in array order; leftovers are appended. kind defaults to image; video requires Substack as the sole platform. Supports public URLs, data URIs, and base64 bytes. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      -            "items": {
      -              "properties": {
      -                "data": {
      -                  "type": "string"
      -                },
      -                "fileName": {
      -                  "type": "string"
      -                },
      -                "kind": {
      -                  "description": "Defaults to image when omitted.",
      -                  "enum": [
      -                    "image",
      -                    "video"
      -                  ],
      -                  "type": "string"
      -                },
      -                "mimeType": {
      -                  "type": "string"
      -                },
      -                "sourceType": {
      -                  "enum": [
      -                    "url",
      -                    "data_uri",
      -                    "base64"
      -                  ],
      -                  "type": "string"
      -                },
      -                "url": {
      -                  "type": "string"
      -                }
      -              },
      -              "type": "object"
      -            },
      -            "type": "array"
      -          },
      -          "mediumNotifyFollowers": {
      -            "description": "Whether to email Medium subscribers about this story. Only valid when platforms includes MEDIUM. Defaults to false (no email). Best-effort: a failure to apply this setting never blocks the publish/schedule and is reported as a warning.",
      -            "type": "boolean"
      -          },
      -          "mediumPublicationId": {
      -            "description": "Optional authorized Medium publication id when platforms includes MEDIUM. Absent means the personal profile. Writer-only access submits for editorial review and leaves the story unscheduled until acceptance. Explicit publication rejection allows personal-profile delivery with a warning; ambiguous submissions remain unpublished for review. Draft-only delivery does not submit to a publication.",
      -            "type": "string"
      -          },
      -          "paywallMarker": {
      -            "description": "Optional custom marker in contentHtml where the selected free preview ends; must appear exactly once. The standard {{NARRAREACH_PAYWALL}} marker is recognized without this field. Creates a native divider without changing sendToNewsletter. With freewall true it allows free and paid subscribers; otherwise it enables paid access.",
      -            "maxLength": 200,
      -            "type": "string"
      -          },
      -          "platforms": {
      -            "items": {
      -              "enum": [
      -                "SUBSTACK",
      -                "MEDIUM",
      -                "LINKEDIN",
      -                "X",
      -                "WORDPRESS",
      -                "GHOST"
      -              ],
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "publication": {
      -            "description": "Substack destination as a publication name, handle, or URL, for example \"AI Newsroom\", \"@theainewsroom\", or \"https://theainewsroom.substack.com\". Optional when exactly one active Substack publication is connected; Narrareach selects it automatically. Required when more than one active Substack publication is connected, except that when it is missing Narrareach uses the publication the writer scheduled or published to most recently and says so in substackPublicationSelection.message, with publicationChoices listing the others; tell the writer which one was used. If there is no previous choice, the value is ambiguous, or Narrareach cannot confirm the session publishes there, nothing is scheduled and the result has requiresPublicationChoice: true with publicationChoices (name, handle, url, substackConnectionId). Ask which one they want, then call again with publication set to the chosen handle (and draftId when a draft was already saved).",
      -            "type": "string"
      -          },
      -          "publishMode": {
      -            "description": "Only valid when all selected destinations are WordPress or Ghost. Defaults to publish; draft saves a remote draft at the scheduled time without publication.",
      -            "enum": [
      -              "publish",
      -              "draft"
      -            ],
      -            "type": "string"
      -          },
      -          "scheduledFor": {
      -            "description": "Required unless publishNow or platformSchedules is given, and must be in the future. Shared local wall-clock publishing date/time interpreted in timezone, including DST. A Z or explicit UTC offset represents an absolute instant. LinkedIn articles require at least 20 minutes of lead time.",
      -            "type": "string"
      -          },
      -          "sendToNewsletter": {
      -            "description": "Substack email delivery setting. Default true.",
      -            "type": "boolean"
      -          },
      -          "substackConnectionId": {
      -            "deprecated": true,
      -            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      -            "type": "string"
      -          },
      -          "subtitle": {
      -            "description": "Optional article subtitle for newly created drafts. Substack omits subtitles over 250 characters and returns a warning without changing the saved draft.",
      -            "type": "string"
      -          },
      -          "tags": {
      -            "description": "Optional tag list for newly created drafts. Substack receives all supplied tags. Medium receives its supported first 5 topics and returns a warning when extras are omitted. The saved draft remains unchanged.",
      -            "items": {
      -              "maxLength": 50,
      -              "type": "string"
      -            },
      -            "maxItems": 50,
      -            "type": "array"
      -          },
      -          "timezone": {
      -            "description": "IANA timezone the scheduledFor time(s) above are expressed in (e.g. \"Europe/London\"). Defaults to the writer's saved timezone, else UTC.",
      -            "type": "string"
      -          },
      -          "title": {
      -            "description": "Required when creating a new draft.",
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "platforms",
      -          "scheduledFor",
      -          "timezone",
      -          "title",
      -          "contentHtml",
      -          "addSearchMetadata"
      -        ],
      -        "type": "object"
      -      },
      -      "tool": {
      -        "const": "schedule_article",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "tool",
      -      "arguments"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "arguments": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "clientRequestId": {
      +            "description": "Optional but recommended: your own id for this note, 8 to 80 letters, numbers, hyphens or underscores. Use a new one for each note and the same one when retrying it (for example after a timeout or a rate-limit pause): the retry returns the original result and schedules nothing again. Reusing it with different text, platforms or time is refused.",
      +            "pattern": "^[A-Za-z0-9_-]{8,80}$",
      +            "type": "string"
      +          },
      +          "content": {
      +            "description": "Used only when creating a new note draft.",
      +            "type": "string"
      +          },
      +          "firstReply": {
      +            "description": "Optional first reply for supported destinations. An invalid reply is omitted per platform without cancelling the root post.",
      +            "type": "string"
      +          },
      +          "imageUrls": {
      +            "description": "Optional image URLs or image data URIs to attach to the scheduled note.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "instagramDestinations": {
      +            "description": "Instagram destinations with accountId returned by list_instagram_destinations and optional independent caption. Each account receives its own delivery receipt.",
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "accountId": {
      +                  "type": "string"
      +                },
      +                "caption": {
      +                  "maxLength": 2200,
      +                  "type": "string"
      +                },
      +                "label": {
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "accountId"
      +              ],
      +              "type": "object"
      +            },
      +            "maxItems": 5,
      +            "minItems": 1,
      +            "type": "array"
      +          },
      +          "linkedInAccountId": {
      +            "description": "Optional LinkedIn account id for a connected LinkedIn destination. Absence of both this field and linkedInOrganizationUrn selects the configured default.",
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "linkedInOrganizationUrn": {
      +            "description": "Optional LinkedIn Company Page URN for a connected LinkedIn destination. Requires linkedInAccountId.",
      +            "minLength": 1,
      +            "pattern": "^urn:li:organization:[^\\s]+$",
      +            "type": "string"
      +          },
      +          "platformVersions": {
      +            "additionalProperties": {
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "description": "Optional platform-specific text keyed by platform, e.g. { \"BLUESKY\": \"...\" }. Each supplied version must fit its limit (Bluesky 300, Threads 500, LinkedIn 3000, X 25000) or nothing is scheduled. Saved as the draft’s platform-specific version.",
      +            "type": "object"
      +          },
      +          "platforms": {
      +            "items": {
      +              "enum": [
      +                "SUBSTACK",
      +                "LINKEDIN",
      +                "X",
      +                "BLUESKY",
      +                "THREADS",
      +                "INSTAGRAM",
      +                "FACEBOOK",
      +                "TIKTOK",
      +                "PINTEREST"
      +              ],
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "publication": {
      +            "description": "Substack publication name, handle, or URL selected by the user. Optional when exactly one active Substack publication is connected: Narrareach uses it when its session is ready and says which one was used in substackPublicationSelection.message (source \"sole_connection\"); if the session needs a sync or the profile cannot be verified, nothing is scheduled and the result says what to fix. In a team workspace with one publication, or when a writer who is also a team member omits workspace, nothing is scheduled until the writer confirms it (requiresPublicationChoice: true, publicationChoiceReason: \"confirmation_required\"). Notes publish from the profile signed in to that connection, including publications sharing one login. Unverified or mismatched profile identity returns action_required without publishing. Notes are profile-level: when it is missing and all of the writer’s publications are signed in to one Substack profile, no choice is needed and the note posts from that profile. Only when the publications span two or more Substack profiles does the writer choose a profile: Narrareach uses the one they chose most recently (and says so in substackPublicationSelection.message), or, with no previous choice, nothing is scheduled and the result has requiresPublicationChoice: true, choiceScope: \"profile\" and publicationChoices (one per profile); ask the user, then call again with substackConnectionId set to the chosen publicationChoices[].substackConnectionId. An ambiguous publication value also returns publicationChoices.",
      +            "type": "string"
      +          },
      +          "scheduledFor": {
      +            "description": "Local wall-clock publishing date/time interpreted in timezone, including DST (e.g. \"2026-07-01T14:30:00\" means 2:30 PM). A Z or explicit UTC offset represents an absolute instant instead.",
      +            "type": "string"
      +          },
      +          "socialAccountIds": {
      +            "additionalProperties": {
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "description": "Optional account to post to on Threads, Facebook, TikTok, Pinterest or X, keyed by platform, e.g. { \"THREADS\": \"<accountId>\" }, with accountId values from list_social_accounts. Omit a platform to use its only account or its default. Required for a platform where list_social_accounts reports accountChoiceRequired; ask the writer which account rather than picking one.",
      +            "type": "object"
      +          },
      +          "substackConnectionId": {
      +            "deprecated": true,
      +            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      +            "type": "string"
      +          },
      +          "threadsTopicTag": {
      +            "description": "Optional Threads topic tag. Threads must be selected; maximum 50 characters.",
      +            "type": "string"
      +          },
      +          "timezone": {
      +            "description": "IANA timezone the scheduledFor time above is expressed in (e.g. \"Europe/London\"). Defaults to the writer's saved timezone, else UTC.",
      +            "type": "string"
      +          },
      +          "videoUrls": {
      +            "description": "Optional video URLs or video data URIs to attach to the scheduled note.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "workspace": {
      +            "description": "Authorized team workspace name or id for team scheduling. Absence selects the authenticated user’s personal account.",
      +            "type": "string"
      +          },
      +          "writer": {
      +            "description": "Authorized team writer name, handle, or id. \"me\" selects the linked team voice. Required when a team workspace has multiple writers.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "scheduledFor",
      +          "platforms",
      +          "timezone",
      +          "content",
      +          "clientRequestId"
      +        ],
      +        "type": "object"
      +      },
      +      "tool": {
      +        "const": "schedule_note",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "tool",
      +      "arguments"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "arguments": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "addSearchMetadata": {
      +            "description": "Generate SEO titles, descriptions, and a Substack slug for supported article destinations. SEO metadata is generated automatically on Revenue Writer, Full Agentic Mode, and Teams & Agencies, and for trials or other accounts with article SEO access. Set this option to false to turn it off. X does not support separate article SEO settings.",
      +            "type": "boolean"
      +          },
      +          "contentHtml": {
      +            "description": "Required when creating a new draft. Supports public <img> or <video> elements and {{media:N}} placeholders resolved from media entries. Video articles require Substack as the sole platform. Native Substack paywall markup is <hr data-type=\"paywall\"> at the selected paragraph boundary, or a single {{NARRAREACH_PAYWALL}} token; paywallMarker supports custom tokens. A Substack Freewall (free and paid subscribers keep reading) is <hr data-type=\"paywall\" data-access=\"subscribers\">, or set freewall to true. Native subscribe block markup is <div data-type=\"button\" data-kind=\"subscribeCaption\" data-text=\"Subscribe\" data-caption=\"Your caption\"></div> with HTML-escaped attribute values. data-kind=\"subscribe\" represents a button without caption. Ordinary links remain links. Audience sections use a div with data-dynamic-content=\"true\" and data-dynamic-audiences=\"paid_sub\", containing data-dynamic-content-match=\"true\" and data-dynamic-content-else=\"true\" divs. Supported audience conditions: non_sub, free_sub, paid_sub, founding_sub (comma-separated). Keep both branches. Subscriber-tag targeting must be published in Substack.",
      +            "type": "string"
      +          },
      +          "coverImage": {
      +            "description": "Optional cover image for a newly created draft, placed at the top of the published body. Supports public HTTPS URLs, data URIs, or base64 image bytes. URL ingestion depends on source-host access. For an image attached in ChatGPT, use coverFile instead. For a saved draft (draftId), attach the cover first with update_draft.",
      +            "properties": {
      +              "data": {
      +                "description": "Data URI or raw base64 image bytes.",
      +                "type": "string"
      +              },
      +              "mimeType": {
      +                "description": "Required for raw base64. Example: image/png.",
      +                "type": "string"
      +              },
      +              "sourceType": {
      +                "enum": [
      +                  "url",
      +                  "data_uri",
      +                  "base64"
      +                ],
      +                "type": "string"
      +              },
      +              "url": {
      +                "description": "Public HTTPS image URL.",
      +                "type": "string"
      +              }
      +            },
      +            "type": "object"
      +          },
      +          "freewall": {
      +            "description": "Make the article's single wall divider (or paywallMarker) a Substack Freewall: everyone sees the content above it; free and paid subscribers keep reading below it. Requires SUBSTACK and a publication with Substack Freewalls. For a new draft (title and contentHtml) it sets the Freewall. A saved draft (draftId) keeps the wall already in its body: a Freewall there is scheduled as a Freewall with or without this field, and true only confirms it. Never combine with isPaidContent. Default false.",
      +            "type": "boolean"
      +          },
      +          "isPaidContent": {
      +            "description": "Whether the Substack article is paid-only. Default false. Do not combine with freewall.",
      +            "type": "boolean"
      +          },
      +          "linkedinAuthorUrn": {
      +            "description": "LinkedIn personal profile or Company Page author URN belonging to the connected LinkedIn Articles account.",
      +            "type": "string"
      +          },
      +          "linkedinNewsletterUrn": {
      +            "description": "LinkedIn newsletter URN belonging to the connected LinkedIn Articles account. Required when linkedinPublicationType is newsletter.",
      +            "type": "string"
      +          },
      +          "linkedinPublicationType": {
      +            "description": "LinkedIn destination type. Defaults to an individual article; newsletter represents a user-selected newsletter destination.",
      +            "enum": [
      +              "article",
      +              "newsletter"
      +            ],
      +            "type": "string"
      +          },
      +          "linkedinShareCommentary": {
      +            "description": "Optional LinkedIn share text used when publishing a LinkedIn article.",
      +            "type": "string"
      +          },
      +          "media": {
      +            "description": "Optional inline images or Substack article videos for a newly created draft. Replaces {{media:N}} placeholders in array order; leftovers are appended. kind defaults to image; video requires Substack as the sole platform. Supports public URLs, data URIs, and base64 bytes. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      +            "items": {
      +              "properties": {
      +                "data": {
      +                  "type": "string"
      +                },
      +                "fileName": {
      +                  "type": "string"
      +                },
      +                "kind": {
      +                  "description": "Defaults to image when omitted.",
      +                  "enum": [
      +                    "image",
      +                    "video"
      +                  ],
      +                  "type": "string"
      +                },
      +                "mimeType": {
      +                  "type": "string"
      +                },
      +                "sourceType": {
      +                  "enum": [
      +                    "url",
      +                    "data_uri",
      +                    "base64"
      +                  ],
      +                  "type": "string"
      +                },
      +                "url": {
      +                  "type": "string"
      +                }
      +              },
      +              "type": "object"
      +            },
      +            "type": "array"
      +          },
      +          "mediumNotifyFollowers": {
      +            "description": "Whether to email Medium subscribers about this story. true is only valid when platforms includes MEDIUM; false is ignored. Defaults to false (no email). Best-effort: a failure to apply this setting never blocks the publish/schedule and is reported as a warning.",
      +            "type": "boolean"
      +          },
      +          "mediumPublicationId": {
      +            "description": "Optional authorized Medium publication id when platforms includes MEDIUM. Absent means the personal profile. Writer-only access submits for editorial review and leaves the story unscheduled until acceptance. Explicit publication rejection allows personal-profile delivery with a warning; ambiguous submissions remain unpublished for review. Draft-only delivery does not submit to a publication.",
      +            "type": "string"
      +          },
      +          "paywallMarker": {
      +            "description": "Optional custom marker in contentHtml where the selected free preview ends; must appear exactly once. The standard {{NARRAREACH_PAYWALL}} marker is recognized without this field. Creates a native divider without changing sendToNewsletter. With freewall true it allows free and paid subscribers; otherwise it enables paid access.",
      +            "maxLength": 200,
      +            "type": "string"
      +          },
      +          "platforms": {
      +            "items": {
      +              "enum": [
      +                "SUBSTACK",
      +                "MEDIUM",
      +                "LINKEDIN",
      +                "X",
      +                "WORDPRESS",
      +                "GHOST"
      +              ],
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "publication": {
      +            "description": "Substack destination as a publication name, handle, or URL, for example \"AI Newsroom\", \"@theainewsroom\", or \"https://theainewsroom.substack.com\". Optional when exactly one active Substack publication is connected; Narrareach selects it automatically. Required when more than one active Substack publication is connected, except that when it is missing Narrareach uses the publication the writer scheduled or published to most recently and says so in substackPublicationSelection.message, with publicationChoices listing the others; tell the writer which one was used. If there is no previous choice, the value is ambiguous, or Narrareach cannot confirm the session publishes there, nothing is scheduled and the result has requiresPublicationChoice: true with publicationChoices (name, handle, url, substackConnectionId). Ask which one they want, then call again with publication set to the chosen handle (and draftId when a draft was already saved).",
      +            "type": "string"
      +          },
      +          "publishMode": {
      +            "description": "Only valid when all selected destinations are WordPress or Ghost. Defaults to publish; draft saves a remote draft at the scheduled time without publication.",
      +            "enum": [
      +              "publish",
      +              "draft"
      +            ],
      +            "type": "string"
      +          },
      +          "scheduledFor": {
      +            "description": "Required unless publishNow or platformSchedules is given, and must be in the future. Shared local wall-clock publishing date/time interpreted in timezone, including DST. A Z or explicit UTC offset represents an absolute instant. LinkedIn articles require at least 20 minutes of lead time.",
      +            "type": "string"
      +          },
      +          "sendToNewsletter": {
      +            "description": "Substack email delivery setting. Default true.",
      +            "type": "boolean"
      +          },
      +          "substackConnectionId": {
      +            "deprecated": true,
      +            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      +            "type": "string"
      +          },
      +          "subtitle": {
      +            "description": "Optional article subtitle for newly created drafts. Substack omits subtitles over 250 characters and returns a warning without changing the saved draft.",
      +            "type": "string"
      +          },
      +          "tags": {
      +            "description": "Optional tag list for newly created drafts. Substack receives all supplied tags. Medium receives its supported first 5 topics and returns a warning when extras are omitted. The saved draft remains unchanged.",
      +            "items": {
      +              "maxLength": 50,
      +              "type": "string"
      +            },
      +            "maxItems": 50,
      +            "type": "array"
      +          },
      +          "timezone": {
      +            "description": "IANA timezone the scheduledFor time(s) above are expressed in (e.g. \"Europe/London\"). Defaults to the writer's saved timezone, else UTC.",
      +            "type": "string"
      +          },
      +          "title": {
      +            "description": "Required when creating a new draft.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "platforms",
      +          "scheduledFor",
      +          "timezone",
      +          "title",
      +          "contentHtml",
      +          "addSearchMetadata"
      +        ],
      +        "type": "object"
      +      },
      +      "tool": {
      +        "const": "schedule_article",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "tool",
      +      "arguments"
      +    ],
      +    "type": "object"
      +  }
      +]
  2. Changed1 schema field changed
    • changedInput schema / properties / calls / items / oneOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "arguments": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "clientRequestId": {
      -            "description": "Optional but recommended: your own id for this note, 8 to 80 letters, numbers, hyphens or underscores. Use a new one for each note and the same one when retrying it (for example after a timeout or a rate-limit pause): the retry returns the original result and schedules nothing again. Reusing it with different text, platforms or time is refused.",
      -            "pattern": "^[A-Za-z0-9_-]{8,80}$",
      -            "type": "string"
      -          },
      -          "content": {
      -            "description": "Used only when creating a new note draft.",
      -            "type": "string"
      -          },
      -          "firstReply": {
      -            "description": "Optional first reply for supported destinations. An invalid reply is omitted per platform without cancelling the root post.",
      -            "type": "string"
      -          },
      -          "imageUrls": {
      -            "description": "Optional image URLs or image data URIs to attach to the scheduled note.",
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "instagramDestinations": {
      -            "description": "Instagram destinations with accountId returned by list_instagram_destinations and optional independent caption. Each account receives its own delivery receipt.",
      -            "items": {
      -              "additionalProperties": false,
      -              "properties": {
      -                "accountId": {
      -                  "type": "string"
      -                },
      -                "caption": {
      -                  "maxLength": 2200,
      -                  "type": "string"
      -                },
      -                "label": {
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "accountId"
      -              ],
      -              "type": "object"
      -            },
      -            "maxItems": 5,
      -            "minItems": 1,
      -            "type": "array"
      -          },
      -          "linkedInAccountId": {
      -            "description": "Optional LinkedIn account id for a connected LinkedIn destination. Absence of both this field and linkedInOrganizationUrn selects the configured default.",
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "linkedInOrganizationUrn": {
      -            "description": "Optional LinkedIn Company Page URN for a connected LinkedIn destination. Requires linkedInAccountId.",
      -            "minLength": 1,
      -            "pattern": "^urn:li:organization:[^\\s]+$",
      -            "type": "string"
      -          },
      -          "platformVersions": {
      -            "additionalProperties": {
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "description": "Optional platform-specific text keyed by platform, e.g. { \"BLUESKY\": \"...\" }. Each supplied version must fit its limit (Bluesky 300, Threads 500, LinkedIn 3000, X 25000) or nothing is scheduled. Saved as the draft’s platform-specific version.",
      -            "type": "object"
      -          },
      -          "platforms": {
      -            "items": {
      -              "enum": [
      -                "SUBSTACK",
      -                "LINKEDIN",
      -                "X",
      -                "BLUESKY",
      -                "THREADS",
      -                "INSTAGRAM",
      -                "FACEBOOK",
      -                "TIKTOK",
      -                "PINTEREST"
      -              ],
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "publication": {
      -            "description": "Substack publication name, handle, or URL selected by the user. Optional when exactly one active Substack publication is connected: Narrareach uses it when its session is ready and says which one was used in substackPublicationSelection.message (source \"sole_connection\"); if the session needs a sync or the profile cannot be verified, nothing is scheduled and the result says what to fix. In a team workspace with one publication, or when a writer who is also a team member omits workspace, nothing is scheduled until the writer confirms it (requiresPublicationChoice: true, publicationChoiceReason: \"confirmation_required\"). Notes publish from the profile signed in to that connection, including publications sharing one login. Unverified or mismatched profile identity returns action_required without publishing. Notes are profile-level: when it is missing and all of the writer’s publications are signed in to one Substack profile, no choice is needed and the note posts from that profile. Only when the publications span two or more Substack profiles does the writer choose a profile: Narrareach uses the one they chose most recently (and says so in substackPublicationSelection.message), or, with no previous choice, nothing is scheduled and the result has requiresPublicationChoice: true, choiceScope: \"profile\" and publicationChoices (one per profile); ask the user, then call again with substackConnectionId set to the chosen publicationChoices[].substackConnectionId. An ambiguous publication value also returns publicationChoices.",
      -            "type": "string"
      -          },
      -          "scheduledFor": {
      -            "description": "Local wall-clock publishing date/time interpreted in timezone, including DST (e.g. \"2026-07-01T14:30:00\" means 2:30 PM). A Z or explicit UTC offset represents an absolute instant instead.",
      -            "type": "string"
      -          },
      -          "socialAccountIds": {
      -            "additionalProperties": {
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "description": "Optional account to post to on Threads, Facebook, TikTok, Pinterest or X, keyed by platform, e.g. { \"THREADS\": \"<accountId>\" }, with accountId values from list_social_accounts. Omit a platform to use its only account or its default. Required for a platform where list_social_accounts reports accountChoiceRequired; ask the writer which account rather than picking one.",
      -            "type": "object"
      -          },
      -          "substackConnectionId": {
      -            "deprecated": true,
      -            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      -            "type": "string"
      -          },
      -          "threadsTopicTag": {
      -            "description": "Optional Threads topic tag. Threads must be selected; maximum 50 characters.",
      -            "type": "string"
      -          },
      -          "timezone": {
      -            "description": "IANA timezone the scheduledFor time above is expressed in (e.g. \"Europe/London\"). Defaults to the writer's saved timezone, else UTC.",
      -            "type": "string"
      -          },
      -          "videoUrls": {
      -            "description": "Optional video URLs or video data URIs to attach to the scheduled note.",
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "workspace": {
      -            "description": "Authorized team workspace name or id for team scheduling. Absence selects the authenticated user’s personal account.",
      -            "type": "string"
      -          },
      -          "writer": {
      -            "description": "Authorized team writer name, handle, or id. \"me\" selects the linked team voice. Required when a team workspace has multiple writers.",
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "scheduledFor",
      -          "platforms",
      -          "timezone",
      -          "content",
      -          "clientRequestId"
      -        ],
      -        "type": "object"
      -      },
      -      "tool": {
      -        "const": "schedule_note",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "tool",
      -      "arguments"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "arguments": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "addSearchMetadata": {
      -            "description": "Generate SEO titles, descriptions, and a Substack slug for supported article destinations. SEO metadata is generated automatically on Revenue Writer, Full Agentic Mode, and Teams & Agencies, and for trials or other accounts with article SEO access. Set this option to false to turn it off. X does not support separate article SEO settings.",
      -            "type": "boolean"
      -          },
      -          "contentHtml": {
      -            "description": "Required when creating a new draft. Supports public <img> or <video> elements and {{media:N}} placeholders resolved from media entries. Video articles require Substack as the sole platform. Native Substack paywall markup is <hr data-type=\"paywall\"> at the selected paragraph boundary, or a single {{NARRAREACH_PAYWALL}} token; paywallMarker supports custom tokens. A Substack Freewall (free and paid subscribers keep reading) is <hr data-type=\"paywall\" data-access=\"subscribers\">, or set freewall to true. Native subscribe block markup is <div data-type=\"button\" data-kind=\"subscribeCaption\" data-text=\"Subscribe\" data-caption=\"Your caption\"></div> with HTML-escaped attribute values. data-kind=\"subscribe\" represents a button without caption. Ordinary links remain links. Audience sections use a div with data-dynamic-content=\"true\" and data-dynamic-audiences=\"paid_sub\", containing data-dynamic-content-match=\"true\" and data-dynamic-content-else=\"true\" divs. Supported audience conditions: non_sub, free_sub, paid_sub, founding_sub (comma-separated). Keep both branches. Subscriber-tag targeting must be published in Substack.",
      -            "type": "string"
      -          },
      -          "coverImage": {
      -            "description": "Optional cover image for a newly created draft, placed at the top of the published body. Supports public HTTPS URLs, data URIs, or base64 image bytes. URL ingestion depends on source-host access. For an image attached in ChatGPT, use coverFile instead. For a saved draft (draftId), attach the cover first with update_draft.",
      -            "properties": {
      -              "data": {
      -                "description": "Data URI or raw base64 image bytes.",
      -                "type": "string"
      -              },
      -              "mimeType": {
      -                "description": "Required for raw base64. Example: image/png.",
      -                "type": "string"
      -              },
      -              "sourceType": {
      -                "enum": [
      -                  "url",
      -                  "data_uri",
      -                  "base64"
      -                ],
      -                "type": "string"
      -              },
      -              "url": {
      -                "description": "Public HTTPS image URL.",
      -                "type": "string"
      -              }
      -            },
      -            "type": "object"
      -          },
      -          "freewall": {
      -            "description": "Make the article's single wall divider (or paywallMarker) a Substack Freewall: everyone sees the content above it; free and paid subscribers keep reading below it. Requires SUBSTACK and a publication with Substack Freewalls. For a new draft (title and contentHtml) it sets the Freewall. A saved draft (draftId) keeps the wall already in its body: a Freewall there is scheduled as a Freewall with or without this field, and true only confirms it. Never combine with isPaidContent. Default false.",
      -            "type": "boolean"
      -          },
      -          "isPaidContent": {
      -            "description": "Whether the Substack article is paid-only. Default false. Do not combine with freewall.",
      -            "type": "boolean"
      -          },
      -          "linkedinAuthorUrn": {
      -            "description": "LinkedIn personal profile or Company Page author URN belonging to the connected LinkedIn Articles account.",
      -            "type": "string"
      -          },
      -          "linkedinNewsletterUrn": {
      -            "description": "LinkedIn newsletter URN belonging to the connected LinkedIn Articles account. Required when linkedinPublicationType is newsletter.",
      -            "type": "string"
      -          },
      -          "linkedinPublicationType": {
      -            "description": "LinkedIn destination type. Defaults to an individual article; newsletter represents a user-selected newsletter destination.",
      -            "enum": [
      -              "article",
      -              "newsletter"
      -            ],
      -            "type": "string"
      -          },
      -          "linkedinShareCommentary": {
      -            "description": "Optional LinkedIn share text used when publishing a LinkedIn article.",
      -            "type": "string"
      -          },
      -          "media": {
      -            "description": "Optional inline images or Substack article videos for a newly created draft. Replaces {{media:N}} placeholders in array order; leftovers are appended. kind defaults to image; video requires Substack as the sole platform. Supports public URLs, data URIs, and base64 bytes. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      -            "items": {
      -              "properties": {
      -                "data": {
      -                  "type": "string"
      -                },
      -                "fileName": {
      -                  "type": "string"
      -                },
      -                "kind": {
      -                  "description": "Defaults to image when omitted.",
      -                  "enum": [
      -                    "image",
      -                    "video"
      -                  ],
      -                  "type": "string"
      -                },
      -                "mimeType": {
      -                  "type": "string"
      -                },
      -                "sourceType": {
      -                  "enum": [
      -                    "url",
      -                    "data_uri",
      -                    "base64"
      -                  ],
      -                  "type": "string"
      -                },
      -                "url": {
      -                  "type": "string"
      -                }
      -              },
      -              "type": "object"
      -            },
      -            "type": "array"
      -          },
      -          "mediumNotifyFollowers": {
      -            "description": "Whether to email Medium subscribers about this story. Only valid when platforms includes MEDIUM. Defaults to false (no email). Best-effort: a failure to apply this setting never blocks the publish/schedule and is reported as a warning.",
      -            "type": "boolean"
      -          },
      -          "mediumPublicationId": {
      -            "description": "Optional authorized Medium publication id when platforms includes MEDIUM. Absent means the personal profile. Writer-only access submits for editorial review and leaves the story unscheduled until acceptance. Explicit publication rejection allows personal-profile delivery with a warning; ambiguous submissions remain unpublished for review. Draft-only delivery does not submit to a publication.",
      -            "type": "string"
      -          },
      -          "paywallMarker": {
      -            "description": "Optional custom marker in contentHtml where the selected free preview ends; must appear exactly once. The standard {{NARRAREACH_PAYWALL}} marker is recognized without this field. Creates a native divider without changing sendToNewsletter. With freewall true it allows free and paid subscribers; otherwise it enables paid access.",
      -            "maxLength": 200,
      -            "type": "string"
      -          },
      -          "platforms": {
      -            "items": {
      -              "enum": [
      -                "SUBSTACK",
      -                "MEDIUM",
      -                "LINKEDIN",
      -                "X",
      -                "WORDPRESS",
      -                "GHOST"
      -              ],
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "publication": {
      -            "description": "Substack destination as a publication name, handle, or URL, for example \"AI Newsroom\", \"@theainewsroom\", or \"https://theainewsroom.substack.com\". Optional when exactly one active Substack publication is connected; Narrareach selects it automatically. Required when more than one active Substack publication is connected, except that when it is missing Narrareach uses the publication the writer scheduled or published to most recently and says so in substackPublicationSelection.message, with publicationChoices listing the others; tell the writer which one was used. If there is no previous choice, the value is ambiguous, or Narrareach cannot confirm the session publishes there, nothing is scheduled and the result has requiresPublicationChoice: true with publicationChoices (name, handle, url, substackConnectionId). Ask which one they want, then call again with publication set to the chosen handle (and draftId when a draft was already saved).",
      -            "type": "string"
      -          },
      -          "publishMode": {
      -            "description": "Only valid when all selected destinations are WordPress or Ghost. Defaults to publish; draft saves a remote draft at the scheduled time without publication.",
      -            "enum": [
      -              "publish",
      -              "draft"
      -            ],
      -            "type": "string"
      -          },
      -          "scheduledFor": {
      -            "description": "Required unless platformSchedules is given, and must be in the future. Shared local wall-clock publishing date/time interpreted in timezone, including DST. A Z or explicit UTC offset represents an absolute instant. LinkedIn articles require at least 20 minutes of lead time.",
      -            "type": "string"
      -          },
      -          "sendToNewsletter": {
      -            "description": "Substack email delivery setting. Default true.",
      -            "type": "boolean"
      -          },
      -          "substackConnectionId": {
      -            "deprecated": true,
      -            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      -            "type": "string"
      -          },
      -          "subtitle": {
      -            "description": "Optional article subtitle for newly created drafts. Substack omits subtitles over 250 characters and returns a warning without changing the saved draft.",
      -            "type": "string"
      -          },
      -          "tags": {
      -            "description": "Optional tag list for newly created drafts. Substack receives all supplied tags. Medium receives its supported first 5 topics and returns a warning when extras are omitted. The saved draft remains unchanged.",
      -            "items": {
      -              "maxLength": 50,
      -              "type": "string"
      -            },
      -            "maxItems": 50,
      -            "type": "array"
      -          },
      -          "timezone": {
      -            "description": "IANA timezone the scheduledFor time(s) above are expressed in (e.g. \"Europe/London\"). Defaults to the writer's saved timezone, else UTC.",
      -            "type": "string"
      -          },
      -          "title": {
      -            "description": "Required when creating a new draft.",
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "platforms",
      -          "scheduledFor",
      -          "timezone",
      -          "title",
      -          "contentHtml",
      -          "addSearchMetadata"
      -        ],
      -        "type": "object"
      -      },
      -      "tool": {
      -        "const": "schedule_article",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "tool",
      -      "arguments"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "arguments": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "clientRequestId": {
      +            "description": "Optional but recommended: your own id for this note, 8 to 80 letters, numbers, hyphens or underscores. Use a new one for each note and the same one when retrying it (for example after a timeout or a rate-limit pause): the retry returns the original result and schedules nothing again. Reusing it with different text, platforms or time is refused.",
      +            "pattern": "^[A-Za-z0-9_-]{8,80}$",
      +            "type": "string"
      +          },
      +          "content": {
      +            "description": "Used only when creating a new note draft.",
      +            "type": "string"
      +          },
      +          "firstReply": {
      +            "description": "Optional first reply for supported destinations. An invalid reply is omitted per platform without cancelling the root post.",
      +            "type": "string"
      +          },
      +          "imageUrls": {
      +            "description": "Optional image URLs or image data URIs to attach to the scheduled note.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "instagramDestinations": {
      +            "description": "Instagram destinations with accountId returned by list_instagram_destinations and optional independent caption. Each account receives its own delivery receipt.",
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "accountId": {
      +                  "type": "string"
      +                },
      +                "caption": {
      +                  "maxLength": 2200,
      +                  "type": "string"
      +                },
      +                "label": {
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "accountId"
      +              ],
      +              "type": "object"
      +            },
      +            "maxItems": 5,
      +            "minItems": 1,
      +            "type": "array"
      +          },
      +          "linkedInAccountId": {
      +            "description": "Optional LinkedIn account id for a connected LinkedIn destination. Absence of both this field and linkedInOrganizationUrn selects the configured default.",
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "linkedInOrganizationUrn": {
      +            "description": "Optional LinkedIn Company Page URN for a connected LinkedIn destination. Requires linkedInAccountId.",
      +            "minLength": 1,
      +            "pattern": "^urn:li:organization:[^\\s]+$",
      +            "type": "string"
      +          },
      +          "platformVersions": {
      +            "additionalProperties": {
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "description": "Optional platform-specific text keyed by platform, e.g. { \"BLUESKY\": \"...\" }. Each supplied version must fit its limit (Bluesky 300, Threads 500, LinkedIn 3000, X 25000) or nothing is scheduled. Saved as the draft’s platform-specific version.",
      +            "type": "object"
      +          },
      +          "platforms": {
      +            "items": {
      +              "enum": [
      +                "SUBSTACK",
      +                "LINKEDIN",
      +                "X",
      +                "BLUESKY",
      +                "THREADS",
      +                "INSTAGRAM",
      +                "FACEBOOK",
      +                "TIKTOK",
      +                "PINTEREST"
      +              ],
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "publication": {
      +            "description": "Substack publication name, handle, or URL selected by the user. Optional when exactly one active Substack publication is connected: Narrareach uses it when its session is ready and says which one was used in substackPublicationSelection.message (source \"sole_connection\"); if the session needs a sync or the profile cannot be verified, nothing is scheduled and the result says what to fix. In a team workspace with one publication, or when a writer who is also a team member omits workspace, nothing is scheduled until the writer confirms it (requiresPublicationChoice: true, publicationChoiceReason: \"confirmation_required\"). Notes publish from the profile signed in to that connection, including publications sharing one login. Unverified or mismatched profile identity returns action_required without publishing. Notes are profile-level: when it is missing and all of the writer’s publications are signed in to one Substack profile, no choice is needed and the note posts from that profile. Only when the publications span two or more Substack profiles does the writer choose a profile: Narrareach uses the one they chose most recently (and says so in substackPublicationSelection.message), or, with no previous choice, nothing is scheduled and the result has requiresPublicationChoice: true, choiceScope: \"profile\" and publicationChoices (one per profile); ask the user, then call again with substackConnectionId set to the chosen publicationChoices[].substackConnectionId. An ambiguous publication value also returns publicationChoices.",
      +            "type": "string"
      +          },
      +          "scheduledFor": {
      +            "description": "Local wall-clock publishing date/time interpreted in timezone, including DST (e.g. \"2026-07-01T14:30:00\" means 2:30 PM). A Z or explicit UTC offset represents an absolute instant instead.",
      +            "type": "string"
      +          },
      +          "socialAccountIds": {
      +            "additionalProperties": {
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "description": "Optional account to post to on Threads, Facebook, TikTok, Pinterest or X, keyed by platform, e.g. { \"THREADS\": \"<accountId>\" }, with accountId values from list_social_accounts. Omit a platform to use its only account or its default. Required for a platform where list_social_accounts reports accountChoiceRequired; ask the writer which account rather than picking one.",
      +            "type": "object"
      +          },
      +          "substackConnectionId": {
      +            "deprecated": true,
      +            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      +            "type": "string"
      +          },
      +          "threadsTopicTag": {
      +            "description": "Optional Threads topic tag. Threads must be selected; maximum 50 characters.",
      +            "type": "string"
      +          },
      +          "timezone": {
      +            "description": "IANA timezone the scheduledFor time above is expressed in (e.g. \"Europe/London\"). Defaults to the writer's saved timezone, else UTC.",
      +            "type": "string"
      +          },
      +          "videoUrls": {
      +            "description": "Optional video URLs or video data URIs to attach to the scheduled note.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "workspace": {
      +            "description": "Authorized team workspace name or id for team scheduling. Absence selects the authenticated user’s personal account.",
      +            "type": "string"
      +          },
      +          "writer": {
      +            "description": "Authorized team writer name, handle, or id. \"me\" selects the linked team voice. Required when a team workspace has multiple writers.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "scheduledFor",
      +          "platforms",
      +          "timezone",
      +          "content",
      +          "clientRequestId"
      +        ],
      +        "type": "object"
      +      },
      +      "tool": {
      +        "const": "schedule_note",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "tool",
      +      "arguments"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "arguments": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "addSearchMetadata": {
      +            "description": "Generate SEO titles, descriptions, and a Substack slug for supported article destinations. SEO metadata is generated automatically on Revenue Writer, Full Agentic Mode, and Teams & Agencies, and for trials or other accounts with article SEO access. Set this option to false to turn it off. X does not support separate article SEO settings.",
      +            "type": "boolean"
      +          },
      +          "contentHtml": {
      +            "description": "Required when creating a new draft. Supports public <img> or <video> elements and {{media:N}} placeholders resolved from media entries. Video articles require Substack as the sole platform. Native Substack paywall markup is <hr data-type=\"paywall\"> at the selected paragraph boundary, or a single {{NARRAREACH_PAYWALL}} token; paywallMarker supports custom tokens. A Substack Freewall (free and paid subscribers keep reading) is <hr data-type=\"paywall\" data-access=\"subscribers\">, or set freewall to true. Native subscribe block markup is <div data-type=\"button\" data-kind=\"subscribeCaption\" data-text=\"Subscribe\" data-caption=\"Your caption\"></div> with HTML-escaped attribute values. data-kind=\"subscribe\" represents a button without caption. Ordinary links remain links. Audience sections use a div with data-dynamic-content=\"true\" and data-dynamic-audiences=\"paid_sub\", containing data-dynamic-content-match=\"true\" and data-dynamic-content-else=\"true\" divs. Supported audience conditions: non_sub, free_sub, paid_sub, founding_sub (comma-separated). Keep both branches. Subscriber-tag targeting must be published in Substack.",
      +            "type": "string"
      +          },
      +          "coverImage": {
      +            "description": "Optional cover image for a newly created draft, placed at the top of the published body. Supports public HTTPS URLs, data URIs, or base64 image bytes. URL ingestion depends on source-host access. For an image attached in ChatGPT, use coverFile instead. For a saved draft (draftId), attach the cover first with update_draft.",
      +            "properties": {
      +              "data": {
      +                "description": "Data URI or raw base64 image bytes.",
      +                "type": "string"
      +              },
      +              "mimeType": {
      +                "description": "Required for raw base64. Example: image/png.",
      +                "type": "string"
      +              },
      +              "sourceType": {
      +                "enum": [
      +                  "url",
      +                  "data_uri",
      +                  "base64"
      +                ],
      +                "type": "string"
      +              },
      +              "url": {
      +                "description": "Public HTTPS image URL.",
      +                "type": "string"
      +              }
      +            },
      +            "type": "object"
      +          },
      +          "freewall": {
      +            "description": "Make the article's single wall divider (or paywallMarker) a Substack Freewall: everyone sees the content above it; free and paid subscribers keep reading below it. Requires SUBSTACK and a publication with Substack Freewalls. For a new draft (title and contentHtml) it sets the Freewall. A saved draft (draftId) keeps the wall already in its body: a Freewall there is scheduled as a Freewall with or without this field, and true only confirms it. Never combine with isPaidContent. Default false.",
      +            "type": "boolean"
      +          },
      +          "isPaidContent": {
      +            "description": "Whether the Substack article is paid-only. Default false. Do not combine with freewall.",
      +            "type": "boolean"
      +          },
      +          "linkedinAuthorUrn": {
      +            "description": "LinkedIn personal profile or Company Page author URN belonging to the connected LinkedIn Articles account.",
      +            "type": "string"
      +          },
      +          "linkedinNewsletterUrn": {
      +            "description": "LinkedIn newsletter URN belonging to the connected LinkedIn Articles account. Required when linkedinPublicationType is newsletter.",
      +            "type": "string"
      +          },
      +          "linkedinPublicationType": {
      +            "description": "LinkedIn destination type. Defaults to an individual article; newsletter represents a user-selected newsletter destination.",
      +            "enum": [
      +              "article",
      +              "newsletter"
      +            ],
      +            "type": "string"
      +          },
      +          "linkedinShareCommentary": {
      +            "description": "Optional LinkedIn share text used when publishing a LinkedIn article.",
      +            "type": "string"
      +          },
      +          "media": {
      +            "description": "Optional inline images or Substack article videos for a newly created draft. Replaces {{media:N}} placeholders in array order; leftovers are appended. kind defaults to image; video requires Substack as the sole platform. Supports public URLs, data URIs, and base64 bytes. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      +            "items": {
      +              "properties": {
      +                "data": {
      +                  "type": "string"
      +                },
      +                "fileName": {
      +                  "type": "string"
      +                },
      +                "kind": {
      +                  "description": "Defaults to image when omitted.",
      +                  "enum": [
      +                    "image",
      +                    "video"
      +                  ],
      +                  "type": "string"
      +                },
      +                "mimeType": {
      +                  "type": "string"
      +                },
      +                "sourceType": {
      +                  "enum": [
      +                    "url",
      +                    "data_uri",
      +                    "base64"
      +                  ],
      +                  "type": "string"
      +                },
      +                "url": {
      +                  "type": "string"
      +                }
      +              },
      +              "type": "object"
      +            },
      +            "type": "array"
      +          },
      +          "mediumNotifyFollowers": {
      +            "description": "Whether to email Medium subscribers about this story. Only valid when platforms includes MEDIUM. Defaults to false (no email). Best-effort: a failure to apply this setting never blocks the publish/schedule and is reported as a warning.",
      +            "type": "boolean"
      +          },
      +          "mediumPublicationId": {
      +            "description": "Optional authorized Medium publication id when platforms includes MEDIUM. Absent means the personal profile. Writer-only access submits for editorial review and leaves the story unscheduled until acceptance. Explicit publication rejection allows personal-profile delivery with a warning; ambiguous submissions remain unpublished for review. Draft-only delivery does not submit to a publication.",
      +            "type": "string"
      +          },
      +          "paywallMarker": {
      +            "description": "Optional custom marker in contentHtml where the selected free preview ends; must appear exactly once. The standard {{NARRAREACH_PAYWALL}} marker is recognized without this field. Creates a native divider without changing sendToNewsletter. With freewall true it allows free and paid subscribers; otherwise it enables paid access.",
      +            "maxLength": 200,
      +            "type": "string"
      +          },
      +          "platforms": {
      +            "items": {
      +              "enum": [
      +                "SUBSTACK",
      +                "MEDIUM",
      +                "LINKEDIN",
      +                "X",
      +                "WORDPRESS",
      +                "GHOST"
      +              ],
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "publication": {
      +            "description": "Substack destination as a publication name, handle, or URL, for example \"AI Newsroom\", \"@theainewsroom\", or \"https://theainewsroom.substack.com\". Optional when exactly one active Substack publication is connected; Narrareach selects it automatically. Required when more than one active Substack publication is connected, except that when it is missing Narrareach uses the publication the writer scheduled or published to most recently and says so in substackPublicationSelection.message, with publicationChoices listing the others; tell the writer which one was used. If there is no previous choice, the value is ambiguous, or Narrareach cannot confirm the session publishes there, nothing is scheduled and the result has requiresPublicationChoice: true with publicationChoices (name, handle, url, substackConnectionId). Ask which one they want, then call again with publication set to the chosen handle (and draftId when a draft was already saved).",
      +            "type": "string"
      +          },
      +          "publishMode": {
      +            "description": "Only valid when all selected destinations are WordPress or Ghost. Defaults to publish; draft saves a remote draft at the scheduled time without publication.",
      +            "enum": [
      +              "publish",
      +              "draft"
      +            ],
      +            "type": "string"
      +          },
      +          "scheduledFor": {
      +            "description": "Required unless publishNow or platformSchedules is given, and must be in the future. Shared local wall-clock publishing date/time interpreted in timezone, including DST. A Z or explicit UTC offset represents an absolute instant. LinkedIn articles require at least 20 minutes of lead time.",
      +            "type": "string"
      +          },
      +          "sendToNewsletter": {
      +            "description": "Substack email delivery setting. Default true.",
      +            "type": "boolean"
      +          },
      +          "substackConnectionId": {
      +            "deprecated": true,
      +            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      +            "type": "string"
      +          },
      +          "subtitle": {
      +            "description": "Optional article subtitle for newly created drafts. Substack omits subtitles over 250 characters and returns a warning without changing the saved draft.",
      +            "type": "string"
      +          },
      +          "tags": {
      +            "description": "Optional tag list for newly created drafts. Substack receives all supplied tags. Medium receives its supported first 5 topics and returns a warning when extras are omitted. The saved draft remains unchanged.",
      +            "items": {
      +              "maxLength": 50,
      +              "type": "string"
      +            },
      +            "maxItems": 50,
      +            "type": "array"
      +          },
      +          "timezone": {
      +            "description": "IANA timezone the scheduledFor time(s) above are expressed in (e.g. \"Europe/London\"). Defaults to the writer's saved timezone, else UTC.",
      +            "type": "string"
      +          },
      +          "title": {
      +            "description": "Required when creating a new draft.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "platforms",
      +          "scheduledFor",
      +          "timezone",
      +          "title",
      +          "contentHtml",
      +          "addSearchMetadata"
      +        ],
      +        "type": "object"
      +      },
      +      "tool": {
      +        "const": "schedule_article",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "tool",
      +      "arguments"
      +    ],
      +    "type": "object"
      +  }
      +]
  3. Changed1 schema field changed
    • changedInput schema / properties / calls / items / oneOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "arguments": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "clientRequestId": {
      -            "description": "Optional but recommended: your own id for this note, 8 to 80 letters, numbers, hyphens or underscores. Use a new one for each note and the same one when retrying it (for example after a timeout or a rate-limit pause): the retry returns the original result and schedules nothing again. Reusing it with different text, platforms or time is refused.",
      -            "pattern": "^[A-Za-z0-9_-]{8,80}$",
      -            "type": "string"
      -          },
      -          "content": {
      -            "description": "Used only when creating a new note draft.",
      -            "type": "string"
      -          },
      -          "firstReply": {
      -            "description": "Optional first reply for supported destinations. An invalid reply is omitted per platform without cancelling the root post.",
      -            "type": "string"
      -          },
      -          "imageUrls": {
      -            "description": "Optional image URLs or image data URIs to attach to the scheduled note.",
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "instagramDestinations": {
      -            "description": "Instagram destinations with accountId returned by list_instagram_destinations and optional independent caption. Each account receives its own delivery receipt.",
      -            "items": {
      -              "additionalProperties": false,
      -              "properties": {
      -                "accountId": {
      -                  "type": "string"
      -                },
      -                "caption": {
      -                  "maxLength": 2200,
      -                  "type": "string"
      -                },
      -                "label": {
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "accountId"
      -              ],
      -              "type": "object"
      -            },
      -            "maxItems": 5,
      -            "minItems": 1,
      -            "type": "array"
      -          },
      -          "linkedInAccountId": {
      -            "description": "Optional LinkedIn account id for a connected LinkedIn destination. Absence of both this field and linkedInOrganizationUrn selects the configured default.",
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "linkedInOrganizationUrn": {
      -            "description": "Optional LinkedIn Company Page URN for a connected LinkedIn destination. Requires linkedInAccountId.",
      -            "minLength": 1,
      -            "pattern": "^urn:li:organization:[^\\s]+$",
      -            "type": "string"
      -          },
      -          "platformVersions": {
      -            "additionalProperties": {
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "description": "Optional platform-specific text keyed by platform, e.g. { \"BLUESKY\": \"...\" }. Each supplied version must fit its limit (Bluesky 300, Threads 500, LinkedIn 3000, X 25000) or nothing is scheduled. Saved as the draft’s platform-specific version.",
      -            "type": "object"
      -          },
      -          "platforms": {
      -            "items": {
      -              "enum": [
      -                "SUBSTACK",
      -                "LINKEDIN",
      -                "X",
      -                "BLUESKY",
      -                "THREADS",
      -                "INSTAGRAM",
      -                "FACEBOOK",
      -                "TIKTOK",
      -                "PINTEREST"
      -              ],
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "publication": {
      -            "description": "Substack publication name, handle, or URL selected by the user. Optional when exactly one active Substack publication is connected: Narrareach uses it when its session is ready and says which one was used in substackPublicationSelection.message (source \"sole_connection\"); if the session needs a sync or the profile cannot be verified, nothing is scheduled and the result says what to fix. In a team workspace with one publication, or when a writer who is also a team member omits workspace, nothing is scheduled until the writer confirms it (requiresPublicationChoice: true, publicationChoiceReason: \"confirmation_required\"). Notes publish from the profile signed in to that connection, including publications sharing one login. Unverified or mismatched profile identity returns action_required without publishing. Notes are profile-level: when it is missing and all of the writer’s publications are signed in to one Substack profile, no choice is needed and the note posts from that profile. Only when the publications span two or more Substack profiles does the writer choose a profile: Narrareach uses the one they chose most recently (and says so in substackPublicationSelection.message), or, with no previous choice, nothing is scheduled and the result has requiresPublicationChoice: true, choiceScope: \"profile\" and publicationChoices (one per profile); ask the user, then call again with substackConnectionId set to the chosen publicationChoices[].substackConnectionId. An ambiguous publication value also returns publicationChoices.",
      -            "type": "string"
      -          },
      -          "scheduledFor": {
      -            "description": "Local wall-clock publishing date/time interpreted in timezone, including DST (e.g. \"2026-07-01T14:30:00\" means 2:30 PM). A Z or explicit UTC offset represents an absolute instant instead.",
      -            "type": "string"
      -          },
      -          "socialAccountIds": {
      -            "additionalProperties": {
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "description": "Optional account to post to on Threads, Facebook, TikTok, Pinterest or X, keyed by platform, e.g. { \"THREADS\": \"<accountId>\" }, with accountId values from list_social_accounts. Omit a platform to use its only account or its default. Required for a platform where list_social_accounts reports accountChoiceRequired; ask the writer which account rather than picking one.",
      -            "type": "object"
      -          },
      -          "substackConnectionId": {
      -            "deprecated": true,
      -            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      -            "type": "string"
      -          },
      -          "threadsTopicTag": {
      -            "description": "Optional Threads topic tag. Threads must be selected; maximum 50 characters.",
      -            "type": "string"
      -          },
      -          "timezone": {
      -            "description": "IANA timezone the scheduledFor time above is expressed in (e.g. \"Europe/London\"). Default UTC.",
      -            "type": "string"
      -          },
      -          "videoUrls": {
      -            "description": "Optional video URLs or video data URIs to attach to the scheduled note.",
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "workspace": {
      -            "description": "Authorized team workspace name or id for team scheduling. Absence selects the authenticated user’s personal account.",
      -            "type": "string"
      -          },
      -          "writer": {
      -            "description": "Authorized team writer name, handle, or id. \"me\" selects the linked team voice. Required when a team workspace has multiple writers.",
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "scheduledFor",
      -          "platforms",
      -          "timezone",
      -          "content",
      -          "clientRequestId"
      -        ],
      -        "type": "object"
      -      },
      -      "tool": {
      -        "const": "schedule_note",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "tool",
      -      "arguments"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "arguments": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "addSearchMetadata": {
      -            "description": "Generate SEO titles, descriptions, and a Substack slug for supported article destinations. SEO metadata is generated automatically on Revenue Writer, Full Agentic Mode, and Teams & Agencies, and for trials or other accounts with article SEO access. Set this option to false to turn it off. X does not support separate article SEO settings.",
      -            "type": "boolean"
      -          },
      -          "contentHtml": {
      -            "description": "Required when creating a new draft. Supports public <img> or <video> elements and {{media:N}} placeholders resolved from media entries. Video articles require Substack as the sole platform. Native Substack paywall markup is <hr data-type=\"paywall\"> at the selected paragraph boundary, or a single {{NARRAREACH_PAYWALL}} token; paywallMarker supports custom tokens. A Substack Freewall (free and paid subscribers keep reading) is <hr data-type=\"paywall\" data-access=\"subscribers\">, or set freewall to true. Native subscribe block markup is <div data-type=\"button\" data-kind=\"subscribeCaption\" data-text=\"Subscribe\" data-caption=\"Your caption\"></div> with HTML-escaped attribute values. data-kind=\"subscribe\" represents a button without caption. Ordinary links remain links. Audience sections use a div with data-dynamic-content=\"true\" and data-dynamic-audiences=\"paid_sub\", containing data-dynamic-content-match=\"true\" and data-dynamic-content-else=\"true\" divs. Supported audience conditions: non_sub, free_sub, paid_sub, founding_sub (comma-separated). Keep both branches. Subscriber-tag targeting must be published in Substack.",
      -            "type": "string"
      -          },
      -          "coverImage": {
      -            "description": "Optional cover image for a newly created draft, placed at the top of the published body. Supports public HTTPS URLs, data URIs, or base64 image bytes. URL ingestion depends on source-host access. For an image attached in ChatGPT, use coverFile instead. For a saved draft (draftId), attach the cover first with update_draft.",
      -            "properties": {
      -              "data": {
      -                "description": "Data URI or raw base64 image bytes.",
      -                "type": "string"
      -              },
      -              "mimeType": {
      -                "description": "Required for raw base64. Example: image/png.",
      -                "type": "string"
      -              },
      -              "sourceType": {
      -                "enum": [
      -                  "url",
      -                  "data_uri",
      -                  "base64"
      -                ],
      -                "type": "string"
      -              },
      -              "url": {
      -                "description": "Public HTTPS image URL.",
      -                "type": "string"
      -              }
      -            },
      -            "type": "object"
      -          },
      -          "freewall": {
      -            "description": "Make the article's single wall divider (or paywallMarker) a Substack Freewall: everyone sees the content above it; free and paid subscribers keep reading below it. Requires SUBSTACK and a new draft (title and contentHtml). The publication must have Substack Freewalls available. Default false.",
      -            "type": "boolean"
      -          },
      -          "isPaidContent": {
      -            "description": "Whether the Substack article is paid-only. Default false. Do not combine with freewall.",
      -            "type": "boolean"
      -          },
      -          "linkedinAuthorUrn": {
      -            "description": "LinkedIn personal profile or Company Page author URN belonging to the connected LinkedIn Articles account.",
      -            "type": "string"
      -          },
      -          "linkedinNewsletterUrn": {
      -            "description": "LinkedIn newsletter URN belonging to the connected LinkedIn Articles account. Required when linkedinPublicationType is newsletter.",
      -            "type": "string"
      -          },
      -          "linkedinPublicationType": {
      -            "description": "LinkedIn destination type. Defaults to an individual article; newsletter represents a user-selected newsletter destination.",
      -            "enum": [
      -              "article",
      -              "newsletter"
      -            ],
      -            "type": "string"
      -          },
      -          "linkedinShareCommentary": {
      -            "description": "Optional LinkedIn share text used when publishing a LinkedIn article.",
      -            "type": "string"
      -          },
      -          "media": {
      -            "description": "Optional inline images or Substack article videos for a newly created draft. Replaces {{media:N}} placeholders in array order; leftovers are appended. kind defaults to image; video requires Substack as the sole platform. Supports public URLs, data URIs, and base64 bytes. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      -            "items": {
      -              "properties": {
      -                "data": {
      -                  "type": "string"
      -                },
      -                "fileName": {
      -                  "type": "string"
      -                },
      -                "kind": {
      -                  "description": "Defaults to image when omitted.",
      -                  "enum": [
      -                    "image",
      -                    "video"
      -                  ],
      -                  "type": "string"
      -                },
      -                "mimeType": {
      -                  "type": "string"
      -                },
      -                "sourceType": {
      -                  "enum": [
      -                    "url",
      -                    "data_uri",
      -                    "base64"
      -                  ],
      -                  "type": "string"
      -                },
      -                "url": {
      -                  "type": "string"
      -                }
      -              },
      -              "type": "object"
      -            },
      -            "type": "array"
      -          },
      -          "mediumNotifyFollowers": {
      -            "description": "Whether to email Medium subscribers about this story. Only valid when platforms includes MEDIUM. Defaults to false (no email). Best-effort: a failure to apply this setting never blocks the publish/schedule and is reported as a warning.",
      -            "type": "boolean"
      -          },
      -          "mediumPublicationId": {
      -            "description": "Optional authorized Medium publication id when platforms includes MEDIUM. Absent means the personal profile. Writer-only access submits for editorial review and leaves the story unscheduled until acceptance. Explicit publication rejection allows personal-profile delivery with a warning; ambiguous submissions remain unpublished for review. Draft-only delivery does not submit to a publication.",
      -            "type": "string"
      -          },
      -          "paywallMarker": {
      -            "description": "Optional custom marker in contentHtml where the selected free preview ends; must appear exactly once. The standard {{NARRAREACH_PAYWALL}} marker is recognized without this field. Creates a native divider without changing sendToNewsletter. With freewall true it allows free and paid subscribers; otherwise it enables paid access.",
      -            "maxLength": 200,
      -            "type": "string"
      -          },
      -          "platforms": {
      -            "items": {
      -              "enum": [
      -                "SUBSTACK",
      -                "MEDIUM",
      -                "LINKEDIN",
      -                "X",
      -                "WORDPRESS",
      -                "GHOST"
      -              ],
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "publication": {
      -            "description": "Substack destination as a publication name, handle, or URL, for example \"AI Newsroom\", \"@theainewsroom\", or \"https://theainewsroom.substack.com\". Optional when exactly one active Substack publication is connected; Narrareach selects it automatically. Required when more than one active Substack publication is connected, except that when it is missing Narrareach uses the publication the writer scheduled or published to most recently and says so in substackPublicationSelection.message, with publicationChoices listing the others; tell the writer which one was used. If there is no previous choice, the value is ambiguous, or Narrareach cannot confirm the session publishes there, nothing is scheduled and the result has requiresPublicationChoice: true with publicationChoices (name, handle, url, substackConnectionId). Ask which one they want, then call again with publication set to the chosen handle (and draftId when a draft was already saved).",
      -            "type": "string"
      -          },
      -          "publishMode": {
      -            "description": "Only valid when all selected destinations are WordPress or Ghost. Defaults to publish; draft saves a remote draft at the scheduled time without publication.",
      -            "enum": [
      -              "publish",
      -              "draft"
      -            ],
      -            "type": "string"
      -          },
      -          "scheduledFor": {
      -            "description": "Required unless platformSchedules is given, and must be in the future. Shared local wall-clock publishing date/time interpreted in timezone, including DST. A Z or explicit UTC offset represents an absolute instant. LinkedIn articles require at least 20 minutes of lead time.",
      -            "type": "string"
      -          },
      -          "sendToNewsletter": {
      -            "description": "Substack email delivery setting. Default true.",
      -            "type": "boolean"
      -          },
      -          "substackConnectionId": {
      -            "deprecated": true,
      -            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      -            "type": "string"
      -          },
      -          "subtitle": {
      -            "description": "Optional article subtitle for newly created drafts. Substack omits subtitles over 250 characters and returns a warning without changing the saved draft.",
      -            "type": "string"
      -          },
      -          "tags": {
      -            "description": "Optional tag list for newly created drafts. Substack receives all supplied tags. Medium receives its supported first 5 topics and returns a warning when extras are omitted. The saved draft remains unchanged.",
      -            "items": {
      -              "maxLength": 50,
      -              "type": "string"
      -            },
      -            "maxItems": 50,
      -            "type": "array"
      -          },
      -          "timezone": {
      -            "description": "IANA timezone the scheduledFor time(s) above are expressed in (e.g. \"Europe/London\"). Default UTC.",
      -            "type": "string"
      -          },
      -          "title": {
      -            "description": "Required when creating a new draft.",
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "platforms",
      -          "scheduledFor",
      -          "timezone",
      -          "title",
      -          "contentHtml",
      -          "addSearchMetadata"
      -        ],
      -        "type": "object"
      -      },
      -      "tool": {
      -        "const": "schedule_article",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "tool",
      -      "arguments"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "arguments": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "clientRequestId": {
      +            "description": "Optional but recommended: your own id for this note, 8 to 80 letters, numbers, hyphens or underscores. Use a new one for each note and the same one when retrying it (for example after a timeout or a rate-limit pause): the retry returns the original result and schedules nothing again. Reusing it with different text, platforms or time is refused.",
      +            "pattern": "^[A-Za-z0-9_-]{8,80}$",
      +            "type": "string"
      +          },
      +          "content": {
      +            "description": "Used only when creating a new note draft.",
      +            "type": "string"
      +          },
      +          "firstReply": {
      +            "description": "Optional first reply for supported destinations. An invalid reply is omitted per platform without cancelling the root post.",
      +            "type": "string"
      +          },
      +          "imageUrls": {
      +            "description": "Optional image URLs or image data URIs to attach to the scheduled note.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "instagramDestinations": {
      +            "description": "Instagram destinations with accountId returned by list_instagram_destinations and optional independent caption. Each account receives its own delivery receipt.",
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "accountId": {
      +                  "type": "string"
      +                },
      +                "caption": {
      +                  "maxLength": 2200,
      +                  "type": "string"
      +                },
      +                "label": {
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "accountId"
      +              ],
      +              "type": "object"
      +            },
      +            "maxItems": 5,
      +            "minItems": 1,
      +            "type": "array"
      +          },
      +          "linkedInAccountId": {
      +            "description": "Optional LinkedIn account id for a connected LinkedIn destination. Absence of both this field and linkedInOrganizationUrn selects the configured default.",
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "linkedInOrganizationUrn": {
      +            "description": "Optional LinkedIn Company Page URN for a connected LinkedIn destination. Requires linkedInAccountId.",
      +            "minLength": 1,
      +            "pattern": "^urn:li:organization:[^\\s]+$",
      +            "type": "string"
      +          },
      +          "platformVersions": {
      +            "additionalProperties": {
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "description": "Optional platform-specific text keyed by platform, e.g. { \"BLUESKY\": \"...\" }. Each supplied version must fit its limit (Bluesky 300, Threads 500, LinkedIn 3000, X 25000) or nothing is scheduled. Saved as the draft’s platform-specific version.",
      +            "type": "object"
      +          },
      +          "platforms": {
      +            "items": {
      +              "enum": [
      +                "SUBSTACK",
      +                "LINKEDIN",
      +                "X",
      +                "BLUESKY",
      +                "THREADS",
      +                "INSTAGRAM",
      +                "FACEBOOK",
      +                "TIKTOK",
      +                "PINTEREST"
      +              ],
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "publication": {
      +            "description": "Substack publication name, handle, or URL selected by the user. Optional when exactly one active Substack publication is connected: Narrareach uses it when its session is ready and says which one was used in substackPublicationSelection.message (source \"sole_connection\"); if the session needs a sync or the profile cannot be verified, nothing is scheduled and the result says what to fix. In a team workspace with one publication, or when a writer who is also a team member omits workspace, nothing is scheduled until the writer confirms it (requiresPublicationChoice: true, publicationChoiceReason: \"confirmation_required\"). Notes publish from the profile signed in to that connection, including publications sharing one login. Unverified or mismatched profile identity returns action_required without publishing. Notes are profile-level: when it is missing and all of the writer’s publications are signed in to one Substack profile, no choice is needed and the note posts from that profile. Only when the publications span two or more Substack profiles does the writer choose a profile: Narrareach uses the one they chose most recently (and says so in substackPublicationSelection.message), or, with no previous choice, nothing is scheduled and the result has requiresPublicationChoice: true, choiceScope: \"profile\" and publicationChoices (one per profile); ask the user, then call again with substackConnectionId set to the chosen publicationChoices[].substackConnectionId. An ambiguous publication value also returns publicationChoices.",
      +            "type": "string"
      +          },
      +          "scheduledFor": {
      +            "description": "Local wall-clock publishing date/time interpreted in timezone, including DST (e.g. \"2026-07-01T14:30:00\" means 2:30 PM). A Z or explicit UTC offset represents an absolute instant instead.",
      +            "type": "string"
      +          },
      +          "socialAccountIds": {
      +            "additionalProperties": {
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "description": "Optional account to post to on Threads, Facebook, TikTok, Pinterest or X, keyed by platform, e.g. { \"THREADS\": \"<accountId>\" }, with accountId values from list_social_accounts. Omit a platform to use its only account or its default. Required for a platform where list_social_accounts reports accountChoiceRequired; ask the writer which account rather than picking one.",
      +            "type": "object"
      +          },
      +          "substackConnectionId": {
      +            "deprecated": true,
      +            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      +            "type": "string"
      +          },
      +          "threadsTopicTag": {
      +            "description": "Optional Threads topic tag. Threads must be selected; maximum 50 characters.",
      +            "type": "string"
      +          },
      +          "timezone": {
      +            "description": "IANA timezone the scheduledFor time above is expressed in (e.g. \"Europe/London\"). Defaults to the writer's saved timezone, else UTC.",
      +            "type": "string"
      +          },
      +          "videoUrls": {
      +            "description": "Optional video URLs or video data URIs to attach to the scheduled note.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "workspace": {
      +            "description": "Authorized team workspace name or id for team scheduling. Absence selects the authenticated user’s personal account.",
      +            "type": "string"
      +          },
      +          "writer": {
      +            "description": "Authorized team writer name, handle, or id. \"me\" selects the linked team voice. Required when a team workspace has multiple writers.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "scheduledFor",
      +          "platforms",
      +          "timezone",
      +          "content",
      +          "clientRequestId"
      +        ],
      +        "type": "object"
      +      },
      +      "tool": {
      +        "const": "schedule_note",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "tool",
      +      "arguments"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "arguments": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "addSearchMetadata": {
      +            "description": "Generate SEO titles, descriptions, and a Substack slug for supported article destinations. SEO metadata is generated automatically on Revenue Writer, Full Agentic Mode, and Teams & Agencies, and for trials or other accounts with article SEO access. Set this option to false to turn it off. X does not support separate article SEO settings.",
      +            "type": "boolean"
      +          },
      +          "contentHtml": {
      +            "description": "Required when creating a new draft. Supports public <img> or <video> elements and {{media:N}} placeholders resolved from media entries. Video articles require Substack as the sole platform. Native Substack paywall markup is <hr data-type=\"paywall\"> at the selected paragraph boundary, or a single {{NARRAREACH_PAYWALL}} token; paywallMarker supports custom tokens. A Substack Freewall (free and paid subscribers keep reading) is <hr data-type=\"paywall\" data-access=\"subscribers\">, or set freewall to true. Native subscribe block markup is <div data-type=\"button\" data-kind=\"subscribeCaption\" data-text=\"Subscribe\" data-caption=\"Your caption\"></div> with HTML-escaped attribute values. data-kind=\"subscribe\" represents a button without caption. Ordinary links remain links. Audience sections use a div with data-dynamic-content=\"true\" and data-dynamic-audiences=\"paid_sub\", containing data-dynamic-content-match=\"true\" and data-dynamic-content-else=\"true\" divs. Supported audience conditions: non_sub, free_sub, paid_sub, founding_sub (comma-separated). Keep both branches. Subscriber-tag targeting must be published in Substack.",
      +            "type": "string"
      +          },
      +          "coverImage": {
      +            "description": "Optional cover image for a newly created draft, placed at the top of the published body. Supports public HTTPS URLs, data URIs, or base64 image bytes. URL ingestion depends on source-host access. For an image attached in ChatGPT, use coverFile instead. For a saved draft (draftId), attach the cover first with update_draft.",
      +            "properties": {
      +              "data": {
      +                "description": "Data URI or raw base64 image bytes.",
      +                "type": "string"
      +              },
      +              "mimeType": {
      +                "description": "Required for raw base64. Example: image/png.",
      +                "type": "string"
      +              },
      +              "sourceType": {
      +                "enum": [
      +                  "url",
      +                  "data_uri",
      +                  "base64"
      +                ],
      +                "type": "string"
      +              },
      +              "url": {
      +                "description": "Public HTTPS image URL.",
      +                "type": "string"
      +              }
      +            },
      +            "type": "object"
      +          },
      +          "freewall": {
      +            "description": "Make the article's single wall divider (or paywallMarker) a Substack Freewall: everyone sees the content above it; free and paid subscribers keep reading below it. Requires SUBSTACK and a publication with Substack Freewalls. For a new draft (title and contentHtml) it sets the Freewall. A saved draft (draftId) keeps the wall already in its body: a Freewall there is scheduled as a Freewall with or without this field, and true only confirms it. Never combine with isPaidContent. Default false.",
      +            "type": "boolean"
      +          },
      +          "isPaidContent": {
      +            "description": "Whether the Substack article is paid-only. Default false. Do not combine with freewall.",
      +            "type": "boolean"
      +          },
      +          "linkedinAuthorUrn": {
      +            "description": "LinkedIn personal profile or Company Page author URN belonging to the connected LinkedIn Articles account.",
      +            "type": "string"
      +          },
      +          "linkedinNewsletterUrn": {
      +            "description": "LinkedIn newsletter URN belonging to the connected LinkedIn Articles account. Required when linkedinPublicationType is newsletter.",
      +            "type": "string"
      +          },
      +          "linkedinPublicationType": {
      +            "description": "LinkedIn destination type. Defaults to an individual article; newsletter represents a user-selected newsletter destination.",
      +            "enum": [
      +              "article",
      +              "newsletter"
      +            ],
      +            "type": "string"
      +          },
      +          "linkedinShareCommentary": {
      +            "description": "Optional LinkedIn share text used when publishing a LinkedIn article.",
      +            "type": "string"
      +          },
      +          "media": {
      +            "description": "Optional inline images or Substack article videos for a newly created draft. Replaces {{media:N}} placeholders in array order; leftovers are appended. kind defaults to image; video requires Substack as the sole platform. Supports public URLs, data URIs, and base64 bytes. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      +            "items": {
      +              "properties": {
      +                "data": {
      +                  "type": "string"
      +                },
      +                "fileName": {
      +                  "type": "string"
      +                },
      +                "kind": {
      +                  "description": "Defaults to image when omitted.",
      +                  "enum": [
      +                    "image",
      +                    "video"
      +                  ],
      +                  "type": "string"
      +                },
      +                "mimeType": {
      +                  "type": "string"
      +                },
      +                "sourceType": {
      +                  "enum": [
      +                    "url",
      +                    "data_uri",
      +                    "base64"
      +                  ],
      +                  "type": "string"
      +                },
      +                "url": {
      +                  "type": "string"
      +                }
      +              },
      +              "type": "object"
      +            },
      +            "type": "array"
      +          },
      +          "mediumNotifyFollowers": {
      +            "description": "Whether to email Medium subscribers about this story. Only valid when platforms includes MEDIUM. Defaults to false (no email). Best-effort: a failure to apply this setting never blocks the publish/schedule and is reported as a warning.",
      +            "type": "boolean"
      +          },
      +          "mediumPublicationId": {
      +            "description": "Optional authorized Medium publication id when platforms includes MEDIUM. Absent means the personal profile. Writer-only access submits for editorial review and leaves the story unscheduled until acceptance. Explicit publication rejection allows personal-profile delivery with a warning; ambiguous submissions remain unpublished for review. Draft-only delivery does not submit to a publication.",
      +            "type": "string"
      +          },
      +          "paywallMarker": {
      +            "description": "Optional custom marker in contentHtml where the selected free preview ends; must appear exactly once. The standard {{NARRAREACH_PAYWALL}} marker is recognized without this field. Creates a native divider without changing sendToNewsletter. With freewall true it allows free and paid subscribers; otherwise it enables paid access.",
      +            "maxLength": 200,
      +            "type": "string"
      +          },
      +          "platforms": {
      +            "items": {
      +              "enum": [
      +                "SUBSTACK",
      +                "MEDIUM",
      +                "LINKEDIN",
      +                "X",
      +                "WORDPRESS",
      +                "GHOST"
      +              ],
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "publication": {
      +            "description": "Substack destination as a publication name, handle, or URL, for example \"AI Newsroom\", \"@theainewsroom\", or \"https://theainewsroom.substack.com\". Optional when exactly one active Substack publication is connected; Narrareach selects it automatically. Required when more than one active Substack publication is connected, except that when it is missing Narrareach uses the publication the writer scheduled or published to most recently and says so in substackPublicationSelection.message, with publicationChoices listing the others; tell the writer which one was used. If there is no previous choice, the value is ambiguous, or Narrareach cannot confirm the session publishes there, nothing is scheduled and the result has requiresPublicationChoice: true with publicationChoices (name, handle, url, substackConnectionId). Ask which one they want, then call again with publication set to the chosen handle (and draftId when a draft was already saved).",
      +            "type": "string"
      +          },
      +          "publishMode": {
      +            "description": "Only valid when all selected destinations are WordPress or Ghost. Defaults to publish; draft saves a remote draft at the scheduled time without publication.",
      +            "enum": [
      +              "publish",
      +              "draft"
      +            ],
      +            "type": "string"
      +          },
      +          "scheduledFor": {
      +            "description": "Required unless platformSchedules is given, and must be in the future. Shared local wall-clock publishing date/time interpreted in timezone, including DST. A Z or explicit UTC offset represents an absolute instant. LinkedIn articles require at least 20 minutes of lead time.",
      +            "type": "string"
      +          },
      +          "sendToNewsletter": {
      +            "description": "Substack email delivery setting. Default true.",
      +            "type": "boolean"
      +          },
      +          "substackConnectionId": {
      +            "deprecated": true,
      +            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      +            "type": "string"
      +          },
      +          "subtitle": {
      +            "description": "Optional article subtitle for newly created drafts. Substack omits subtitles over 250 characters and returns a warning without changing the saved draft.",
      +            "type": "string"
      +          },
      +          "tags": {
      +            "description": "Optional tag list for newly created drafts. Substack receives all supplied tags. Medium receives its supported first 5 topics and returns a warning when extras are omitted. The saved draft remains unchanged.",
      +            "items": {
      +              "maxLength": 50,
      +              "type": "string"
      +            },
      +            "maxItems": 50,
      +            "type": "array"
      +          },
      +          "timezone": {
      +            "description": "IANA timezone the scheduledFor time(s) above are expressed in (e.g. \"Europe/London\"). Defaults to the writer's saved timezone, else UTC.",
      +            "type": "string"
      +          },
      +          "title": {
      +            "description": "Required when creating a new draft.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "platforms",
      +          "scheduledFor",
      +          "timezone",
      +          "title",
      +          "contentHtml",
      +          "addSearchMetadata"
      +        ],
      +        "type": "object"
      +      },
      +      "tool": {
      +        "const": "schedule_article",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "tool",
      +      "arguments"
      +    ],
      +    "type": "object"
      +  }
      +]
  4. Changed1 schema field changed
    • changedInput schema / properties / calls / items / oneOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "arguments": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "clientRequestId": {
      -            "description": "Optional but recommended: your own id for this note, 8 to 80 letters, numbers, hyphens or underscores. Use a new one for each note and the same one when retrying it (for example after a timeout or a rate-limit pause): the retry returns the original result and schedules nothing again. Reusing it with different text, platforms or time is refused.",
      -            "pattern": "^[A-Za-z0-9_-]{8,80}$",
      -            "type": "string"
      -          },
      -          "content": {
      -            "description": "Used only when creating a new note draft.",
      -            "type": "string"
      -          },
      -          "firstReply": {
      -            "description": "Optional first reply for supported destinations. An invalid reply is omitted per platform without cancelling the root post.",
      -            "type": "string"
      -          },
      -          "imageUrls": {
      -            "description": "Optional image URLs or image data URIs to attach to the scheduled note.",
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "instagramDestinations": {
      -            "description": "Instagram destinations with accountId returned by list_instagram_destinations and optional independent caption. Each account receives its own delivery receipt.",
      -            "items": {
      -              "additionalProperties": false,
      -              "properties": {
      -                "accountId": {
      -                  "type": "string"
      -                },
      -                "caption": {
      -                  "maxLength": 2200,
      -                  "type": "string"
      -                },
      -                "label": {
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "accountId"
      -              ],
      -              "type": "object"
      -            },
      -            "maxItems": 5,
      -            "minItems": 1,
      -            "type": "array"
      -          },
      -          "linkedInAccountId": {
      -            "description": "Optional LinkedIn account id for a connected LinkedIn destination. Absence of both this field and linkedInOrganizationUrn selects the configured default.",
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "linkedInOrganizationUrn": {
      -            "description": "Optional LinkedIn Company Page URN for a connected LinkedIn destination. Requires linkedInAccountId.",
      -            "minLength": 1,
      -            "pattern": "^urn:li:organization:[^\\s]+$",
      -            "type": "string"
      -          },
      -          "platformVersions": {
      -            "additionalProperties": {
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "description": "Optional platform-specific text keyed by platform, e.g. { \"BLUESKY\": \"...\" }. Each supplied version must fit its limit (Bluesky 300, Threads 500, LinkedIn 3000, X 25000) or nothing is scheduled. Saved as the draft’s platform-specific version.",
      -            "type": "object"
      -          },
      -          "platforms": {
      -            "items": {
      -              "enum": [
      -                "SUBSTACK",
      -                "LINKEDIN",
      -                "X",
      -                "BLUESKY",
      -                "THREADS",
      -                "INSTAGRAM",
      -                "FACEBOOK",
      -                "TIKTOK",
      -                "PINTEREST"
      -              ],
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "publication": {
      -            "description": "Substack publication name, handle, or URL selected by the user. Optional when exactly one active Substack publication is connected: Narrareach uses it when its session is ready and says which one was used in substackPublicationSelection.message (source \"sole_connection\"); if the session needs a sync or the profile cannot be verified, nothing is scheduled and the result says what to fix. In a team workspace with one publication, or when a writer who is also a team member omits workspace, nothing is scheduled until the writer confirms it (requiresPublicationChoice: true, publicationChoiceReason: \"confirmation_required\"). Notes publish from the profile signed in to that connection, including publications sharing one login. Unverified or mismatched profile identity returns action_required without publishing. Notes are profile-level: when it is missing and all of the writer’s publications are signed in to one Substack profile, no choice is needed and the note posts from that profile. Only when the publications span two or more Substack profiles does the writer choose a profile: Narrareach uses the one they chose most recently (and says so in substackPublicationSelection.message), or, with no previous choice, nothing is scheduled and the result has requiresPublicationChoice: true, choiceScope: \"profile\" and publicationChoices (one per profile); ask the user, then call again with substackConnectionId set to the chosen publicationChoices[].substackConnectionId. An ambiguous publication value also returns publicationChoices.",
      -            "type": "string"
      -          },
      -          "scheduledFor": {
      -            "description": "Local wall-clock publishing date/time interpreted in timezone, including DST (e.g. \"2026-07-01T14:30:00\" means 2:30 PM). A Z or explicit UTC offset represents an absolute instant instead.",
      -            "type": "string"
      -          },
      -          "socialAccountIds": {
      -            "additionalProperties": {
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "description": "Optional account to post to on Threads, Facebook, TikTok, Pinterest or X, keyed by platform, e.g. { \"THREADS\": \"<accountId>\" }, with accountId values from list_social_accounts. Omit a platform to use its only account or its default. Required for a platform where list_social_accounts reports accountChoiceRequired; ask the writer which account rather than picking one.",
      -            "type": "object"
      -          },
      -          "substackConnectionId": {
      -            "deprecated": true,
      -            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      -            "type": "string"
      -          },
      -          "threadsTopicTag": {
      -            "description": "Optional Threads topic tag. Threads must be selected; maximum 50 characters.",
      -            "type": "string"
      -          },
      -          "timezone": {
      -            "description": "IANA timezone the scheduledFor time above is expressed in (e.g. \"Europe/London\"). Default UTC.",
      -            "type": "string"
      -          },
      -          "videoUrls": {
      -            "description": "Optional video URLs or video data URIs to attach to the scheduled note.",
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "workspace": {
      -            "description": "Authorized team workspace name or id for team scheduling. Absence selects the authenticated user’s personal account.",
      -            "type": "string"
      -          },
      -          "writer": {
      -            "description": "Authorized team writer name, handle, or id. \"me\" selects the linked team voice. Required when a team workspace has multiple writers.",
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "scheduledFor",
      -          "platforms",
      -          "timezone",
      -          "content",
      -          "clientRequestId"
      -        ],
      -        "type": "object"
      -      },
      -      "tool": {
      -        "const": "schedule_note",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "tool",
      -      "arguments"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "arguments": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "addSearchMetadata": {
      -            "description": "Generate SEO titles, descriptions, and a Substack slug for supported article destinations. SEO metadata is generated automatically on Revenue Writer, Full Agentic Mode, and Teams & Agencies, and for trials or other accounts with article SEO access. Set this option to false to turn it off. X does not support separate article SEO settings.",
      -            "type": "boolean"
      -          },
      -          "contentHtml": {
      -            "description": "Required when creating a new draft. Supports public <img> or <video> elements and {{media:N}} placeholders resolved from media entries. Video articles require Substack as the sole platform. Native Substack paywall markup is <hr data-type=\"paywall\"> at the selected paragraph boundary, or a single {{NARRAREACH_PAYWALL}} token; paywallMarker supports custom tokens. A Substack Freewall (free and paid subscribers keep reading) is <hr data-type=\"paywall\" data-access=\"subscribers\">, or set freewall to true. Native subscribe block markup is <div data-type=\"button\" data-kind=\"subscribeCaption\" data-text=\"Subscribe\" data-caption=\"Your caption\"></div> with HTML-escaped attribute values. data-kind=\"subscribe\" represents a button without caption. Ordinary links remain links. Audience sections use a div with data-dynamic-content=\"true\" and data-dynamic-audiences=\"paid_sub\", containing data-dynamic-content-match=\"true\" and data-dynamic-content-else=\"true\" divs. Supported audience conditions: non_sub, free_sub, paid_sub, founding_sub (comma-separated). Keep both branches. Subscriber-tag targeting must be published in Substack.",
      -            "type": "string"
      -          },
      -          "coverImage": {
      -            "description": "Optional cover image for a newly created draft, placed at the top of the published body. Supports public HTTPS URLs, data URIs, or base64 image bytes. URL ingestion depends on source-host access. For an image attached in ChatGPT, use coverFile instead. For a saved draft (draftId), attach the cover first with update_draft.",
      -            "properties": {
      -              "data": {
      -                "description": "Data URI or raw base64 image bytes.",
      -                "type": "string"
      -              },
      -              "mimeType": {
      -                "description": "Required for raw base64. Example: image/png.",
      -                "type": "string"
      -              },
      -              "sourceType": {
      -                "enum": [
      -                  "url",
      -                  "data_uri",
      -                  "base64"
      -                ],
      -                "type": "string"
      -              },
      -              "url": {
      -                "description": "Public HTTPS image URL.",
      -                "type": "string"
      -              }
      -            },
      -            "type": "object"
      -          },
      -          "freewall": {
      -            "description": "Make the article's single wall divider (or paywallMarker) a Substack Freewall: everyone sees the content above it; free and paid subscribers keep reading below it. Requires SUBSTACK and a new draft (title and contentHtml). The publication must have Substack Freewalls available. Default false.",
      -            "type": "boolean"
      -          },
      -          "isPaidContent": {
      -            "description": "Whether the Substack article is paid-only. Default false. Do not combine with freewall.",
      -            "type": "boolean"
      -          },
      -          "linkedinAuthorUrn": {
      -            "description": "LinkedIn personal profile or Company Page author URN belonging to the connected LinkedIn Articles account.",
      -            "type": "string"
      -          },
      -          "linkedinNewsletterUrn": {
      -            "description": "LinkedIn newsletter URN belonging to the connected LinkedIn Articles account. Required when linkedinPublicationType is newsletter.",
      -            "type": "string"
      -          },
      -          "linkedinPublicationType": {
      -            "description": "LinkedIn destination type. Defaults to an individual article; newsletter represents a user-selected newsletter destination.",
      -            "enum": [
      -              "article",
      -              "newsletter"
      -            ],
      -            "type": "string"
      -          },
      -          "linkedinShareCommentary": {
      -            "description": "Optional LinkedIn share text used when publishing a LinkedIn article.",
      -            "type": "string"
      -          },
      -          "media": {
      -            "description": "Optional inline images or Substack article videos for a newly created draft. Replaces {{media:N}} placeholders in array order; leftovers are appended. kind defaults to image; video requires Substack as the sole platform. Supports public URLs, data URIs, and base64 bytes. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      -            "items": {
      -              "properties": {
      -                "data": {
      -                  "type": "string"
      -                },
      -                "fileName": {
      -                  "type": "string"
      -                },
      -                "kind": {
      -                  "description": "Defaults to image when omitted.",
      -                  "enum": [
      -                    "image",
      -                    "video"
      -                  ],
      -                  "type": "string"
      -                },
      -                "mimeType": {
      -                  "type": "string"
      -                },
      -                "sourceType": {
      -                  "enum": [
      -                    "url",
      -                    "data_uri",
      -                    "base64"
      -                  ],
      -                  "type": "string"
      -                },
      -                "url": {
      -                  "type": "string"
      -                }
      -              },
      -              "type": "object"
      -            },
      -            "type": "array"
      -          },
      -          "mediumNotifyFollowers": {
      -            "description": "Whether to email Medium subscribers about this story. Only valid when platforms includes MEDIUM. Defaults to false (no email). Best-effort: a failure to apply this setting never blocks the publish/schedule and is reported as a warning.",
      -            "type": "boolean"
      -          },
      -          "mediumPublicationId": {
      -            "description": "Optional authorized Medium publication id when platforms includes MEDIUM. Absent means the personal profile. Writer-only access submits for editorial review and leaves the story unscheduled until acceptance. Explicit publication rejection allows personal-profile delivery with a warning; ambiguous submissions remain unpublished for review. Draft-only delivery does not submit to a publication.",
      -            "type": "string"
      -          },
      -          "paywallMarker": {
      -            "description": "Optional custom marker in contentHtml where the selected free preview ends; must appear exactly once. The standard {{NARRAREACH_PAYWALL}} marker is recognized without this field. Creates a native divider without changing sendToNewsletter. With freewall true it allows free and paid subscribers; otherwise it enables paid access.",
      -            "maxLength": 200,
      -            "type": "string"
      -          },
      -          "platforms": {
      -            "items": {
      -              "enum": [
      -                "SUBSTACK",
      -                "MEDIUM",
      -                "LINKEDIN",
      -                "X",
      -                "WORDPRESS",
      -                "GHOST"
      -              ],
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "publication": {
      -            "description": "Substack destination as a publication name, handle, or URL, for example \"AI Newsroom\", \"@theainewsroom\", or \"https://theainewsroom.substack.com\". Optional when exactly one active Substack publication is connected; Narrareach selects it automatically. Required when more than one active Substack publication is connected, except that when it is missing Narrareach uses the publication the writer scheduled or published to most recently and says so in substackPublicationSelection.message, with publicationChoices listing the others; tell the writer which one was used. If there is no previous choice, the value is ambiguous, or Narrareach cannot confirm the session publishes there, nothing is scheduled and the result has requiresPublicationChoice: true with publicationChoices (name, handle, url, substackConnectionId). Ask which one they want, then call again with publication set to the chosen handle (and draftId when a draft was already saved).",
      -            "type": "string"
      -          },
      -          "publishMode": {
      -            "description": "Only valid when all selected destinations are WordPress or Ghost. Defaults to publish; draft saves a remote draft at the scheduled time without publication.",
      -            "enum": [
      -              "publish",
      -              "draft"
      -            ],
      -            "type": "string"
      -          },
      -          "scheduledFor": {
      -            "description": "Shared local wall-clock publishing date/time interpreted in timezone, including DST. A Z or explicit UTC offset represents an absolute instant. LinkedIn articles require at least 20 minutes of lead time.",
      -            "type": "string"
      -          },
      -          "sendToNewsletter": {
      -            "description": "Substack email delivery setting. Default true.",
      -            "type": "boolean"
      -          },
      -          "substackConnectionId": {
      -            "deprecated": true,
      -            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      -            "type": "string"
      -          },
      -          "subtitle": {
      -            "description": "Optional article subtitle for newly created drafts. Substack omits subtitles over 250 characters and returns a warning without changing the saved draft.",
      -            "type": "string"
      -          },
      -          "tags": {
      -            "description": "Optional tag list for newly created drafts. Substack receives all supplied tags. Medium receives its supported first 5 topics and returns a warning when extras are omitted. The saved draft remains unchanged.",
      -            "items": {
      -              "maxLength": 50,
      -              "type": "string"
      -            },
      -            "maxItems": 50,
      -            "type": "array"
      -          },
      -          "timezone": {
      -            "description": "IANA timezone the scheduledFor time(s) above are expressed in (e.g. \"Europe/London\"). Default UTC.",
      -            "type": "string"
      -          },
      -          "title": {
      -            "description": "Required when creating a new draft.",
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "platforms",
      -          "scheduledFor",
      -          "timezone",
      -          "title",
      -          "contentHtml",
      -          "addSearchMetadata"
      -        ],
      -        "type": "object"
      -      },
      -      "tool": {
      -        "const": "schedule_article",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "tool",
      -      "arguments"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "arguments": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "clientRequestId": {
      +            "description": "Optional but recommended: your own id for this note, 8 to 80 letters, numbers, hyphens or underscores. Use a new one for each note and the same one when retrying it (for example after a timeout or a rate-limit pause): the retry returns the original result and schedules nothing again. Reusing it with different text, platforms or time is refused.",
      +            "pattern": "^[A-Za-z0-9_-]{8,80}$",
      +            "type": "string"
      +          },
      +          "content": {
      +            "description": "Used only when creating a new note draft.",
      +            "type": "string"
      +          },
      +          "firstReply": {
      +            "description": "Optional first reply for supported destinations. An invalid reply is omitted per platform without cancelling the root post.",
      +            "type": "string"
      +          },
      +          "imageUrls": {
      +            "description": "Optional image URLs or image data URIs to attach to the scheduled note.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "instagramDestinations": {
      +            "description": "Instagram destinations with accountId returned by list_instagram_destinations and optional independent caption. Each account receives its own delivery receipt.",
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "accountId": {
      +                  "type": "string"
      +                },
      +                "caption": {
      +                  "maxLength": 2200,
      +                  "type": "string"
      +                },
      +                "label": {
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "accountId"
      +              ],
      +              "type": "object"
      +            },
      +            "maxItems": 5,
      +            "minItems": 1,
      +            "type": "array"
      +          },
      +          "linkedInAccountId": {
      +            "description": "Optional LinkedIn account id for a connected LinkedIn destination. Absence of both this field and linkedInOrganizationUrn selects the configured default.",
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "linkedInOrganizationUrn": {
      +            "description": "Optional LinkedIn Company Page URN for a connected LinkedIn destination. Requires linkedInAccountId.",
      +            "minLength": 1,
      +            "pattern": "^urn:li:organization:[^\\s]+$",
      +            "type": "string"
      +          },
      +          "platformVersions": {
      +            "additionalProperties": {
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "description": "Optional platform-specific text keyed by platform, e.g. { \"BLUESKY\": \"...\" }. Each supplied version must fit its limit (Bluesky 300, Threads 500, LinkedIn 3000, X 25000) or nothing is scheduled. Saved as the draft’s platform-specific version.",
      +            "type": "object"
      +          },
      +          "platforms": {
      +            "items": {
      +              "enum": [
      +                "SUBSTACK",
      +                "LINKEDIN",
      +                "X",
      +                "BLUESKY",
      +                "THREADS",
      +                "INSTAGRAM",
      +                "FACEBOOK",
      +                "TIKTOK",
      +                "PINTEREST"
      +              ],
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "publication": {
      +            "description": "Substack publication name, handle, or URL selected by the user. Optional when exactly one active Substack publication is connected: Narrareach uses it when its session is ready and says which one was used in substackPublicationSelection.message (source \"sole_connection\"); if the session needs a sync or the profile cannot be verified, nothing is scheduled and the result says what to fix. In a team workspace with one publication, or when a writer who is also a team member omits workspace, nothing is scheduled until the writer confirms it (requiresPublicationChoice: true, publicationChoiceReason: \"confirmation_required\"). Notes publish from the profile signed in to that connection, including publications sharing one login. Unverified or mismatched profile identity returns action_required without publishing. Notes are profile-level: when it is missing and all of the writer’s publications are signed in to one Substack profile, no choice is needed and the note posts from that profile. Only when the publications span two or more Substack profiles does the writer choose a profile: Narrareach uses the one they chose most recently (and says so in substackPublicationSelection.message), or, with no previous choice, nothing is scheduled and the result has requiresPublicationChoice: true, choiceScope: \"profile\" and publicationChoices (one per profile); ask the user, then call again with substackConnectionId set to the chosen publicationChoices[].substackConnectionId. An ambiguous publication value also returns publicationChoices.",
      +            "type": "string"
      +          },
      +          "scheduledFor": {
      +            "description": "Local wall-clock publishing date/time interpreted in timezone, including DST (e.g. \"2026-07-01T14:30:00\" means 2:30 PM). A Z or explicit UTC offset represents an absolute instant instead.",
      +            "type": "string"
      +          },
      +          "socialAccountIds": {
      +            "additionalProperties": {
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "description": "Optional account to post to on Threads, Facebook, TikTok, Pinterest or X, keyed by platform, e.g. { \"THREADS\": \"<accountId>\" }, with accountId values from list_social_accounts. Omit a platform to use its only account or its default. Required for a platform where list_social_accounts reports accountChoiceRequired; ask the writer which account rather than picking one.",
      +            "type": "object"
      +          },
      +          "substackConnectionId": {
      +            "deprecated": true,
      +            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      +            "type": "string"
      +          },
      +          "threadsTopicTag": {
      +            "description": "Optional Threads topic tag. Threads must be selected; maximum 50 characters.",
      +            "type": "string"
      +          },
      +          "timezone": {
      +            "description": "IANA timezone the scheduledFor time above is expressed in (e.g. \"Europe/London\"). Default UTC.",
      +            "type": "string"
      +          },
      +          "videoUrls": {
      +            "description": "Optional video URLs or video data URIs to attach to the scheduled note.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "workspace": {
      +            "description": "Authorized team workspace name or id for team scheduling. Absence selects the authenticated user’s personal account.",
      +            "type": "string"
      +          },
      +          "writer": {
      +            "description": "Authorized team writer name, handle, or id. \"me\" selects the linked team voice. Required when a team workspace has multiple writers.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "scheduledFor",
      +          "platforms",
      +          "timezone",
      +          "content",
      +          "clientRequestId"
      +        ],
      +        "type": "object"
      +      },
      +      "tool": {
      +        "const": "schedule_note",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "tool",
      +      "arguments"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "arguments": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "addSearchMetadata": {
      +            "description": "Generate SEO titles, descriptions, and a Substack slug for supported article destinations. SEO metadata is generated automatically on Revenue Writer, Full Agentic Mode, and Teams & Agencies, and for trials or other accounts with article SEO access. Set this option to false to turn it off. X does not support separate article SEO settings.",
      +            "type": "boolean"
      +          },
      +          "contentHtml": {
      +            "description": "Required when creating a new draft. Supports public <img> or <video> elements and {{media:N}} placeholders resolved from media entries. Video articles require Substack as the sole platform. Native Substack paywall markup is <hr data-type=\"paywall\"> at the selected paragraph boundary, or a single {{NARRAREACH_PAYWALL}} token; paywallMarker supports custom tokens. A Substack Freewall (free and paid subscribers keep reading) is <hr data-type=\"paywall\" data-access=\"subscribers\">, or set freewall to true. Native subscribe block markup is <div data-type=\"button\" data-kind=\"subscribeCaption\" data-text=\"Subscribe\" data-caption=\"Your caption\"></div> with HTML-escaped attribute values. data-kind=\"subscribe\" represents a button without caption. Ordinary links remain links. Audience sections use a div with data-dynamic-content=\"true\" and data-dynamic-audiences=\"paid_sub\", containing data-dynamic-content-match=\"true\" and data-dynamic-content-else=\"true\" divs. Supported audience conditions: non_sub, free_sub, paid_sub, founding_sub (comma-separated). Keep both branches. Subscriber-tag targeting must be published in Substack.",
      +            "type": "string"
      +          },
      +          "coverImage": {
      +            "description": "Optional cover image for a newly created draft, placed at the top of the published body. Supports public HTTPS URLs, data URIs, or base64 image bytes. URL ingestion depends on source-host access. For an image attached in ChatGPT, use coverFile instead. For a saved draft (draftId), attach the cover first with update_draft.",
      +            "properties": {
      +              "data": {
      +                "description": "Data URI or raw base64 image bytes.",
      +                "type": "string"
      +              },
      +              "mimeType": {
      +                "description": "Required for raw base64. Example: image/png.",
      +                "type": "string"
      +              },
      +              "sourceType": {
      +                "enum": [
      +                  "url",
      +                  "data_uri",
      +                  "base64"
      +                ],
      +                "type": "string"
      +              },
      +              "url": {
      +                "description": "Public HTTPS image URL.",
      +                "type": "string"
      +              }
      +            },
      +            "type": "object"
      +          },
      +          "freewall": {
      +            "description": "Make the article's single wall divider (or paywallMarker) a Substack Freewall: everyone sees the content above it; free and paid subscribers keep reading below it. Requires SUBSTACK and a new draft (title and contentHtml). The publication must have Substack Freewalls available. Default false.",
      +            "type": "boolean"
      +          },
      +          "isPaidContent": {
      +            "description": "Whether the Substack article is paid-only. Default false. Do not combine with freewall.",
      +            "type": "boolean"
      +          },
      +          "linkedinAuthorUrn": {
      +            "description": "LinkedIn personal profile or Company Page author URN belonging to the connected LinkedIn Articles account.",
      +            "type": "string"
      +          },
      +          "linkedinNewsletterUrn": {
      +            "description": "LinkedIn newsletter URN belonging to the connected LinkedIn Articles account. Required when linkedinPublicationType is newsletter.",
      +            "type": "string"
      +          },
      +          "linkedinPublicationType": {
      +            "description": "LinkedIn destination type. Defaults to an individual article; newsletter represents a user-selected newsletter destination.",
      +            "enum": [
      +              "article",
      +              "newsletter"
      +            ],
      +            "type": "string"
      +          },
      +          "linkedinShareCommentary": {
      +            "description": "Optional LinkedIn share text used when publishing a LinkedIn article.",
      +            "type": "string"
      +          },
      +          "media": {
      +            "description": "Optional inline images or Substack article videos for a newly created draft. Replaces {{media:N}} placeholders in array order; leftovers are appended. kind defaults to image; video requires Substack as the sole platform. Supports public URLs, data URIs, and base64 bytes. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      +            "items": {
      +              "properties": {
      +                "data": {
      +                  "type": "string"
      +                },
      +                "fileName": {
      +                  "type": "string"
      +                },
      +                "kind": {
      +                  "description": "Defaults to image when omitted.",
      +                  "enum": [
      +                    "image",
      +                    "video"
      +                  ],
      +                  "type": "string"
      +                },
      +                "mimeType": {
      +                  "type": "string"
      +                },
      +                "sourceType": {
      +                  "enum": [
      +                    "url",
      +                    "data_uri",
      +                    "base64"
      +                  ],
      +                  "type": "string"
      +                },
      +                "url": {
      +                  "type": "string"
      +                }
      +              },
      +              "type": "object"
      +            },
      +            "type": "array"
      +          },
      +          "mediumNotifyFollowers": {
      +            "description": "Whether to email Medium subscribers about this story. Only valid when platforms includes MEDIUM. Defaults to false (no email). Best-effort: a failure to apply this setting never blocks the publish/schedule and is reported as a warning.",
      +            "type": "boolean"
      +          },
      +          "mediumPublicationId": {
      +            "description": "Optional authorized Medium publication id when platforms includes MEDIUM. Absent means the personal profile. Writer-only access submits for editorial review and leaves the story unscheduled until acceptance. Explicit publication rejection allows personal-profile delivery with a warning; ambiguous submissions remain unpublished for review. Draft-only delivery does not submit to a publication.",
      +            "type": "string"
      +          },
      +          "paywallMarker": {
      +            "description": "Optional custom marker in contentHtml where the selected free preview ends; must appear exactly once. The standard {{NARRAREACH_PAYWALL}} marker is recognized without this field. Creates a native divider without changing sendToNewsletter. With freewall true it allows free and paid subscribers; otherwise it enables paid access.",
      +            "maxLength": 200,
      +            "type": "string"
      +          },
      +          "platforms": {
      +            "items": {
      +              "enum": [
      +                "SUBSTACK",
      +                "MEDIUM",
      +                "LINKEDIN",
      +                "X",
      +                "WORDPRESS",
      +                "GHOST"
      +              ],
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "publication": {
      +            "description": "Substack destination as a publication name, handle, or URL, for example \"AI Newsroom\", \"@theainewsroom\", or \"https://theainewsroom.substack.com\". Optional when exactly one active Substack publication is connected; Narrareach selects it automatically. Required when more than one active Substack publication is connected, except that when it is missing Narrareach uses the publication the writer scheduled or published to most recently and says so in substackPublicationSelection.message, with publicationChoices listing the others; tell the writer which one was used. If there is no previous choice, the value is ambiguous, or Narrareach cannot confirm the session publishes there, nothing is scheduled and the result has requiresPublicationChoice: true with publicationChoices (name, handle, url, substackConnectionId). Ask which one they want, then call again with publication set to the chosen handle (and draftId when a draft was already saved).",
      +            "type": "string"
      +          },
      +          "publishMode": {
      +            "description": "Only valid when all selected destinations are WordPress or Ghost. Defaults to publish; draft saves a remote draft at the scheduled time without publication.",
      +            "enum": [
      +              "publish",
      +              "draft"
      +            ],
      +            "type": "string"
      +          },
      +          "scheduledFor": {
      +            "description": "Required unless platformSchedules is given, and must be in the future. Shared local wall-clock publishing date/time interpreted in timezone, including DST. A Z or explicit UTC offset represents an absolute instant. LinkedIn articles require at least 20 minutes of lead time.",
      +            "type": "string"
      +          },
      +          "sendToNewsletter": {
      +            "description": "Substack email delivery setting. Default true.",
      +            "type": "boolean"
      +          },
      +          "substackConnectionId": {
      +            "deprecated": true,
      +            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      +            "type": "string"
      +          },
      +          "subtitle": {
      +            "description": "Optional article subtitle for newly created drafts. Substack omits subtitles over 250 characters and returns a warning without changing the saved draft.",
      +            "type": "string"
      +          },
      +          "tags": {
      +            "description": "Optional tag list for newly created drafts. Substack receives all supplied tags. Medium receives its supported first 5 topics and returns a warning when extras are omitted. The saved draft remains unchanged.",
      +            "items": {
      +              "maxLength": 50,
      +              "type": "string"
      +            },
      +            "maxItems": 50,
      +            "type": "array"
      +          },
      +          "timezone": {
      +            "description": "IANA timezone the scheduledFor time(s) above are expressed in (e.g. \"Europe/London\"). Default UTC.",
      +            "type": "string"
      +          },
      +          "title": {
      +            "description": "Required when creating a new draft.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "platforms",
      +          "scheduledFor",
      +          "timezone",
      +          "title",
      +          "contentHtml",
      +          "addSearchMetadata"
      +        ],
      +        "type": "object"
      +      },
      +      "tool": {
      +        "const": "schedule_article",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "tool",
      +      "arguments"
      +    ],
      +    "type": "object"
      +  }
      +]
  5. Changed1 schema field changed
    • changedInput schema / properties / calls / items / oneOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "arguments": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "clientRequestId": {
      -            "description": "Optional but recommended: your own id for this note, 8 to 80 letters, numbers, hyphens or underscores. Use a new one for each note and the same one when retrying it (for example after a timeout or a rate-limit pause): the retry returns the original result and schedules nothing again. Reusing it with different text, platforms or time is refused.",
      -            "pattern": "^[A-Za-z0-9_-]{8,80}$",
      -            "type": "string"
      -          },
      -          "content": {
      -            "description": "Used only when creating a new note draft.",
      -            "type": "string"
      -          },
      -          "firstReply": {
      -            "description": "Optional first reply for supported destinations. An invalid reply is omitted per platform without cancelling the root post.",
      -            "type": "string"
      -          },
      -          "imageUrls": {
      -            "description": "Optional image URLs or image data URIs to attach to the scheduled note.",
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "instagramDestinations": {
      -            "description": "Instagram destinations with accountId returned by list_instagram_destinations and optional independent caption. Each account receives its own delivery receipt.",
      -            "items": {
      -              "additionalProperties": false,
      -              "properties": {
      -                "accountId": {
      -                  "type": "string"
      -                },
      -                "caption": {
      -                  "maxLength": 2200,
      -                  "type": "string"
      -                },
      -                "label": {
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "accountId"
      -              ],
      -              "type": "object"
      -            },
      -            "maxItems": 5,
      -            "minItems": 1,
      -            "type": "array"
      -          },
      -          "linkedInAccountId": {
      -            "description": "Optional LinkedIn account id for a connected LinkedIn destination. Absence of both this field and linkedInOrganizationUrn selects the configured default.",
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "linkedInOrganizationUrn": {
      -            "description": "Optional LinkedIn Company Page URN for a connected LinkedIn destination. Requires linkedInAccountId.",
      -            "minLength": 1,
      -            "pattern": "^urn:li:organization:[^\\s]+$",
      -            "type": "string"
      -          },
      -          "platformVersions": {
      -            "additionalProperties": {
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "description": "Optional platform-specific text keyed by platform, e.g. { \"BLUESKY\": \"...\" }. Each supplied version must fit its limit (Bluesky 300, Threads 500, LinkedIn 3000, X 25000) or nothing is scheduled. Saved as the draft’s platform-specific version.",
      -            "type": "object"
      -          },
      -          "platforms": {
      -            "items": {
      -              "enum": [
      -                "SUBSTACK",
      -                "LINKEDIN",
      -                "X",
      -                "BLUESKY",
      -                "THREADS",
      -                "INSTAGRAM",
      -                "FACEBOOK",
      -                "TIKTOK",
      -                "PINTEREST"
      -              ],
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "publication": {
      -            "description": "Substack publication name, handle, or URL selected by the user. Optional when exactly one active Substack publication is connected: Narrareach uses it when its session is ready and says which one was used in substackPublicationSelection.message (source \"sole_connection\"); if the session needs a sync or the profile cannot be verified, nothing is scheduled and the result says what to fix. In a team workspace with one publication, or when a writer who is also a team member omits workspace, nothing is scheduled until the writer confirms it (requiresPublicationChoice: true, publicationChoiceReason: \"confirmation_required\"). Notes publish from the profile signed in to that connection, including publications sharing one login. Unverified or mismatched profile identity returns action_required without publishing. Notes are profile-level: when it is missing and all of the writer’s publications are signed in to one Substack profile, no choice is needed and the note posts from that profile. Only when the publications span two or more Substack profiles does the writer choose a profile: Narrareach uses the one they chose most recently (and says so in substackPublicationSelection.message), or, with no previous choice, nothing is scheduled and the result has requiresPublicationChoice: true, choiceScope: \"profile\" and publicationChoices (one per profile); ask the user, then call again with substackConnectionId set to the chosen publicationChoices[].substackConnectionId. An ambiguous publication value also returns publicationChoices.",
      -            "type": "string"
      -          },
      -          "scheduledFor": {
      -            "description": "Local wall-clock publishing date/time interpreted in timezone, including DST (e.g. \"2026-07-01T14:30:00\" means 2:30 PM). A Z or explicit UTC offset represents an absolute instant instead.",
      -            "type": "string"
      -          },
      -          "socialAccountIds": {
      -            "additionalProperties": {
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "description": "Optional account to post to on Threads, Facebook, TikTok, Pinterest or X, keyed by platform, e.g. { \"THREADS\": \"<accountId>\" }, with accountId values from list_social_accounts. Omit a platform to use its only account or its default. Required for a platform where list_social_accounts reports accountChoiceRequired; ask the writer which account rather than picking one.",
      -            "type": "object"
      -          },
      -          "substackConnectionId": {
      -            "deprecated": true,
      -            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      -            "type": "string"
      -          },
      -          "threadsTopicTag": {
      -            "description": "Optional Threads topic tag. Threads must be selected; maximum 50 characters.",
      -            "type": "string"
      -          },
      -          "timezone": {
      -            "description": "IANA timezone the scheduledFor time above is expressed in (e.g. \"Europe/London\"). Default UTC.",
      -            "type": "string"
      -          },
      -          "videoUrls": {
      -            "description": "Optional video URLs or video data URIs to attach to the scheduled note.",
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "workspace": {
      -            "description": "Authorized team workspace name or id for team scheduling. Absence selects the authenticated user’s personal account.",
      -            "type": "string"
      -          },
      -          "writer": {
      -            "description": "Authorized team writer name, handle, or id. \"me\" selects the linked team voice. Required when a team workspace has multiple writers.",
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "scheduledFor",
      -          "platforms",
      -          "timezone",
      -          "content",
      -          "clientRequestId"
      -        ],
      -        "type": "object"
      -      },
      -      "tool": {
      -        "const": "schedule_note",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "tool",
      -      "arguments"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "arguments": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "addSearchMetadata": {
      -            "description": "Generate SEO titles, descriptions, and a Substack slug for supported article destinations. SEO metadata is generated automatically on Revenue Writer, Full Agentic Mode, and Teams & Agencies, and for trials or other accounts with article SEO access. Set this option to false to turn it off. X does not support separate article SEO settings.",
      -            "type": "boolean"
      -          },
      -          "contentHtml": {
      -            "description": "Required when creating a new draft. Supports public <img> or <video> elements and {{media:N}} placeholders resolved from media entries. Video articles require Substack as the sole platform. Native Substack paywall markup is <hr data-type=\"paywall\"> at the selected paragraph boundary, or a single {{NARRAREACH_PAYWALL}} token; paywallMarker supports custom tokens. A Substack Freewall (free and paid subscribers keep reading) is <hr data-type=\"paywall\" data-access=\"subscribers\">, or set freewall to true. Native subscribe block markup is <div data-type=\"button\" data-kind=\"subscribeCaption\" data-text=\"Subscribe\" data-caption=\"Your caption\"></div> with HTML-escaped attribute values. data-kind=\"subscribe\" represents a button without caption. Ordinary links remain links. Audience sections use a div with data-dynamic-content=\"true\" and data-dynamic-audiences=\"paid_sub\", containing data-dynamic-content-match=\"true\" and data-dynamic-content-else=\"true\" divs. Supported audience conditions: non_sub, free_sub, paid_sub, founding_sub (comma-separated). Keep both branches. Subscriber-tag targeting must be published in Substack.",
      -            "type": "string"
      -          },
      -          "coverImage": {
      -            "description": "Optional cover image for a newly created draft, placed at the top of the published body. Supports public HTTPS URLs, data URIs, or base64 image bytes. URL ingestion depends on source-host access. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      -            "properties": {
      -              "data": {
      -                "description": "Data URI or raw base64 image bytes.",
      -                "type": "string"
      -              },
      -              "mimeType": {
      -                "description": "Required for raw base64. Example: image/png.",
      -                "type": "string"
      -              },
      -              "sourceType": {
      -                "enum": [
      -                  "url",
      -                  "data_uri",
      -                  "base64"
      -                ],
      -                "type": "string"
      -              },
      -              "url": {
      -                "description": "Public HTTPS image URL.",
      -                "type": "string"
      -              }
      -            },
      -            "type": "object"
      -          },
      -          "freewall": {
      -            "description": "Make the article's single wall divider (or paywallMarker) a Substack Freewall: everyone sees the content above it; free and paid subscribers keep reading below it. Requires SUBSTACK and a new draft (title and contentHtml). The publication must have Substack Freewalls available. Default false.",
      -            "type": "boolean"
      -          },
      -          "isPaidContent": {
      -            "description": "Whether the Substack article is paid-only. Default false. Do not combine with freewall.",
      -            "type": "boolean"
      -          },
      -          "linkedinAuthorUrn": {
      -            "description": "LinkedIn personal profile or Company Page author URN belonging to the connected LinkedIn Articles account.",
      -            "type": "string"
      -          },
      -          "linkedinNewsletterUrn": {
      -            "description": "LinkedIn newsletter URN belonging to the connected LinkedIn Articles account. Required when linkedinPublicationType is newsletter.",
      -            "type": "string"
      -          },
      -          "linkedinPublicationType": {
      -            "description": "LinkedIn destination type. Defaults to an individual article; newsletter represents a user-selected newsletter destination.",
      -            "enum": [
      -              "article",
      -              "newsletter"
      -            ],
      -            "type": "string"
      -          },
      -          "linkedinShareCommentary": {
      -            "description": "Optional LinkedIn share text used when publishing a LinkedIn article.",
      -            "type": "string"
      -          },
      -          "media": {
      -            "description": "Optional inline images or Substack article videos for a newly created draft. Replaces {{media:N}} placeholders in array order; leftovers are appended. kind defaults to image; video requires Substack as the sole platform. Supports public URLs, data URIs, and base64 bytes. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      -            "items": {
      -              "properties": {
      -                "data": {
      -                  "type": "string"
      -                },
      -                "fileName": {
      -                  "type": "string"
      -                },
      -                "kind": {
      -                  "description": "Defaults to image when omitted.",
      -                  "enum": [
      -                    "image",
      -                    "video"
      -                  ],
      -                  "type": "string"
      -                },
      -                "mimeType": {
      -                  "type": "string"
      -                },
      -                "sourceType": {
      -                  "enum": [
      -                    "url",
      -                    "data_uri",
      -                    "base64"
      -                  ],
      -                  "type": "string"
      -                },
      -                "url": {
      -                  "type": "string"
      -                }
      -              },
      -              "type": "object"
      -            },
      -            "type": "array"
      -          },
      -          "mediumNotifyFollowers": {
      -            "description": "Whether to email Medium subscribers about this story. Only valid when platforms includes MEDIUM. Defaults to false (no email). Best-effort: a failure to apply this setting never blocks the publish/schedule and is reported as a warning.",
      -            "type": "boolean"
      -          },
      -          "mediumPublicationId": {
      -            "description": "Optional authorized Medium publication id when platforms includes MEDIUM. Absent means the personal profile. Writer-only access submits for editorial review and leaves the story unscheduled until acceptance. Explicit publication rejection allows personal-profile delivery with a warning; ambiguous submissions remain unpublished for review. Draft-only delivery does not submit to a publication.",
      -            "type": "string"
      -          },
      -          "paywallMarker": {
      -            "description": "Optional custom marker in contentHtml where the selected free preview ends; must appear exactly once. The standard {{NARRAREACH_PAYWALL}} marker is recognized without this field. Creates a native divider without changing sendToNewsletter. With freewall true it allows free and paid subscribers; otherwise it enables paid access.",
      -            "maxLength": 200,
      -            "type": "string"
      -          },
      -          "platforms": {
      -            "items": {
      -              "enum": [
      -                "SUBSTACK",
      -                "MEDIUM",
      -                "LINKEDIN",
      -                "X",
      -                "WORDPRESS",
      -                "GHOST"
      -              ],
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "publication": {
      -            "description": "Substack destination as a publication name, handle, or URL, for example \"AI Newsroom\", \"@theainewsroom\", or \"https://theainewsroom.substack.com\". Optional when exactly one active Substack publication is connected; Narrareach selects it automatically. Required when more than one active Substack publication is connected, except that when it is missing Narrareach uses the publication the writer scheduled or published to most recently and says so in substackPublicationSelection.message, with publicationChoices listing the others; tell the writer which one was used. If there is no previous choice, the value is ambiguous, or Narrareach cannot confirm the session publishes there, nothing is scheduled and the result has requiresPublicationChoice: true with publicationChoices (name, handle, url, substackConnectionId). Ask which one they want, then call again with publication set to the chosen handle (and draftId when a draft was already saved).",
      -            "type": "string"
      -          },
      -          "publishMode": {
      -            "description": "Only valid when all selected destinations are WordPress or Ghost. Defaults to publish; draft saves a remote draft at the scheduled time without publication.",
      -            "enum": [
      -              "publish",
      -              "draft"
      -            ],
      -            "type": "string"
      -          },
      -          "scheduledFor": {
      -            "description": "Shared local wall-clock publishing date/time interpreted in timezone, including DST. A Z or explicit UTC offset represents an absolute instant. LinkedIn articles require at least 20 minutes of lead time.",
      -            "type": "string"
      -          },
      -          "sendToNewsletter": {
      -            "description": "Substack email delivery setting. Default true.",
      -            "type": "boolean"
      -          },
      -          "substackConnectionId": {
      -            "deprecated": true,
      -            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      -            "type": "string"
      -          },
      -          "subtitle": {
      -            "description": "Optional article subtitle for newly created drafts. Substack omits subtitles over 250 characters and returns a warning without changing the saved draft.",
      -            "type": "string"
      -          },
      -          "tags": {
      -            "description": "Optional tag list for newly created drafts. Substack receives all supplied tags. Medium receives its supported first 5 topics and returns a warning when extras are omitted. The saved draft remains unchanged.",
      -            "items": {
      -              "maxLength": 50,
      -              "type": "string"
      -            },
      -            "maxItems": 50,
      -            "type": "array"
      -          },
      -          "timezone": {
      -            "description": "IANA timezone the scheduledFor time(s) above are expressed in (e.g. \"Europe/London\"). Default UTC.",
      -            "type": "string"
      -          },
      -          "title": {
      -            "description": "Required when creating a new draft.",
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "platforms",
      -          "scheduledFor",
      -          "timezone",
      -          "title",
      -          "contentHtml",
      -          "addSearchMetadata"
      -        ],
      -        "type": "object"
      -      },
      -      "tool": {
      -        "const": "schedule_article",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "tool",
      -      "arguments"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "arguments": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "clientRequestId": {
      +            "description": "Optional but recommended: your own id for this note, 8 to 80 letters, numbers, hyphens or underscores. Use a new one for each note and the same one when retrying it (for example after a timeout or a rate-limit pause): the retry returns the original result and schedules nothing again. Reusing it with different text, platforms or time is refused.",
      +            "pattern": "^[A-Za-z0-9_-]{8,80}$",
      +            "type": "string"
      +          },
      +          "content": {
      +            "description": "Used only when creating a new note draft.",
      +            "type": "string"
      +          },
      +          "firstReply": {
      +            "description": "Optional first reply for supported destinations. An invalid reply is omitted per platform without cancelling the root post.",
      +            "type": "string"
      +          },
      +          "imageUrls": {
      +            "description": "Optional image URLs or image data URIs to attach to the scheduled note.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "instagramDestinations": {
      +            "description": "Instagram destinations with accountId returned by list_instagram_destinations and optional independent caption. Each account receives its own delivery receipt.",
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "accountId": {
      +                  "type": "string"
      +                },
      +                "caption": {
      +                  "maxLength": 2200,
      +                  "type": "string"
      +                },
      +                "label": {
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "accountId"
      +              ],
      +              "type": "object"
      +            },
      +            "maxItems": 5,
      +            "minItems": 1,
      +            "type": "array"
      +          },
      +          "linkedInAccountId": {
      +            "description": "Optional LinkedIn account id for a connected LinkedIn destination. Absence of both this field and linkedInOrganizationUrn selects the configured default.",
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "linkedInOrganizationUrn": {
      +            "description": "Optional LinkedIn Company Page URN for a connected LinkedIn destination. Requires linkedInAccountId.",
      +            "minLength": 1,
      +            "pattern": "^urn:li:organization:[^\\s]+$",
      +            "type": "string"
      +          },
      +          "platformVersions": {
      +            "additionalProperties": {
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "description": "Optional platform-specific text keyed by platform, e.g. { \"BLUESKY\": \"...\" }. Each supplied version must fit its limit (Bluesky 300, Threads 500, LinkedIn 3000, X 25000) or nothing is scheduled. Saved as the draft’s platform-specific version.",
      +            "type": "object"
      +          },
      +          "platforms": {
      +            "items": {
      +              "enum": [
      +                "SUBSTACK",
      +                "LINKEDIN",
      +                "X",
      +                "BLUESKY",
      +                "THREADS",
      +                "INSTAGRAM",
      +                "FACEBOOK",
      +                "TIKTOK",
      +                "PINTEREST"
      +              ],
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "publication": {
      +            "description": "Substack publication name, handle, or URL selected by the user. Optional when exactly one active Substack publication is connected: Narrareach uses it when its session is ready and says which one was used in substackPublicationSelection.message (source \"sole_connection\"); if the session needs a sync or the profile cannot be verified, nothing is scheduled and the result says what to fix. In a team workspace with one publication, or when a writer who is also a team member omits workspace, nothing is scheduled until the writer confirms it (requiresPublicationChoice: true, publicationChoiceReason: \"confirmation_required\"). Notes publish from the profile signed in to that connection, including publications sharing one login. Unverified or mismatched profile identity returns action_required without publishing. Notes are profile-level: when it is missing and all of the writer’s publications are signed in to one Substack profile, no choice is needed and the note posts from that profile. Only when the publications span two or more Substack profiles does the writer choose a profile: Narrareach uses the one they chose most recently (and says so in substackPublicationSelection.message), or, with no previous choice, nothing is scheduled and the result has requiresPublicationChoice: true, choiceScope: \"profile\" and publicationChoices (one per profile); ask the user, then call again with substackConnectionId set to the chosen publicationChoices[].substackConnectionId. An ambiguous publication value also returns publicationChoices.",
      +            "type": "string"
      +          },
      +          "scheduledFor": {
      +            "description": "Local wall-clock publishing date/time interpreted in timezone, including DST (e.g. \"2026-07-01T14:30:00\" means 2:30 PM). A Z or explicit UTC offset represents an absolute instant instead.",
      +            "type": "string"
      +          },
      +          "socialAccountIds": {
      +            "additionalProperties": {
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "description": "Optional account to post to on Threads, Facebook, TikTok, Pinterest or X, keyed by platform, e.g. { \"THREADS\": \"<accountId>\" }, with accountId values from list_social_accounts. Omit a platform to use its only account or its default. Required for a platform where list_social_accounts reports accountChoiceRequired; ask the writer which account rather than picking one.",
      +            "type": "object"
      +          },
      +          "substackConnectionId": {
      +            "deprecated": true,
      +            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      +            "type": "string"
      +          },
      +          "threadsTopicTag": {
      +            "description": "Optional Threads topic tag. Threads must be selected; maximum 50 characters.",
      +            "type": "string"
      +          },
      +          "timezone": {
      +            "description": "IANA timezone the scheduledFor time above is expressed in (e.g. \"Europe/London\"). Default UTC.",
      +            "type": "string"
      +          },
      +          "videoUrls": {
      +            "description": "Optional video URLs or video data URIs to attach to the scheduled note.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "workspace": {
      +            "description": "Authorized team workspace name or id for team scheduling. Absence selects the authenticated user’s personal account.",
      +            "type": "string"
      +          },
      +          "writer": {
      +            "description": "Authorized team writer name, handle, or id. \"me\" selects the linked team voice. Required when a team workspace has multiple writers.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "scheduledFor",
      +          "platforms",
      +          "timezone",
      +          "content",
      +          "clientRequestId"
      +        ],
      +        "type": "object"
      +      },
      +      "tool": {
      +        "const": "schedule_note",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "tool",
      +      "arguments"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "arguments": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "addSearchMetadata": {
      +            "description": "Generate SEO titles, descriptions, and a Substack slug for supported article destinations. SEO metadata is generated automatically on Revenue Writer, Full Agentic Mode, and Teams & Agencies, and for trials or other accounts with article SEO access. Set this option to false to turn it off. X does not support separate article SEO settings.",
      +            "type": "boolean"
      +          },
      +          "contentHtml": {
      +            "description": "Required when creating a new draft. Supports public <img> or <video> elements and {{media:N}} placeholders resolved from media entries. Video articles require Substack as the sole platform. Native Substack paywall markup is <hr data-type=\"paywall\"> at the selected paragraph boundary, or a single {{NARRAREACH_PAYWALL}} token; paywallMarker supports custom tokens. A Substack Freewall (free and paid subscribers keep reading) is <hr data-type=\"paywall\" data-access=\"subscribers\">, or set freewall to true. Native subscribe block markup is <div data-type=\"button\" data-kind=\"subscribeCaption\" data-text=\"Subscribe\" data-caption=\"Your caption\"></div> with HTML-escaped attribute values. data-kind=\"subscribe\" represents a button without caption. Ordinary links remain links. Audience sections use a div with data-dynamic-content=\"true\" and data-dynamic-audiences=\"paid_sub\", containing data-dynamic-content-match=\"true\" and data-dynamic-content-else=\"true\" divs. Supported audience conditions: non_sub, free_sub, paid_sub, founding_sub (comma-separated). Keep both branches. Subscriber-tag targeting must be published in Substack.",
      +            "type": "string"
      +          },
      +          "coverImage": {
      +            "description": "Optional cover image for a newly created draft, placed at the top of the published body. Supports public HTTPS URLs, data URIs, or base64 image bytes. URL ingestion depends on source-host access. For an image attached in ChatGPT, use coverFile instead. For a saved draft (draftId), attach the cover first with update_draft.",
      +            "properties": {
      +              "data": {
      +                "description": "Data URI or raw base64 image bytes.",
      +                "type": "string"
      +              },
      +              "mimeType": {
      +                "description": "Required for raw base64. Example: image/png.",
      +                "type": "string"
      +              },
      +              "sourceType": {
      +                "enum": [
      +                  "url",
      +                  "data_uri",
      +                  "base64"
      +                ],
      +                "type": "string"
      +              },
      +              "url": {
      +                "description": "Public HTTPS image URL.",
      +                "type": "string"
      +              }
      +            },
      +            "type": "object"
      +          },
      +          "freewall": {
      +            "description": "Make the article's single wall divider (or paywallMarker) a Substack Freewall: everyone sees the content above it; free and paid subscribers keep reading below it. Requires SUBSTACK and a new draft (title and contentHtml). The publication must have Substack Freewalls available. Default false.",
      +            "type": "boolean"
      +          },
      +          "isPaidContent": {
      +            "description": "Whether the Substack article is paid-only. Default false. Do not combine with freewall.",
      +            "type": "boolean"
      +          },
      +          "linkedinAuthorUrn": {
      +            "description": "LinkedIn personal profile or Company Page author URN belonging to the connected LinkedIn Articles account.",
      +            "type": "string"
      +          },
      +          "linkedinNewsletterUrn": {
      +            "description": "LinkedIn newsletter URN belonging to the connected LinkedIn Articles account. Required when linkedinPublicationType is newsletter.",
      +            "type": "string"
      +          },
      +          "linkedinPublicationType": {
      +            "description": "LinkedIn destination type. Defaults to an individual article; newsletter represents a user-selected newsletter destination.",
      +            "enum": [
      +              "article",
      +              "newsletter"
      +            ],
      +            "type": "string"
      +          },
      +          "linkedinShareCommentary": {
      +            "description": "Optional LinkedIn share text used when publishing a LinkedIn article.",
      +            "type": "string"
      +          },
      +          "media": {
      +            "description": "Optional inline images or Substack article videos for a newly created draft. Replaces {{media:N}} placeholders in array order; leftovers are appended. kind defaults to image; video requires Substack as the sole platform. Supports public URLs, data URIs, and base64 bytes. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      +            "items": {
      +              "properties": {
      +                "data": {
      +                  "type": "string"
      +                },
      +                "fileName": {
      +                  "type": "string"
      +                },
      +                "kind": {
      +                  "description": "Defaults to image when omitted.",
      +                  "enum": [
      +                    "image",
      +                    "video"
      +                  ],
      +                  "type": "string"
      +                },
      +                "mimeType": {
      +                  "type": "string"
      +                },
      +                "sourceType": {
      +                  "enum": [
      +                    "url",
      +                    "data_uri",
      +                    "base64"
      +                  ],
      +                  "type": "string"
      +                },
      +                "url": {
      +                  "type": "string"
      +                }
      +              },
      +              "type": "object"
      +            },
      +            "type": "array"
      +          },
      +          "mediumNotifyFollowers": {
      +            "description": "Whether to email Medium subscribers about this story. Only valid when platforms includes MEDIUM. Defaults to false (no email). Best-effort: a failure to apply this setting never blocks the publish/schedule and is reported as a warning.",
      +            "type": "boolean"
      +          },
      +          "mediumPublicationId": {
      +            "description": "Optional authorized Medium publication id when platforms includes MEDIUM. Absent means the personal profile. Writer-only access submits for editorial review and leaves the story unscheduled until acceptance. Explicit publication rejection allows personal-profile delivery with a warning; ambiguous submissions remain unpublished for review. Draft-only delivery does not submit to a publication.",
      +            "type": "string"
      +          },
      +          "paywallMarker": {
      +            "description": "Optional custom marker in contentHtml where the selected free preview ends; must appear exactly once. The standard {{NARRAREACH_PAYWALL}} marker is recognized without this field. Creates a native divider without changing sendToNewsletter. With freewall true it allows free and paid subscribers; otherwise it enables paid access.",
      +            "maxLength": 200,
      +            "type": "string"
      +          },
      +          "platforms": {
      +            "items": {
      +              "enum": [
      +                "SUBSTACK",
      +                "MEDIUM",
      +                "LINKEDIN",
      +                "X",
      +                "WORDPRESS",
      +                "GHOST"
      +              ],
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "publication": {
      +            "description": "Substack destination as a publication name, handle, or URL, for example \"AI Newsroom\", \"@theainewsroom\", or \"https://theainewsroom.substack.com\". Optional when exactly one active Substack publication is connected; Narrareach selects it automatically. Required when more than one active Substack publication is connected, except that when it is missing Narrareach uses the publication the writer scheduled or published to most recently and says so in substackPublicationSelection.message, with publicationChoices listing the others; tell the writer which one was used. If there is no previous choice, the value is ambiguous, or Narrareach cannot confirm the session publishes there, nothing is scheduled and the result has requiresPublicationChoice: true with publicationChoices (name, handle, url, substackConnectionId). Ask which one they want, then call again with publication set to the chosen handle (and draftId when a draft was already saved).",
      +            "type": "string"
      +          },
      +          "publishMode": {
      +            "description": "Only valid when all selected destinations are WordPress or Ghost. Defaults to publish; draft saves a remote draft at the scheduled time without publication.",
      +            "enum": [
      +              "publish",
      +              "draft"
      +            ],
      +            "type": "string"
      +          },
      +          "scheduledFor": {
      +            "description": "Shared local wall-clock publishing date/time interpreted in timezone, including DST. A Z or explicit UTC offset represents an absolute instant. LinkedIn articles require at least 20 minutes of lead time.",
      +            "type": "string"
      +          },
      +          "sendToNewsletter": {
      +            "description": "Substack email delivery setting. Default true.",
      +            "type": "boolean"
      +          },
      +          "substackConnectionId": {
      +            "deprecated": true,
      +            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      +            "type": "string"
      +          },
      +          "subtitle": {
      +            "description": "Optional article subtitle for newly created drafts. Substack omits subtitles over 250 characters and returns a warning without changing the saved draft.",
      +            "type": "string"
      +          },
      +          "tags": {
      +            "description": "Optional tag list for newly created drafts. Substack receives all supplied tags. Medium receives its supported first 5 topics and returns a warning when extras are omitted. The saved draft remains unchanged.",
      +            "items": {
      +              "maxLength": 50,
      +              "type": "string"
      +            },
      +            "maxItems": 50,
      +            "type": "array"
      +          },
      +          "timezone": {
      +            "description": "IANA timezone the scheduledFor time(s) above are expressed in (e.g. \"Europe/London\"). Default UTC.",
      +            "type": "string"
      +          },
      +          "title": {
      +            "description": "Required when creating a new draft.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "platforms",
      +          "scheduledFor",
      +          "timezone",
      +          "title",
      +          "contentHtml",
      +          "addSearchMetadata"
      +        ],
      +        "type": "object"
      +      },
      +      "tool": {
      +        "const": "schedule_article",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "tool",
      +      "arguments"
      +    ],
      +    "type": "object"
      +  }
      +]
  6. Changed1 schema field changed
    • changedInput schema / properties / calls / items / oneOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "arguments": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "clientRequestId": {
      -            "description": "Optional but recommended: your own id for this note, 8 to 80 letters, numbers, hyphens or underscores. Use a new one for each note and the same one when retrying it (for example after a timeout or a rate-limit pause): the retry returns the original result and schedules nothing again. Reusing it with different text, platforms or time is refused.",
      -            "pattern": "^[A-Za-z0-9_-]{8,80}$",
      -            "type": "string"
      -          },
      -          "content": {
      -            "description": "Used only when creating a new note draft.",
      -            "type": "string"
      -          },
      -          "firstReply": {
      -            "description": "Optional first reply for supported destinations. An invalid reply is omitted per platform without cancelling the root post.",
      -            "type": "string"
      -          },
      -          "imageUrls": {
      -            "description": "Optional image URLs or image data URIs to attach to the scheduled note.",
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "instagramDestinations": {
      -            "description": "Instagram destinations with accountId returned by list_instagram_destinations and optional independent caption. Each account receives its own delivery receipt.",
      -            "items": {
      -              "additionalProperties": false,
      -              "properties": {
      -                "accountId": {
      -                  "type": "string"
      -                },
      -                "caption": {
      -                  "maxLength": 2200,
      -                  "type": "string"
      -                },
      -                "label": {
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "accountId"
      -              ],
      -              "type": "object"
      -            },
      -            "maxItems": 5,
      -            "minItems": 1,
      -            "type": "array"
      -          },
      -          "linkedInAccountId": {
      -            "description": "Optional LinkedIn account id for a connected LinkedIn destination. Absence of both this field and linkedInOrganizationUrn selects the configured default.",
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "linkedInOrganizationUrn": {
      -            "description": "Optional LinkedIn Company Page URN for a connected LinkedIn destination. Requires linkedInAccountId.",
      -            "minLength": 1,
      -            "pattern": "^urn:li:organization:[^\\s]+$",
      -            "type": "string"
      -          },
      -          "platformVersions": {
      -            "additionalProperties": {
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "description": "Optional platform-specific text keyed by platform, e.g. { \"BLUESKY\": \"...\" }. Each supplied version must fit its limit (Bluesky 300, Threads 500, LinkedIn 3000, X 25000) or nothing is scheduled. Saved as the draft’s platform-specific version.",
      -            "type": "object"
      -          },
      -          "platforms": {
      -            "items": {
      -              "enum": [
      -                "SUBSTACK",
      -                "LINKEDIN",
      -                "X",
      -                "BLUESKY",
      -                "THREADS",
      -                "INSTAGRAM",
      -                "FACEBOOK",
      -                "TIKTOK",
      -                "PINTEREST"
      -              ],
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "publication": {
      -            "description": "Substack publication name, handle, or URL selected by the user. Optional when exactly one active Substack publication is connected: Narrareach uses it when its session is ready and says which one was used in substackPublicationSelection.message (source \"sole_connection\"); if the session needs a sync or the profile cannot be verified, nothing is scheduled and the result says what to fix. In a team workspace with one publication, or when a writer who is also a team member omits workspace, nothing is scheduled until the writer confirms it (requiresPublicationChoice: true, publicationChoiceReason: \"confirmation_required\"). Notes publish from the profile signed in to that connection, including publications sharing one login. Unverified or mismatched profile identity returns action_required without publishing. Notes are profile-level: when it is missing and all of the writer’s publications are signed in to one Substack profile, no choice is needed and the note posts from that profile. Only when the publications span two or more Substack profiles does the writer choose a profile: Narrareach uses the one they chose most recently (and says so in substackPublicationSelection.message), or, with no previous choice, nothing is scheduled and the result has requiresPublicationChoice: true, choiceScope: \"profile\" and publicationChoices (one per profile); ask the user, then call again with substackConnectionId set to the chosen publicationChoices[].substackConnectionId. An ambiguous publication value also returns publicationChoices.",
      -            "type": "string"
      -          },
      -          "scheduledFor": {
      -            "description": "Local wall-clock publishing date/time interpreted in timezone, including DST (e.g. \"2026-07-01T14:30:00\" means 2:30 PM). A Z or explicit UTC offset represents an absolute instant instead.",
      -            "type": "string"
      -          },
      -          "socialAccountIds": {
      -            "additionalProperties": {
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "description": "Optional account to post to on Threads, Facebook, TikTok, Pinterest or X, keyed by platform, e.g. { \"THREADS\": \"<accountId>\" }, with accountId values from list_social_accounts. Omit a platform to use its only account or its default. Required for a platform where list_social_accounts reports accountChoiceRequired; ask the writer which account rather than picking one.",
      -            "type": "object"
      -          },
      -          "substackConnectionId": {
      -            "deprecated": true,
      -            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      -            "type": "string"
      -          },
      -          "threadsTopicTag": {
      -            "description": "Optional Threads topic tag. Threads must be selected; maximum 50 characters.",
      -            "type": "string"
      -          },
      -          "timezone": {
      -            "description": "IANA timezone the scheduledFor time above is expressed in (e.g. \"Europe/London\"). Default UTC.",
      -            "type": "string"
      -          },
      -          "videoUrls": {
      -            "description": "Optional video URLs or video data URIs to attach to the scheduled note.",
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "workspace": {
      -            "description": "Authorized team workspace name or id for team scheduling. Absence selects the authenticated user’s personal account.",
      -            "type": "string"
      -          },
      -          "writer": {
      -            "description": "Authorized team writer name, handle, or id. \"me\" selects the linked team voice. Required when a team workspace has multiple writers.",
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "scheduledFor",
      -          "platforms",
      -          "timezone",
      -          "content",
      -          "clientRequestId"
      -        ],
      -        "type": "object"
      -      },
      -      "tool": {
      -        "const": "schedule_note",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "tool",
      -      "arguments"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "arguments": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "addSearchMetadata": {
      -            "description": "Generate SEO titles, descriptions, and a Substack slug for supported article destinations. SEO metadata is generated automatically on Revenue Writer, Full Agentic Mode, and Teams & Agencies, and for trials or other accounts with article SEO access. Set this option to false to turn it off. X does not support separate article SEO settings.",
      -            "type": "boolean"
      -          },
      -          "contentHtml": {
      -            "description": "Required when creating a new draft. Supports public <img> or <video> elements and {{media:N}} placeholders resolved from media entries. Video articles require Substack as the sole platform. Native Substack paywall markup is <hr data-type=\"paywall\"> at the selected paragraph boundary, or a single {{NARRAREACH_PAYWALL}} token; paywallMarker supports custom tokens. A Substack Freewall (free and paid subscribers keep reading) is <hr data-type=\"paywall\" data-access=\"subscribers\">, or set freewall to true. Native subscribe block markup is <div data-type=\"button\" data-kind=\"subscribeCaption\" data-text=\"Subscribe\" data-caption=\"Your caption\"></div> with HTML-escaped attribute values. data-kind=\"subscribe\" represents a button without caption. Ordinary links remain links.",
      -            "type": "string"
      -          },
      -          "coverImage": {
      -            "description": "Optional cover image for a newly created draft, placed at the top of the published body. Supports public HTTPS URLs, data URIs, or base64 image bytes. URL ingestion depends on source-host access. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      -            "properties": {
      -              "data": {
      -                "description": "Data URI or raw base64 image bytes.",
      -                "type": "string"
      -              },
      -              "mimeType": {
      -                "description": "Required for raw base64. Example: image/png.",
      -                "type": "string"
      -              },
      -              "sourceType": {
      -                "enum": [
      -                  "url",
      -                  "data_uri",
      -                  "base64"
      -                ],
      -                "type": "string"
      -              },
      -              "url": {
      -                "description": "Public HTTPS image URL.",
      -                "type": "string"
      -              }
      -            },
      -            "type": "object"
      -          },
      -          "freewall": {
      -            "description": "Make the article's single wall divider (or paywallMarker) a Substack Freewall: everyone sees the content above it; free and paid subscribers keep reading below it. Requires SUBSTACK and a new draft (title and contentHtml). The publication must have Substack Freewalls available. Default false.",
      -            "type": "boolean"
      -          },
      -          "isPaidContent": {
      -            "description": "Whether the Substack article is paid-only. Default false. Do not combine with freewall.",
      -            "type": "boolean"
      -          },
      -          "linkedinAuthorUrn": {
      -            "description": "LinkedIn personal profile or Company Page author URN belonging to the connected LinkedIn Articles account.",
      -            "type": "string"
      -          },
      -          "linkedinNewsletterUrn": {
      -            "description": "LinkedIn newsletter URN belonging to the connected LinkedIn Articles account. Required when linkedinPublicationType is newsletter.",
      -            "type": "string"
      -          },
      -          "linkedinPublicationType": {
      -            "description": "LinkedIn destination type. Defaults to an individual article; newsletter represents a user-selected newsletter destination.",
      -            "enum": [
      -              "article",
      -              "newsletter"
      -            ],
      -            "type": "string"
      -          },
      -          "linkedinShareCommentary": {
      -            "description": "Optional LinkedIn share text used when publishing a LinkedIn article.",
      -            "type": "string"
      -          },
      -          "media": {
      -            "description": "Optional inline images or Substack article videos for a newly created draft. Replaces {{media:N}} placeholders in array order; leftovers are appended. kind defaults to image; video requires Substack as the sole platform. Supports public URLs, data URIs, and base64 bytes. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      -            "items": {
      -              "properties": {
      -                "data": {
      -                  "type": "string"
      -                },
      -                "fileName": {
      -                  "type": "string"
      -                },
      -                "kind": {
      -                  "description": "Defaults to image when omitted.",
      -                  "enum": [
      -                    "image",
      -                    "video"
      -                  ],
      -                  "type": "string"
      -                },
      -                "mimeType": {
      -                  "type": "string"
      -                },
      -                "sourceType": {
      -                  "enum": [
      -                    "url",
      -                    "data_uri",
      -                    "base64"
      -                  ],
      -                  "type": "string"
      -                },
      -                "url": {
      -                  "type": "string"
      -                }
      -              },
      -              "type": "object"
      -            },
      -            "type": "array"
      -          },
      -          "mediumNotifyFollowers": {
      -            "description": "Whether to email Medium subscribers about this story. Only valid when platforms includes MEDIUM. Defaults to false (no email). Best-effort: a failure to apply this setting never blocks the publish/schedule and is reported as a warning.",
      -            "type": "boolean"
      -          },
      -          "mediumPublicationId": {
      -            "description": "Optional authorized Medium publication id when platforms includes MEDIUM. Absent means the personal profile. Writer-only access submits for editorial review and leaves the story unscheduled until acceptance. Explicit publication rejection allows personal-profile delivery with a warning; ambiguous submissions remain unpublished for review. Draft-only delivery does not submit to a publication.",
      -            "type": "string"
      -          },
      -          "paywallMarker": {
      -            "description": "Optional custom marker in contentHtml where the selected free preview ends; must appear exactly once. The standard {{NARRAREACH_PAYWALL}} marker is recognized without this field. Creates a native paywall and enables paid access without changing sendToNewsletter.",
      -            "maxLength": 200,
      -            "type": "string"
      -          },
      -          "platforms": {
      -            "items": {
      -              "enum": [
      -                "SUBSTACK",
      -                "MEDIUM",
      -                "LINKEDIN",
      -                "X",
      -                "WORDPRESS",
      -                "GHOST"
      -              ],
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "publication": {
      -            "description": "Substack destination as a publication name, handle, or URL, for example \"AI Newsroom\", \"@theainewsroom\", or \"https://theainewsroom.substack.com\". Optional when exactly one active Substack publication is connected; Narrareach selects it automatically. Required when more than one active Substack publication is connected, except that when it is missing Narrareach uses the publication the writer scheduled or published to most recently and says so in substackPublicationSelection.message, with publicationChoices listing the others; tell the writer which one was used. If there is no previous choice, the value is ambiguous, or Narrareach cannot confirm the session publishes there, nothing is scheduled and the result has requiresPublicationChoice: true with publicationChoices (name, handle, url, substackConnectionId). Ask which one they want, then call again with publication set to the chosen handle (and draftId when a draft was already saved).",
      -            "type": "string"
      -          },
      -          "publishMode": {
      -            "description": "Only valid when all selected destinations are WordPress or Ghost. Defaults to publish; draft saves a remote draft at the scheduled time without publication.",
      -            "enum": [
      -              "publish",
      -              "draft"
      -            ],
      -            "type": "string"
      -          },
      -          "scheduledFor": {
      -            "description": "Shared local wall-clock publishing date/time interpreted in timezone, including DST. A Z or explicit UTC offset represents an absolute instant. LinkedIn articles require at least 20 minutes of lead time.",
      -            "type": "string"
      -          },
      -          "sendToNewsletter": {
      -            "description": "Substack email delivery setting. Default true.",
      -            "type": "boolean"
      -          },
      -          "substackConnectionId": {
      -            "deprecated": true,
      -            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      -            "type": "string"
      -          },
      -          "subtitle": {
      -            "description": "Optional article subtitle for newly created drafts. Substack omits subtitles over 250 characters and returns a warning without changing the saved draft.",
      -            "type": "string"
      -          },
      -          "tags": {
      -            "description": "Optional tag list for newly created drafts. Substack receives all supplied tags. Medium receives its supported first 5 topics and returns a warning when extras are omitted. The saved draft remains unchanged.",
      -            "items": {
      -              "maxLength": 50,
      -              "type": "string"
      -            },
      -            "maxItems": 50,
      -            "type": "array"
      -          },
      -          "timezone": {
      -            "description": "IANA timezone the scheduledFor time(s) above are expressed in (e.g. \"Europe/London\"). Default UTC.",
      -            "type": "string"
      -          },
      -          "title": {
      -            "description": "Required when creating a new draft.",
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "platforms",
      -          "scheduledFor",
      -          "timezone",
      -          "title",
      -          "contentHtml",
      -          "addSearchMetadata"
      -        ],
      -        "type": "object"
      -      },
      -      "tool": {
      -        "const": "schedule_article",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "tool",
      -      "arguments"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "arguments": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "clientRequestId": {
      +            "description": "Optional but recommended: your own id for this note, 8 to 80 letters, numbers, hyphens or underscores. Use a new one for each note and the same one when retrying it (for example after a timeout or a rate-limit pause): the retry returns the original result and schedules nothing again. Reusing it with different text, platforms or time is refused.",
      +            "pattern": "^[A-Za-z0-9_-]{8,80}$",
      +            "type": "string"
      +          },
      +          "content": {
      +            "description": "Used only when creating a new note draft.",
      +            "type": "string"
      +          },
      +          "firstReply": {
      +            "description": "Optional first reply for supported destinations. An invalid reply is omitted per platform without cancelling the root post.",
      +            "type": "string"
      +          },
      +          "imageUrls": {
      +            "description": "Optional image URLs or image data URIs to attach to the scheduled note.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "instagramDestinations": {
      +            "description": "Instagram destinations with accountId returned by list_instagram_destinations and optional independent caption. Each account receives its own delivery receipt.",
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "accountId": {
      +                  "type": "string"
      +                },
      +                "caption": {
      +                  "maxLength": 2200,
      +                  "type": "string"
      +                },
      +                "label": {
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "accountId"
      +              ],
      +              "type": "object"
      +            },
      +            "maxItems": 5,
      +            "minItems": 1,
      +            "type": "array"
      +          },
      +          "linkedInAccountId": {
      +            "description": "Optional LinkedIn account id for a connected LinkedIn destination. Absence of both this field and linkedInOrganizationUrn selects the configured default.",
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "linkedInOrganizationUrn": {
      +            "description": "Optional LinkedIn Company Page URN for a connected LinkedIn destination. Requires linkedInAccountId.",
      +            "minLength": 1,
      +            "pattern": "^urn:li:organization:[^\\s]+$",
      +            "type": "string"
      +          },
      +          "platformVersions": {
      +            "additionalProperties": {
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "description": "Optional platform-specific text keyed by platform, e.g. { \"BLUESKY\": \"...\" }. Each supplied version must fit its limit (Bluesky 300, Threads 500, LinkedIn 3000, X 25000) or nothing is scheduled. Saved as the draft’s platform-specific version.",
      +            "type": "object"
      +          },
      +          "platforms": {
      +            "items": {
      +              "enum": [
      +                "SUBSTACK",
      +                "LINKEDIN",
      +                "X",
      +                "BLUESKY",
      +                "THREADS",
      +                "INSTAGRAM",
      +                "FACEBOOK",
      +                "TIKTOK",
      +                "PINTEREST"
      +              ],
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "publication": {
      +            "description": "Substack publication name, handle, or URL selected by the user. Optional when exactly one active Substack publication is connected: Narrareach uses it when its session is ready and says which one was used in substackPublicationSelection.message (source \"sole_connection\"); if the session needs a sync or the profile cannot be verified, nothing is scheduled and the result says what to fix. In a team workspace with one publication, or when a writer who is also a team member omits workspace, nothing is scheduled until the writer confirms it (requiresPublicationChoice: true, publicationChoiceReason: \"confirmation_required\"). Notes publish from the profile signed in to that connection, including publications sharing one login. Unverified or mismatched profile identity returns action_required without publishing. Notes are profile-level: when it is missing and all of the writer’s publications are signed in to one Substack profile, no choice is needed and the note posts from that profile. Only when the publications span two or more Substack profiles does the writer choose a profile: Narrareach uses the one they chose most recently (and says so in substackPublicationSelection.message), or, with no previous choice, nothing is scheduled and the result has requiresPublicationChoice: true, choiceScope: \"profile\" and publicationChoices (one per profile); ask the user, then call again with substackConnectionId set to the chosen publicationChoices[].substackConnectionId. An ambiguous publication value also returns publicationChoices.",
      +            "type": "string"
      +          },
      +          "scheduledFor": {
      +            "description": "Local wall-clock publishing date/time interpreted in timezone, including DST (e.g. \"2026-07-01T14:30:00\" means 2:30 PM). A Z or explicit UTC offset represents an absolute instant instead.",
      +            "type": "string"
      +          },
      +          "socialAccountIds": {
      +            "additionalProperties": {
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "description": "Optional account to post to on Threads, Facebook, TikTok, Pinterest or X, keyed by platform, e.g. { \"THREADS\": \"<accountId>\" }, with accountId values from list_social_accounts. Omit a platform to use its only account or its default. Required for a platform where list_social_accounts reports accountChoiceRequired; ask the writer which account rather than picking one.",
      +            "type": "object"
      +          },
      +          "substackConnectionId": {
      +            "deprecated": true,
      +            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      +            "type": "string"
      +          },
      +          "threadsTopicTag": {
      +            "description": "Optional Threads topic tag. Threads must be selected; maximum 50 characters.",
      +            "type": "string"
      +          },
      +          "timezone": {
      +            "description": "IANA timezone the scheduledFor time above is expressed in (e.g. \"Europe/London\"). Default UTC.",
      +            "type": "string"
      +          },
      +          "videoUrls": {
      +            "description": "Optional video URLs or video data URIs to attach to the scheduled note.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "workspace": {
      +            "description": "Authorized team workspace name or id for team scheduling. Absence selects the authenticated user’s personal account.",
      +            "type": "string"
      +          },
      +          "writer": {
      +            "description": "Authorized team writer name, handle, or id. \"me\" selects the linked team voice. Required when a team workspace has multiple writers.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "scheduledFor",
      +          "platforms",
      +          "timezone",
      +          "content",
      +          "clientRequestId"
      +        ],
      +        "type": "object"
      +      },
      +      "tool": {
      +        "const": "schedule_note",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "tool",
      +      "arguments"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "arguments": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "addSearchMetadata": {
      +            "description": "Generate SEO titles, descriptions, and a Substack slug for supported article destinations. SEO metadata is generated automatically on Revenue Writer, Full Agentic Mode, and Teams & Agencies, and for trials or other accounts with article SEO access. Set this option to false to turn it off. X does not support separate article SEO settings.",
      +            "type": "boolean"
      +          },
      +          "contentHtml": {
      +            "description": "Required when creating a new draft. Supports public <img> or <video> elements and {{media:N}} placeholders resolved from media entries. Video articles require Substack as the sole platform. Native Substack paywall markup is <hr data-type=\"paywall\"> at the selected paragraph boundary, or a single {{NARRAREACH_PAYWALL}} token; paywallMarker supports custom tokens. A Substack Freewall (free and paid subscribers keep reading) is <hr data-type=\"paywall\" data-access=\"subscribers\">, or set freewall to true. Native subscribe block markup is <div data-type=\"button\" data-kind=\"subscribeCaption\" data-text=\"Subscribe\" data-caption=\"Your caption\"></div> with HTML-escaped attribute values. data-kind=\"subscribe\" represents a button without caption. Ordinary links remain links. Audience sections use a div with data-dynamic-content=\"true\" and data-dynamic-audiences=\"paid_sub\", containing data-dynamic-content-match=\"true\" and data-dynamic-content-else=\"true\" divs. Supported audience conditions: non_sub, free_sub, paid_sub, founding_sub (comma-separated). Keep both branches. Subscriber-tag targeting must be published in Substack.",
      +            "type": "string"
      +          },
      +          "coverImage": {
      +            "description": "Optional cover image for a newly created draft, placed at the top of the published body. Supports public HTTPS URLs, data URIs, or base64 image bytes. URL ingestion depends on source-host access. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      +            "properties": {
      +              "data": {
      +                "description": "Data URI or raw base64 image bytes.",
      +                "type": "string"
      +              },
      +              "mimeType": {
      +                "description": "Required for raw base64. Example: image/png.",
      +                "type": "string"
      +              },
      +              "sourceType": {
      +                "enum": [
      +                  "url",
      +                  "data_uri",
      +                  "base64"
      +                ],
      +                "type": "string"
      +              },
      +              "url": {
      +                "description": "Public HTTPS image URL.",
      +                "type": "string"
      +              }
      +            },
      +            "type": "object"
      +          },
      +          "freewall": {
      +            "description": "Make the article's single wall divider (or paywallMarker) a Substack Freewall: everyone sees the content above it; free and paid subscribers keep reading below it. Requires SUBSTACK and a new draft (title and contentHtml). The publication must have Substack Freewalls available. Default false.",
      +            "type": "boolean"
      +          },
      +          "isPaidContent": {
      +            "description": "Whether the Substack article is paid-only. Default false. Do not combine with freewall.",
      +            "type": "boolean"
      +          },
      +          "linkedinAuthorUrn": {
      +            "description": "LinkedIn personal profile or Company Page author URN belonging to the connected LinkedIn Articles account.",
      +            "type": "string"
      +          },
      +          "linkedinNewsletterUrn": {
      +            "description": "LinkedIn newsletter URN belonging to the connected LinkedIn Articles account. Required when linkedinPublicationType is newsletter.",
      +            "type": "string"
      +          },
      +          "linkedinPublicationType": {
      +            "description": "LinkedIn destination type. Defaults to an individual article; newsletter represents a user-selected newsletter destination.",
      +            "enum": [
      +              "article",
      +              "newsletter"
      +            ],
      +            "type": "string"
      +          },
      +          "linkedinShareCommentary": {
      +            "description": "Optional LinkedIn share text used when publishing a LinkedIn article.",
      +            "type": "string"
      +          },
      +          "media": {
      +            "description": "Optional inline images or Substack article videos for a newly created draft. Replaces {{media:N}} placeholders in array order; leftovers are appended. kind defaults to image; video requires Substack as the sole platform. Supports public URLs, data URIs, and base64 bytes. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      +            "items": {
      +              "properties": {
      +                "data": {
      +                  "type": "string"
      +                },
      +                "fileName": {
      +                  "type": "string"
      +                },
      +                "kind": {
      +                  "description": "Defaults to image when omitted.",
      +                  "enum": [
      +                    "image",
      +                    "video"
      +                  ],
      +                  "type": "string"
      +                },
      +                "mimeType": {
      +                  "type": "string"
      +                },
      +                "sourceType": {
      +                  "enum": [
      +                    "url",
      +                    "data_uri",
      +                    "base64"
      +                  ],
      +                  "type": "string"
      +                },
      +                "url": {
      +                  "type": "string"
      +                }
      +              },
      +              "type": "object"
      +            },
      +            "type": "array"
      +          },
      +          "mediumNotifyFollowers": {
      +            "description": "Whether to email Medium subscribers about this story. Only valid when platforms includes MEDIUM. Defaults to false (no email). Best-effort: a failure to apply this setting never blocks the publish/schedule and is reported as a warning.",
      +            "type": "boolean"
      +          },
      +          "mediumPublicationId": {
      +            "description": "Optional authorized Medium publication id when platforms includes MEDIUM. Absent means the personal profile. Writer-only access submits for editorial review and leaves the story unscheduled until acceptance. Explicit publication rejection allows personal-profile delivery with a warning; ambiguous submissions remain unpublished for review. Draft-only delivery does not submit to a publication.",
      +            "type": "string"
      +          },
      +          "paywallMarker": {
      +            "description": "Optional custom marker in contentHtml where the selected free preview ends; must appear exactly once. The standard {{NARRAREACH_PAYWALL}} marker is recognized without this field. Creates a native divider without changing sendToNewsletter. With freewall true it allows free and paid subscribers; otherwise it enables paid access.",
      +            "maxLength": 200,
      +            "type": "string"
      +          },
      +          "platforms": {
      +            "items": {
      +              "enum": [
      +                "SUBSTACK",
      +                "MEDIUM",
      +                "LINKEDIN",
      +                "X",
      +                "WORDPRESS",
      +                "GHOST"
      +              ],
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "publication": {
      +            "description": "Substack destination as a publication name, handle, or URL, for example \"AI Newsroom\", \"@theainewsroom\", or \"https://theainewsroom.substack.com\". Optional when exactly one active Substack publication is connected; Narrareach selects it automatically. Required when more than one active Substack publication is connected, except that when it is missing Narrareach uses the publication the writer scheduled or published to most recently and says so in substackPublicationSelection.message, with publicationChoices listing the others; tell the writer which one was used. If there is no previous choice, the value is ambiguous, or Narrareach cannot confirm the session publishes there, nothing is scheduled and the result has requiresPublicationChoice: true with publicationChoices (name, handle, url, substackConnectionId). Ask which one they want, then call again with publication set to the chosen handle (and draftId when a draft was already saved).",
      +            "type": "string"
      +          },
      +          "publishMode": {
      +            "description": "Only valid when all selected destinations are WordPress or Ghost. Defaults to publish; draft saves a remote draft at the scheduled time without publication.",
      +            "enum": [
      +              "publish",
      +              "draft"
      +            ],
      +            "type": "string"
      +          },
      +          "scheduledFor": {
      +            "description": "Shared local wall-clock publishing date/time interpreted in timezone, including DST. A Z or explicit UTC offset represents an absolute instant. LinkedIn articles require at least 20 minutes of lead time.",
      +            "type": "string"
      +          },
      +          "sendToNewsletter": {
      +            "description": "Substack email delivery setting. Default true.",
      +            "type": "boolean"
      +          },
      +          "substackConnectionId": {
      +            "deprecated": true,
      +            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      +            "type": "string"
      +          },
      +          "subtitle": {
      +            "description": "Optional article subtitle for newly created drafts. Substack omits subtitles over 250 characters and returns a warning without changing the saved draft.",
      +            "type": "string"
      +          },
      +          "tags": {
      +            "description": "Optional tag list for newly created drafts. Substack receives all supplied tags. Medium receives its supported first 5 topics and returns a warning when extras are omitted. The saved draft remains unchanged.",
      +            "items": {
      +              "maxLength": 50,
      +              "type": "string"
      +            },
      +            "maxItems": 50,
      +            "type": "array"
      +          },
      +          "timezone": {
      +            "description": "IANA timezone the scheduledFor time(s) above are expressed in (e.g. \"Europe/London\"). Default UTC.",
      +            "type": "string"
      +          },
      +          "title": {
      +            "description": "Required when creating a new draft.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "platforms",
      +          "scheduledFor",
      +          "timezone",
      +          "title",
      +          "contentHtml",
      +          "addSearchMetadata"
      +        ],
      +        "type": "object"
      +      },
      +      "tool": {
      +        "const": "schedule_article",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "tool",
      +      "arguments"
      +    ],
      +    "type": "object"
      +  }
      +]
  7. Changed1 schema field changed
    • changedInput schema / properties / calls / items / oneOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "arguments": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "clientRequestId": {
      -            "description": "Optional but recommended: your own id for this note, 8 to 80 letters, numbers, hyphens or underscores. Use a new one for each note and the same one when retrying it (for example after a timeout or a rate-limit pause): the retry returns the original result and schedules nothing again. Reusing it with different text, platforms or time is refused.",
      -            "pattern": "^[A-Za-z0-9_-]{8,80}$",
      -            "type": "string"
      -          },
      -          "content": {
      -            "description": "Used only when creating a new note draft.",
      -            "type": "string"
      -          },
      -          "firstReply": {
      -            "description": "Optional first reply for supported destinations. An invalid reply is omitted per platform without cancelling the root post.",
      -            "type": "string"
      -          },
      -          "imageUrls": {
      -            "description": "Optional image URLs or image data URIs to attach to the scheduled note.",
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "instagramDestinations": {
      -            "description": "Instagram destinations with accountId returned by list_instagram_destinations and optional independent caption. Each account receives its own delivery receipt.",
      -            "items": {
      -              "additionalProperties": false,
      -              "properties": {
      -                "accountId": {
      -                  "type": "string"
      -                },
      -                "caption": {
      -                  "maxLength": 2200,
      -                  "type": "string"
      -                },
      -                "label": {
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "accountId"
      -              ],
      -              "type": "object"
      -            },
      -            "maxItems": 5,
      -            "minItems": 1,
      -            "type": "array"
      -          },
      -          "linkedInAccountId": {
      -            "description": "Optional LinkedIn account id for a connected LinkedIn destination. Absence of both this field and linkedInOrganizationUrn selects the configured default.",
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "linkedInOrganizationUrn": {
      -            "description": "Optional LinkedIn Company Page URN for a connected LinkedIn destination. Requires linkedInAccountId.",
      -            "minLength": 1,
      -            "pattern": "^urn:li:organization:[^\\s]+$",
      -            "type": "string"
      -          },
      -          "platformVersions": {
      -            "additionalProperties": {
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "description": "Optional platform-specific text keyed by platform, e.g. { \"BLUESKY\": \"...\" }. Each supplied version must fit its limit (Bluesky 300, Threads 500, LinkedIn 3000, X 25000) or nothing is scheduled. Saved as the draft’s platform-specific version.",
      -            "type": "object"
      -          },
      -          "platforms": {
      -            "items": {
      -              "enum": [
      -                "SUBSTACK",
      -                "LINKEDIN",
      -                "X",
      -                "BLUESKY",
      -                "THREADS",
      -                "INSTAGRAM",
      -                "FACEBOOK",
      -                "TIKTOK",
      -                "PINTEREST"
      -              ],
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "publication": {
      -            "description": "Substack publication name, handle, or URL selected by the user. Optional when exactly one active Substack publication is connected: Narrareach uses it when its session is ready and says which one was used in substackPublicationSelection.message (source \"sole_connection\"); if the session needs a sync or the profile cannot be verified, nothing is scheduled and the result says what to fix. In a team workspace with one publication, or when a writer who is also a team member omits workspace, nothing is scheduled until the writer confirms it (requiresPublicationChoice: true, publicationChoiceReason: \"confirmation_required\"). Notes publish from the profile signed in to that connection, including publications sharing one login. Unverified or mismatched profile identity returns action_required without publishing. Notes are profile-level: when it is missing and all of the writer’s publications are signed in to one Substack profile, no choice is needed and the note posts from that profile. Only when the publications span two or more Substack profiles does the writer choose a profile: Narrareach uses the one they chose most recently (and says so in substackPublicationSelection.message), or, with no previous choice, nothing is scheduled and the result has requiresPublicationChoice: true, choiceScope: \"profile\" and publicationChoices (one per profile); ask the user, then call again with substackConnectionId set to the chosen publicationChoices[].substackConnectionId. An ambiguous publication value also returns publicationChoices.",
      -            "type": "string"
      -          },
      -          "scheduledFor": {
      -            "description": "Local wall-clock publishing date/time interpreted in timezone, including DST (e.g. \"2026-07-01T14:30:00\" means 2:30 PM). A Z or explicit UTC offset represents an absolute instant instead.",
      -            "type": "string"
      -          },
      -          "socialAccountIds": {
      -            "additionalProperties": {
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "description": "Optional account to post to on Threads, Facebook, TikTok, Pinterest or X, keyed by platform, e.g. { \"THREADS\": \"<accountId>\" }, with accountId values from list_social_accounts. Omit a platform to use its only account or its default. Required for a platform where list_social_accounts reports accountChoiceRequired; ask the writer which account rather than picking one.",
      -            "type": "object"
      -          },
      -          "substackConnectionId": {
      -            "deprecated": true,
      -            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      -            "type": "string"
      -          },
      -          "threadsTopicTag": {
      -            "description": "Optional Threads topic tag. Threads must be selected; maximum 50 characters.",
      -            "type": "string"
      -          },
      -          "timezone": {
      -            "description": "IANA timezone the scheduledFor time above is expressed in (e.g. \"Europe/London\"). Default UTC.",
      -            "type": "string"
      -          },
      -          "videoUrls": {
      -            "description": "Optional video URLs or video data URIs to attach to the scheduled note.",
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "workspace": {
      -            "description": "Authorized team workspace name or id for team scheduling. Absence selects the authenticated user’s personal account.",
      -            "type": "string"
      -          },
      -          "writer": {
      -            "description": "Authorized team writer name, handle, or id. \"me\" selects the linked team voice. Required when a team workspace has multiple writers.",
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "scheduledFor",
      -          "platforms",
      -          "timezone",
      -          "content",
      -          "clientRequestId"
      -        ],
      -        "type": "object"
      -      },
      -      "tool": {
      -        "const": "schedule_note",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "tool",
      -      "arguments"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "arguments": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "addSearchMetadata": {
      -            "description": "Generate SEO titles, descriptions, and a Substack slug for supported article destinations. SEO metadata is generated automatically on Revenue Writer, Full Agentic Mode, and Teams & Agencies, and for trials or other accounts with article SEO access. Set this option to false to turn it off. X does not support separate article SEO settings.",
      -            "type": "boolean"
      -          },
      -          "contentHtml": {
      -            "description": "Required when creating a new draft. Supports public <img> or <video> elements and {{media:N}} placeholders resolved from media entries. Video articles require Substack as the sole platform. Native Substack paywall markup is <hr data-type=\"paywall\"> at the selected paragraph boundary, or a single {{NARRAREACH_PAYWALL}} token; paywallMarker supports custom tokens. Native subscribe block markup is <div data-type=\"button\" data-kind=\"subscribeCaption\" data-text=\"Subscribe\" data-caption=\"Your caption\"></div> with HTML-escaped attribute values. data-kind=\"subscribe\" represents a button without caption. Ordinary links remain links.",
      -            "type": "string"
      -          },
      -          "coverImage": {
      -            "description": "Optional cover image for a newly created draft, placed at the top of the published body. Supports public HTTPS URLs, data URIs, or base64 image bytes. URL ingestion depends on source-host access. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      -            "properties": {
      -              "data": {
      -                "description": "Data URI or raw base64 image bytes.",
      -                "type": "string"
      -              },
      -              "mimeType": {
      -                "description": "Required for raw base64. Example: image/png.",
      -                "type": "string"
      -              },
      -              "sourceType": {
      -                "enum": [
      -                  "url",
      -                  "data_uri",
      -                  "base64"
      -                ],
      -                "type": "string"
      -              },
      -              "url": {
      -                "description": "Public HTTPS image URL.",
      -                "type": "string"
      -              }
      -            },
      -            "type": "object"
      -          },
      -          "isPaidContent": {
      -            "description": "Whether the Substack article is paid-only. Default false.",
      -            "type": "boolean"
      -          },
      -          "linkedinAuthorUrn": {
      -            "description": "LinkedIn personal profile or Company Page author URN belonging to the connected LinkedIn Articles account.",
      -            "type": "string"
      -          },
      -          "linkedinNewsletterUrn": {
      -            "description": "LinkedIn newsletter URN belonging to the connected LinkedIn Articles account. Required when linkedinPublicationType is newsletter.",
      -            "type": "string"
      -          },
      -          "linkedinPublicationType": {
      -            "description": "LinkedIn destination type. Defaults to an individual article; newsletter represents a user-selected newsletter destination.",
      -            "enum": [
      -              "article",
      -              "newsletter"
      -            ],
      -            "type": "string"
      -          },
      -          "linkedinShareCommentary": {
      -            "description": "Optional LinkedIn share text used when publishing a LinkedIn article.",
      -            "type": "string"
      -          },
      -          "media": {
      -            "description": "Optional inline images or Substack article videos for a newly created draft. Replaces {{media:N}} placeholders in array order; leftovers are appended. kind defaults to image; video requires Substack as the sole platform. Supports public URLs, data URIs, and base64 bytes. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      -            "items": {
      -              "properties": {
      -                "data": {
      -                  "type": "string"
      -                },
      -                "fileName": {
      -                  "type": "string"
      -                },
      -                "kind": {
      -                  "description": "Defaults to image when omitted.",
      -                  "enum": [
      -                    "image",
      -                    "video"
      -                  ],
      -                  "type": "string"
      -                },
      -                "mimeType": {
      -                  "type": "string"
      -                },
      -                "sourceType": {
      -                  "enum": [
      -                    "url",
      -                    "data_uri",
      -                    "base64"
      -                  ],
      -                  "type": "string"
      -                },
      -                "url": {
      -                  "type": "string"
      -                }
      -              },
      -              "type": "object"
      -            },
      -            "type": "array"
      -          },
      -          "mediumNotifyFollowers": {
      -            "description": "Whether to email Medium subscribers about this story. Only valid when platforms includes MEDIUM. Defaults to false (no email). Best-effort: a failure to apply this setting never blocks the publish/schedule and is reported as a warning.",
      -            "type": "boolean"
      -          },
      -          "mediumPublicationId": {
      -            "description": "Optional authorized Medium publication id when platforms includes MEDIUM. Absent means the personal profile. Writer-only access submits for editorial review and leaves the story unscheduled until acceptance. Explicit publication rejection allows personal-profile delivery with a warning; ambiguous submissions remain unpublished for review. Draft-only delivery does not submit to a publication.",
      -            "type": "string"
      -          },
      -          "paywallMarker": {
      -            "description": "Optional custom marker in contentHtml where the selected free preview ends; must appear exactly once. The standard {{NARRAREACH_PAYWALL}} marker is recognized without this field. Creates a native paywall and enables paid access without changing sendToNewsletter.",
      -            "maxLength": 200,
      -            "type": "string"
      -          },
      -          "platforms": {
      -            "items": {
      -              "enum": [
      -                "SUBSTACK",
      -                "MEDIUM",
      -                "LINKEDIN",
      -                "X",
      -                "WORDPRESS",
      -                "GHOST"
      -              ],
      -              "type": "string"
      -            },
      -            "type": "array"
      -          },
      -          "publication": {
      -            "description": "Substack destination as a publication name, handle, or URL, for example \"AI Newsroom\", \"@theainewsroom\", or \"https://theainewsroom.substack.com\". Optional when exactly one active Substack publication is connected; Narrareach selects it automatically. Required when more than one active Substack publication is connected, except that when it is missing Narrareach uses the publication the writer scheduled or published to most recently and says so in substackPublicationSelection.message, with publicationChoices listing the others; tell the writer which one was used. If there is no previous choice, the value is ambiguous, or Narrareach cannot confirm the session publishes there, nothing is scheduled and the result has requiresPublicationChoice: true with publicationChoices (name, handle, url, substackConnectionId). Ask which one they want, then call again with publication set to the chosen handle (and draftId when a draft was already saved).",
      -            "type": "string"
      -          },
      -          "publishMode": {
      -            "description": "Only valid when all selected destinations are WordPress or Ghost. Defaults to publish; draft saves a remote draft at the scheduled time without publication.",
      -            "enum": [
      -              "publish",
      -              "draft"
      -            ],
      -            "type": "string"
      -          },
      -          "scheduledFor": {
      -            "description": "Shared local wall-clock publishing date/time interpreted in timezone, including DST. A Z or explicit UTC offset represents an absolute instant. LinkedIn articles require at least 20 minutes of lead time.",
      -            "type": "string"
      -          },
      -          "sendToNewsletter": {
      -            "description": "Substack email delivery setting. Default true.",
      -            "type": "boolean"
      -          },
      -          "substackConnectionId": {
      -            "deprecated": true,
      -            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      -            "type": "string"
      -          },
      -          "subtitle": {
      -            "description": "Optional article subtitle for newly created drafts. Substack omits subtitles over 250 characters and returns a warning without changing the saved draft.",
      -            "type": "string"
      -          },
      -          "tags": {
      -            "description": "Optional tag list for newly created drafts. Substack receives all supplied tags. Medium receives its supported first 5 topics and returns a warning when extras are omitted. The saved draft remains unchanged.",
      -            "items": {
      -              "maxLength": 50,
      -              "type": "string"
      -            },
      -            "maxItems": 50,
      -            "type": "array"
      -          },
      -          "timezone": {
      -            "description": "IANA timezone the scheduledFor time(s) above are expressed in (e.g. \"Europe/London\"). Default UTC.",
      -            "type": "string"
      -          },
      -          "title": {
      -            "description": "Required when creating a new draft.",
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "platforms",
      -          "scheduledFor",
      -          "timezone",
      -          "title",
      -          "contentHtml",
      -          "addSearchMetadata"
      -        ],
      -        "type": "object"
      -      },
      -      "tool": {
      -        "const": "schedule_article",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "tool",
      -      "arguments"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "arguments": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "clientRequestId": {
      +            "description": "Optional but recommended: your own id for this note, 8 to 80 letters, numbers, hyphens or underscores. Use a new one for each note and the same one when retrying it (for example after a timeout or a rate-limit pause): the retry returns the original result and schedules nothing again. Reusing it with different text, platforms or time is refused.",
      +            "pattern": "^[A-Za-z0-9_-]{8,80}$",
      +            "type": "string"
      +          },
      +          "content": {
      +            "description": "Used only when creating a new note draft.",
      +            "type": "string"
      +          },
      +          "firstReply": {
      +            "description": "Optional first reply for supported destinations. An invalid reply is omitted per platform without cancelling the root post.",
      +            "type": "string"
      +          },
      +          "imageUrls": {
      +            "description": "Optional image URLs or image data URIs to attach to the scheduled note.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "instagramDestinations": {
      +            "description": "Instagram destinations with accountId returned by list_instagram_destinations and optional independent caption. Each account receives its own delivery receipt.",
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "accountId": {
      +                  "type": "string"
      +                },
      +                "caption": {
      +                  "maxLength": 2200,
      +                  "type": "string"
      +                },
      +                "label": {
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "accountId"
      +              ],
      +              "type": "object"
      +            },
      +            "maxItems": 5,
      +            "minItems": 1,
      +            "type": "array"
      +          },
      +          "linkedInAccountId": {
      +            "description": "Optional LinkedIn account id for a connected LinkedIn destination. Absence of both this field and linkedInOrganizationUrn selects the configured default.",
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "linkedInOrganizationUrn": {
      +            "description": "Optional LinkedIn Company Page URN for a connected LinkedIn destination. Requires linkedInAccountId.",
      +            "minLength": 1,
      +            "pattern": "^urn:li:organization:[^\\s]+$",
      +            "type": "string"
      +          },
      +          "platformVersions": {
      +            "additionalProperties": {
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "description": "Optional platform-specific text keyed by platform, e.g. { \"BLUESKY\": \"...\" }. Each supplied version must fit its limit (Bluesky 300, Threads 500, LinkedIn 3000, X 25000) or nothing is scheduled. Saved as the draft’s platform-specific version.",
      +            "type": "object"
      +          },
      +          "platforms": {
      +            "items": {
      +              "enum": [
      +                "SUBSTACK",
      +                "LINKEDIN",
      +                "X",
      +                "BLUESKY",
      +                "THREADS",
      +                "INSTAGRAM",
      +                "FACEBOOK",
      +                "TIKTOK",
      +                "PINTEREST"
      +              ],
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "publication": {
      +            "description": "Substack publication name, handle, or URL selected by the user. Optional when exactly one active Substack publication is connected: Narrareach uses it when its session is ready and says which one was used in substackPublicationSelection.message (source \"sole_connection\"); if the session needs a sync or the profile cannot be verified, nothing is scheduled and the result says what to fix. In a team workspace with one publication, or when a writer who is also a team member omits workspace, nothing is scheduled until the writer confirms it (requiresPublicationChoice: true, publicationChoiceReason: \"confirmation_required\"). Notes publish from the profile signed in to that connection, including publications sharing one login. Unverified or mismatched profile identity returns action_required without publishing. Notes are profile-level: when it is missing and all of the writer’s publications are signed in to one Substack profile, no choice is needed and the note posts from that profile. Only when the publications span two or more Substack profiles does the writer choose a profile: Narrareach uses the one they chose most recently (and says so in substackPublicationSelection.message), or, with no previous choice, nothing is scheduled and the result has requiresPublicationChoice: true, choiceScope: \"profile\" and publicationChoices (one per profile); ask the user, then call again with substackConnectionId set to the chosen publicationChoices[].substackConnectionId. An ambiguous publication value also returns publicationChoices.",
      +            "type": "string"
      +          },
      +          "scheduledFor": {
      +            "description": "Local wall-clock publishing date/time interpreted in timezone, including DST (e.g. \"2026-07-01T14:30:00\" means 2:30 PM). A Z or explicit UTC offset represents an absolute instant instead.",
      +            "type": "string"
      +          },
      +          "socialAccountIds": {
      +            "additionalProperties": {
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "description": "Optional account to post to on Threads, Facebook, TikTok, Pinterest or X, keyed by platform, e.g. { \"THREADS\": \"<accountId>\" }, with accountId values from list_social_accounts. Omit a platform to use its only account or its default. Required for a platform where list_social_accounts reports accountChoiceRequired; ask the writer which account rather than picking one.",
      +            "type": "object"
      +          },
      +          "substackConnectionId": {
      +            "deprecated": true,
      +            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      +            "type": "string"
      +          },
      +          "threadsTopicTag": {
      +            "description": "Optional Threads topic tag. Threads must be selected; maximum 50 characters.",
      +            "type": "string"
      +          },
      +          "timezone": {
      +            "description": "IANA timezone the scheduledFor time above is expressed in (e.g. \"Europe/London\"). Default UTC.",
      +            "type": "string"
      +          },
      +          "videoUrls": {
      +            "description": "Optional video URLs or video data URIs to attach to the scheduled note.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "workspace": {
      +            "description": "Authorized team workspace name or id for team scheduling. Absence selects the authenticated user’s personal account.",
      +            "type": "string"
      +          },
      +          "writer": {
      +            "description": "Authorized team writer name, handle, or id. \"me\" selects the linked team voice. Required when a team workspace has multiple writers.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "scheduledFor",
      +          "platforms",
      +          "timezone",
      +          "content",
      +          "clientRequestId"
      +        ],
      +        "type": "object"
      +      },
      +      "tool": {
      +        "const": "schedule_note",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "tool",
      +      "arguments"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "arguments": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "addSearchMetadata": {
      +            "description": "Generate SEO titles, descriptions, and a Substack slug for supported article destinations. SEO metadata is generated automatically on Revenue Writer, Full Agentic Mode, and Teams & Agencies, and for trials or other accounts with article SEO access. Set this option to false to turn it off. X does not support separate article SEO settings.",
      +            "type": "boolean"
      +          },
      +          "contentHtml": {
      +            "description": "Required when creating a new draft. Supports public <img> or <video> elements and {{media:N}} placeholders resolved from media entries. Video articles require Substack as the sole platform. Native Substack paywall markup is <hr data-type=\"paywall\"> at the selected paragraph boundary, or a single {{NARRAREACH_PAYWALL}} token; paywallMarker supports custom tokens. A Substack Freewall (free and paid subscribers keep reading) is <hr data-type=\"paywall\" data-access=\"subscribers\">, or set freewall to true. Native subscribe block markup is <div data-type=\"button\" data-kind=\"subscribeCaption\" data-text=\"Subscribe\" data-caption=\"Your caption\"></div> with HTML-escaped attribute values. data-kind=\"subscribe\" represents a button without caption. Ordinary links remain links.",
      +            "type": "string"
      +          },
      +          "coverImage": {
      +            "description": "Optional cover image for a newly created draft, placed at the top of the published body. Supports public HTTPS URLs, data URIs, or base64 image bytes. URL ingestion depends on source-host access. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      +            "properties": {
      +              "data": {
      +                "description": "Data URI or raw base64 image bytes.",
      +                "type": "string"
      +              },
      +              "mimeType": {
      +                "description": "Required for raw base64. Example: image/png.",
      +                "type": "string"
      +              },
      +              "sourceType": {
      +                "enum": [
      +                  "url",
      +                  "data_uri",
      +                  "base64"
      +                ],
      +                "type": "string"
      +              },
      +              "url": {
      +                "description": "Public HTTPS image URL.",
      +                "type": "string"
      +              }
      +            },
      +            "type": "object"
      +          },
      +          "freewall": {
      +            "description": "Make the article's single wall divider (or paywallMarker) a Substack Freewall: everyone sees the content above it; free and paid subscribers keep reading below it. Requires SUBSTACK and a new draft (title and contentHtml). The publication must have Substack Freewalls available. Default false.",
      +            "type": "boolean"
      +          },
      +          "isPaidContent": {
      +            "description": "Whether the Substack article is paid-only. Default false. Do not combine with freewall.",
      +            "type": "boolean"
      +          },
      +          "linkedinAuthorUrn": {
      +            "description": "LinkedIn personal profile or Company Page author URN belonging to the connected LinkedIn Articles account.",
      +            "type": "string"
      +          },
      +          "linkedinNewsletterUrn": {
      +            "description": "LinkedIn newsletter URN belonging to the connected LinkedIn Articles account. Required when linkedinPublicationType is newsletter.",
      +            "type": "string"
      +          },
      +          "linkedinPublicationType": {
      +            "description": "LinkedIn destination type. Defaults to an individual article; newsletter represents a user-selected newsletter destination.",
      +            "enum": [
      +              "article",
      +              "newsletter"
      +            ],
      +            "type": "string"
      +          },
      +          "linkedinShareCommentary": {
      +            "description": "Optional LinkedIn share text used when publishing a LinkedIn article.",
      +            "type": "string"
      +          },
      +          "media": {
      +            "description": "Optional inline images or Substack article videos for a newly created draft. Replaces {{media:N}} placeholders in array order; leftovers are appended. kind defaults to image; video requires Substack as the sole platform. Supports public URLs, data URIs, and base64 bytes. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
      +            "items": {
      +              "properties": {
      +                "data": {
      +                  "type": "string"
      +                },
      +                "fileName": {
      +                  "type": "string"
      +                },
      +                "kind": {
      +                  "description": "Defaults to image when omitted.",
      +                  "enum": [
      +                    "image",
      +                    "video"
      +                  ],
      +                  "type": "string"
      +                },
      +                "mimeType": {
      +                  "type": "string"
      +                },
      +                "sourceType": {
      +                  "enum": [
      +                    "url",
      +                    "data_uri",
      +                    "base64"
      +                  ],
      +                  "type": "string"
      +                },
      +                "url": {
      +                  "type": "string"
      +                }
      +              },
      +              "type": "object"
      +            },
      +            "type": "array"
      +          },
      +          "mediumNotifyFollowers": {
      +            "description": "Whether to email Medium subscribers about this story. Only valid when platforms includes MEDIUM. Defaults to false (no email). Best-effort: a failure to apply this setting never blocks the publish/schedule and is reported as a warning.",
      +            "type": "boolean"
      +          },
      +          "mediumPublicationId": {
      +            "description": "Optional authorized Medium publication id when platforms includes MEDIUM. Absent means the personal profile. Writer-only access submits for editorial review and leaves the story unscheduled until acceptance. Explicit publication rejection allows personal-profile delivery with a warning; ambiguous submissions remain unpublished for review. Draft-only delivery does not submit to a publication.",
      +            "type": "string"
      +          },
      +          "paywallMarker": {
      +            "description": "Optional custom marker in contentHtml where the selected free preview ends; must appear exactly once. The standard {{NARRAREACH_PAYWALL}} marker is recognized without this field. Creates a native paywall and enables paid access without changing sendToNewsletter.",
      +            "maxLength": 200,
      +            "type": "string"
      +          },
      +          "platforms": {
      +            "items": {
      +              "enum": [
      +                "SUBSTACK",
      +                "MEDIUM",
      +                "LINKEDIN",
      +                "X",
      +                "WORDPRESS",
      +                "GHOST"
      +              ],
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "publication": {
      +            "description": "Substack destination as a publication name, handle, or URL, for example \"AI Newsroom\", \"@theainewsroom\", or \"https://theainewsroom.substack.com\". Optional when exactly one active Substack publication is connected; Narrareach selects it automatically. Required when more than one active Substack publication is connected, except that when it is missing Narrareach uses the publication the writer scheduled or published to most recently and says so in substackPublicationSelection.message, with publicationChoices listing the others; tell the writer which one was used. If there is no previous choice, the value is ambiguous, or Narrareach cannot confirm the session publishes there, nothing is scheduled and the result has requiresPublicationChoice: true with publicationChoices (name, handle, url, substackConnectionId). Ask which one they want, then call again with publication set to the chosen handle (and draftId when a draft was already saved).",
      +            "type": "string"
      +          },
      +          "publishMode": {
      +            "description": "Only valid when all selected destinations are WordPress or Ghost. Defaults to publish; draft saves a remote draft at the scheduled time without publication.",
      +            "enum": [
      +              "publish",
      +              "draft"
      +            ],
      +            "type": "string"
      +          },
      +          "scheduledFor": {
      +            "description": "Shared local wall-clock publishing date/time interpreted in timezone, including DST. A Z or explicit UTC offset represents an absolute instant. LinkedIn articles require at least 20 minutes of lead time.",
      +            "type": "string"
      +          },
      +          "sendToNewsletter": {
      +            "description": "Substack email delivery setting. Default true.",
      +            "type": "boolean"
      +          },
      +          "substackConnectionId": {
      +            "deprecated": true,
      +            "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
      +            "type": "string"
      +          },
      +          "subtitle": {
      +            "description": "Optional article subtitle for newly created drafts. Substack omits subtitles over 250 characters and returns a warning without changing the saved draft.",
      +            "type": "string"
      +          },
      +          "tags": {
      +            "description": "Optional tag list for newly created drafts. Substack receives all supplied tags. Medium receives its supported first 5 topics and returns a warning when extras are omitted. The saved draft remains unchanged.",
      +            "items": {
      +              "maxLength": 50,
      +              "type": "string"
      +            },
      +            "maxItems": 50,
      +            "type": "array"
      +          },
      +          "timezone": {
      +            "description": "IANA timezone the scheduledFor time(s) above are expressed in (e.g. \"Europe/London\"). Default UTC.",
      +            "type": "string"
      +          },
      +          "title": {
      +            "description": "Required when creating a new draft.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "platforms",
      +          "scheduledFor",
      +          "timezone",
      +          "title",
      +          "contentHtml",
      +          "addSearchMetadata"
      +        ],
      +        "type": "object"
      +      },
      +      "tool": {
      +        "const": "schedule_article",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "tool",
      +      "arguments"
      +    ],
      +    "type": "object"
      +  }
      +]
  8. Added

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint and idempotentHint, and the description reinforces this with 'No scheduling occurs' plus the approval round-trip to the conversation. It adds real constraints beyond the annotations — article scheduling is personal-account only, and account identifiers must be explicit rather than implicit multi-account defaults — though it does not say how large a plan can be or what a rejection looks like.

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?

The core purpose and the no-scheduling guarantee are front-loaded, then the content requirements follow in a dense but scannable list. Every sentence carries operative information, though the run of requirements in the middle is long enough that an agent could lose the ordering.

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 with deeply nested oneOf arguments, an output schema and full annotations, the description covers the workflow, the approval gate, account-selection discipline and the required content payload. The remaining details — call limits, result shape — are already supplied by the schema and output schema.

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?

Top-level schema coverage is 0% (neither calls nor voice carries a description), so the description has to carry weight, and it does: full inline content instead of draftId, dates with explicit UTC offsets and time zones, explicit account ids, subscriber-email/audience/SEO choices, and a clientRequestId per note. It still does not explain the shape of the voice object or the per-call constraints inherited from the nested schemas.

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 two sentences give a precise verb and resource — show the exact proposed schedule_note and schedule_article calls for review — and immediately bound the scope with 'No scheduling occurs.' That is enough to separate it from the mutating siblings schedule_note and schedule_article 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?

It states the position in the workflow (review happens before any scheduling), the exit condition ('execute scheduling only after that approval'), where the voice parameter comes from (open_publishing_studio), and what to do when the plan cannot be represented ('review in the conversation instead'). Those are explicit use, prerequisite and fallback rules.

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