Skip to main content
Glama

Server Details

Schedule and post to Instagram, TikTok, YouTube, X, Facebook, LinkedIn, Pinterest, Threads, Bluesky.

Ownership verified
Status
Healthy
Uptime
90.4% over 41 days
OAuth
Works in Glama
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL

TDQS

A4.2/5.0

Scored across 31 tools

Disambiguation4/5

Most tools target clearly distinct resources and actions, and descriptions cross-reference alternatives well. However, the upload cluster (upload_media, get_upload_urls, get_upload_ticket, open_upload_widget) and analytics cluster (overview, timeseries, breakdown, post_analytics) contain multiple similar-sounding tools that require careful reading to select correctly.

Naming Consistency5/5

Tool names consistently use snake_case with a predictable verb_noun pattern (create_post, list_posts, get_analytics_overview, pause_recurring_post). The few noun-like or compound names still fit the same convention and remain readable.

Tool Count2/5

31 tools is too many for a typical MCP server surface, exceeding the recommended range and making the set unwieldy. Several analytics, upload, and recurring-post operations could be consolidated, and get_upload_ticket is explicitly internal rather than intended for direct agent use.

Completeness4/5

The surface covers the core social publishing lifecycle: create/update/delete/schedule/publish posts, recurring posts, analytics, media uploads, AI generation, accounts, and workspaces. Minor gaps exist, such as no update_recurring_post tool and limited account/media management, but the main workflows are well covered.

Available Tools

31 tools
bulk_schedule_postsBulk Schedule Posts
Destructive
Inspect

Schedule up to 100 posts in one call to the same platforms and accounts. Each item supplies its own text, contentType, scheduledAt, and optional media; platforms, connection-id arrays, timezone, and platform configs are shared by every item, though an item may carry its own tiktokConfigs, youtubeConfigs, instagramConfigs, facebookConfigs or pinterestConfigs to replace the shared ones. Items are processed independently: each is validated and created like create_post, so one bad item fails alone while the rest are scheduled. Returns { totalScheduled, totalFailed, results[] } with a postId or errorMessage per item, in input order; read every row. An item with a past scheduledAt publishes immediately rather than being rejected. Call list_accounts first; TikTok needs tiktokConfigs with privacyLevel and Pinterest needs pinterestConfigs with boardId. Use create_post for a single post or a draft; this tool has no draft mode. These posts publish publicly to the user's social accounts: show the user every item's text, media and time plus the accounts, and get their confirmation before calling. Each call creates new posts, so calling again after an error or timeout can publish duplicates; check list_posts first.

ParametersJSON Schema
NameRequiredDescriptionDefault
postsYes1 to 100 posts to schedule; each is created independently
pageIdsNoFacebook page account ids from list_accounts (the account id; its pageId value is also accepted). Facebook has no connection-id array
timezoneNoIANA timezone stored with every post for display; does not shift scheduledAtUTC
platformsYesTarget platforms shared by every item. Each needs its connection-id array (pageIds for FACEBOOK)
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another
tiktokConfigsNoTikTok per-connection config. Each entry needs connectionId + privacyLevel at minimum
youtubeConfigsNoYouTube per-connection config with video title, tags, privacy, etc.
facebookConfigsNoFacebook per-page config with post type and video title. pageId must match an entry in pageIds
instagramConfigsNoInstagram per-connection config to set post type (FEED, REEL, STORY) and publish a reel as a trial reel
pinterestConfigsNoPinterest per-connection config. Each entry needs connectionId + boardId; there is no API to list boards, so ask the user for the board id
tiktokConnectionIdsNoTikTok account connection IDs to post from
blueskyConnectionIdsNoBluesky account connection IDs to post from
threadsConnectionIdsNoThreads account connection IDs to post from
twitterConnectionIdsNoX (Twitter) account connection IDs to post from
youtubeConnectionIdsNoYouTube channel connection IDs to post from
linkedinConnectionIdsNoLinkedIn account connection IDs to post from
mastodonConnectionIdsNoMastodon account connection IDs to post from
instagramConnectionIdsNoInstagram account connection IDs to post from
pinterestConnectionIdsNoPinterest account connection IDs to post from

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with totalScheduled, totalFailed, and results: one { postId, success, isScheduled, scheduledAt, errorMessage } per input item, in input order.
create_postCreate Post
Destructive
Inspect

Create one post for one or more platforms: publish now, schedule, or save a draft. Omit scheduledAt to publish immediately; a future scheduledAt sets status SCHEDULED; saveAsDraft stores it as DRAFT and defers validation to publish_draft. Publishing runs asynchronously per platform, so the response ({ postId, queuedPlatforms, isScheduled, scheduledAt }) is not the outcome; read list_post_results, where each platform succeeds or fails on its own. Call list_accounts first: each platform in platforms needs its connection-id array (linkedinConnectionIds, pageIds for Facebook, and so on), one account per platform. TikTok needs tiktokConfigs with privacyLevel; Pinterest needs pinterestConfigs with boardId. For a LinkedIn document (PDF, slides or Word file) use contentType DOCUMENT with the one file in mediaUrls and only LINKEDIN in platforms. mediaUrls must come from upload_media, or the call fails with "Media file(s) not found in storage". Pass recurrence with a future scheduledAt to repeat the post daily, weekly or monthly; the response then adds recurringPostId and postId is the first occurrence. Use bulk_schedule_posts for many posts on the same accounts, and update_post or publish_draft for an existing post. This publishes publicly to the user's social accounts: unless saveAsDraft is set, show the user the final text, media, accounts and time or repeat schedule, and get their confirmation before calling. Each call creates a new post, so calling again after an error or timeout can publish a duplicate; check list_posts first.

ParametersJSON Schema
NameRequiredDescriptionDefault
textNoDefault post text shared across platforms
pageIdsNoFacebook page account ids from list_accounts (the account id; its pageId value is also accepted). Facebook has no connection-id array
timezoneNoIANA timezone stored with the post for display (e.g. "America/New_York"); it does not shift scheduledAtUTC
mediaUrlsNoMedia URLs to attach. Use publicUrl values from upload_media or get_upload_urls; the same publicUrl may be reused across posts. Do not reuse mediaUrls read back from a published post, which may be expiring platform links
platformsYesTarget platforms (e.g. ["LINKEDIN", "TWITTER"]). Each one needs its matching connection-id array (pageIds for FACEBOOK) filled with ids from list_accounts
recurrenceNoRepeat the post on a schedule. Needs a future scheduledAt, which becomes the first post and sets the time of day in timezone. Cannot be combined with saveAsDraft or TIKTOK. Missed slots, for example while paused, are skipped and never published late. X and LinkedIn reject identical text, so use spintax such as {Hi|Hello} to vary each post. Manage the series with list_recurring_posts, pause_recurring_post, resume_recurring_post and delete_recurring_post
contentTypeYesContent type: TEXT, IMAGE, VIDEO, CAROUSEL, or DOCUMENT. Must match mediaUrls (CAROUSEL needs several). DOCUMENT publishes one PDF, PPT, PPTX, DOC or DOCX file (max 100 MB, 300 pages) as a LinkedIn document post and is LinkedIn only: put exactly that one file in mediaUrls, target only LINKEDIN, and set the title with linkedinConfigs
saveAsDraftNoSave as DRAFT instead of publishing or scheduling; publish later with publish_draft
scheduledAtNoAbsolute ISO 8601 instant to schedule (e.g. "2026-03-15T10:00:00Z"). Omit to post immediately; a past time also posts immediately
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another
thumbnailUrlNoCustom thumbnail image URL for video posts
mediaAltTextsNoAlt text per image, in the same order as mediaUrls (max 1000 characters each; use "" to skip an image). Sent to X, Bluesky, Mastodon, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it
platformTextsNoPer-platform caption overrides
tiktokConfigsNoTikTok per-connection config. Each entry needs connectionId + privacyLevel at minimum
youtubeConfigsNoYouTube per-connection config with video title, tags, privacy, etc.
facebookConfigsNoFacebook per-page config with post type and video title. pageId must match an entry in pageIds
linkedinConfigsNoLinkedIn per-connection config: documentTitle names a DOCUMENT post. connectionId must match an entry in linkedinConnectionIds
instagramConfigsNoInstagram per-connection config to set post type (FEED, REEL, STORY) and publish a reel as a trial reel
pinterestConfigsNoPinterest per-connection config. Each entry needs connectionId + boardId; there is no API to list boards, so ask the user for the board id
tiktokConnectionIdsNoTikTok account connection IDs to post from
blueskyConnectionIdsNoBluesky account connection IDs to post from
threadsConnectionIdsNoThreads account connection IDs to post from
thumbnailTimestampMsNoGenerate thumbnail from video at this timestamp (milliseconds)
twitterConnectionIdsNoX (Twitter) account connection IDs to post from
youtubeConnectionIdsNoYouTube channel connection IDs to post from
linkedinConnectionIdsNoLinkedIn account connection IDs to post from
mastodonConnectionIdsNoMastodon account connection IDs to post from
instagramConnectionIdsNoInstagram account connection IDs to post from
pinterestConnectionIdsNoPinterest account connection IDs to post from

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with postId, queuedPlatforms (platforms whose publishing job was queued; empty for scheduled posts and drafts), skippedPlatforms, isScheduled, and scheduledAt, plus recurringPostId when recurrence was sent. Publishing is asynchronous: check list_post_results for outcomes.
delete_postDelete PostA
Destructive
Inspect

Delete a post record from AdaptlyPost by id. Use it to cancel a DRAFT or SCHEDULED post before it goes out; a deleted scheduled post will not publish. Deleting never removes content already on a network: for a COMPLETED or PARTIAL_FAILURE post this only drops AdaptlyPost's record, and the live posts stay up until removed on each platform. Prefer update_post to change a post instead of deleting and recreating it. A post in PUBLISHING fails with 409; wait for list_post_results to settle. Only posts in the workspace (the current one unless workspaceId names another) can be deleted; others return "Post not found or access denied". Returns { deleted: true }. Irreversible.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesPost ID to delete, from list_posts or create_post
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with deleted: true once the post record is removed from AdaptlyPost.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations declare destructiveHint=true, but the description goes well beyond them: it clarifies that deletion only drops AdaptlyPost's record while live COMPLETED/PARTIAL_FAILURE posts stay up, discloses the 409 state conflict, the access-denied response for out-of-workspace posts, and that the operation is irreversible.

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

Conciseness4/5

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

Front-loaded with the core action and use case, then layered with edge cases and constraints; nearly every sentence earns its place. The 'Returns { deleted: true }' line is redundant given an output schema exists, a minor efficiency loss.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation tool this is complete: state-dependent behavior, error handling, access-control semantics, sibling alternative, and irreversibility are all covered, and the output schema carries return details.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds meaning on top of the schema by stating the workspace scoping consequence ('Only posts in the workspace... others return "Post not found or access denied"'), which the schema does not express.

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?

Clear specific verb + resource ('Delete a post record from AdaptlyPost by id') with the exact scope of what is affected. It explicitly names the sibling alternative (update_post) and distinguishes cancel-before-publish from removing live content.

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?

Explicit when-to-use (cancel DRAFT/SCHEDULED before it goes out), when-not (prefer update_post instead of delete/recreate), plus the state-specific failure condition (PUBLISHING returns 409; wait for list_post_results). Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_recurring_postDelete Recurring PostA
Destructive
Inspect

Delete a recurring post: the series stops for good and its upcoming SCHEDULED post is deleted. Posts that already went out are kept. Prefer pause_recurring_post when the user may want the series back. To skip a single date, delete that occurrence with delete_post instead; the series continues. Ids outside the workspace (the current one unless workspaceId names another) return "Recurring post not found". Returns { deleted: true }. Irreversible.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesRecurring post ID to delete, from list_recurring_posts
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with deleted: true once the recurring post is removed.

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, and the description goes further by specifying exactly what is destroyed (series + upcoming scheduled post, past posts retained), that the action is irreversible, and that out-of-workspace ids return "Recurring post not found". It also reports the return shape ({ deleted: true }). Rates just under 5 only because it omits permission/auth requirements and any cascade effects on analytics or linked drafts.

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

Conciseness5/5

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

Front-loads the destructive consequence and then layers routing guidance, error behaviour, return value, and irreversibility in short declarative clauses. No sentence is filler, despite covering a lot of ground.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive two-parameter tool with an output schema present, the description supplies everything the agent needs: scope of deletion, irreversibility, sibling routing, and error semantics. Return-value explanation is redundant with the output schema but harmless.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so both id and workspaceId are already documented, giving a baseline of 3. The description adds meaning beyond that by explaining the workspace-scoping consequence tied to workspaceId (ids outside the current workspace yield "Recurring post not found"), which helps the agent reason about cross-workspace misuse.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Delete) and resource (recurring post), and immediately defines the scope of the deletion: the whole series stops permanently and the upcoming scheduled post is removed while already-published posts are kept. It distinguishes itself from the near neighbours delete_post and pause_recurring_post by name without the agent needing to open their schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing rules in both directions: prefer pause_recurring_post when the user might want the series back, and use delete_post to skip a single occurrence so the series continues. It effectively covers when-to-use and when-not-to-use with the alternatives named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

generate_captionGenerate CaptionAInspect

Write a new social media caption from a prompt with AdaptlyPost AI. Returns { caption }, text only; nothing is saved or posted, so pass the caption to create_post, update_post or bulk_schedule_posts yourself. Pass platform and generation targets that platform's character limit; check the returned text before posting. Needs the ai.generate permission, which Admin, Editor and Contributor hold and Viewer does not (403 permission_denied). Each call spends 2 of the member's AI credits (the member who signed in or created the key), refunded if generation fails, unless the member has their own AI provider key connected in AdaptlyPost. With no credits left the call fails: explain that generation is unavailable with the current credit balance and do not retry automatically. To rework a caption you already have, use refine_caption instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
promptYesWhat the caption should say or be about, including tone, audience, hashtags or a call to action (max 2000 characters)
platformNoPlatform the caption is for; generation targets that platform's character limit; check the returned text before posting. Omit for a general caption
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with caption: the generated text.

TDQS

A4.6/5.0
Behavior5/5

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

Far exceeds the annotations (which only mark it as non-read-only, non-idempotent, non-destructive). It discloses that nothing is saved or posted, the ai.generate permission and the exact 403 permission_denied code, the 2-credit cost, the member who is billed, refund-on-failure, the own-provider-key exception, and the no-retry rule when credits are exhausted.

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?

One dense paragraph, front-loaded with the core action and return shape before permissions and billing. Nearly every sentence carries operational value, though the credit/permission detail is lengthy enough that the routing advice gets slightly buried mid-paragraph.

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?

Given an output schema exists, the description need not explain the { caption } payload further, and it volunteers the return shape anyway. Permissions, credit economics, failure handling, and sibling routing together leave nothing an agent needs missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so prompt, platform and workspaceId are already fully documented, so a 3 baseline applies. The description reinforces the platform character-limit behavior and the general-caption fallback, but adds little syntax or semantic nuance beyond what the schema states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Write a new social media caption from a prompt') and immediately names the sibling to use for a different need ('To rework a caption you already have, use refine_caption instead'). An agent can distinguish this from refine_caption, generate_image and create_post without opening any 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?

Explicit routing: generated output must be passed to create_post, update_post or bulk_schedule_posts because nothing is persisted, and existing captions should go to refine_caption. Also states the pre-post check and the no-retry behavior on exhausted credits. All when/when-not/alternatives are covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

generate_imageGenerate ImageA
Destructive
Inspect

Start generating an image from a prompt with AdaptlyPost AI. This is asynchronous: it returns { jobId, sessionId, status } right away with status queued, not the image. Poll get_image_job with the jobId every few seconds until status is completed or failed (usually 10 to 40 seconds), or wait for the image.completed or image.failed webhook if the workspace has one. A completed job carries imageUrl, a public URL you can pass straight into mediaUrls of create_post, so there is no need to run it through upload_media. The image is also saved to the member's AI image studio in AdaptlyPost; reuse sessionId to group related images. Needs the ai.generate permission, which Admin, Editor and Contributor hold and Viewer does not (403 permission_denied). Charges the member's AI credits when generation starts (2 for standard, 4 for premium) unless the member has their own image provider key connected in AdaptlyPost, and refunds them if generation fails. With no credits left the job ends as failed and its error says so: explain that generation is unavailable with the current credit balance and do not retry automatically.

ParametersJSON Schema
NameRequiredDescriptionDefault
modelNostandard (default, 2 credits) or premium (higher fidelity, 4 credits)
promptYesWhat the image should show, including style and composition (max 2000 characters)
qualityNoLOW, MEDIUM or HIGH rendering quality
sessionIdNoImage studio session to add the image to, as returned by an earlier generate_image. Omit to start a new session
aspectRatioNoImage shape (default 1:1). Pick one that suits the target platform, e.g. 9:16 for stories and reels, 4:5 for Instagram feed, 16:9 for YouTube and X
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another
referenceImagesNoUp to 5 public image URLs that steer the style or subject of the result

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with jobId (pass it to get_image_job), sessionId, and status (queued).

TDQS

A4.6/5.0
Behavior5/5

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

With annotations covering mutation/safety hints, the description adds substantial operational context: asynchronous job semantics, returned { jobId, sessionId, status }, polling vs webhook, 10-40 second typical duration, permission requirement (ai.generate, with role exclusions and 403), credit cost and refund behavior, no-credit failure mode, and explicit advice not to retry. This far exceeds what the annotations disclose.

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 description is front-loaded with the core action and async behavior, and every sentence carries information useful for correct invocation or integration. It is necessarily long given the async job, credit, permission, webhook, and integration details, though a bulleted structure could improve scanability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex asynchronous, credit-consuming, permission-gated tool, the description covers all agent-relevant behavior: return shape, polling/webhook options, timing, integration with create_post, permission errors, credit costs, refunds, and no-credit guidance. The presence of an output schema does not leave gaps, and the description is complete for correct use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the parameter descriptions already document prompt, model, quality, aspectRatio, sessionId, workspaceId, and referenceImages thoroughly. The description adds only marginal parameter meaning, such as reusing sessionId to group related images; baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Start generating an image from a prompt') and immediately distinguishes the tool from siblings by naming get_image_job for polling, create_post for using the result, and upload_media as unnecessary. An agent can identify exactly what this tool does and how it differs from adjacent tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit post-call workflow (poll get_image_job every few seconds until completed/failed, or wait for image.completed/image.failed webhook) and routes the result into create_post's mediaUrls instead of upload_media. It also states when not to retry automatically after a no-credit failure, covering both how and when to use the tool versus alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_analytics_overviewGet Analytics OverviewA
Read-only
Inspect

Workspace-wide performance for a date window: views, likes, comments, shares, followers, posts published, average views per post and engagement rate, each as { value, previousValue, deltaPercent } against the window of the same length just before it. Use this for "how did we do this month" questions and for follower counts. Metrics are summed over the selected platforms; partialMetrics names metrics some selected platform cannot report, and a metric no platform reports is null. Analytics cover the last 180 days and refresh every few hours (lastSyncedAt says when); if the user just published, call trigger_analytics_sync first. Use get_analytics_timeseries for a trend, get_platform_breakdown to compare platforms, and list_post_analytics for individual posts.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesEnd of the reporting window (ISO 8601). Must not be earlier than from
fromYesStart of the reporting window as an ISO 8601 date or instant (e.g. "2026-08-01"). Metrics cover posts published between from and to; the comparison window is the same length immediately before from
platformsNoRestrict to these platforms; omit for every platform with analytics. X (TWITTER) and MASTODON have no analytics and are ignored; LinkedIn analytics are pending platform approval and return no data yet
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with views, likes, comments, shares, followers, postsCount, avgViewsPerPost and engagementRate (each { value, previousValue, deltaPercent }), partialMetrics, and lastSyncedAt.

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already declare a safe read (readOnlyHint=true, destructiveHint=false), yet the description adds substantial behavioral context: 180-day coverage limit, multi-hour refresh cadence with lastSyncedAt, summed-over-platforms semantics, partialMetrics for partial coverage, and null for wholly unreported metrics. None of this is in the annotations.

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

Conciseness5/5

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

Front-loaded with the metric list and return shape, then usage routing, then preconditions, then caveats. Dense but every sentence carries distinct information; no filler or restatement.

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 read-only analytics tool with an output schema, the description supplies everything an agent needs: metric set, comparison semantics, coverage limits, refresh behavior, platform exceptions, and alternatives. Return formatting is correctly left to the 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?

Schema coverage is 100%, so the baseline is 3, and the description goes beyond it by explaining the comparison-window math and platform caveats (X/MASTODON ignored, LinkedIn pending) that the schema only partially encodes. It doesn't add syntax details beyond the schema, but the extra cross-parameter semantics justify a bump.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Workspace-wide performance for a date window') and enumerates exactly which metrics are returned, including their shape ({ value, previousValue, deltaPercent }). It clearly distinguishes itself from get_analytics_timeseries, get_platform_breakdown, and list_post_analytics by naming each.

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?

Explicitly names the use case ('how did we do this month' questions, follower counts), names the three alternative tools with the condition that selects each, and adds a precondition ('if the user just published, call trigger_analytics_sync first'). This is textbook routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_analytics_sync_statusGet Analytics Sync StatusA
Read-only
Inspect

How fresh the analytics are, per connected account. Returns syncInProgress, lastSyncedAt, historyHorizonAt (the earliest date any account has data for; earlier dates have no data rather than zero activity) and platforms: one row per account with status (IDLE, QUEUED, SYNCING, FAILED), lastSyncedAt, lastErrorMessage, historyHorizonAt and needsAnalyticsReconnect. When needsAnalyticsReconnect is true the account was connected before analytics permissions existed and returns nothing until the user reconnects it (a connect link works); tell them, do not keep querying. Call this when numbers look stale or empty, and after trigger_analytics_sync to see the run finish. Takes only the optional workspaceId.

ParametersJSON Schema
NameRequiredDescriptionDefault
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with accountGroupId, syncInProgress, lastSyncedAt, historyHorizonAt, and platforms: one { platform, connectionId, accountName, status, lastSyncedAt, lastErrorMessage, historyHorizonAt, lastDiscoveryAt, needsAnalyticsReconnect } per connected account.

TDQS

A4.1/5.0
Behavior5/5

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

Goes well beyond the readOnly/non-destructive annotations by disclosing the sync state enum, the meaning of historyHorizonAt ('earlier dates have no data rather than zero activity'), lastErrorMessage, and the reconnect remediation including the instruction 'tell them, do not keep querying'. This is exactly the kind of behavioral context annotations cannot carry.

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

Conciseness4/5

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

Front-loaded with the core purpose in one clause, and every subsequent sentence carries real information. The field enumeration is dense and somewhat list-like, and it partly duplicates the output schema, but nothing is wasted filler.

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?

Covers purpose, triggers, sub-field meaning, failure states, and remediation, so an agent can both decide to call it and interpret the response. With an output schema present it need not explain return values, yet it does so usefully and consistently.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single workspaceId parameter is fully documented in the schema (id source, omission behavior, cross-workspace consistency). The description only adds 'Takes only the optional workspaceId', which is redundant, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a precise statement of what the tool reports ('How fresh the analytics are, per connected account') and enumerates the specific return fields, making it clearly distinct from get_analytics_overview and get_analytics_timeseries in intent. It stops short of explicitly naming those siblings as alternatives, so it lands at 4 rather than 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete triggers: 'Call this when numbers look stale or empty, and after trigger_analytics_sync to see the run finish' — a clear when-to-use plus an explicit companion tool. It also implicitly says when NOT to keep calling (needsAnalyticsReconnect accounts), but does not contrast with the other analytics siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_analytics_timeseriesGet Analytics TimeseriesA
Read-only
Inspect

Views, likes, comments, shares, followers, posts published and engagement rate bucketed by day (default), week or month across the window, for trend questions such as "how are views moving" or "when did followers jump". Returns { points } with one { date, ...metrics } per bucket; followers is the latest count at the end of the bucket, the other counters sum posts published inside it, and a metric no selected platform reports is null. Use get_analytics_overview for totals and list_post_analytics to see which posts drove a spike.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesEnd of the reporting window (ISO 8601). Must not be earlier than from
fromYesStart of the reporting window as an ISO 8601 date or instant (e.g. "2026-08-01"). Metrics cover posts published between from and to; the comparison window is the same length immediately before from
platformsNoRestrict to these platforms; omit for every platform with analytics. X (TWITTER) and MASTODON have no analytics and are ignored; LinkedIn analytics are pending platform approval and return no data yet
granularityNoDAILY (default), WEEKLY, or MONTHLY buckets
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with points: one { date, views, likes, comments, shares, followers, postsCount, engagementRate } per bucket, in date order.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already cover the safety profile (readOnlyHint true, destructiveHint false, openWorldHint false), so the bar is lower. The description adds valuable behavioral detail beyond annotations: the return shape ({ points } with one { date, ...metrics } per bucket), the aggregation semantics (followers is the latest count at bucket end, other counters sum posts published inside it), and null handling for metrics not reported by a selected platform.

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

Conciseness5/5

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

The description is front-loaded with what the tool does, then returns semantics, then alternatives. Every sentence earns its place: the first defines the tool, the second describes the output and aggregation rules, the third routes to siblings. No filler.

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?

With an output schema present, the description need not explain return values, but it does so succinctly where it matters for interpretation. Combined with full schema coverage and clear annotations, an agent has everything needed to invoke the tool correctly: purpose, alternatives, return shape, and aggregation rules.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all five parameters in detail, including platform restrictions, granularity default, and workspaceId usage. The description adds little parameter-specific meaning beyond what the schema provides; it reinforces platform behavior indirectly through the null-returning metric note, but that is not parameter guidance per se.

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 description names the specific metrics (views, likes, comments, shares, followers, posts published, engagement rate) and the bucketing dimension (day, week, month), so the agent knows exactly what the tool produces. It also distinguishes the tool from siblings by naming get_analytics_overview for totals and list_post_analytics for post-level drill-down.

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?

Explicitly states the use case (trend questions such as 'how are views moving' or 'when did followers jump') and names the two alternatives with their respective roles. This gives the agent a clear routing decision without needing to infer from schemas.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_image_jobGet Image JobA
Read-only
Inspect

Read the state of an image started with generate_image. Returns { jobId, sessionId, status, imageUrl, imageId, error }; status moves from queued through processing and generating to completed or failed. When completed, imageUrl is a public URL ready for mediaUrls in create_post. When failed, error says why, for example no credits left; a failed job is final, so do not poll it again. Poll every few seconds while status is queued, processing or generating, and stop after a couple of minutes. Only jobs started by the same member are visible. Needs the ai.generate permission, which Admin, Editor and Contributor hold and Viewer does not (403 permission_denied). Reading a job spends no credits.

ParametersJSON Schema
NameRequiredDescriptionDefault
jobIdYesjobId returned by generate_image
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with jobId, sessionId, status (queued, processing, generating, completed or failed), imageUrl (null until completed), imageId, and error (null unless failed).

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already declare readOnlyHint/destructiveHint=false, but the description adds substantial behavioral context: the status state machine, terminal failure semantics, member-scoped visibility, the ai.generate permission with 403 permission_denied and which roles hold it, and that reading spends no credits.

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?

Dense but front-loaded: purpose first, then return shape, lifecycle, usage cadence, and constraints. Every sentence carries operative information, though the explicit return-value enumeration partially duplicates the output schema.

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 polling tool, the definition covers lifecycle states, terminal conditions, polling cadence, permissions, visibility scoping, and cost. With an output schema present, the return description is a bonus rather than a necessity, so nothing an agent needs to invoke this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents jobId and workspaceId in detail; schema description even repeats 'jobId returned by generate_image.' The description adds only marginal meaning (same-member visibility constraints) beyond the structured fields, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Read the state of an image started with generate_image.' It explicitly ties the tool to its sibling generate_image as the producer of the job, so an agent can distinguish polling from generation without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use (poll every few seconds while queued/processing/generating), when-to-stop (after a couple of minutes), and when-not-to-use (a failed job is final, do not poll again). It also directs the agent to consume imageUrl via create_post.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_platform_breakdownGet Platform BreakdownA
Read-only
Inspect

The overview metrics split per platform for a date window, for "which platform performs best" comparisons. Returns { platforms }: one row per platform with analytics data, carrying followers, views, likes, comments, shares, postsCount, avgViewsPerPost and engagementRate (each { value, previousValue, deltaPercent }) plus supportedMetrics, the metrics that platform actually reports; compare only metrics both platforms list there. Takes no platform filter. Use get_analytics_overview for the combined total.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesEnd of the reporting window (ISO 8601). Must not be earlier than from
fromYesStart of the reporting window as an ISO 8601 date or instant (e.g. "2026-08-01"). Metrics cover posts published between from and to; the comparison window is the same length immediately before from
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with platforms: one { platform, followers, views, likes, comments, shares, postsCount, avgViewsPerPost, engagementRate, supportedMetrics } per platform.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already establish readOnly/safe/no-destructive behavior, so the bar is lower. The description adds genuine behavioral context beyond annotations: the shape of the response ({platforms} rows), which metrics each row carries, per-metric {value, previousValue, deltaPercent} semantics, and the supportedMetrics caveat about comparing only commonly-reported metrics.

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?

Purpose and comparison use case are front-loaded, and the alternative-tool routing closes the paragraph. It is dense but every clause carries meaning; the field-level enumeration is somewhat verbose relative to the output schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

A read-only analytics query with full schema coverage, annotations, and an output schema — nothing needed to invoke it correctly is missing. It arguably over-explains return fields that the output schema already supplies.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so from/to/workspaceId are already fully documented, and the baseline is 3. The description only adds that no platform filter exists, which is marginal beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource plus scope: 'overview metrics split per platform for a date window.' It even names the use case ('which platform performs best') and explicitly contrasts with the sibling get_analytics_overview, so an agent can select it 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?

Explicit routing: use get_analytics_overview for the combined total, and this one for per-platform comparison. It also rules out a platform filter ('Takes no platform filter') and gives a comparison caveat about only comparing metrics both platforms report.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_postGet PostA
Read-only
Inspect

Get one post's full record by id: text, contentType, status, scheduledAt, timezone, and a platforms array with each target's connection, status, errorMessage, and media. Visible only within the workspace (the current one unless workspaceId names another); any other id returns "Post not found or access denied". Use this to inspect content before update_post or publish_draft. Use list_post_results instead when you only need per-platform publishing outcomes and the platformIds for retry_failed_platforms, and list_posts to find ids by status, platform, or date. Post ids come from create_post, bulk_schedule_posts, or list_posts.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesPost ID from create_post, bulk_schedule_posts, or list_posts
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoThe full post record: id, status, contentType, text, scheduledAt, timezone, mediaUrls, createdAt, updatedAt, recurringPostId and occurrenceAt (set when the post is an occurrence of a recurring post; occurrenceAt is its slot in the series and stays the same when the post is rescheduled), and platforms (one entry per target with id, platform, connectionId or pageId, status, errorMessage, platformPostId, postUrl once published, mediaUrls, previewUrls). previewUrls holds one permanent preview image per media item, a still frame for videos; after publishing, mediaUrls may become platform CDN links that expire within days, so show previewUrls instead.

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already declare the safe read profile (readOnlyHint, destructiveHint=false, openWorldHint=false), so the bar is lower. The description nonetheless adds real behavioral context: workspace scoping rules and the exact failure mode ('any other id returns Post not found or access denied'), which preempts confusion about cross-workspace ids.

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?

Dense but front-loaded: the resource and return shape lead, then scoping, then sibling routing. Every sentence carries information, though the field enumeration and id-provenance sentence edge toward redundancy with the schema.

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 two-parameter read tool with an output schema already present, the description covers scope, access failure, provenance, and sibling routing. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both id and workspaceId are already fully documented in the schema. The description largely restates the id provenance ('Post ids come from create_post, bulk_schedule_posts, or list_posts') rather than adding new format or constraint meaning, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get one post's full record by id') and enumerates the returned shape (text, contentType, status, scheduledAt, timezone, platforms array). It is immediately distinguishable from list_posts and list_post_results, which it names explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use ('inspect content before update_post or publish_draft') and when-not-to with named alternatives ('list_post_results instead when you only need per-platform publishing outcomes... list_posts to find ids by status, platform, or date'). Routing is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_recurring_postGet Recurring PostA
Read-only
Inspect

Get one recurring post (series) by id: status, pauseReason and lastError when paused, the schedule (frequency, interval, weekdays, startsAt, timezone, endsOn, maxOccurrences), nextOccurrenceAt (the next slot not yet created as a post; absent once ENDED), occurrenceCount (posts created so far), and the content and platforms each occurrence copies. Ids outside the workspace (the current one unless workspaceId names another) return "Recurring post not found". Ids come from list_recurring_posts, the recurringPostId returned by create_post, or the recurringPostId on a post from get_post or list_posts.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesRecurring post ID from list_recurring_posts, create_post, or a post's recurringPostId
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoThe recurring post: id, userId, status, pauseReason, lastError, frequency, interval, weekdays, startsAt, timezone, endsOn, maxOccurrences, nextOccurrenceAt, occurrenceCount, contentType, text, mediaUrls, mediaAltTexts, thumbnailUrl, platformTypes, platforms, createdAt, and updatedAt.

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnly/non-destructive, so the safety bar is low; the description goes further by disclosing the exact fields returned, the semantic of nextOccurrenceAt (next slot not yet created; absent once ENDED), and the cross-workspace error message. It stops short of describing pagination or auth requirements, but for a read tool that is minor.

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?

One dense but front-loaded sentence that leads with the verb/resource and then enumerates returned data. The field list is long, but each item is meaningful; nothing is padded with filler or restated boilerplate.

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?

With an output schema present, the description needn't re-explain return values, yet it adds the semantics an agent needs (nextOccurrenceAt absence at ENDED, cross-workspace not-found behavior, id provenance). Nothing required to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both id and workspaceId are already documented in the schema, giving a baseline of 3. The description reinforces id sourcing and workspace scoping but adds no syntax or format detail beyond what the schema already carries.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Get) and resource (one recurring post/series) by id, and immediately differentiates from list_recurring_posts by scoping to a single record. An agent can tell it apart from the sibling list tool without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly tells the agent where valid ids come from (list_recurring_posts, create_post's recurringPostId, get_post/list_posts), which is the key prerequisite for calling it. It gives clear context but never states a when-not-to-use case or explicitly contrasts with list_recurring_posts.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_upload_ticketGet Upload TicketA
Destructive
Inspect

Called by the upload box that open_upload_widget shows, once per file, to authorize storing that file in AdaptlyPost media storage. Returns a ticket valid for 5 minutes. Do not call this yourself; call open_upload_widget instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with expiresAt and uploadUrl for the upload box.

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=false, destructiveHint=true and openWorldHint=true, so the mutation/world profile is covered structurally. The description adds genuinely new behavioral context: the ticket's 5-minute validity window and the fact that it is issued by an internal widget rather than the agent. It does not, however, explain what a ticket grants or what happens on expiry.

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

Conciseness5/5

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

Two sentences, zero filler, with the operational constraint (who calls it) and the key return trait (5-minute validity) both front-loaded.

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?

An output schema exists, so return shape need not be described; the description supplies the one non-schema fact an agent needs (don't invoke directly, validity window). Complete for a single-parameter, non-agent-facing tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the sole workspaceId parameter is fully documented in the schema, including scoping rules and the current-workspace default. The description adds no parameter-level meaning, so the baseline 3 is correct.

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?

Names a specific verb and resource (authorize storing one file in media storage, return a ticket) and identifies the exact caller (the upload box shown by open_upload_widget). This cleanly distinguishes it from siblings like upload_media and open_upload_widget.

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?

Explicitly states when not to use it and where to go instead: 'Do not call this yourself; call open_upload_widget instead.' It also gives the invocation cadence (once per file) via the described caller. Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_upload_urlsGet Media Upload URLsAInspect

Get presigned upload URLs for direct file uploads. Returns uploadUrl (PUT your file here) and publicUrl (use in create_post mediaUrls). This only mints a URL. You MUST PUT the file to uploadUrl and confirm a 2xx response before using publicUrl, otherwise create_post/bulk rejects it with "Media file(s) not found in storage". Prefer upload_media for public URLs and for inline files under 30 MB; use this for larger files you hold yourself. For each file, provide fileName and mimeType. Supported types: image/jpeg, image/png, image/webp, video/mp4, video/quicktime, and for LinkedIn DOCUMENT posts application/pdf, application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation, application/msword and application/vnd.openxmlformats-officedocument.wordprocessingml.document; keep the extension in fileName, since the post reads the file type from it. A publicUrl may be reused across any number of posts; the file is kept until the last post referencing it has published.

ParametersJSON Schema
NameRequiredDescriptionDefault
filesYesFiles to get upload URLs for
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with urls: one { uploadUrl, publicUrl, key } entry per requested file.

TDQS

A4.8/5.0
Behavior5/5

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

Goes well beyond the annotations (readOnlyHint=false, destructiveHint=false, openWorldHint=false) by disclosing the two-step upload flow, the exact downstream failure mode ('Media file(s) not found in storage'), and the retention/lifecycle rule that a publicUrl survives until the last referencing post publishes. It also flags that the tool 'only mints a URL', preventing the common mistake of assuming upload already happened. No contradiction with annotations.

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

Conciseness4/5

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

Front-loaded with the purpose and the critical action, then ordered by relevance (requirement, alternative, per-file params, MIME list, lifecycle). The justification is dense but the long MIME enumeration duplicates the schema enum verbatim, which is the one block that does not earn its place.

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?

Despite an output schema existing, the description still explains what the returned fields are for and how to consume them, plus the constraint set (max 20 files implied, allowed types, extension rule, reuse semantics). Nothing an agent needs to call this correctly and follow through on the second step is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so baseline is 3, and the description adds real meaning on top: it tells the agent that fileName and mimeType must be supplied per file, and that the extension in fileName is load-bearing because the post reads file type from it. It also restates the supported MIME set (already in the schema enum) rather than extending it, which caps the score below 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get presigned upload URLs for direct file uploads') and immediately distinguishes the output contract by naming the two returned fields (uploadUrl, publicUrl) and their downstream use. An agent can tell this apart from upload_media without opening either 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?

Explicitly names the alternative and the selection condition: 'Prefer upload_media for public URLs and for inline files under 30 MB; use this for larger files you hold yourself.' It also states the hard requirement (PUT to uploadUrl and confirm 2xx) before the URL is usable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_accountsList Connected AccountsA
Read-only
Inspect

List the social accounts connected to the workspace (the current one unless workspaceId names another) across all ten platforms. Returns { accounts } with id, platform, displayName, username, avatarUrl, status, and pageId for Facebook pages. status is active or unauthorized; an unauthorized account (unauthorizedReason carries the platform's message) is refused with 400 by create_post until the user reconnects it in AdaptlyPost, so leave it out and tell the user. Call this before create_post, update_post, or bulk_schedule_posts: they take these ids, never usernames. Put each id in the array for its platform (linkedinConnectionIds, tiktokConnectionIds, and so on); Facebook page accounts go in pageIds. Not for post history or publishing status: use list_posts or list_post_results for those. Takes only the optional workspaceId.

ParametersJSON Schema
NameRequiredDescriptionDefault
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with accounts: one { id, platform, displayName, username, avatarUrl, status } per connected account, plus unauthorizedReason when status is unauthorized and pageId for Facebook pages. Use id as the connection id (or in pageIds for Facebook).

TDQS

A4.6/5.0
Behavior5/5

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

Annotations only declare the safe read profile; the description adds real behavioral context beyond them: the meaning of status active vs unauthorized, that an unauthorized account is refused with 400 by create_post until reconnection, that unauthorizedReason carries the platform message, and that downstream tools require ids rather than usernames. This is exactly the extra context annotations cannot provide.

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?

Dense but front-loaded: purpose and return shape first, then status semantics, then usage routing and exclusions. Slightly redundant in enumerating the returned fields (id, platform, displayName, etc.) when an output schema already exists, which is the only wasted sentence.

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?

Given a single fully documented optional parameter, a rich output schema, and clear read-only annotations, the description supplies everything else an agent needs: missing or unauthorized accounts, id-vs-username requirements, platform-specific id arrays, and the correct sibling for adjacent tasks.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so workspaceId is already fully documented (including the cross-workspace id scoping rule). The description only adds 'Takes only the optional workspaceId', a small boundary clarification; baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List the social accounts connected to the workspace') with scope across all ten platforms, and names the sibling tools it feeds (create_post, update_post, bulk_schedule_posts) as well as the ones it is not for (list_posts, list_post_results). An agent can distinguish it from every sibling 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?

Explicit sequencing guidance ('Call this before create_post, update_post, or bulk_schedule_posts: they take these ids, never usernames'), explicit exclusions ('Not for post history or publishing status: use list_posts or list_post_results'), and operational guidance to omit unauthorized accounts and inform the user.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_post_analyticsList Post AnalyticsA
Read-only
Inspect

Per-post metrics for posts published inside the window, sorted by a metric or by publish date, paginated. Use it for "top posts", "which post got the most comments" and "how did post X do". Covers posts published through AdaptlyPost and posts discovered on the connected accounts; discovered posts have postId and postPlatformId set to null, while AdaptlyPost posts carry the postId used by get_post. Returns { posts, total, page, limit, hasMore }; each post has platform, publishedAt, title, thumbnailUrl, permalink, accountName and metrics { views, likes, comments, shares, saves, clicks, impressions, reach, engagementRate }, with null for metrics the platform does not report. Sort by VIEWS with a small limit for a top list; PUBLISHED_AT (default) for a chronological review. Not for publishing status: use list_post_results for that.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesEnd of the reporting window (ISO 8601). Must not be earlier than from
fromYesStart of the reporting window as an ISO 8601 date or instant (e.g. "2026-08-01"). Metrics cover posts published between from and to; the comparison window is the same length immediately before from
pageNoPage number, from 1
limitNoPosts per page, 1 to 100
sortByNoMetric to sort by, descending. PUBLISHED_AT (default) lists newest first
platformsNoRestrict to these platforms; omit for every platform with analytics. X (TWITTER) and MASTODON have no analytics and are ignored; LinkedIn analytics are pending platform approval and return no data yet
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with posts (each { id, postId, postPlatformId, platform, publishedAt, title, thumbnailUrl, permalink, accountName, metrics }), total, page, limit, and hasMore.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations declare this a safe read (readOnlyHint=true, destructiveHint=false), and the description adds behavior annotations could not: discovered posts have postId/postPlatformId null, metrics are null where the platform does not report them, and TWITTER/MASTODON are ignored while LinkedIn analytics are pending approval. These are the exact gotchas that would otherwise cause misinterpretation of results.

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?

Purpose, sort guidance and the sibling exclusion are front-loaded, and every clause is informative. It is dense and runs long, and the enumerated return-field list partly duplicates the output schema, keeping it short of a 5.

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?

With an output schema present, the description need not restate return values, yet it supplies the null-semantics and platform-coverage caveats an agent needs to interpret them. Combined with window, sorting, pagination and workspace scoping, nothing required to call or read the tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all seven parameters, and the description stays above baseline by adding operational meaning: sort semantics (descending, PUBLISHED_AT newest first, VIEWS+small limit for a top list) and the platform restriction caveats. It does not materially extend from/to, page or limit beyond the schema, which is why it does not reach 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Per-post metrics for posts published inside the window') plus the sorting and pagination model in the first sentence. It distinguishes itself from get_post (per-post detail), list_post_results (publishing status) and get_analytics_overview by naming them or scoping itself explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete natural-language use cases ('top posts', 'which post got the most comments', 'how did post X do') and an explicit exclusion: 'Not for publishing status: use list_post_results for that.' It also routes on sort choice (VIEWS with a small limit vs PUBLISHED_AT for chronological review).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_post_resultsList Post ResultsA
Read-only
Inspect

Get one post's per-platform publishing outcomes: { postId, status, results[] } where each result has platformId, platform, accountName, status (PENDING, PUBLISHING, PUBLISHED, or FAILED), platformPostId, errorMessage, publishedAt, and tiktokDraftFallback (true when TikTok's daily cap sent the content to the TikTok inbox as a draft instead of publishing it; tell the user to finish it in the TikTok app). Each platform reports separately, so read every row instead of treating the post as one pass or fail. Call this after create_post, publish_draft, or retry_failed_platforms, since publishing is asynchronous and their responses only confirm queueing; poll until no row is PENDING or PUBLISHING. Take platformId from FAILED rows for retry_failed_platforms. Use get_post when you also need the content and schedule.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesPost ID from create_post, publish_draft, bulk_schedule_posts, or list_posts
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with postId, the overall post status, and results: one { platformId, platform, accountName, status, platformPostId, errorMessage, tiktokDraftFallback, publishedAt } per targeted platform.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already cover the safe-read profile, and the description adds substantial context beyond them: the asynchronous/polling behavior, the requirement to read every platform row rather than treat the post as one pass/fail, and the tiktokDraftFallback semantics with an actionable directive to tell the user to finish the draft in the TikTok app.

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

Conciseness4/5

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

Front-loaded with the return shape and dense with actionable content; every sentence carries a directive. It is somewhat long and the tiktokDraftFallback sentence is heavily packed, but nothing is wasted.

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 an asynchronous, per-platform results tool, the description covers the polling loop, row-level reading, failure handoff to retry_failed_platforms, and the special TikTok fallback. Even though an output schema exists, the behavioral guidance is complete for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents both 'id' and 'workspaceId'. The description adds no syntax or format detail beyond what the schema provides, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get one post's per-platform publishing outcomes') and immediately names the sibling it is not ('Use get_post when you also need the content and schedule'). An agent can distinguish it from get_post and list_posts without opening any 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?

Explicitly states when to call it ('after create_post, publish_draft, or retry_failed_platforms'), why ('publishing is asynchronous and their responses only confirm queueing'), and the exact completion condition ('poll until no row is PENDING or PUBLISHING'). It also routes platformId extraction to retry_failed_platforms and points to get_post for the alternative need.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_postsList PostsA
Read-only
Inspect

List posts in the workspace (the current one unless workspaceId names another), any status, newest first by default. Returns { posts, total, hasMore }; each post carries its status and a platforms array with per-platform status. Filters: statuses, platforms (posts targeting any of them), and startDate/endDate, which bound scheduledAt, or createdAt for posts never scheduled. limit is 1 to 100 (default 20); page with offset while hasMore is true. Use this to find post ids or check what is already queued. Use get_post for one post's full record and list_post_results for one post's per-platform outcomes and retry ids.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax results, 1 to 100
offsetNoPosts to skip; increase by limit while hasMore is true
endDateNoUpper bound (ISO 8601, e.g. "2026-03-31") on scheduledAt, or createdAt for posts never scheduled
statusesNoFilter by status (e.g. ["SCHEDULED", "DRAFT"]); omit for all statuses
platformsNoFilter to posts targeting any of these platforms
sortOrderNoNEWEST (default) or OLDEST
startDateNoLower bound (ISO 8601, e.g. "2026-03-01") on scheduledAt, or createdAt for posts never scheduled
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with posts (each with id, status, contentType, text, scheduledAt, timezone, recurringPostId and occurrenceAt for occurrences of a recurring post, and platforms with per-platform status), total (count of all matches), and hasMore.

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already declare a safe read (readOnlyHint=true, destructiveHint=false), so the bar is lower. The description still adds real operational context: default sort order, pagination workflow tied to hasMore, and the non-obvious rule that startDate/endDate bound scheduledAt but fall back to createdAt for never-scheduled posts. It does not cover rate limits or workspace-access caveats beyond the workspaceId note.

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

Conciseness5/5

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

Front-loads purpose and scope, then return shape, then filters, then routing to siblings. Every clause carries distinct information (pagination, filter-bound semantics, alternatives) with no filler or restated marketing prose.

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?

With an output schema present the description need not explain the payload in depth, yet it still summarizes { posts, total, hasMore } and per-platform status shape. Combined with filter semantics, pagination rules, and sibling routing, an agent has everything needed to call this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds matching semantics not stated per-parameter: platforms is an OR match ('posts targeting any of them') and the date filters bound scheduledAt with a createdAt fallback. It also ties offset to the returned hasMore flag, which is a behavioral tie the schema alone does not express.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with scope ('posts in the workspace, the current one unless workspaceId names another'), default ordering, and default status breadth. It explicitly contrasts itself with get_post and list_post_results, so an agent can distinguish it from siblings without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use ('find post ids or check what is already queued') and names both alternatives with the condition that selects each (get_post for one full record, list_post_results for per-platform outcomes and retry ids). Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_recurring_postsList Recurring PostsA
Read-only
Inspect

List the recurring posts (series) in the workspace (the current one unless workspaceId names another), created by passing recurrence to create_post. Returns { recurringPosts, total, hasMore }; each series has id, status (ACTIVE, PAUSED or ENDED), pauseReason when paused, frequency, interval, weekdays, startsAt, timezone, endsOn or maxOccurrences, nextOccurrenceAt, occurrenceCount, and the content and platforms every occurrence copies. Only the next occurrence of an ACTIVE series exists as a SCHEDULED post, created about 24 hours ahead; list_posts shows it with recurringPostId set. A series pauses itself after 3 failed posts in a row, when the subscription lapses, when its creator loses workspace access, when one of its accounts is disconnected, or when a platform rejects the content; pauseReason and lastError say which. limit is 1 to 100 (default 20); page with offset while hasMore is true. Editing a series or skipping one date is only possible in the AdaptlyPost app.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax results, 1 to 100
offsetNoRecurring posts to skip; increase by limit while hasMore is true
statusesNoFilter by status (e.g. ["ACTIVE", "PAUSED"]); omit for all statuses
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with recurringPosts (each with id, status, pauseReason, lastError, frequency, interval, weekdays, startsAt, timezone, endsOn, maxOccurrences, nextOccurrenceAt, occurrenceCount, contentType, text, mediaUrls, platformTypes, and platforms), total (count of all matches), and hasMore.

TDQS

A4.4/5.0
Behavior5/5

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

Annotations already cover the read-only, non-destructive, closed-world profile, and the description adds substantial non-obvious behavior: only the next occurrence of an ACTIVE series exists as a SCHEDULED post (~24 hours ahead), and the five conditions that self-pause a series (3 consecutive failures, lapsed subscription, creator losing access, disconnected account, platform rejection) with pauseReason/lastError as the signal. That is exactly the kind of lifecycle context annotations cannot provide.

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

Conciseness4/5

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

Front-loaded with purpose and return shape, then lifecycle and pagination detail. It is dense but nearly every sentence carries information; the one partial redundancy is restating the limit range and default that the schema already specifies.

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 read-only list tool with a full output schema, the description covers purpose, filtering, pagination, workspace scoping, and the lifecycle semantics an agent needs to interpret statuses and pause reasons. Nothing material for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so limit, offset, statuses, and workspaceId are already documented in structured form. The description largely restates these (limit 1-100 default 20, paging with offset), adding little beyond the schema, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List the recurring posts (series) in the workspace') and immediately defines what a recurring post is (created by passing recurrence to create_post). This lets an agent distinguish it from get_recurring_post, list_posts, and delete_recurring_post without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear usage context: pagination via offset/limit while hasMore is true, workspaceId should be reused for related calls, and it points out that list_posts surfaces the scheduled next occurrence. It does not explicitly state when to prefer this over get_recurring_post (single series) or how it relates to the pause/resume siblings, so routing guidance is slightly incomplete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_workspacesList WorkspacesA
Read-only
Inspect

List the workspaces this sign-in can act in, across every organization the user belongs to. Returns { workspaces } with id, name, organization { id, name }, role { key, name }, permissions (the permission keys held there), isDefault, current and can { draft, schedule, publish }. Call this when the user names a workspace, brand, client or organization, or when accounts or posts they expect are missing: then pass the matching id as workspaceId to every other tool. Without workspaceId, tools act in the workspace marked current. An API key belongs to one workspace, so it lists only that one. Takes no arguments.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with workspaces: one { id, name, organization, role, permissions, isDefault, current, can } per workspace. Pass id as workspaceId to other tools.

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnly/openWorld/destructive hints, and the description goes beyond them with real behavioral context: the API-key scoping rule ('an API key belongs to one workspace, so it lists only that one') and the default-current-workspace behavior that governs every other tool. It does not mention pagination or result limits, which is the only notable omission for a cross-org list.

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

Conciseness4/5

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

Front-loaded with the purpose, then the return shape, then the usage condition and cross-tool wiring; every sentence carries operational value. The trailing 'Takes no arguments' is mildly redundant against the empty schema, a small blemish on an otherwise tight structure.

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?

An output schema exists so return-field documentation is not strictly required, yet the description still summarizes the payload. Combined with the workspaceId routing rule and API-key exception, an agent has everything needed to call this tool correctly and to use its results in subsequent calls.

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?

Zero parameters, so the baseline is 4 per the rubric. The description confirms 'Takes no arguments,' which is consistent with the empty schema but adds no semantic detail beyond it, as expected for a parameterless tool.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with scope: 'List the workspaces this sign-in can act in, across every organization the user belongs to.' It is immediately distinguishable from sibling list tools like list_accounts, and it even enumerates the returned fields so the agent knows the tool's identity 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?

Explicit trigger conditions are given ('when the user names a workspace, brand, client or organization, or when accounts or posts they expect are missing') along with the follow-up action ('pass the matching id as workspaceId to every other tool'). It also states the fallback semantics when no workspaceId is supplied, so the agent knows when this tool is required versus optional.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

open_upload_widgetUpload From DeviceAInspect

Show an upload box in the chat so the user can add photos, videos or documents from their phone or computer. Use it when the user wants to post a file that has no public URL, such as a photo on their phone or a file attached in the chat that upload_media cannot read. Nothing is uploaded until the user picks files in the box. When the upload finishes, the box sends a message listing the public media URLs; pass them as mediaUrls to create_post, update_post or bulk_schedule_posts. Accepts JPEG, PNG, WebP, MP4, QuickTime, PDF, PPT, PPTX, DOC and DOCX, up to 250 MB per file, 50 MB per image and 100 MB per document. Uploaded files are stored at public URLs. The box only appears in apps that show MCP Apps widgets, such as ChatGPT and Claude; elsewhere ask the user for a public URL and use upload_media.

ParametersJSON Schema
NameRequiredDescriptionDefault
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with status waiting_for_upload. The media URLs arrive later, in a message the upload box sends when the user finishes.

TDQS

A4.6/5.0
Behavior5/5

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

Adds substantial context beyond the annotations: nothing is uploaded until the user picks files, the widget only renders in MCP Apps hosts like ChatGPT and Claude, files land at public URLs, and the box posts back a message of media URLs. It also discloses accepted formats and per-file size limits.

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

Conciseness4/5

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

Front-loaded with the purpose, then prerequisites and downstream usage. Slightly long due to the format/size inventory, but nearly every sentence carries operational value.

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?

An output schema exists so return values need no explanation, yet the description still explains the URL handoff to post-creation tools. For a widget-launch tool with one optional param, nothing an agent needs is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and there is a single optional workspaceId whose semantics are fully documented in the schema; the description adds no parameter detail, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action and resource ('Show an upload box in the chat so the user can add photos, videos or documents') and clearly separates itself from upload_media and get_upload_urls, which it names.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use ('when the user wants to post a file that has no public URL'), a fallback for unsupported environments ('elsewhere ask the user for a public URL and use upload_media'), and ties the result to the downstream create_post/update_post/bulk_schedule_posts calls.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pause_recurring_postPause Recurring PostA
DestructiveIdempotent
Inspect

Pause a recurring post: it stops creating occurrences and deletes its upcoming SCHEDULED post, preventing future scheduled occurrences until resume_recurring_post; an occurrence already publishing may still complete. Posts already published are kept. Slots that pass while paused are skipped, never published later. Use it when the user wants to hold the series; use delete_recurring_post to stop it for good. Deleting only the upcoming post with delete_post skips that one date and the series continues. Ids outside the workspace (the current one unless workspaceId names another) return "Recurring post not found". Returns the recurring post with status PAUSED and pauseReason USER.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesRecurring post ID to pause, from list_recurring_posts
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoThe paused recurring post: id, status PAUSED, pauseReason USER, the schedule, occurrenceCount, and the content and platforms.

TDQS

A4.8/5.0
Behavior5/5

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

Adds substantial behavior beyond the annotations: the upcoming scheduled post is deleted, an in-flight publishing occurrence may still complete, already-published posts are kept, and skipped slots are never backfilled. It also documents the not-found error for out-of-workspace ids and the returned status/pauseReason, which the destructiveHint/idempotentHint annotations cannot convey.

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

Conciseness4/5

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

Front-loaded with the core action and its immediate side effect, then the usage routing, then edge cases. Dense but every sentence carries distinct information; slightly long, though nothing is filler.

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?

With an output schema present, the description need not restate the return shape, and it still summarizes status PAUSED/pauseReason USER. Combined with annotations (destructive, idempotent) and full schema coverage, an agent has everything needed to call it correctly and predict consequences.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description still adds value by explaining workspace scoping (ids outside the current/other workspace yield 'Recurring post not found') and reinforcing that id comes from list_recurring_posts. This goes modestly beyond the schema's own parameter text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (pause a recurring post) and immediately clarifies the scope: it stops occurrence creation and deletes the upcoming SCHEDULED post. It explicitly contrasts with delete_recurring_post, resume_recurring_post, and delete_post, so an agent can distinguish it from every relevant sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use ('when the user wants to hold the series'), when-not ('use delete_recurring_post to stop it for good'), and the alternative for a one-off skip (delete_post). The selection logic between pause vs delete vs single-skip is fully spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

publish_draftPublish DraftA
Destructive
Inspect

Publish a DRAFT post now or schedule it; SCHEDULED posts are accepted too, to reschedule or push live. Other statuses fail with "Post is not a draft". Without scheduledAt (or with a past one) the post moves to PENDING and a publishing job is queued per platform: content reaches the networks within moments and cannot be recalled. A future scheduledAt sets SCHEDULED and queues nothing yet. Fails if an account was disconnected or a TikTok entry lacks privacyLevel; fix with update_post first. Not for new content, use create_post. Check list_post_results afterwards for per-platform outcomes.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesPost ID with status DRAFT (or SCHEDULED)
timezoneNoIANA timezone stored with the post for display (e.g. "America/New_York"); it does not shift scheduledAtUTC
scheduledAtNoAbsolute ISO 8601 instant (e.g. "2026-03-15T10:00:00Z"). Omit, or pass a past time, to publish now
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with postId, queuedPlatforms (platforms whose publishing job was queued; empty when scheduled for later), isScheduled, and scheduledAt.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations declare destructiveHint=true and openWorldHint=true, and the description goes well beyond them: it states that publishing cannot be recalled, that a job is queued per platform, that PENDING/SCHEDULED states differ by scheduledAt, and enumerates failure causes (disconnected account, missing TikTok privacyLevel). This is exactly the irreversibility and side-effect disclosure a mutation tool needs.

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

Conciseness4/5

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

Front-loaded with purpose, then failure modes, alternatives, and follow-ups; nearly every clause earns its place. It is dense and long, but the density is informational rather than redundant, so only slightly below optimal.

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?

An output schema exists, so return values needn't be explained, and the description still routes the agent to list_post_results for per-platform outcomes. Combined with failure conditions and state transitions, an agent has everything needed to invoke this mutation correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds real semantics: scheduledAt omission or a past value means publish-now while a future value queues nothing yet, and timezone is display-only and does not shift scheduledAt. These behavioral consequences exceed the schema text.

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?

Opens with a specific verb+resource ('Publish a DRAFT post now or schedule it') and extends to SCHEDULED posts. Explicitly distinguishes itself from create_post for new content, so the agent can differentiate it from siblings without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use (DRAFT or SCHEDULED), when it fails ('Other statuses fail with "Post is not a draft"'), prerequisites to fix via update_post, alternatives (create_post for new content), and a follow-up tool (list_post_results). Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

refine_captionRefine CaptionAInspect

Rewrite an existing caption following an instruction, such as "shorter", "more playful" or "add a question at the end". Returns { caption }, the rewritten text; nothing is saved or posted. Send partialText to continue from a partly written caption. Pass platform to target that platform's character limit; check the returned text before posting. Needs the ai.generate permission, which Admin, Editor and Contributor hold and Viewer does not (403 permission_denied). Each call spends 2 of the member's AI credits (the member who signed in or created the key), refunded if generation fails, unless the member has their own AI provider key connected in AdaptlyPost. With no credits left the call fails: explain that generation is unavailable with the current credit balance and do not retry automatically. Costs the same as generate_caption.

ParametersJSON Schema
NameRequiredDescriptionDefault
promptYesHow the caption should change (max 2000 characters)
platformNoPlatform the caption is for; generation targets that platform's character limit; check the returned text before posting
partialTextNoA partly written caption to continue from (max 10000 characters)
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another
originalTextYesThe caption to rewrite (max 10000 characters)

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with caption: the rewritten text.

TDQS

A4.4/5.0
Behavior5/5

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

Goes well past the annotations (readOnlyHint=false, destructiveHint=false, idempotentHint=false): it states nothing is saved or posted, names the required permission and which roles hold it, documents the 403 permission_denied code, quantifies the cost as 2 AI credits with refund-on-failure semantics, and prescribes behavior when credits run out (explain unavailability, do not auto-retry). This is unusually rich behavioral disclosure for a generation tool.

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

Conciseness4/5

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

Front-loads the core purpose in the first clause, then layers operational details in a single dense paragraph with no filler. Some sentences pack permission, credit, and failure semantics together, which is heavy but each clause earns its place.

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?

With an output schema present, return values need not be explained, yet the description still states it returns { caption }. Between the description and annotations, an agent has purpose, permission model, cost, failure handling, and non-persistence — everything needed to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all five parameters, including platform's enum and the partialText/originalText distinction. The description reinforces the purpose of platform and partialText but adds little syntax or interaction detail beyond the schema (e.g., it does not say how partialText and the required originalText combine). Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Rewrite an existing caption following an instruction") and immediately distinguishes itself from the sibling generate_caption by operating on an existing caption rather than producing a new one. The example instructions ("shorter", "more playful") make the operation concrete.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear contextual triggers: send partialText to continue a partly written caption, pass platform to target a character limit, check the returned text before posting, and compares cost to generate_caption. It never states the inverse routing rule (use generate_caption when there is no existing caption to rewrite), so the alternative is implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resume_recurring_postResume Recurring PostA
Destructive
Inspect

Resume a PAUSED recurring post. It continues from the next occurrence after now; slots missed while paused are not published. The next occurrence is created as a SCHEDULED post about 24 hours before it goes out and then publishes to the networks, so confirm with the user first. If the series has no slot left (endsOn passed or maxOccurrences reached) it comes back ENDED instead. When pauseReason is CONNECTION_REMOVED, ACCESS_LOST, SUBSCRIPTION_INACTIVE or INVALID_CONTENT, fix the cause first or the series pauses again. Ids outside the workspace (the current one unless workspaceId names another) return "Recurring post not found". Returns the recurring post with its new status and nextOccurrenceAt.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesRecurring post ID to resume, from list_recurring_posts
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoThe resumed recurring post: id, status (ACTIVE, or ENDED when no slot is left), nextOccurrenceAt, the schedule, occurrenceCount, and the content and platforms.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations (destructiveHint=true, openWorldHint=true, readOnlyHint=false) mark this as a state-changing, outward-facing call, and the description adds substantial extra context: missed slots are not published, the next occurrence becomes a SCHEDULED post ~24h ahead, ENDED is returned when the series is exhausted, and workspace-scoped ids yield 'Recurring post not found'. This is exactly the behavioral disclosure the annotations cannot carry.

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 most decision-relevant facts (what resume does, when confirmation is needed) are front-loaded, and every sentence carries operational information. It is dense rather than padded, though the string of pauseReason enum values and ending-status note makes it slightly long for two parameters.

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?

With an output schema present, the description does not need to enumerate return fields, yet it still names the returned statuses and nextOccurrenceAt. For a destructive, world-affecting mutation tool with two fully documented parameters, nothing an agent needs to invoke it safely is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the field definitions by explaining that ids outside the named or current workspace return 'Recurring post not found' and by tying id provenance to list_recurring_posts. The workspace scoping rule is largely duplicated from the schema, keeping it short of a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Resume a PAUSED recurring post') and the scope is tightened by 'PAUSED', which clearly separates it from pause_recurring_post and the generic get/delete recurring post siblings. An agent can identify the operation without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear when-to-use context ('confirm with the user first', fix the cause when pauseReason is CONNECTION_REMOVED/ACCESS_LOST/etc.) and describes the outcome when no slot remains. It does not explicitly name pause_recurring_post as the inverse alternative, but the preconditions are well specified.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

retry_failed_platformsRetry Failed PlatformsA
Destructive
Inspect

Re-queue publishing for a post's FAILED platforms. platformIds takes platformId values from list_post_results, platform names such as "BLUESKY" (every failed row of that platform), or can be omitted to retry every failed row. Only rows with status FAILED are reset to PENDING and retried with the same content. A value matching neither a row id nor a platform of the post fails with "Unknown retry target"; with nothing failed among the matches the call fails with "No failed platforms to retry". The post moves to PUBLISHING and the retry is asynchronous, so check list_post_results for the outcome. Read each errorMessage first and retry once the cause is fixed (reconnected account, replaced media), not for a platform-side restriction, which will just fail again. Content cannot change on retry.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesPost ID whose platforms failed
platformIdsNoplatformId values from list_post_results or platform names such as "BLUESKY". Omit to retry every FAILED row
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with postId, queuedPlatforms (platforms re-queued for publishing), and isScheduled: false. Outcomes arrive asynchronously in list_post_results.

TDQS

A4.8/5.0
Behavior5/5

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

Goes well beyond the annotations (readOnlyHint=false, destructiveHint=true, openWorldHint=true) by disclosing state transitions (post moves to PUBLISHING), that retries are asynchronous, that content cannot change on retry, and the exact failure messages ('Unknown retry target', 'No failed platforms to retry'). This is unusually rich behavioral context for a mutation tool.

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

Conciseness4/5

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

Front-loaded with the core action, then constraints, failure modes, and post-call guidance in a logical order. Dense and slightly long, but virtually every clause carries distinct operational information rather than filler.

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?

An output schema exists, so return values need not be described. With error cases, state transition, async caveat, and the follow-up tool all covered, an agent has everything needed to invoke this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description still adds value: it clarifies that platformIds accepts row ids, platform names, or omission, and specifies the failure behavior for values matching neither a row id nor a platform of the post.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: re-queue publishing for a post's FAILED platforms. It scopes exactly which rows are affected ('Only rows with status FAILED are reset to PENDING'), which distinguishes it from siblings like publish_draft or update_post without needing to open their schemas.

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?

Explicit when-to-use and when-not: read each errorMessage first and retry only once the cause is fixed (reconnected account, replaced media), not for a platform-side restriction, 'which will just fail again'. It also routes the agent to list_post_results for the outcome, covering the follow-up step.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

trigger_analytics_syncTrigger Analytics SyncA
Idempotent
Inspect

Ask AdaptlyPost to refresh analytics now instead of waiting for the scheduled sync: every connected account is queued and the last 7 days are re-read. Use it when the user just published and wants numbers, or when get_analytics_overview shows an old lastSyncedAt. Allowed once per workspace every 10 minutes; inside the cooldown it returns queued: false with cooldownSecondsRemaining rather than an error, so do not retry in a loop. The sync runs in the background: poll get_analytics_sync_status until syncInProgress is false, then read the metrics again. Takes only the optional workspaceId and changes no content.

ParametersJSON Schema
NameRequiredDescriptionDefault
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with queued (true when a sync was started), message, and cooldownSecondsRemaining (seconds until the next allowed sync, null when queued).

TDQS

A4.7/5.0
Behavior5/5

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

The description adds substantial behavior beyond annotations: a once-per-workspace 10-minute cooldown, cooldown return shape with queued:false and cooldownSecondsRemaining, background execution, and the need to poll get_analytics_sync_status. It is consistent with readOnlyHint=false, idempotentHint=true, and destructiveHint=false without repeating them.

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

Conciseness5/5

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

The description is front-loaded with the core action and then layers in usage, cooldown, and polling guidance. Every sentence carries operational value, with no redundant or filler content.

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?

An output schema exists, so the description need not explain return values. It still covers everything an agent needs to invoke the tool correctly: purpose, timing, cooldown behavior, background execution, and follow-up polling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the single workspaceId parameter is already well documented in the schema. The description only notes that it takes an optional workspaceId, adding no syntax or selection detail beyond the schema baseline.

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 description states a specific verb and resource: refresh analytics now instead of waiting for the scheduled sync. It distinguishes itself from get_analytics_overview and get_analytics_sync_status by describing its trigger role and the downstream polling workflow.

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 explicitly says when to use it: when the user just published and wants numbers, or when get_analytics_overview shows an old lastSyncedAt. It also provides a clear when-not-to-retry rule inside the cooldown.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

unschedule_postUnschedule PostA
Idempotent
Inspect

Take a DRAFT or SCHEDULED post off the calendar without deleting it: the post becomes an undated DRAFT (status DRAFT, scheduledAt null) and nothing publishes. Use it when the user wants to hold a scheduled post back; reschedule it later with update_post or publish_draft, and use delete_post only to drop it entirely. Any other status (PENDING, PUBLISHING, COMPLETED, FAILED, PARTIAL_FAILURE) fails with 400 because the post is already going out or out. Ids outside the workspace (the current one unless workspaceId names another) return 404. Safe to repeat on a post that is already an undated draft. Returns the post record.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesPost ID with status DRAFT or SCHEDULED, from list_posts or create_post
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoThe post record as an undated draft: id, status DRAFT, scheduledAt null, text, contentType, timezone, and platforms with per-target details.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations cover the safety profile (not read-only, idempotent, non-destructive), and the description adds real context beyond them: the exact post-state transition, error codes for disallowed statuses (400), cross-workspace 404 behavior, and idempotency on an already-undated draft. No contradiction with idempotentHint=true.

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

Conciseness4/5

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

Front-loaded with purpose and transition, then usage and error semantics, all earning their place. It is a single dense compound string rather than clearly separated clauses, so slightly harder to scan than ideal.

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?

An output schema exists, yet the description still names the return ("Returns the post record") and covers state transitions, error conditions, workspace scoping, and idempotency. Nothing needed to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters are already documented, which sets a baseline of 3. The description reinforces workspaceId scoping via the 404 note but adds no new format or syntax meaning for the id itself.

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?

Names a specific verb+resource (take a post off the calendar) plus the exact resulting state (undated DRAFT, scheduledAt null, nothing publishes). It also distinguishes itself from siblings by name (update_post, publish_draft, delete_post), so an agent can separate it from adjacent tools without opening schemas.

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?

Explicit when-to-use ("hold a scheduled post back") and explicit alternatives for other intents (reschedule with update_post/publish_draft, drop entirely with delete_post). It also states the when-not case: other statuses fail with 400.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_postUpdate PostA
Destructive
Inspect

Update a DRAFT or SCHEDULED post in place; any other status fails with "Cannot edit post in current state", so published posts cannot be changed. Updates are partial: text, contentType, scheduledAt, timezone, and thumbnail fields you omit keep their values. The exception is platforms: sending it rebuilds the post's target set from this request alone, so include every connection-id array and platform config you want to keep (TikTok with privacyLevel, Pinterest with boardId); omitting platforms leaves accounts, configs, and media untouched. mediaUrls only take effect together with platforms; use publicUrl values from upload_media. On SCHEDULED posts new media is verified in storage. Returns the updated post record. Use publish_draft to change a draft's status, unschedule_post to take a scheduled post off the calendar, delete_post to cancel, and create_post for a new post.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesPost ID to update (must be DRAFT or SCHEDULED)
textNoUpdated text; omit to keep the current text
pageIdsNoFacebook page account ids from list_accounts (the account id; its pageId value is also accepted). Facebook has no connection-id array
timezoneNoIANA timezone stored for display; does not shift scheduledAt
mediaUrlsNoReplacement media URLs, applied only when platforms is also sent. Use publicUrl values from upload_media or get_upload_urls
platformsNoNew target platforms. Sending this replaces every target, so also resend the connection-id arrays and platform configs to keep; omit to leave targets unchanged
contentTypeNoNew content type; must match the media on the post. DOCUMENT publishes one PDF, PPT, PPTX, DOC or DOCX file (max 100 MB, 300 pages) as a LinkedIn document post and is LinkedIn only: put exactly that one file in mediaUrls, target only LINKEDIN, and set the title with linkedinConfigs
scheduledAtNoNew schedule time as an absolute ISO 8601 instant; omit to keep. Moving a SCHEDULED post more than a minute into the past fails with 400; use publish_draft to publish now
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another
thumbnailUrlNoCustom thumbnail image URL for video posts
mediaAltTextsNoAlt text per image, in the same order as mediaUrls (max 1000 characters each; use "" to skip an image). Sent to X, Bluesky, Mastodon, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it. Applied only when platforms is also sent
platformTextsNoPer-platform caption overrides; applied to the targets sent in platforms
tiktokConfigsNoTikTok per-connection config. Each entry needs connectionId + privacyLevel at minimum
youtubeConfigsNoYouTube per-connection config with video title, tags, privacy, etc.
facebookConfigsNoFacebook per-page config with post type and video title. pageId must match an entry in pageIds
linkedinConfigsNoLinkedIn per-connection config: documentTitle names a DOCUMENT post. connectionId must match an entry in linkedinConnectionIds
instagramConfigsNoInstagram per-connection config to set post type (FEED, REEL, STORY) and publish a reel as a trial reel
pinterestConfigsNoPinterest per-connection config. Each entry needs connectionId + boardId; there is no API to list boards, so ask the user for the board id
tiktokConnectionIdsNoTikTok account connection IDs to post from
blueskyConnectionIdsNoBluesky account connection IDs to post from
threadsConnectionIdsNoThreads account connection IDs to post from
thumbnailTimestampMsNoGenerate thumbnail from video at this timestamp (milliseconds)
twitterConnectionIdsNoX (Twitter) account connection IDs to post from
youtubeConnectionIdsNoYouTube channel connection IDs to post from
linkedinConnectionIdsNoLinkedIn account connection IDs to post from
mastodonConnectionIdsNoMastodon account connection IDs to post from
instagramConnectionIdsNoInstagram account connection IDs to post from
pinterestConnectionIdsNoPinterest account connection IDs to post from

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoThe updated post record: id, status (still DRAFT or SCHEDULED), text, contentType, scheduledAt, timezone, and platforms with per-target details.

TDQS

A4.9/5.0
Behavior5/5

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

Annotations mark it destructive and open-world, but the description goes far beyond that: it explains partial-update semantics for the omitted fields, the exception that sending platforms rebuilds the entire target set, the mediaUrls-only-with-platforms dependency, storage verification for new media on scheduled posts, and the exact 400 failure wording. This is unusually rich disclosure of mutation behavior.

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

Conciseness5/5

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

The most consequential constraint (which statuses can be edited) is front-loaded in the first clause. Despite its length, nearly every sentence carries non-redundant operational information, and it closes with sibling routing rather than trailing tangents.

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 28-parameter destructive mutation with an output schema and full annotation coverage, the description supplies the state preconditions, partial-update contract, platform-replacement hazard, and dependency rules an agent needs to call it correctly. Return values are covered by the output schema, so omitting them is correct.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds cross-parameter interaction semantics the schema does not: that platforms replaces every target requiring the connection-id arrays and configs be resent, that mediaUrls only applies alongside platforms, and the publicUrl sourcing. It does not re-derive most per-field details, which is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Update a DRAFT or SCHEDULED post in place') and immediately bounds the scope by status, naming the exact failure for other states. It also routes to four sibling tools by name, so the agent can distinguish it without opening any 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?

Explicitly says when-not to use it ('published posts cannot be changed') and names the alternatives with their conditions: publish_draft for status changes, unschedule_post to remove from the calendar, delete_post to cancel, create_post for new posts. Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

upload_mediaUpload MediaA
Destructive
Inspect

Upload images, videos or documents to AdaptlyPost storage and return public URLs for the mediaUrls of create_post, update_post, or bulk_schedule_posts. Two sources, combinable in one call: urls (public https URLs the server streams straight into storage; private, internal and non-https addresses are refused, and the source must send a Content-Length) and files (base64 data, for media attached in the conversation; 30 MB decoded per call in total). Omitting both returns an error. Accepts JPEG, PNG, WebP, MP4 and QuickTime, plus PDF, PPT, PPTX, DOC and DOCX for LinkedIn DOCUMENT posts, checked by file content (and, for Office files, the extension, so keep it in the name or URL); 50 MB per image, 100 MB per document, 250 MB per URL download. Stored files are public immediately, post or no post, so only upload media the user supplied or asked for. For inline files over 30 MB use get_upload_urls and PUT the bytes yourself. Returns uploaded ({ publicUrl, key } per file) and mediaUrls; pass mediaUrls straight into the post. One publicUrl may be reused across any number of posts; the file is kept until the last post referencing it has published, so upload once and reuse rather than re-uploading per post.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlsNoPublic https URLs of images, videos or documents to upload (e.g. ["https://example.com/photo.jpg", "https://example.com/deck.pdf"])
filesNoDirect file uploads as base64, 30 MB decoded per call in total. Use this when the user attaches/pastes an image, video or document in the conversation
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultNoAn object with uploaded (array of { publicUrl, key } per file) and mediaUrls (the public URLs ready to pass to create_post).

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only declare write/openWorld/destructive; the description adds the genuinely useful behavioral facts: files become public immediately even with no post, retention lasts until the last referencing post publishes, source URLs must be https and send a Content-Length, private/internal addresses are refused, and validation is by file content plus extension for Office files. These are exactly the side effects and constraints an agent needs before calling a write tool.

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

Conciseness4/5

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

Front-loaded with purpose and usage, and nearly every clause carries operational information (limits, validation, rejection rules, reuse). It is a long single block, and a few asides (e.g. the repeated Office-extension note) could be tightened, but density is high rather than padded.

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 write tool with an output schema, everything an agent needs is covered: sources, limits, validation, refusal conditions, public-visibility warning, retention semantics, and the escape hatch for oversized files. Return values are given anyway, and the output schema covers the rest.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description goes beyond it: it explains the https/Content-Length/private-address constraints on urls, the 30 MB decoded ceiling on files, and the 50/100/250 MB per-type limits. workspaceId is left to the schema, so the add is substantial but not exhaustive.

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?

Opens with a specific verb+resource ('Upload images, videos or documents to AdaptlyPost storage') and states the output (public URLs for mediaUrls). It explicitly routes into sibling tools (create_post, update_post, bulk_schedule_posts) and names get_upload_urls as the alternative path, so an agent can distinguish it from siblings without reading schemas.

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?

Explicit when-to-use for both sources ('urls' for public https links the server streams, 'files' for media attached in the conversation), states they are combinable, states that omitting both errors, tells when to use the alternative (inline files over 30 MB → get_upload_urls), and advises upload-once/reuse-across-posts. This is about as complete as usage guidance gets.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updates
    • Addedget_upload_ticket
    • Addedopen_upload_widget
  2. 2 tool updates
    • Changedgenerate_caption1 field changed
      • changedInput schema / properties / platform / description
        Previous value: -"Platform the caption is for; the caption is kept within that platform's character limit. Omit for a general caption"New value: +"Platform the caption is for; generation targets that platform's character limit; check the returned text before posting. Omit for a general caption"
    • Changedrefine_caption1 field changed
      • changedInput schema / properties / platform / description
        Previous value: -"Platform the caption is for; the result is kept within that platform's character limit"New value: +"Platform the caption is for; generation targets that platform's character limit; check the returned text before posting"
  3. 29 tool updates
    • Changedbulk_schedule_posts2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedcreate_post2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changeddelete_post2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changeddelete_recurring_post2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedgenerate_caption2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedgenerate_image2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedget_analytics_overview2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedget_analytics_sync_status2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedget_analytics_timeseries2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedget_image_job2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedget_platform_breakdown2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedget_post2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedget_recurring_post2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedget_upload_urls2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedlist_accounts2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedlist_post_analytics2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedlist_post_results2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedlist_posts2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedlist_recurring_posts2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedlist_workspaces2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedpause_recurring_post2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedpublish_draft2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedrefine_caption2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedresume_recurring_post2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedretry_failed_platforms2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedtrigger_analytics_sync2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedunschedule_post2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedupdate_post2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedupload_media2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
  4. 29 tool updates
    • Changedbulk_schedule_posts33 fields changed
      • addedInput schema / properties / facebookConfigs / items / $ref
        Added value: +"#/properties/posts/items/properties/facebookConfigs/items"
      • removedInput schema / properties / facebookConfigs / items / additionalProperties
        Removed value: -false
      • removedInput schema / properties / facebookConfigs / items / properties
        Removed value: -{
        -  "pageId": {
        -    "description": "Facebook page ID from list_accounts",
        -    "type": "string"
        -  },
        -  "postType": {
        -    "description": "Facebook post type — FEED, REEL, or STORY",
        -    "enum": [
        -      "FEED",
        -      "REEL",
        -      "STORY"
        -    ],
        -    "type": "string"
        -  },
        -  "videoTitle": {
        -    "description": "Video title for Facebook (max 255 chars)",
        -    "maxLength": 255,
        -    "type": "string"
        -  }
        -}
      • removedInput schema / properties / facebookConfigs / items / required
        Removed value: -[
        -  "pageId"
        -]
      • removedInput schema / properties / facebookConfigs / items / type
        Removed value: -"object"
      • addedInput schema / properties / instagramConfigs / items / $ref
        Added value: +"#/properties/posts/items/properties/instagramConfigs/items"
      • removedInput schema / properties / instagramConfigs / items / additionalProperties
        Removed value: -false
      • removedInput schema / properties / instagramConfigs / items / properties
        Removed value: -{
        -  "connectionId": {
        -    "description": "Instagram connection ID from list_accounts",
        -    "type": "string"
        -  },
        -  "postType": {
        -    "description": "Instagram post type — FEED, REEL, or STORY",
        -    "enum": [
        -      "FEED",
        -      "REEL",
        -      "STORY"
        -    ],
        -    "type": "string"
        -  },
        -  "trialGraduation": {
        -    "description": "Publish a video reel as a trial reel: Instagram shows it to non-followers first and keeps it off followers' feeds and the profile grid until it is shared. MANUAL means the account owner shares it from the Instagram app; SS_PERFORMANCE means Instagram shares it if it performs well. Only for a single video posted as a reel or feed video, never a story, image or carousel (400 otherwise). Needs a professional account Instagram has enabled for trial reels; otherwise that platform fails with a message saying so",
        -    "enum": [
        -      "MANUAL",
        -      "SS_PERFORMANCE"
        -    ],
        -    "type": "string"
        -  }
        -}
      • removedInput schema / properties / instagramConfigs / items / required
        Removed value: -[
        -  "connectionId"
        -]
      • removedInput schema / properties / instagramConfigs / items / type
        Removed value: -"object"
      • addedInput schema / properties / pinterestConfigs / items / $ref
        Added value: +"#/properties/posts/items/properties/pinterestConfigs/items"
      • removedInput schema / properties / pinterestConfigs / items / additionalProperties
        Removed value: -false
      • removedInput schema / properties / pinterestConfigs / items / properties
        Removed value: -{
        -  "boardId": {
        -    "description": "Pinterest board ID to pin to (required)",
        -    "type": "string"
        -  },
        -  "connectionId": {
        -    "description": "Pinterest connection ID from list_accounts",
        -    "type": "string"
        -  },
        -  "link": {
        -    "description": "Destination URL for the pin",
        -    "type": "string"
        -  },
        -  "title": {
        -    "description": "Pin title (max 100 chars)",
        -    "maxLength": 100,
        -    "type": "string"
        -  }
        -}
      • removedInput schema / properties / pinterestConfigs / items / required
        Removed value: -[
        -  "connectionId",
        -  "boardId"
        -]
      • removedInput schema / properties / pinterestConfigs / items / type
        Removed value: -"object"
      • addedInput schema / properties / posts / items / properties / facebookConfigs
        Added value: +{
        +  "description": "Facebook config for this item only; replaces the batch-level facebookConfigs",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "pageId": {
        +        "description": "Facebook page ID from list_accounts",
        +        "type": "string"
        +      },
        +      "postType": {
        +        "description": "Where the post goes: FEED works with every content type, REEL needs contentType VIDEO, STORY needs IMAGE or VIDEO. Any other combination is refused with 400",
        +        "enum": [
        +          "FEED",
        +          "REEL",
        +          "STORY"
        +        ],
        +        "type": "string"
        +      },
        +      "videoTitle": {
        +        "description": "Video title for Facebook (max 255 chars)",
        +        "maxLength": 255,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "pageId"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / posts / items / properties / instagramConfigs
        Added value: +{
        +  "description": "Instagram config for this item only; replaces the batch-level instagramConfigs",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "connectionId": {
        +        "description": "Instagram connection ID from list_accounts",
        +        "type": "string"
        +      },
        +      "postType": {
        +        "description": "Where the post goes: FEED works with every content type, REEL needs contentType VIDEO, STORY needs IMAGE or VIDEO. Any other combination is refused with 400",
        +        "enum": [
        +          "FEED",
        +          "REEL",
        +          "STORY"
        +        ],
        +        "type": "string"
        +      },
        +      "trialGraduation": {
        +        "description": "Publish a video reel as a trial reel: Instagram shows it to non-followers first and keeps it off followers' feeds and the profile grid until it is shared. MANUAL means the account owner shares it from the Instagram app; SS_PERFORMANCE means Instagram shares it if it performs well. Only for a single video posted as a reel or feed video, never a story, image or carousel (400 otherwise). Needs a professional account Instagram has enabled for trial reels; otherwise that platform fails with a message saying so",
        +        "enum": [
        +          "MANUAL",
        +          "SS_PERFORMANCE"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "connectionId"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / posts / items / properties / pinterestConfigs
        Added value: +{
        +  "description": "Pinterest config for this item only, such as its own title or link; replaces the batch-level pinterestConfigs",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "boardId": {
        +        "description": "Pinterest board ID to pin to (required)",
        +        "type": "string"
        +      },
        +      "connectionId": {
        +        "description": "Pinterest connection ID from list_accounts",
        +        "type": "string"
        +      },
        +      "link": {
        +        "description": "Destination URL for the pin",
        +        "type": "string"
        +      },
        +      "title": {
        +        "description": "Pin title (max 100 chars)",
        +        "maxLength": 100,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "connectionId",
        +      "boardId"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / posts / items / properties / tiktokConfigs
        Added value: +{
        +  "description": "TikTok config for this item only; replaces the batch-level tiktokConfigs",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "aiGenerated": {
        +        "description": "Label content as AI-generated",
        +        "type": "boolean"
        +      },
        +      "allowComments": {
        +        "description": "Allow comments on the TikTok post",
        +        "type": "boolean"
        +      },
        +      "allowDuet": {
        +        "description": "Allow other users to Duet this video",
        +        "type": "boolean"
        +      },
        +      "allowStitch": {
        +        "description": "Allow other users to Stitch this video",
        +        "type": "boolean"
        +      },
        +      "autoAddMusic": {
        +        "description": "Let TikTok auto-add music to the video",
        +        "type": "boolean"
        +      },
        +      "brandedContent": {
        +        "description": "Disclose as branded content (paid partnership)",
        +        "type": "boolean"
        +      },
        +      "brandedContentOwnBrand": {
        +        "description": "Disclose as promoting your own brand",
        +        "type": "boolean"
        +      },
        +      "caption": {
        +        "description": "TikTok-specific caption (max 2200 chars)",
        +        "maxLength": 2200,
        +        "type": "string"
        +      },
        +      "connectionId": {
        +        "description": "TikTok connection ID from list_accounts",
        +        "type": "string"
        +      },
        +      "privacyLevel": {
        +        "description": "TikTok privacy level",
        +        "enum": [
        +          "PUBLIC_TO_EVERYONE",
        +          "MUTUAL_FOLLOW_FRIENDS",
        +          "FOLLOWER_OF_CREATOR",
        +          "SELF_ONLY"
        +        ],
        +        "type": "string"
        +      },
        +      "sendAsDraft": {
        +        "description": "Save as TikTok draft so the user can add trending sounds before publishing",
        +        "type": "boolean"
        +      },
        +      "title": {
        +        "description": "Video title (max 90 chars)",
        +        "maxLength": 90,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "connectionId",
        +      "privacyLevel"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / posts / items / properties / youtubeConfigs
        Added value: +{
        +  "description": "YouTube config for this item only, such as its own videoTitle; replaces the batch-level youtubeConfigs",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "allowEmbedding": {
        +        "description": "Allow embedding the video on other sites",
        +        "type": "boolean"
        +      },
        +      "categoryId": {
        +        "description": "YouTube category ID",
        +        "type": "string"
        +      },
        +      "connectionId": {
        +        "description": "YouTube connection ID from list_accounts",
        +        "type": "string"
        +      },
        +      "license": {
        +        "description": "Video license type",
        +        "enum": [
        +          "youtube",
        +          "creativeCommon"
        +        ],
        +        "type": "string"
        +      },
        +      "madeForKids": {
        +        "description": "Mark the video as made for kids (COPPA)",
        +        "type": "boolean"
        +      },
        +      "notifySubscribers": {
        +        "description": "Notify channel subscribers about the upload",
        +        "type": "boolean"
        +      },
        +      "playlistId": {
        +        "description": "Add video to this playlist",
        +        "type": "string"
        +      },
        +      "postType": {
        +        "description": "VIDEO for long-form, SHORTS for YouTube Shorts",
        +        "enum": [
        +          "VIDEO",
        +          "SHORTS"
        +        ],
        +        "type": "string"
        +      },
        +      "privacyStatus": {
        +        "description": "Video privacy status",
        +        "enum": [
        +          "public",
        +          "private",
        +          "unlisted"
        +        ],
        +        "type": "string"
        +      },
        +      "tags": {
        +        "description": "Video tags (max 20)",
        +        "items": {
        +          "type": "string"
        +        },
        +        "maxItems": 20,
        +        "type": "array"
        +      },
        +      "videoTitle": {
        +        "description": "YouTube video title (max 100 chars)",
        +        "maxLength": 100,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "connectionId"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / posts / maxItems
        Added value: +100
      • addedInput schema / properties / posts / minItems
        Added value: +1
      • addedInput schema / properties / tiktokConfigs / items / $ref
        Added value: +"#/properties/posts/items/properties/tiktokConfigs/items"
      • removedInput schema / properties / tiktokConfigs / items / additionalProperties
        Removed value: -false
      • removedInput schema / properties / tiktokConfigs / items / properties
        Removed value: -{
        -  "aiGenerated": {
        -    "description": "Label content as AI-generated",
        -    "type": "boolean"
        -  },
        -  "allowComments": {
        -    "description": "Allow comments on the TikTok post",
        -    "type": "boolean"
        -  },
        -  "allowDuet": {
        -    "description": "Allow other users to Duet this video",
        -    "type": "boolean"
        -  },
        -  "allowStitch": {
        -    "description": "Allow other users to Stitch this video",
        -    "type": "boolean"
        -  },
        -  "autoAddMusic": {
        -    "description": "Let TikTok auto-add music to the video",
        -    "type": "boolean"
        -  },
        -  "brandedContent": {
        -    "description": "Disclose as branded content (paid partnership)",
        -    "type": "boolean"
        -  },
        -  "brandedContentOwnBrand": {
        -    "description": "Disclose as promoting your own brand",
        -    "type": "boolean"
        -  },
        -  "caption": {
        -    "description": "TikTok-specific caption (max 2200 chars)",
        -    "maxLength": 2200,
        -    "type": "string"
        -  },
        -  "connectionId": {
        -    "description": "TikTok connection ID from list_accounts",
        -    "type": "string"
        -  },
        -  "privacyLevel": {
        -    "description": "TikTok privacy level",
        -    "enum": [
        -      "PUBLIC_TO_EVERYONE",
        -      "MUTUAL_FOLLOW_FRIENDS",
        -      "FOLLOWER_OF_CREATOR",
        -      "SELF_ONLY"
        -    ],
        -    "type": "string"
        -  },
        -  "sendAsDraft": {
        -    "description": "Save as TikTok draft so the user can add trending sounds before publishing",
        -    "type": "boolean"
        -  },
        -  "title": {
        -    "description": "Video title (max 90 chars)",
        -    "maxLength": 90,
        -    "type": "string"
        -  }
        -}
      • removedInput schema / properties / tiktokConfigs / items / required
        Removed value: -[
        -  "connectionId",
        -  "privacyLevel"
        -]
      • removedInput schema / properties / tiktokConfigs / items / type
        Removed value: -"object"
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
      • addedInput schema / properties / youtubeConfigs / items / $ref
        Added value: +"#/properties/posts/items/properties/youtubeConfigs/items"
      • removedInput schema / properties / youtubeConfigs / items / additionalProperties
        Removed value: -false
      • removedInput schema / properties / youtubeConfigs / items / properties
        Removed value: -{
        -  "allowEmbedding": {
        -    "description": "Allow embedding the video on other sites",
        -    "type": "boolean"
        -  },
        -  "categoryId": {
        -    "description": "YouTube category ID",
        -    "type": "string"
        -  },
        -  "connectionId": {
        -    "description": "YouTube connection ID from list_accounts",
        -    "type": "string"
        -  },
        -  "license": {
        -    "description": "Video license type",
        -    "enum": [
        -      "youtube",
        -      "creativeCommon"
        -    ],
        -    "type": "string"
        -  },
        -  "madeForKids": {
        -    "description": "Mark the video as made for kids (COPPA)",
        -    "type": "boolean"
        -  },
        -  "notifySubscribers": {
        -    "description": "Notify channel subscribers about the upload",
        -    "type": "boolean"
        -  },
        -  "playlistId": {
        -    "description": "Add video to this playlist",
        -    "type": "string"
        -  },
        -  "postType": {
        -    "description": "VIDEO for long-form, SHORTS for YouTube Shorts",
        -    "enum": [
        -      "VIDEO",
        -      "SHORTS"
        -    ],
        -    "type": "string"
        -  },
        -  "privacyStatus": {
        -    "description": "Video privacy status",
        -    "enum": [
        -      "public",
        -      "private",
        -      "unlisted"
        -    ],
        -    "type": "string"
        -  },
        -  "tags": {
        -    "description": "Video tags (max 20)",
        -    "items": {
        -      "type": "string"
        -    },
        -    "maxItems": 20,
        -    "type": "array"
        -  },
        -  "videoTitle": {
        -    "description": "YouTube video title (max 100 chars)",
        -    "maxLength": 100,
        -    "type": "string"
        -  }
        -}
      • removedInput schema / properties / youtubeConfigs / items / required
        Removed value: -[
        -  "connectionId"
        -]
      • removedInput schema / properties / youtubeConfigs / items / type
        Removed value: -"object"
    • Changedcreate_post4 fields changed
      • changedInput schema / properties / facebookConfigs / items / properties / postType / description
        Previous value: -"Facebook post type — FEED, REEL, or STORY"New value: +"Where the post goes: FEED works with every content type, REEL needs contentType VIDEO, STORY needs IMAGE or VIDEO. Any other combination is refused with 400"
      • changedInput schema / properties / instagramConfigs / items / properties / postType / description
        Previous value: -"Instagram post type — FEED, REEL, or STORY"New value: +"Where the post goes: FEED works with every content type, REEL needs contentType VIDEO, STORY needs IMAGE or VIDEO. Any other combination is refused with 400"
      • addedInput schema / properties / recurrence / properties / weekdays / maxItems
        Added value: +7
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changeddelete_post1 field changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changeddelete_recurring_post1 field changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Addedgenerate_caption
    • Addedgenerate_image
    • Changedget_analytics_overview1 field changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changedget_analytics_sync_status1 field changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changedget_analytics_timeseries1 field changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Addedget_image_job
    • Changedget_platform_breakdown1 field changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changedget_post1 field changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changedget_recurring_post1 field changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changedget_upload_urls1 field changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changedlist_accounts2 fields changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
      • changedOutput schema / properties / result / description
        Previous value: -"An object with accounts: one { id, platform, displayName, username, avatarUrl } per connected account, plus pageId for Facebook pages. Use id as the connection id (or in pageIds for Facebook)."New value: +"An object with accounts: one { id, platform, displayName, username, avatarUrl, status } per connected account, plus unauthorizedReason when status is unauthorized and pageId for Facebook pages. Use id as the connection id (or in pageIds for Facebook)."
    • Changedlist_post_analytics6 fields changed
      • addedInput schema / properties / limit / maximum
        Added value: +100
      • addedInput schema / properties / limit / minimum
        Added value: +1
      • changedInput schema / properties / limit / type
        Previous value: -"number"New value: +"integer"
      • addedInput schema / properties / page / minimum
        Added value: +1
      • changedInput schema / properties / page / type
        Previous value: -"number"New value: +"integer"
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changedlist_post_results2 fields changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
      • changedOutput schema / properties / result / description
        Previous value: -"An object with postId, the overall post status, and results: one { platformId, platform, accountName, status, platformPostId, errorMessage, publishedAt } per targeted platform."New value: +"An object with postId, the overall post status, and results: one { platformId, platform, accountName, status, platformPostId, errorMessage, tiktokDraftFallback, publishedAt } per targeted platform."
    • Changedlist_posts6 fields changed
      • addedInput schema / properties / limit / maximum
        Added value: +100
      • addedInput schema / properties / limit / minimum
        Added value: +1
      • changedInput schema / properties / limit / type
        Previous value: -"number"New value: +"integer"
      • addedInput schema / properties / offset / minimum
        Added value: +0
      • changedInput schema / properties / offset / type
        Previous value: -"number"New value: +"integer"
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changedlist_recurring_posts6 fields changed
      • addedInput schema / properties / limit / maximum
        Added value: +100
      • addedInput schema / properties / limit / minimum
        Added value: +1
      • changedInput schema / properties / limit / type
        Previous value: -"number"New value: +"integer"
      • addedInput schema / properties / offset / minimum
        Added value: +0
      • changedInput schema / properties / offset / type
        Previous value: -"number"New value: +"integer"
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changedlist_workspaces1 field changed
      • changedOutput schema / properties / result / description
        Previous value: -"An object with workspaces: one { id, name, organization, role, isDefault, current, can } per workspace. Pass id as workspaceId to other tools."New value: +"An object with workspaces: one { id, name, organization, role, permissions, isDefault, current, can } per workspace. Pass id as workspaceId to other tools."
    • Changedpause_recurring_post1 field changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changedpublish_draft1 field changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Addedrefine_caption
    • Changedresume_recurring_post1 field changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changedretry_failed_platforms1 field changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changedtrigger_analytics_sync1 field changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changedunschedule_post1 field changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changedupdate_post4 fields changed
      • changedInput schema / properties / facebookConfigs / items / properties / postType / description
        Previous value: -"Facebook post type — FEED, REEL, or STORY"New value: +"Where the post goes: FEED works with every content type, REEL needs contentType VIDEO, STORY needs IMAGE or VIDEO. Any other combination is refused with 400"
      • changedInput schema / properties / instagramConfigs / items / properties / postType / description
        Previous value: -"Instagram post type — FEED, REEL, or STORY"New value: +"Where the post goes: FEED works with every content type, REEL needs contentType VIDEO, STORY needs IMAGE or VIDEO. Any other combination is refused with 400"
      • changedInput schema / properties / mediaAltTexts / description
        Previous value: -"Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, Mastodon, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it"New value: +"Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, Mastodon, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it. Applied only when platforms is also sent"
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • Changedupload_media1 field changed
      • changedInput schema / properties / workspaceId / description
        Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
  5. 25 tool updates
    • Changedbulk_schedule_posts1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedcreate_post1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changeddelete_post1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changeddelete_recurring_post1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedget_analytics_overview1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedget_analytics_sync_status2 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedget_analytics_timeseries1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedget_platform_breakdown1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedget_post1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedget_recurring_post1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedget_upload_urls1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedlist_accounts2 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedlist_post_analytics1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedlist_post_results1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedlist_posts1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedlist_recurring_posts1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Addedlist_workspaces
    • Changedpause_recurring_post1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedpublish_draft1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedresume_recurring_post1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedretry_failed_platforms1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedtrigger_analytics_sync2 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedunschedule_post1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedupdate_post1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
    • Changedupload_media1 field changed
      • addedInput schema / properties / workspaceId
        Added value: +{
        +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
        +  "type": "string"
        +}
  6. 3 tool updates
    • Changedbulk_schedule_posts2 fields changed
      • changedInput schema / properties / instagramConfigs / description
        Previous value: -"Instagram per-connection config to set post type (FEED, REEL, STORY)"New value: +"Instagram per-connection config to set post type (FEED, REEL, STORY) and publish a reel as a trial reel"
      • addedInput schema / properties / instagramConfigs / items / properties / trialGraduation
        Added value: +{
        +  "description": "Publish a video reel as a trial reel: Instagram shows it to non-followers first and keeps it off followers' feeds and the profile grid until it is shared. MANUAL means the account owner shares it from the Instagram app; SS_PERFORMANCE means Instagram shares it if it performs well. Only for a single video posted as a reel or feed video, never a story, image or carousel (400 otherwise). Needs a professional account Instagram has enabled for trial reels; otherwise that platform fails with a message saying so",
        +  "enum": [
        +    "MANUAL",
        +    "SS_PERFORMANCE"
        +  ],
        +  "type": "string"
        +}
    • Changedcreate_post2 fields changed
      • changedInput schema / properties / instagramConfigs / description
        Previous value: -"Instagram per-connection config to set post type (FEED, REEL, STORY)"New value: +"Instagram per-connection config to set post type (FEED, REEL, STORY) and publish a reel as a trial reel"
      • addedInput schema / properties / instagramConfigs / items / properties / trialGraduation
        Added value: +{
        +  "description": "Publish a video reel as a trial reel: Instagram shows it to non-followers first and keeps it off followers' feeds and the profile grid until it is shared. MANUAL means the account owner shares it from the Instagram app; SS_PERFORMANCE means Instagram shares it if it performs well. Only for a single video posted as a reel or feed video, never a story, image or carousel (400 otherwise). Needs a professional account Instagram has enabled for trial reels; otherwise that platform fails with a message saying so",
        +  "enum": [
        +    "MANUAL",
        +    "SS_PERFORMANCE"
        +  ],
        +  "type": "string"
        +}
    • Changedupdate_post2 fields changed
      • changedInput schema / properties / instagramConfigs / description
        Previous value: -"Instagram per-connection config to set post type (FEED, REEL, STORY)"New value: +"Instagram per-connection config to set post type (FEED, REEL, STORY) and publish a reel as a trial reel"
      • addedInput schema / properties / instagramConfigs / items / properties / trialGraduation
        Added value: +{
        +  "description": "Publish a video reel as a trial reel: Instagram shows it to non-followers first and keeps it off followers' feeds and the profile grid until it is shared. MANUAL means the account owner shares it from the Instagram app; SS_PERFORMANCE means Instagram shares it if it performs well. Only for a single video posted as a reel or feed video, never a story, image or carousel (400 otherwise). Needs a professional account Instagram has enabled for trial reels; otherwise that platform fails with a message saying so",
        +  "enum": [
        +    "MANUAL",
        +    "SS_PERFORMANCE"
        +  ],
        +  "type": "string"
        +}
  7. 8 tool updates
    • Changedcreate_post2 fields changed
      • addedInput schema / properties / recurrence
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Repeat the post on a schedule. Needs a future scheduledAt, which becomes the first post and sets the time of day in timezone. Cannot be combined with saveAsDraft or TIKTOK. Missed slots, for example while paused, are skipped and never published late. X and LinkedIn reject identical text, so use spintax such as {Hi|Hello} to vary each post. Manage the series with list_recurring_posts, pause_recurring_post, resume_recurring_post and delete_recurring_post",
        +  "properties": {
        +    "endsOn": {
        +      "description": "Last day an occurrence may go out on, as YYYY-MM-DD (inclusive). Must be on or after the day of the first post. Cannot be combined with maxOccurrences",
        +      "type": "string"
        +    },
        +    "frequency": {
        +      "description": "How often the post repeats: DAILY, WEEKLY, or MONTHLY",
        +      "enum": [
        +        "DAILY",
        +        "WEEKLY",
        +        "MONTHLY"
        +      ],
        +      "type": "string"
        +    },
        +    "interval": {
        +      "description": "Repeat every N days, weeks or months, 1 to 30 (default 1)",
        +      "maximum": 30,
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    "maxOccurrences": {
        +      "description": "Total number of posts the series publishes, 2 to 365. Cannot be combined with endsOn; omit both to repeat until paused or deleted",
        +      "maximum": 365,
        +      "minimum": 2,
        +      "type": "integer"
        +    },
        +    "weekdays": {
        +      "description": "WEEKLY only: the weekdays it goes out on (e.g. [\"MONDAY\", \"THURSDAY\"]). The weekday of scheduledAt is always included",
        +      "items": {
        +        "enum": [
        +          "MONDAY",
        +          "TUESDAY",
        +          "WEDNESDAY",
        +          "THURSDAY",
        +          "FRIDAY",
        +          "SATURDAY",
        +          "SUNDAY"
        +        ],
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "frequency"
        +  ],
        +  "type": "object"
        +}
      • changedOutput schema / properties / result / description
        Previous value: -"An object with postId, queuedPlatforms (platforms whose publishing job was queued; empty for scheduled posts and drafts), skippedPlatforms, isScheduled, and scheduledAt. Publishing is asynchronous: check list_post_results for outcomes."New value: +"An object with postId, queuedPlatforms (platforms whose publishing job was queued; empty for scheduled posts and drafts), skippedPlatforms, isScheduled, and scheduledAt, plus recurringPostId when recurrence was sent. Publishing is asynchronous: check list_post_results for outcomes."
    • Addeddelete_recurring_post
    • Changedget_post1 field changed
      • changedOutput schema / properties / result / description
        Previous value: -"The full post record: id, status, contentType, text, scheduledAt, timezone, mediaUrls, createdAt, updatedAt, and platforms (one entry per target with id, platform, connectionId or pageId, status, errorMessage, platformPostId, postUrl once published, mediaUrls, previewUrls). previewUrls holds one permanent preview image per media item, a still frame for videos; after publishing, mediaUrls may become platform CDN links that expire within days, so show previewUrls instead."New value: +"The full post record: id, status, contentType, text, scheduledAt, timezone, mediaUrls, createdAt, updatedAt, recurringPostId and occurrenceAt (set when the post is an occurrence of a recurring post; occurrenceAt is its slot in the series and stays the same when the post is rescheduled), and platforms (one entry per target with id, platform, connectionId or pageId, status, errorMessage, platformPostId, postUrl once published, mediaUrls, previewUrls). previewUrls holds one permanent preview image per media item, a still frame for videos; after publishing, mediaUrls may become platform CDN links that expire within days, so show previewUrls instead."
    • Addedget_recurring_post
    • Changedlist_posts1 field changed
      • changedOutput schema / properties / result / description
        Previous value: -"An object with posts (each with id, status, contentType, text, scheduledAt, timezone, and platforms with per-platform status), total (count of all matches), and hasMore."New value: +"An object with posts (each with id, status, contentType, text, scheduledAt, timezone, recurringPostId and occurrenceAt for occurrences of a recurring post, and platforms with per-platform status), total (count of all matches), and hasMore."
    • Addedlist_recurring_posts
    • Addedpause_recurring_post
    • Addedresume_recurring_post
  8. 5 tool updates
    • Changedbulk_schedule_posts1 field changed
      • changedInput schema / properties / posts / items / properties / contentType / description
        Previous value: -"TEXT, IMAGE, VIDEO, or CAROUSEL; must match mediaUrls"New value: +"TEXT, IMAGE, VIDEO, or CAROUSEL; must match mediaUrls. DOCUMENT posts cannot be bulk scheduled; use create_post"
    • Changedcreate_post3 fields changed
      • changedInput schema / properties / contentType / description
        Previous value: -"Content type: TEXT, IMAGE, VIDEO, or CAROUSEL. Must match mediaUrls (CAROUSEL needs several)"New value: +"Content type: TEXT, IMAGE, VIDEO, CAROUSEL, or DOCUMENT. Must match mediaUrls (CAROUSEL needs several). DOCUMENT publishes one PDF, PPT, PPTX, DOC or DOCX file (max 100 MB, 300 pages) as a LinkedIn document post and is LinkedIn only: put exactly that one file in mediaUrls, target only LINKEDIN, and set the title with linkedinConfigs"
      • changedInput schema / properties / contentType / enum
        Previous value: -[
        -  "TEXT",
        -  "IMAGE",
        -  "VIDEO",
        -  "CAROUSEL"
        -]New value: +[
        +  "TEXT",
        +  "IMAGE",
        +  "VIDEO",
        +  "CAROUSEL",
        +  "DOCUMENT"
        +]
      • addedInput schema / properties / linkedinConfigs
        Added value: +{
        +  "description": "LinkedIn per-connection config: documentTitle names a DOCUMENT post. connectionId must match an entry in linkedinConnectionIds",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "connectionId": {
        +        "description": "LinkedIn connection ID from list_accounts",
        +        "type": "string"
        +      },
        +      "documentTitle": {
        +        "description": "Title LinkedIn shows on a DOCUMENT post (max 100 chars). Defaults to the file name; ignored for other content types",
        +        "maxLength": 100,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "connectionId"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedget_upload_urls1 field changed
      • changedInput schema / properties / files / items / properties / mimeType / enum
        Previous value: -[
        -  "image/jpeg",
        -  "image/png",
        -  "image/webp",
        -  "video/mp4",
        -  "video/quicktime"
        -]New value: +[
        +  "image/jpeg",
        +  "image/png",
        +  "image/webp",
        +  "video/mp4",
        +  "video/quicktime",
        +  "application/pdf",
        +  "application/vnd.ms-powerpoint",
        +  "application/vnd.openxmlformats-officedocument.presentationml.presentation",
        +  "application/msword",
        +  "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
        +]
    • Changedupdate_post3 fields changed
      • changedInput schema / properties / contentType / description
        Previous value: -"New content type; must match the media on the post"New value: +"New content type; must match the media on the post. DOCUMENT publishes one PDF, PPT, PPTX, DOC or DOCX file (max 100 MB, 300 pages) as a LinkedIn document post and is LinkedIn only: put exactly that one file in mediaUrls, target only LINKEDIN, and set the title with linkedinConfigs"
      • changedInput schema / properties / contentType / enum
        Previous value: -[
        -  "TEXT",
        -  "IMAGE",
        -  "VIDEO",
        -  "CAROUSEL"
        -]New value: +[
        +  "TEXT",
        +  "IMAGE",
        +  "VIDEO",
        +  "CAROUSEL",
        +  "DOCUMENT"
        +]
      • addedInput schema / properties / linkedinConfigs
        Added value: +{
        +  "description": "LinkedIn per-connection config: documentTitle names a DOCUMENT post. connectionId must match an entry in linkedinConnectionIds",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "connectionId": {
        +        "description": "LinkedIn connection ID from list_accounts",
        +        "type": "string"
        +      },
        +      "documentTitle": {
        +        "description": "Title LinkedIn shows on a DOCUMENT post (max 100 chars). Defaults to the file name; ignored for other content types",
        +        "maxLength": 100,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "connectionId"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedupload_media4 fields changed
      • changedInput schema / properties / files / description
        Previous value: -"Direct file uploads as base64, 30 MB decoded per call in total. Use this when the user attaches/pastes an image or video in the conversation"New value: +"Direct file uploads as base64, 30 MB decoded per call in total. Use this when the user attaches/pastes an image, video or document in the conversation"
      • changedInput schema / properties / files / items / properties / fileName / description
        Previous value: -"File name with extension (e.g. \"photo.jpg\")"New value: +"File name with extension (e.g. \"photo.jpg\" or \"deck.pptx\")"
      • changedInput schema / properties / files / items / properties / mimeType / enum
        Previous value: -[
        -  "image/jpeg",
        -  "image/png",
        -  "image/webp",
        -  "video/mp4",
        -  "video/quicktime"
        -]New value: +[
        +  "image/jpeg",
        +  "image/png",
        +  "image/webp",
        +  "video/mp4",
        +  "video/quicktime",
        +  "application/pdf",
        +  "application/vnd.ms-powerpoint",
        +  "application/vnd.openxmlformats-officedocument.presentationml.presentation",
        +  "application/msword",
        +  "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
        +]
      • changedInput schema / properties / urls / description
        Previous value: -"Public https URLs of images or videos to upload (e.g. [\"https://example.com/photo.jpg\"])"New value: +"Public https URLs of images, videos or documents to upload (e.g. [\"https://example.com/photo.jpg\", \"https://example.com/deck.pdf\"])"
  9. 3 tool updates
    • Changedcreate_post1 field changed
      • changedInput schema / properties / mediaUrls / description
        Previous value: -"Media URLs to attach. Use publicUrl values from upload_media or get_upload_urls"New value: +"Media URLs to attach. Use publicUrl values from upload_media or get_upload_urls; the same publicUrl may be reused across posts. Do not reuse mediaUrls read back from a published post, which may be expiring platform links"
    • Changedget_post1 field changed
      • changedOutput schema / properties / result / description
        Previous value: -"The full post record: id, status, contentType, text, scheduledAt, timezone, createdAt, updatedAt, and platforms (one entry per target with id, platform, connectionId or pageId, status, errorMessage, mediaUrls, previewUrls). previewUrls holds one permanent preview image per media item, a still frame for videos; after publishing, mediaUrls may become platform CDN links that expire within days, so show previewUrls instead."New value: +"The full post record: id, status, contentType, text, scheduledAt, timezone, mediaUrls, createdAt, updatedAt, and platforms (one entry per target with id, platform, connectionId or pageId, status, errorMessage, platformPostId, postUrl once published, mediaUrls, previewUrls). previewUrls holds one permanent preview image per media item, a still frame for videos; after publishing, mediaUrls may become platform CDN links that expire within days, so show previewUrls instead."
    • Changedretry_failed_platforms2 fields changed
      • changedInput schema / properties / platformIds / description
        Previous value: -"platformId values of FAILED rows from list_post_results (not platform names). At least one"New value: +"platformId values from list_post_results or platform names such as \"BLUESKY\". Omit to retry every FAILED row"
      • changedInput schema / required
        Previous value: -[
        -  "id",
        -  "platformIds"
        -]New value: +[
        +  "id"
        +]
  10. 1 tool update
    • Removedwhoami
  11. 4 tool updates
    • Changedget_post1 field changed
      • changedOutput schema / properties / result / description
        Previous value: -"The full post record: id, status, contentType, text, scheduledAt, timezone, createdAt, updatedAt, and platforms (one entry per target with id, platform, connectionId or pageId, status, errorMessage, mediaUrls)."New value: +"The full post record: id, status, contentType, text, scheduledAt, timezone, createdAt, updatedAt, and platforms (one entry per target with id, platform, connectionId or pageId, status, errorMessage, mediaUrls, previewUrls). previewUrls holds one permanent preview image per media item, a still frame for videos; after publishing, mediaUrls may become platform CDN links that expire within days, so show previewUrls instead."
    • Addedunschedule_post
    • Changedupdate_post1 field changed
      • changedInput schema / properties / scheduledAt / description
        Previous value: -"New schedule time as an absolute ISO 8601 instant; omit to keep"New value: +"New schedule time as an absolute ISO 8601 instant; omit to keep. Moving a SCHEDULED post more than a minute into the past fails with 400; use publish_draft to publish now"
    • Addedwhoami
  12. 7 tool updates
    • Changedbulk_schedule_posts3 fields changed
      • addedInput schema / properties / mastodonConnectionIds
        Added value: +{
        +  "description": "Mastodon account connection IDs to post from",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • changedInput schema / properties / platforms / items / enum
        Previous value: -[
        -  "LINKEDIN",
        -  "YOUTUBE",
        -  "INSTAGRAM",
        -  "FACEBOOK",
        -  "TIKTOK",
        -  "PINTEREST",
        -  "THREADS",
        -  "BLUESKY",
        -  "TWITTER"
        -]New value: +[
        +  "LINKEDIN",
        +  "YOUTUBE",
        +  "INSTAGRAM",
        +  "FACEBOOK",
        +  "TIKTOK",
        +  "PINTEREST",
        +  "THREADS",
        +  "BLUESKY",
        +  "TWITTER",
        +  "MASTODON"
        +]
      • changedInput schema / properties / posts / items / properties / mediaAltTexts / description
        Previous value: -"Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it"New value: +"Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, Mastodon, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it"
    • Changedcreate_post3 fields changed
      • addedInput schema / properties / mastodonConnectionIds
        Added value: +{
        +  "description": "Mastodon account connection IDs to post from",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • changedInput schema / properties / mediaAltTexts / description
        Previous value: -"Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it"New value: +"Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, Mastodon, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it"
      • changedInput schema / properties / platforms / items / enum
        Previous value: -[
        -  "LINKEDIN",
        -  "YOUTUBE",
        -  "INSTAGRAM",
        -  "FACEBOOK",
        -  "TIKTOK",
        -  "PINTEREST",
        -  "THREADS",
        -  "BLUESKY",
        -  "TWITTER"
        -]New value: +[
        +  "LINKEDIN",
        +  "YOUTUBE",
        +  "INSTAGRAM",
        +  "FACEBOOK",
        +  "TIKTOK",
        +  "PINTEREST",
        +  "THREADS",
        +  "BLUESKY",
        +  "TWITTER",
        +  "MASTODON"
        +]
    • Changedget_analytics_overview2 fields changed
      • changedInput schema / properties / platforms / description
        Previous value: -"Restrict to these platforms; omit for every platform with analytics. X (TWITTER) has no analytics and is ignored; LinkedIn analytics are pending platform approval and return no data yet"New value: +"Restrict to these platforms; omit for every platform with analytics. X (TWITTER) and MASTODON have no analytics and are ignored; LinkedIn analytics are pending platform approval and return no data yet"
      • changedInput schema / properties / platforms / items / enum
        Previous value: -[
        -  "LINKEDIN",
        -  "YOUTUBE",
        -  "INSTAGRAM",
        -  "FACEBOOK",
        -  "TIKTOK",
        -  "PINTEREST",
        -  "THREADS",
        -  "BLUESKY",
        -  "TWITTER"
        -]New value: +[
        +  "LINKEDIN",
        +  "YOUTUBE",
        +  "INSTAGRAM",
        +  "FACEBOOK",
        +  "TIKTOK",
        +  "PINTEREST",
        +  "THREADS",
        +  "BLUESKY",
        +  "TWITTER",
        +  "MASTODON"
        +]
    • Changedget_analytics_timeseries2 fields changed
      • changedInput schema / properties / platforms / description
        Previous value: -"Restrict to these platforms; omit for every platform with analytics. X (TWITTER) has no analytics and is ignored; LinkedIn analytics are pending platform approval and return no data yet"New value: +"Restrict to these platforms; omit for every platform with analytics. X (TWITTER) and MASTODON have no analytics and are ignored; LinkedIn analytics are pending platform approval and return no data yet"
      • changedInput schema / properties / platforms / items / enum
        Previous value: -[
        -  "LINKEDIN",
        -  "YOUTUBE",
        -  "INSTAGRAM",
        -  "FACEBOOK",
        -  "TIKTOK",
        -  "PINTEREST",
        -  "THREADS",
        -  "BLUESKY",
        -  "TWITTER"
        -]New value: +[
        +  "LINKEDIN",
        +  "YOUTUBE",
        +  "INSTAGRAM",
        +  "FACEBOOK",
        +  "TIKTOK",
        +  "PINTEREST",
        +  "THREADS",
        +  "BLUESKY",
        +  "TWITTER",
        +  "MASTODON"
        +]
    • Changedlist_post_analytics2 fields changed
      • changedInput schema / properties / platforms / description
        Previous value: -"Restrict to these platforms; omit for every platform with analytics. X (TWITTER) has no analytics and is ignored; LinkedIn analytics are pending platform approval and return no data yet"New value: +"Restrict to these platforms; omit for every platform with analytics. X (TWITTER) and MASTODON have no analytics and are ignored; LinkedIn analytics are pending platform approval and return no data yet"
      • changedInput schema / properties / platforms / items / enum
        Previous value: -[
        -  "LINKEDIN",
        -  "YOUTUBE",
        -  "INSTAGRAM",
        -  "FACEBOOK",
        -  "TIKTOK",
        -  "PINTEREST",
        -  "THREADS",
        -  "BLUESKY",
        -  "TWITTER"
        -]New value: +[
        +  "LINKEDIN",
        +  "YOUTUBE",
        +  "INSTAGRAM",
        +  "FACEBOOK",
        +  "TIKTOK",
        +  "PINTEREST",
        +  "THREADS",
        +  "BLUESKY",
        +  "TWITTER",
        +  "MASTODON"
        +]
    • Changedlist_posts1 field changed
      • changedInput schema / properties / platforms / items / enum
        Previous value: -[
        -  "LINKEDIN",
        -  "YOUTUBE",
        -  "INSTAGRAM",
        -  "FACEBOOK",
        -  "TIKTOK",
        -  "PINTEREST",
        -  "THREADS",
        -  "BLUESKY",
        -  "TWITTER"
        -]New value: +[
        +  "LINKEDIN",
        +  "YOUTUBE",
        +  "INSTAGRAM",
        +  "FACEBOOK",
        +  "TIKTOK",
        +  "PINTEREST",
        +  "THREADS",
        +  "BLUESKY",
        +  "TWITTER",
        +  "MASTODON"
        +]
    • Changedupdate_post3 fields changed
      • addedInput schema / properties / mastodonConnectionIds
        Added value: +{
        +  "description": "Mastodon account connection IDs to post from",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • changedInput schema / properties / mediaAltTexts / description
        Previous value: -"Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it"New value: +"Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, Mastodon, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it"
      • changedInput schema / properties / platforms / items / enum
        Previous value: -[
        -  "LINKEDIN",
        -  "YOUTUBE",
        -  "INSTAGRAM",
        -  "FACEBOOK",
        -  "TIKTOK",
        -  "PINTEREST",
        -  "THREADS",
        -  "BLUESKY",
        -  "TWITTER"
        -]New value: +[
        +  "LINKEDIN",
        +  "YOUTUBE",
        +  "INSTAGRAM",
        +  "FACEBOOK",
        +  "TIKTOK",
        +  "PINTEREST",
        +  "THREADS",
        +  "BLUESKY",
        +  "TWITTER",
        +  "MASTODON"
        +]
  13. 3 tool updates
    • Changedbulk_schedule_posts1 field changed
      • addedInput schema / properties / posts / items / properties / mediaAltTexts
        Added value: +{
        +  "description": "Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it",
        +  "items": {
        +    "maxLength": 1000,
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
    • Changedcreate_post1 field changed
      • addedInput schema / properties / mediaAltTexts
        Added value: +{
        +  "description": "Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it",
        +  "items": {
        +    "maxLength": 1000,
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
    • Changedupdate_post1 field changed
      • addedInput schema / properties / mediaAltTexts
        Added value: +{
        +  "description": "Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it",
        +  "items": {
        +    "maxLength": 1000,
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
  14. 1 tool update
    • Changedupload_media1 field changed
      • changedInput schema / properties / files / description
        Previous value: -"Direct file uploads as base64. Use this when the user attaches/pastes an image or video in the conversation"New value: +"Direct file uploads as base64, 30 MB decoded per call in total. Use this when the user attaches/pastes an image or video in the conversation"
  15. 1 tool update
    • Changedupload_media1 field changed
      • changedInput schema / properties / urls / description
        Previous value: -"Public URLs of images or videos to upload (e.g. [\"https://example.com/photo.jpg\"])"New value: +"Public https URLs of images or videos to upload (e.g. [\"https://example.com/photo.jpg\"])"
  16. 16 tool updates
    • Changedbulk_schedule_posts11 fields changed
      • changedInput schema / properties / facebookConfigs / description
        Previous value: -"Facebook per-page config with post type and video title"New value: +"Facebook per-page config with post type and video title. pageId must match an entry in pageIds"
      • changedInput schema / properties / pageIds / description
        Previous value: -"Facebook page IDs"New value: +"Facebook page account ids from list_accounts (the account id; its pageId value is also accepted). Facebook has no connection-id array"
      • changedInput schema / properties / pinterestConfigs / description
        Previous value: -"Pinterest per-connection config. boardId is required for Pinterest posts"New value: +"Pinterest per-connection config. Each entry needs connectionId + boardId; there is no API to list boards, so ask the user for the board id"
      • changedInput schema / properties / platforms / description
        Previous value: -"Target platforms"New value: +"Target platforms shared by every item. Each needs its connection-id array (pageIds for FACEBOOK)"
      • changedInput schema / properties / posts / description
        Previous value: -"Array of posts to schedule"New value: +"1 to 100 posts to schedule; each is created independently"
      • addedInput schema / properties / posts / items / properties / contentType / description
        Added value: +"TEXT, IMAGE, VIDEO, or CAROUSEL; must match mediaUrls"
      • changedInput schema / properties / posts / items / properties / mediaUrls / description
        Previous value: -"Image or video URLs to attach"New value: +"publicUrl values from upload_media; unstored URLs fail this item"
      • addedInput schema / properties / posts / items / properties / platformTexts / description
        Added value: +"Per-platform caption overrides for this item"
      • changedInput schema / properties / posts / items / properties / scheduledAt / description
        Previous value: -"ISO 8601 schedule time"New value: +"Absolute ISO 8601 instant; a past time publishes immediately"
      • changedInput schema / properties / timezone / description
        Previous value: -"IANA timezone"New value: +"IANA timezone stored with every post for display; does not shift scheduledAt"
      • changedOutput schema / properties / result / description
        Previous value: -"The created scheduled post records with their ids, statuses, and schedule times as returned by the AdaptlyPost API."New value: +"An object with totalScheduled, totalFailed, and results: one { postId, success, isScheduled, scheduledAt, errorMessage } per input item, in input order."
    • Changedcreate_post9 fields changed
      • changedInput schema / properties / contentType / description
        Previous value: -"Content type: TEXT, IMAGE, VIDEO, or CAROUSEL"New value: +"Content type: TEXT, IMAGE, VIDEO, or CAROUSEL. Must match mediaUrls (CAROUSEL needs several)"
      • changedInput schema / properties / facebookConfigs / description
        Previous value: -"Facebook per-page config with post type and video title"New value: +"Facebook per-page config with post type and video title. pageId must match an entry in pageIds"
      • changedInput schema / properties / pageIds / description
        Previous value: -"Facebook page IDs"New value: +"Facebook page account ids from list_accounts (the account id; its pageId value is also accepted). Facebook has no connection-id array"
      • changedInput schema / properties / pinterestConfigs / description
        Previous value: -"Pinterest per-connection config. boardId is required for Pinterest posts"New value: +"Pinterest per-connection config. Each entry needs connectionId + boardId; there is no API to list boards, so ask the user for the board id"
      • changedInput schema / properties / platforms / description
        Previous value: -"Target platforms (e.g. [\"LINKEDIN\", \"TWITTER\"])"New value: +"Target platforms (e.g. [\"LINKEDIN\", \"TWITTER\"]). Each one needs its matching connection-id array (pageIds for FACEBOOK) filled with ids from list_accounts"
      • changedInput schema / properties / saveAsDraft / description
        Previous value: -"Save as draft instead of publishing"New value: +"Save as DRAFT instead of publishing or scheduling; publish later with publish_draft"
      • changedInput schema / properties / scheduledAt / description
        Previous value: -"ISO 8601 datetime to schedule (e.g. \"2026-03-15T10:00:00Z\"). Omit to post immediately"New value: +"Absolute ISO 8601 instant to schedule (e.g. \"2026-03-15T10:00:00Z\"). Omit to post immediately; a past time also posts immediately"
      • changedInput schema / properties / timezone / description
        Previous value: -"IANA timezone (e.g. \"America/New_York\")"New value: +"IANA timezone stored with the post for display (e.g. \"America/New_York\"); it does not shift scheduledAt"
      • changedOutput schema / properties / result / description
        Previous value: -"The created post record including its id, status, and scheduled time as returned by the AdaptlyPost API."New value: +"An object with postId, queuedPlatforms (platforms whose publishing job was queued; empty for scheduled posts and drafts), skippedPlatforms, isScheduled, and scheduledAt. Publishing is asynchronous: check list_post_results for outcomes."
    • Changeddelete_post2 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"Post ID to delete"New value: +"Post ID to delete, from list_posts or create_post"
      • changedOutput schema / properties / result / description
        Previous value: -"The deletion confirmation for the post as returned by the AdaptlyPost API."New value: +"An object with deleted: true once the post record is removed from AdaptlyPost."
    • Addedget_analytics_overview
    • Addedget_analytics_sync_status
    • Addedget_analytics_timeseries
    • Addedget_platform_breakdown
    • Changedget_post2 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"Post ID"New value: +"Post ID from create_post, bulk_schedule_posts, or list_posts"
      • changedOutput schema / properties / result / description
        Previous value: -"The full post record including its id, status, per-platform publishing status, and error messages as returned by the AdaptlyPost API."New value: +"The full post record: id, status, contentType, text, scheduledAt, timezone, createdAt, updatedAt, and platforms (one entry per target with id, platform, connectionId or pageId, status, errorMessage, mediaUrls)."
    • Changedlist_accounts1 field changed
      • changedOutput schema / properties / result / description
        Previous value: -"The connected social accounts with their platform, connection ID, username, and pageId for Facebook pages as returned by the AdaptlyPost API."New value: +"An object with accounts: one { id, platform, displayName, username, avatarUrl } per connected account, plus pageId for Facebook pages. Use id as the connection id (or in pageIds for Facebook)."
    • Addedlist_post_analytics
    • Changedlist_post_results2 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"Post ID to check results for"New value: +"Post ID from create_post, publish_draft, bulk_schedule_posts, or list_posts"
      • changedOutput schema / properties / result / description
        Previous value: -"The per-platform posting results with success/failure status and error details as returned by the AdaptlyPost API."New value: +"An object with postId, the overall post status, and results: one { platformId, platform, accountName, status, platformPostId, errorMessage, publishedAt } per targeted platform."
    • Changedlist_posts8 fields changed
      • changedInput schema / properties / endDate / description
        Previous value: -"End date (ISO 8601)"New value: +"Upper bound (ISO 8601, e.g. \"2026-03-31\") on scheduledAt, or createdAt for posts never scheduled"
      • changedInput schema / properties / limit / description
        Previous value: -"Max results"New value: +"Max results, 1 to 100"
      • changedInput schema / properties / offset / description
        Previous value: -"Pagination offset"New value: +"Posts to skip; increase by limit while hasMore is true"
      • changedInput schema / properties / platforms / description
        Previous value: -"Filter by platform"New value: +"Filter to posts targeting any of these platforms"
      • changedInput schema / properties / sortOrder / description
        Previous value: -"NEWEST or OLDEST"New value: +"NEWEST (default) or OLDEST"
      • changedInput schema / properties / startDate / description
        Previous value: -"Start date (ISO 8601)"New value: +"Lower bound (ISO 8601, e.g. \"2026-03-01\") on scheduledAt, or createdAt for posts never scheduled"
      • changedInput schema / properties / statuses / description
        Previous value: -"Filter by status (e.g. [\"SCHEDULED\", \"DRAFT\"])"New value: +"Filter by status (e.g. [\"SCHEDULED\", \"DRAFT\"]); omit for all statuses"
      • changedOutput schema / properties / result / description
        Previous value: -"The matching posts with their ids, statuses, platforms, and schedule times as returned by the AdaptlyPost API."New value: +"An object with posts (each with id, status, contentType, text, scheduledAt, timezone, and platforms with per-platform status), total (count of all matches), and hasMore."
    • Changedpublish_draft4 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"Draft post ID"New value: +"Post ID with status DRAFT (or SCHEDULED)"
      • changedInput schema / properties / scheduledAt / description
        Previous value: -"Schedule time (ISO 8601). Omit to publish now"New value: +"Absolute ISO 8601 instant (e.g. \"2026-03-15T10:00:00Z\"). Omit, or pass a past time, to publish now"
      • changedInput schema / properties / timezone / description
        Previous value: -"IANA timezone"New value: +"IANA timezone stored with the post for display (e.g. \"America/New_York\"); it does not shift scheduledAt"
      • changedOutput schema / properties / result / description
        Previous value: -"The published or scheduled post record with its updated status as returned by the AdaptlyPost API."New value: +"An object with postId, queuedPlatforms (platforms whose publishing job was queued; empty when scheduled for later), isScheduled, and scheduledAt."
    • Changedretry_failed_platforms3 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"Post ID"New value: +"Post ID whose platforms failed"
      • changedInput schema / properties / platformIds / description
        Previous value: -"Failed platform IDs to retry"New value: +"platformId values of FAILED rows from list_post_results (not platform names). At least one"
      • changedOutput schema / properties / result / description
        Previous value: -"The retry outcome for the requested platform IDs as returned by the AdaptlyPost API."New value: +"An object with postId, queuedPlatforms (platforms re-queued for publishing), and isScheduled: false. Outcomes arrive asynchronously in list_post_results."
    • Addedtrigger_analytics_sync
    • Changedupdate_post12 fields changed
      • addedInput schema / properties / contentType / description
        Added value: +"New content type; must match the media on the post"
      • changedInput schema / properties / facebookConfigs / description
        Previous value: -"Facebook per-page config with post type and video title"New value: +"Facebook per-page config with post type and video title. pageId must match an entry in pageIds"
      • changedInput schema / properties / id / description
        Previous value: -"Post ID to update"New value: +"Post ID to update (must be DRAFT or SCHEDULED)"
      • changedInput schema / properties / mediaUrls / description
        Previous value: -"Updated media URLs. Use publicUrl values from upload_media or get_upload_urls"New value: +"Replacement media URLs, applied only when platforms is also sent. Use publicUrl values from upload_media or get_upload_urls"
      • changedInput schema / properties / pageIds / description
        Previous value: -"Facebook page IDs"New value: +"Facebook page account ids from list_accounts (the account id; its pageId value is also accepted). Facebook has no connection-id array"
      • changedInput schema / properties / pinterestConfigs / description
        Previous value: -"Pinterest per-connection config. boardId is required for Pinterest posts"New value: +"Pinterest per-connection config. Each entry needs connectionId + boardId; there is no API to list boards, so ask the user for the board id"
      • addedInput schema / properties / platformTexts / description
        Added value: +"Per-platform caption overrides; applied to the targets sent in platforms"
      • changedInput schema / properties / platforms / description
        Previous value: -"Updated target platforms"New value: +"New target platforms. Sending this replaces every target, so also resend the connection-id arrays and platform configs to keep; omit to leave targets unchanged"
      • changedInput schema / properties / scheduledAt / description
        Previous value: -"Updated schedule time (ISO 8601)"New value: +"New schedule time as an absolute ISO 8601 instant; omit to keep"
      • changedInput schema / properties / text / description
        Previous value: -"Updated text"New value: +"Updated text; omit to keep the current text"
      • changedInput schema / properties / timezone / description
        Previous value: -"IANA timezone for the schedule time"New value: +"IANA timezone stored for display; does not shift scheduledAt"
      • changedOutput schema / properties / result / description
        Previous value: -"The updated post record including its id, status, and scheduled time as returned by the AdaptlyPost API."New value: +"The updated post record: id, status (still DRAFT or SCHEDULED), text, contentType, scheduledAt, timezone, and platforms with per-target details."

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Schedule, publish, and measure social posts on Facebook, Instagram, TikTok, LinkedIn, Threads, Pinterest, and X for one brand or many.
    34
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Gives AI agents the ability to schedule and publish social media posts to Instagram, TikTok, YouTube, X, LinkedIn, Facebook, Pinterest, Threads, and Bluesky. Create, schedule, and bulk-plan posts with per-platform captions, then check per-platform results and retry failures.
    12
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    AI-powered social media posting across 14 platforms. Post to Twitter, Instagram, TikTok, Facebook, LinkedIn, YouTube and more with one command. AI adapts content per platform, schedules posts, and generates 30-day content calendars.
    6
    MIT
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources