Skip to main content
Glama

Server Details

Post all your social media with your AI agent — 9 networks, from Claude, ChatGPT or Cursor.

Ownership verified
Status
Healthy
Uptime
75.6% over 41 days
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL
Repository
xpost-to/xpost-agent
GitHub Stars
0
ChatGPT
xpost
Claude
–

TDQS

A4/5.0

Scored across 17 tools

Disambiguation4/5

The lifecycle tools are cleanly separated (create_post vs bulk_post vs update_post vs delete_post vs take_down_post), and the descriptions explicitly draw the boundaries. The only mild overlap is among the read-side tools — get_delivery_receipt, get_post_metrics, get_top_posts, get_insights and list_posts all return post performance data, though each is scoped to a different grain (delivery status, single post numbers, rankings, window totals, list).

Naming Consistency4/5

Nearly all names are snake_case verb_noun (create_post, update_post, delete_post, get_post_metrics, list_accounts, upload_media), which is highly predictable. The deviations are minor: 'bulk_post' uses a qualifier instead of a verb, and 'take_down_post' is a phrasal verb, but both remain readable and unambiguous.

Tool Count4/5

Seventeen tools is slightly heavy but each one covers a genuinely distinct capability across publishing, media, accounts, health, scheduling and analytics. There is no obvious filler — even narrower tools like get_best_times and list_connection_issues serve a specific job an agent would otherwise have to guess at.

Completeness5/5

The surface covers the full post lifecycle — upload media, create (single and bulk), edit, delete drafts, retry failed deliveries, take down live posts — plus accounts, connection health, platform rules, project settings and a full analytics tier. There are no dead ends; even failure paths (retry_delivery, list_connection_issues, approval links) have dedicated tools.

Available Tools

17 tools
bulk_postCreate several posts at onceA
Destructive
Inspect

Create AND SEND up to 100 DIFFERENT posts in one call: each row goes out at its scheduled_at, or now, unless the project holds agent posts. Each row runs the full single-post path — allowance, approval — and reports on its own, so some rows can land while others refuse. A row's media is media_ids (from upload_media) or media_urls. A held row carries its own approval_link. An idempotency_key per row makes a resend after a timeout answer repeated: true instead of a second post. NOT for one post going to several accounts: that is ONE create_post with every account in accounts, with any per-platform wording in platform_configurations.<platform>.caption.

NameRequiredDescriptionDefault
rowsNoThe posts to create, one object per post. `posts` is accepted as the same thing.
postsNoAlias for `rows` — send one or the other.

Output Schema

NameRequiredDescription
okNoPresent and false only on a refusal.
errorNoWhat was refused, in a sentence, when `ok` is false.
failedNo
createdNo
messageNoAbout the whole batch, written to be passed on — today, accounts it puts past a day's worth of posts.
resultsNoOne row per row you sent, in order. Rows are independent — some can land while others refuse.
retriableNoFalse when asking again cannot change the answer.
error_codeNoMachine reason for a refusal.
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.
pace_warningsNoAccounts getting more posts in one day than the network likes — it may treat that as spam. Nothing is held. Mention it to the person once and offer to spread the rest out; don't stop to ask on every post.

TDQS

A4.5/5.0
Behavior5/5

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

Goes well beyond the annotations: rows are independently evaluated through the full single-post path (allowance, approval) and can partially succeed ("some rows can land while others refuse"), held rows return their own approval_link, and a per-row idempotency_key converts a timeout resend into `repeated: true` rather than a duplicate — useful nuance given idempotentHint=false applies to the call, not the row. This is exactly the failure/idempotency context an agent needs before firing 100 writes.

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 create-and-send scope plus the batch limit, then the row-level mechanics, then the exclusion rule — a sensible order with no filler. It is dense (long sentences, heavy backtick usage) but every clause carries operational information.

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?

For a high-blast-radius bulk write with an output schema present, it covers the essentials: partial success, approval holds, idempotent resends, and the sibling alternative. It stops short of stating whether schema-invalid rows fail the whole batch or just that row, and says nothing about rate limits or batch ordering on real-time sends.

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 nested row fields are already documented (accounts refs, media_ids vs media_urls ordering, scheduled_at "next_slot", idempotency_key). The description largely restates those facts rather than adding new meaning — e.g. the media precedence rule already appears in the schema — so the baseline 3 holds.

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 + scale: "Create AND SEND up to 100 DIFFERENT posts in one call." It immediately distinguishes the bulk case from the single-post case, and the closing sentence names the sibling create_post for the opposite pattern (one post, many accounts).

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

Usage Guidelines5/5

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

Gives an explicit negative rule with the alternative: "NOT for one post going to several accounts: that is ONE create_post with every account in `accounts`." It also routes media preparation to upload_media, and states the scheduling default ("or now") and the held-project exception, so the agent knows when this tool applies and when it does not.

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

create_postCreate a postA
Destructive
Inspect

Create a post to connected accounts — X/Twitter, Instagram, LinkedIn, Facebook, TikTok, YouTube, Threads, Bluesky, Pinterest. CREATING IT SENDS IT: no scheduled_at publishes now, one publishes then; a project may hold it instead (status says). The answer carries message and approval_link or preview_link. accounts takes each account's ref. Media is media_ids, files (attachments from this conversation) or media_pending: true, which holds the post until the picture arrives — the reply's upload_url takes a POST of the file (upload_curl), or the person adds it in the card; then it goes out on its own unless the project holds agent posts. "next_slot" takes the queue; is_draft saves without sending. Undo: update_post or delete_post before it goes out; take_down_post after, where networks allow.

NameRequiredDescriptionDefault
filesNoFiles the user attached to this conversation, as the host hands them over, in post order. They are attached after `media_ids`.
captionNoThe post text. Optional only where no destination prints one: a story, or X/Instagram/LinkedIn publishing media alone. WRITE IT TO FIT EVERY TARGET: one destination over its own limit refuses the WHOLE post and nothing goes out anywhere — X is 280 as X counts it, and list_accounts gives each account its `caption_chars_available`. Words the person wrote are theirs: where they do not fit, say so and ask, never quietly shorten them.
accountsNoWhere it posts: each account's `ref` from list_accounts ("x:someone"). LIST EVERY ACCOUNT THIS POST GOES TO — one post, many accounts; a platform that needs different words gets them in platform_configurations.<platform>.caption, never a post of its own. A person reads this request before approving it, and the ref is what they can check. A ref matching nothing refuses the whole post.
is_draftNoSave as a draft: visible in xpost, publishing nowhere until a person sends it.
media_idsNoMedia ids from upload_media; first is the carousel lead.
scheduled_atNoISO 8601 with Z or an offset, or "next_slot" for the project's own posting schedule (get_project shows `queue`). Omit to publish now — or, on a project that holds agent posts, as soon as it is approved.
media_pendingNoThe picture is still to come: the person adds it in the approval card. Lets a post for Instagram, TikTok, YouTube or Pinterest be created without media; it goes out once the media is on it (or, on a project that holds agent posts, can be approved then).
idempotency_keyNoYour own id for THIS request, unique to it (not to the subject). A retry with the same key returns the post the first call made, as `repeated: true`, instead of a second post.
social_account_idsNoDeprecated name for `accounts`.
platform_configurationsNoPer-platform options keyed by platform: `caption` is that platform's own text (so one post can say it differently on X and on Instagram), `placement` picks "reels"/"stories" where offered. Which keys each account takes is what get_posting_rules answers. Example: {"instagram": {"placement": "stories"}, "x": {"caption": "the short one"}}

Output Schema

NameRequiredDescription
idNo
okNoPresent and false only on a refusal.
errorNoWhat was refused, in a sentence, when `ok` is false.
shownNoWhere this post is already on screen, and that a receipt call now would show it a second time.
statusNopending_approval | scheduled | processing | draft
captionNo
messageNoAbout this post, written to be passed on: why it is held, or that a draft goes nowhere until someone sends it.
missingNoWhat the post still lacks before it can go out.
repeatedNoThis idempotency_key was already used — `id` is that earlier post, nothing new was written.
replacedNoupdate_post: the id of the post this one replaced. That post and its approval link are gone; this post's link stands in for them.
timezoneNo
plans_urlNoPublic page explaining what the plans include. Sent with free_first_post, with publishing_needs_plan, and on a refusal with error_code needs_plan.
publishesNoWhat has to happen before it goes out. Null on a draft or a rejected post.
retriableNoFalse when asking again cannot change the answer.
attach_nowNoThis host cannot send the file: the person adds it in the card, which offers its drop zone straight away.
created_atNo
error_codeNoMachine reason for a refusal.
plans_linkNoThe same page as a ready-made Markdown link. On a refusal with error_code needs_plan, include it in the reply as-is — it is where the person activates a plan.
upload_urlNoOn a held post: where a picture is POSTed as multipart form-data with a `file` field, no key needed. An environment that holds the file can run `upload_curl`; the person's card uses the same door.
connect_urlNoWhere an account is connected. On a refusal about an account that is not there.
needs_mediaNoA draft with no picture or video for a destination that needs one; `missing` names them. It cannot be sent as it stands — attach media with update_post, or the person adds it in xpost.
release_urlNoAfter POSTing every file to upload_url, POST this once and the post goes out. In the card the person presses it instead.
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.
upload_curlNoThe upload as one shell command, YOUR_FILE replaced by the path.
preview_linkNoA post nobody has to approve, as a ready-made Markdown link to it — the post as each network will draw it, its slot if it has one, and the receipt per account once it has gone. A DRAFT gets one too: it has no slot and nothing is waiting, and the link is the only way the person can see what was written without going to look for it. Give it to the person.
queued_postsNoHow many posts are scheduled, none of them going anywhere beyond the free first one. Sent with publishing_needs_plan on a scheduled post.
scheduled_atNoThe slot it got. NULL when it waits on approval — never a stand-in time.
approval_linkNoA ready-made Markdown link to the post as a page, with Approve and Reject on it.
free_post_nowNoRefused only because it was scheduled. The same call with no scheduled_at publishes now, free.
pace_warningsNoAccounts getting more posts in one day than the network likes — it may treat that as spam. Nothing is held. Mention it to the person once and offer to spread the rest out; don't stop to ask on every post.
awaiting_mediaNoCreated without its picture (media_pending). It cannot be approved until one is on it.
drafts_waitingNoHow many drafts are now waiting, none of them on its way anywhere. Sent with publishing_needs_plan.
free_post_rideNoWith free_first_post: this post reached another of their accounts as part of the same free first post, sent in the same reply. One free delivery per account, within a few minutes of the first.
replaced_draftNoThis post FINISHED a draft that held the same words for the same accounts: that draft is gone and this post stands in for it. Say there is one copy.
connect_messageNo
free_first_postNoThis post is the user's one free post — no plan was needed for it.
upload_max_bytesNoThe most `upload_url` takes in one request; bigger files go through the card.
releases_on_mediaNoHeld for its picture only: it goes out on its own once every picture is on it. Nothing to approve.
first_post_messageNoAbout that, written to be passed on; it carries the next step.
x_trial_link_limitNoX will not receive this post: the trial's posts with a link on X are used up. Every other account still gets it. Without the link, X gets it as usual.
x_monthly_link_limitNoX will not receive this post: this month's posts with a link on X are used up on their plan. Every other account still gets it. Without the link, X gets it as usual.
publishing_needs_planNoNothing here can publish beyond the one free post: sending needs an xpost subscription. Nothing REFUSES a draft or a scheduled post any more — a queue may be filled without one — so this is the only warning, and it is worth passing on as it is written rather than discovered one slot at a time.
free_post_awaiting_approvalNoRefused because their free first post is already waiting for their approval; approval_link opens it. Nothing needs buying.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only say destructiveHint=true and openWorldHint=true; the description adds the critical context of WHAT gets destroyed and WHEN — 'CREATING IT SENDS IT', plus the project-holds-agent-posts exception and the approval/preview flow. The idempotency discussion is consistent with idempotentHint=false: retries only dedupe when the caller supplies its own `idempotency_key`, which the description makes explicit rather than contradicting the annotation.

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 single most important fact ('CREATING IT SENDS IT') is front-loaded in caps, and nearly every clause carries operational information. It is dense and telegraphic to the point of occasional ambiguity ('one publishes then'), which costs it the top score, but there is 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?

For a 10-parameter, nested-object, open-world mutation tool, the description covers side effects, approval gating, scheduling modes, media staging, partial-caption risk across platforms, and recovery paths. The output schema already documents return shape, so the brief mention of `message`/`approval_link` is sufficient rather than redundant.

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 every field; the description's added value is relational — `accounts` takes refs from list_accounts, per-platform wording belongs in platform_configurations.<platform>.caption, files attach after media_ids, and the media_pending upload_url POST flow. It stops short of explaining `social_account_ids` (deprecated) or the placement key set, leaving those to 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 and resource (create a post) and enumerates the exact destinations it reaches, so the agent knows the blast radius before reading a single parameter. It also carves out the boundary against making multiple posts: 'one post, many accounts; a platform that needs different words gets them in platform_configurations.<platform>.caption, never a post of its own.'

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/when-not guidance across the major modes: omit `scheduled_at` to publish now, `next_slot` to take the queue, `is_draft` to save without sending, `media_pending` to hold until media arrives. It also names the correct undo path per timing (update_post/delete_post before it goes out, take_down_post after), which is exactly the alternative-routing an agent needs.

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

delete_postDelete a postA
DestructiveIdempotent
Inspect

Remove a post this key created that has not gone out. A draft, a post waiting for approval, a rejected or a failed one is deleted with its delivery records. A post already holding a time is taken off the schedule instead, and unscheduled with message says so. Posts a person approved are refused, and so is one that has gone out — removing THAT from the platform is take_down_post.

NameRequiredDescriptionDefault
post_idYesThe post id from create_post

Output Schema

NameRequiredDescription
idNo
okNoPresent and false only on a refusal.
errorNoWhat was refused, in a sentence, when `ok` is false.
statusNo
deletedNoGone permanently, with its delivery records.
messageNo
retriableNoFalse when asking again cannot change the answer.
error_codeNoMachine reason for a refusal.
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.
unscheduledNoTaken off the schedule and handed back to the user instead of deleted.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations declare destructive/idempotent, but the description goes well beyond them: it discloses cascading deletion of delivery records, the non-obvious branch where a scheduled post is unscheduled instead of deleted, and the return signal (`unscheduled` with `message`). It also spells out which posts are refused and why, which an agent cannot infer from the schema.

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?

Highly information-dense with the primary constraint front-loaded and no filler. Some clauses are telegraphic ("a rejected or a failed one is deleted with its delivery records"), which costs a little readability but every sentence carries distinct behavioral information.

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 needn't be explained, yet the description still flags the `unscheduled`/`message` response case. For a single-parameter destructive tool, the destructive scope, cascade effects, refusals, and the alternative path are all covered.

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?

Only one parameter, `post_id`, and schema coverage is 100% with a usable description ("The post id from create_post"). The prose adds no additional meaning about the identifier beyond that, so this sits at the baseline where the schema does all the work.

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 ("Remove a post") plus a precise scope: posts this key created that have not gone out. It explicitly distinguishes itself from the sibling take_down_post for posts that have already published, so an agent can route 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?

Enumerates the eligible states (draft, awaiting approval, rejected, failed) and the two refusal cases (human-approved, already published), naming the alternative tool for the latter. The when-not guidance is explicit and actionable.

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

get_best_timesBest times to postA
Read-onlyIdempotent
Inspect

Posting slots (weekday × hour, UTC) ranked by this workspace's own past engagement. signal says what the order is worth: none means no engagement is recorded and the order is arbitrary; thin means some slots rest on one or two posts (samples); ok means three or more each.

NameRequiredDescriptionDefault
formatNoFilter to one format (feed post / reel / story)
platformNoFilter to one platform, e.g. instagram
since_daysNoWindow in days (default 90)

Output Schema

NameRequiredDescription
okNoPresent and false only on a refusal.
errorNoWhat was refused, in a sentence, when `ok` is false.
slotsNoBest first. Empty when there is not enough history to rank anything.
signalNoHow much the ORDER is worth. "none": no engagement recorded, so the order is arbitrary. "thin": some slots rest on one or two posts. "ok": every slot has 3+.
retriableNoFalse when asking again cannot change the answer.
error_codeNoMachine reason for a refusal.
since_daysNo
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), so the description's added value is the trust model: it explains that `none` means the order is arbitrary, `thin` means one or two underlying posts (`samples`), and `ok` means three or more. That is exactly the kind of behavioral context an agent needs before presenting the ranking as advice.

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?

Two sentences, front-loaded with what the tool returns, then the interpretation key for `signal`. Dense but every clause earns its place; the only slight redundancy is that `signal` may also be documented in 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?

An output schema exists so return values need not be spelled out, the three optional filters are fully documented in schema, and the description closes the main remaining gap by warning when the ranking is meaningless. Nothing an agent needs in order to call or interpret this tool 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%, including the enum for `format` and the 1–365 bounds and default for `since_days`, so the schema carries the parameter burden. The description adds only the UTC timezone qualifier, which pertains to the output rather than to any filter parameter, 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?

The description states a concrete resource (posting slots at weekday × hour granularity in UTC) and the ranking basis (this workspace's own past engagement), which an agent can grasp immediately. It stops short of naming how it differs from overlapping siblings such as get_insights or get_top_posts, so it is clear but not fully differentiated.

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

Usage Guidelines3/5

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

Usage is only implied: an agent must infer that this is for scheduling/planning rather than analytics review. There is no explicit when-to-use or when-not guidance, and no alternative sibling is named, though the `signal` explanation implicitly tells the agent when the ranking is trustworthy enough to act on.

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

get_delivery_receiptDelivery receipt for a postA
Read-onlyIdempotent
Inspect

Per-account delivery receipt for a post: status, the live URL, plain_reason on failure, and note where less was published than was attached. approval_link is the post as a page. Not needed straight after create_post or update_post: their card already follows the delivery live. Not needed before take_down_post either: it takes the post id and draws the post once it is down.

NameRequiredDescriptionDefault
post_idYesThe post id from create_post

Output Schema

NameRequiredDescription
okNoPresent and false only on a refusal.
dataNoOne row per destination account.
errorNoWhat was refused, in a sentence, when `ok` is false.
post_idNo
retriableNoFalse when asking again cannot change the answer.
error_codeNoMachine reason for a refusal.
post_statusNo
release_urlNoPOST once, after every picture is on the post, and it goes out on its own.
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.
approval_linkNoThe post as a page; the card draws the same thing.
picture_on_itNoThe picture has landed; only the release call is missing.
held_for_pictureNoCreated with media_pending and not released yet.
made_by_you_just_nowNoYou created this post minutes ago; its card is already on screen.

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already cover read-only, idempotent, non-destructive, closed-world, so the safety profile is done. The description adds real behavioral context beyond that: it discloses that failures surface as plain_reason, that partial publishing is signalled via note, and that approval_link renders the post as a page — useful signals about outcome states the agent would otherwise have to guess.

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 purpose is front-loaded in the first clause, followed by return-field enumeration and then two tight exclusion sentences. The heavy use of backticked field names is dense but each sentence earns its place; no filler.

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?

With an output schema present, the description needn't explain return structure, yet it still summarizes the key fields and their failure/partial-publish meaning. Combined with annotations and full schema coverage, an agent has enough to call this correctly; only the positive 'use when' trigger is left implicit.

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?

There is a single required post_id parameter at 100% schema description coverage, which already documents it as 'the post id from create_post'. The description text adds nothing about the parameter, so the baseline of 3 applies — correct behavior, no added value.

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?

The description names a specific resource (per-account delivery receipt for a post) and enumerates the exact fields it returns (status, live URL, plain_reason, note, approval_link), which lets an agent tell it apart from get_post_metrics or get_insights. It never states an explicit verb like 'fetch', but the receipt framing is unambiguous.

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

Usage Guidelines4/5

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

It gives unusually specific negative routing: don't call it straight after create_post or update_post because their card already follows delivery, and don't call it before take_down_post because that tool draws the post itself. The positive trigger (call it when you need delivery state later) is only implied, so it falls short of a full when/when-not/alternative triad.

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

get_insightsAccount insightsA
Read-onlyIdempotent
Inspect

Engagement over a window: totals, per platform, per format. coverage says how much of the window the totals rest on: with_metrics + unreportable + awaiting = deliveries. Stories are never reported on by Instagram or Facebook, so format: "story" totals are zero however many went out. ever_delivered separates an empty window from an empty history.

NameRequiredDescriptionDefault
formatNoFilter to one format (feed post / reel / story)
platformNoFilter to one platform, e.g. instagram
since_daysNoWindow in days (default 30)

Output Schema

NameRequiredDescription
okNoPresent and false only on a refusal.
errorNoWhat was refused, in a sentence, when `ok` is false.
postsNo
totalsNo
coverageNoHow much of the window the totals actually cover. with_metrics + unreportable + awaiting === deliveries.
by_formatNo
retriableNoFalse when asking again cannot change the answer.
deliveriesNo
error_codeNoMachine reason for a refusal.
since_daysNo
by_platformNo
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.
median_sampleNoHow many deliveries the median came from. Under a handful it is a coin toss.
median_engagementNoThe baseline one post has to be read against — a raw total says nothing on its own.

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/idempotent annotations: it defines the coverage equation (with_metrics + unreportable + awaiting = deliveries) and warns that story formats always yield zero totals because Instagram/Facebook don't report them. It also explains ever_delivered as the signal separating an empty window from an empty account history — exactly the context needed to interpret results correctly.

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?

Four sentences, each carrying a distinct load — scope first, then the coverage definition, then the story-format trap, then the empty-vs-history distinction. Dense but front-loaded and waste-free, despite the backtick-heavy notation.

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?

An output schema exists so return values needn't be spelled out, and the description still adds the interpretive keys (coverage, ever_delivered) an agent needs. The remaining gap is competitive positioning among 16 siblings — nothing says when this beats get_post_metrics or get_top_posts.

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 genuine meaning beyond the schema: it tells the agent that format: "story" will produce zero totals regardless of volume, which prevents a misread of the parameter's effect. Window semantics for since_days are only lightly reinforced.

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?

States a specific verb+resource with scope: engagement aggregated over a window, broken out as totals, per platform and per format. That distinguishes it in spirit from get_post_metrics/get_top_posts, but it never names a sibling or says explicitly that it is the aggregate endpoint.

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

Usage Guidelines3/5

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

Usage is implied by the window/filter framing and the caveats about story formats, but there is no explicit when-to-use or when-not guidance, and no routing to alternatives like get_post_metrics for per-post detail or get_best_times for timing.

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

get_posting_rulesPosting rules per accountA
Read-onlyIdempotent
Inspect

Every platform_configurations key each account accepts, with kind, accepted values, ceilings and placement gates — the catalog to read before setting anything beyond a caption. A key that is absent cannot be published through that connection: sent anyway it is refused or loses the delivery. Pinterest accounts also list boards, each with eligible. ONE POST CARRIES EVERY ACCOUNT: list them all in create_post's accounts and put a platform's own words in platform_configurations.<platform>.caption, its own options beside them. One post per platform is not how this works — it spends the free first post on a single network, walls the rest, and hands the person one card per network to read instead of one.

NameRequiredDescriptionDefault
social_account_idsNoNarrow to these accounts (ids from list_accounts); omit for all

Output Schema

NameRequiredDescription
okNoPresent and false only on a refusal.
dataNo
errorNoWhat was refused, in a sentence, when `ok` is false.
retriableNoFalse when asking again cannot change the answer.
error_codeNoMachine reason for a refusal.
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint/idempotentHint/destructiveHint=false, so the safety profile is covered. The description adds genuine behavioral context beyond them: absent keys are refused or silently lose the delivery if sent anyway, and Pinterest returns nested `boards` with `eligible`. It does not discuss pagination or rate limits, but for a read-only catalog that gap 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.

Conciseness3/5

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

The first sentence front-loads the resource content well, but roughly half the text is a lecture about how create_post should be called ("ONE POST CARRIES EVERY ACCOUNT", per-platform caption placement). That guidance serves create_post more than this tool and crowds out detail about this tool's own behavior.

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?

An output schema exists, so return values need not be spelled out, yet the description usefully characterizes the payload shape (keys, accepted values, ceilings, gates, boards). With full schema coverage and a documented single optional filter, an agent has what it needs to call this 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% and the single `social_account_ids` parameter is fully documented inline, so the baseline is 3. The description never mentions this parameter, and its "list them all" instruction refers to create_post's `accounts`, not this tool's filter.

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?

The description states precisely what is returned: every `platform_configurations` key accepted per account, with kind, accepted values, ceilings and placement gates, plus Pinterest `boards` with `eligible`. It distinguishes itself from create_post by framing itself as the catalog to read first, though it opens with a noun phrase rather than a verb, making the read action slightly implicit.

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?

"the catalog to read before setting anything beyond a caption" gives a clear trigger condition, and the note that absent keys cannot be published establishes a consequence for skipping it. It does not enumerate other alternatives (e.g., list_accounts for ids is only referenced in the schema), so the routing is clear but not exhaustive.

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

get_post_metricsMetrics for a postA
Read-onlyIdempotent
Inspect

Per-platform engagement for one published post: views, likes, comments, shares, reach, saves, engagement, and the live URL. A null metric is one the platform does not report, not zero; empty data means the numbers have not synced yet (roughly every 6 hours).

NameRequiredDescriptionDefault
post_idYesThe post id from create_post

Output Schema

NameRequiredDescription
okNoPresent and false only on a refusal.
dataNoOne row per platform. EMPTY means the numbers haven't synced yet, not that nobody saw it.
errorNoWhat was refused, in a sentence, when `ok` is false.
post_idNo
retriableNoFalse when asking again cannot change the answer.
error_codeNoMachine reason for a refusal.
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive, so the description is free to spend its words elsewhere — and it does: null vs zero semantics, empty `data` meaning unsynced, and a ~6-hour refresh cadence are exactly the interpretive context an agent needs and cannot get from structured fields. It does not cover rate limits or per-platform keying details, keeping it at 4.

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, both front-loaded with the highest-value information: what comes back first, then how to read ambiguous results. No filler, no restatement of the title.

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?

With an output schema present, return-value structure need not be explained, yet the description still supplies the semantics that a schema cannot express (null meaning, empty-data meaning, sync cadence). The remaining gap is sibling differentiation against get_insights/get_top_posts.

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?

There is one required parameter at 100% schema coverage, and the schema already documents it as 'The post id from create_post' including UUID format and pattern. The description adds nothing about the parameter, 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?

The description names the resource precisely ('per-platform engagement for one published post') and enumerates the returned metrics, so an agent knows exactly what it yields. It does not distinguish itself from plausible siblings such as get_insights or get_top_posts, so it stops short of a 5.

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

Usage Guidelines3/5

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

Usage is only implied by the phrase 'for one published post' — the agent can infer this is the single-post lookup, but there is no explicit when-to-use statement and no routing away from get_insights, get_top_posts, or list_posts. No prerequisites or exclusions are stated.

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

get_projectProject rules and settingsA
Read-onlyIdempotent
Inspect

The project's settings, read before writing: timezone (the clock every bare time is on), queue (its posting schedule and next free slots — scheduled_at: "next_slot" takes one), approval (whether agent posts wait for a person), posts_today (this key's remaining daily allowance) and publishing (whether anything written here can go out at all — read it before writing, not after).

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
okNoPresent and false only on a refusal.
nameNo
errorNoWhat was refused, in a sentence, when `ok` is false.
queueNo
approvalNo
timezoneNoEvery bare timestamp is read in this zone.
retriableNoFalse when asking again cannot change the answer.
signatureNo
error_codeNoMachine reason for a refusal.
guardrailsNo
publishingNo
posts_todayNo
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds meaningful behavioral context beyond annotations: it describes how settings gate writes ('whether agent posts wait for a person', 'whether anything written here can go out at all') and clarifies the operational consequence of each field.

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 definition is front-loaded with the core purpose and then organizes details field-by-field with useful parentheticals. It is dense but not wasteful, though the single long sentence is slightly harder to scan than a more structured list would be.

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 no parameters, rich read-only annotations, and an output schema present, the description supplies everything an agent needs: what the settings mean, why they matter before writing, and how to interpret key values like queue.next_slot. Nothing essential 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?

The tool takes zero parameters, so the baseline is 4. The description does not need to explain parameter semantics, and it correctly focuses on the returned settings instead.

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?

The description clearly identifies the resource as 'the project's settings' and enumerates the specific fields returned: timezone, queue, approval, posts_today, and publishing. It is distinguishable by content from sibling tools, but does not explicitly contrast itself with closely related tools like get_posting_rules, so it falls just short of a 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?

The description provides strong usage guidance with 'read before writing' and the emphatic 'read it before writing, not after', telling the agent exactly when this tool is needed. It lacks explicit exclusions or named alternatives, which prevents a 5.

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

get_top_postsTop postsA
Read-onlyIdempotent
Inspect

Best-performing deliveries ranked by a metric, with caption, platform, username, metrics and live URL — what worked for this audience, as a study aid rather than a template.

NameRequiredDescriptionDefault
limitNoMax results (default 10)
formatNoFilter to one format (feed post / reel / story)
metricNoRanking metric (default engagement)
platformNoFilter to one platform, e.g. instagram
since_daysNoWindow in days (default 30)

Output Schema

NameRequiredDescription
okNoPresent and false only on a refusal.
dataNo
errorNoWhat was refused, in a sentence, when `ok` is false.
metricNo
retriableNoFalse when asking again cannot change the answer.
error_codeNoMachine reason for a refusal.
since_daysNo
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true and destructiveHint=false, so safety is covered by structured data. The description adds useful behavioral context — that results are ranked by a chosen metric and include a live URL — but does not mention defaults (limit 10, 30-day window), pagination, or whose posts are in scope.

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?

A single front-loaded sentence that leads with the core operation and return payload. The trailing 'study aid rather than a template' clause is interpretive but short and arguably aids intent; only mildly ornamental.

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?

An output schema exists, so return values needn't be spelled out, and the annotations plus full schema coverage handle safety and parameters. The only real gap is scope — it is unclear whether this ranks the caller's own accounts' posts or broader data ('this audience' is vague).

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 all five parameters (limit, format, metric, platform, since_days) are already documented including defaults and enums. The description only reiterates that a metric drives ranking, adding little beyond the schema; 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?

States a specific operation — ranking deliveries by a metric — and enumerates the returned fields (caption, platform, username, metrics, live URL). This distinguishes it from list_posts (unranked) and get_post_metrics (a single post), though it never names those siblings explicitly.

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

Usage Guidelines3/5

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

The phrase 'what worked for this audience, as a study aid rather than a template' implies an exploratory/analytical use case, giving some context on intent. But it offers no explicit when-to-use versus alternatives such as get_post_metrics, get_insights, or get_best_times, leaving routing to inference.

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-onlyIdempotent
Inspect

The connected accounts and what each will publish. ref ("x:someone") is what create_post accounts takes. limits carries caption_chars_available (room for your words), max_media, media_required and video_seconds; can carries placements, first comment, people tags, documents and mixed media. These describe the connection, not the platform's brochure. posts_left_today (where present) is how many more posts that account can publish before resets_at (midnight UTC) — schedule past it, not into a full day, which is refused. connect_url is the page where an account is connected — hand it over whenever a platform they asked for is missing. An empty list adds connect_message; a project that has never published adds never_posted_message, which says what to offer them next.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
okNoPresent and false only on a refusal.
dataNo
errorNoWhat was refused, in a sentence, when `ok` is false.
retriableNoFalse when asking again cannot change the answer.
error_codeNoMachine reason for a refusal.
connect_urlNo
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.
connect_messageNo
never_posted_messageNo

TDQS

A3.9/5.0
Behavior4/5

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

Beyond the readOnly/idempotent annotations, it discloses real behavioral detail: empty results append `connect_message`, brand-new projects append `never_posted_message`, and scheduling into a full day is refused with a UTC-midnight reset. It notably warns that limits reflect the actual connection, not the platform's advertised capability. It doesn't describe ordering or pagination, but with zero parameters the payload is presumably a single list.

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

Conciseness3/5

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

Purpose is front-loaded, but the bulk is an enumerated tour of return fields (`limits`, `can`, `posts_left_today`, `connect_url`) that an output schema already covers. The 'not the platform's brochure' clarification earns its place; the field inventory is partially redundant.

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?

With zero parameters, closed-world read-only annotations and an output schema, the definition needs only to route the agent and flag behavioral edge cases. It does both, including the missing-platform handoff and never-posted case. Nothing required for correct invocation is absent.

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?

The tool takes no parameters, which is the documented baseline for full marks. The description spends its space on return-field semantics instead, which is not what this dimension measures but also not harmful.

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?

The opening fragment 'The connected accounts and what each will publish' identifies the resource and scope, and the title supplies the verb. It also differentiates itself by naming create_post's `accounts` parameter as the downstream consumer, which no sibling does. It stops short of an explicit 'list/read' verb and doesn't contrast with list_connection_issues.

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?

Provides concrete usage conditions: use `ref` to fill create_post's `accounts`, hand over `connect_url` when a requested platform is missing, and schedule around `posts_left_today` rather than into a refused full day. These are operating instructions rather than explicit when-to-call-this-vs-alternative guidance, so no exclusion clause is given.

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

list_connection_issuesList account connection problemsA
Read-onlyIdempotent
Inspect

Accounts that cannot publish right now — an expired token, a platform out of reach — each with what happened. The fix is the person reconnecting that account: connect_url is where they do it. An empty list means every account is healthy.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
okNoPresent and false only on a refusal.
dataNoOpen issues only. Empty means every account is healthy.
errorNoWhat was refused, in a sentence, when `ok` is false.
retriableNoFalse when asking again cannot change the answer.
error_codeNoMachine reason for a refusal.
connect_urlNoWhere the person reconnects an account.
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.
connect_messageNo

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, non-destructive, so the safety profile is covered. The description adds genuine behavior the agent would otherwise guess at: what an empty list means (all accounts healthy) and that the remedy lives at connect_url. It omits pagination/volume expectations, keeping it below a 5.

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?

Three short sentences, front-loaded with the definition, then the remediation path, then the empty-list edge case. No filler or repetition of the title.

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 explain return values, so covering the definition, the empty-result case, and the remediation pointer is sufficient for an agent to call and act on this no-parameter read tool.

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?

The tool takes zero parameters, which is the baseline-4 case: there is no parameter meaning to convey and the description correctly spends no words on inputs.

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?

It names the resource (accounts that cannot publish) and enumerates the failure modes (expired token, unreachable platform), which implicitly distinguishes it from list_accounts. It stops short of explicitly contrasting with that sibling, but an agent can tell what the tool returns.

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

Usage Guidelines3/5

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

The description supplies downstream guidance ('the fix is the person reconnecting that account; connect_url is where they do it'), which is useful remediation context. It never states the triggering condition for calling this versus list_accounts or when to skip it, so usage is only implied by the tool's name and scope.

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-onlyIdempotent
Inspect

Recent posts with status, publishes, mediaIds and, on a rejected post, rejectionReason — the person's own words on what to change with update_post (often empty after a one-tap rejection). Filter with status (one or several), limit, and from/to on the scheduled time. A post still waiting carries approval_link. filter echoes what applied. An empty list with nothing filtered adds never_posted_message, which says what to offer them next.

NameRequiredDescriptionDefault
toNoOnly posts whose scheduled time is at or before this instant.
fromNoOnly posts whose scheduled time is at or after this instant (ISO 8601, Z or offset). With `from` or `to` the list runs soonest first and leaves out posts that have no time yet.
limitNoHow many, newest first (default 50, max 100)
statusNoOnly posts in this state (or any of these). Omit for all of them.

Output Schema

NameRequiredDescription
okNoPresent and false only on a refusal.
dataNoNewest first, camelCase here unlike the rest of this server. Up to `limit` (50 by default).
errorNoWhat was refused, in a sentence, when `ok` is false.
filterNoWhat actually applied — null status means nothing was filtered.
retriableNoFalse when asking again cannot change the answer.
error_codeNoMachine reason for a refusal.
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.
never_posted_messageNo

TDQS

A3.9/5.0
Behavior5/5

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

Goes well beyond the annotations: discloses that from/to flips ordering to soonest-first and drops untimed posts, that limit is newest-first, that `filter` echoes applied filters, that an unfiltered empty result adds never_posted_message, and that rejectionReason is often empty after a one-tap rejection. These are non-obvious response behaviors an agent could not infer.

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 single paragraph, front-loaded with the returned shape before filters and edge cases. Backtick-heavy phrasing makes it slightly hard to scan but every clause carries real information; no filler sentences.

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?

An output schema exists, so explaining individual return fields is partly redundant, but the conditional fields (approval_link, never_posted_message, filter echo) and the empty-result semantics are exactly the kind of conditional behavior a schema alone wouldn't surface. Nothing essential 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 coverage is 100% and the schema already documents status-as-single-or-array, the from/to ordering side effect, and limit defaults. The description largely restates those same semantics rather than adding new meaning, so it sits at the baseline for high coverage.

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?

Concrete: lists recent posts, names the exact fields returned (status, publishes, mediaIds, rejectionReason) and the filters available. It's clearly a post-listing read, distinct from get_top_posts or get_post_metrics by virtue of being unfiltered-by-performance, though no sibling is named explicitly.

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

Usage Guidelines3/5

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

Usage is implied through the data: a rejected post's rejectionReason is what to change 'with update_post', and never_posted_message 'says what to offer them next' — so the agent gets workflow cues. But there is no explicit statement of when to choose this over get_top_posts or get_insights.

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

retry_deliveryRetry a failed deliveryAInspect

Send one failed delivery again, by its id from get_delivery_receipt — a delivery id, not a post id. Skip it when the receipt says retry_helps: false: the same failure comes back. A delivery that succeeded is refused. A refusal carries error_code — already_succeeded (with post_url, or taken_down), in_flight, already_claimed, not_found, or is_post_id (a post id was passed; its deliveries are in the answer, pick the failed one) — and retriable, false when asking again cannot change the answer.

NameRequiredDescriptionDefault
delivery_idYes`id` of the failed row in get_delivery_receipt

Output Schema

NameRequiredDescription
idNo
okNoPresent and false only on a refusal.
errorNoWhat was refused, in a sentence, when `ok` is false.
retriedNo
post_urlNoOn `already_succeeded`: the live post. It did land.
retriableNoFalse when asking again cannot change the answer.
error_codeNoMachine reason for a refusal.
taken_downNoWith no post_url: it went out and was removed; no live link exists.
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only declare it is a non-read-only, non-idempotent, open-world write. The description goes well beyond that by enumerating the refusal taxonomy (already_succeeded, in_flight, already_claimed, not_found, is_post_id) and the retriable flag that tells the agent whether re-asking can change the answer. That is exactly the behavioral context an agent needs before calling a non-idempotent mutation.

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 action and the critical skip condition, with zero filler. The long parenthetical enumerating every error_code is dense and slightly harder to scan than a short list, but each item earns its place by telling the agent how to react.

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, and the description still covers the input source, the skip rule, refusal handling, and retriability. Nothing needed to call this correctly is missing.

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

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 real disambiguation beyond the schema text: the id is a delivery id and specifically not a post id, and the is_post_id refusal explains how to recover when the wrong kind of id is supplied. That extra meaning justifies a 4.

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 ('Send one failed delivery again') and immediately pins the identifier to a delivery id from get_delivery_receipt, explicitly excluding a post id. That single clause distinguishes it from get_delivery_receipt and from post-level siblings without needing 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 Guidelines5/5

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

Gives explicit when-to-use (a failed delivery whose receipt does not say retry_helps: false) and when-not (succeeded deliveries are refused), plus an alternative path when a post id is passed: pick the failed row out of the returned deliveries. The preconditions are concrete and actionable.

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

take_down_postTake a live post downA
DestructiveIdempotent
Inspect

Delete a published post from its platforms, by its post_id — every platform it is live on, or only platform. There is no need to call get_delivery_receipt first. There is no undo; reposting is a new post with a new URL. This is the person's own decision about their live post, not a cleanup step. Each delivery answers in deliveries: error_code never_went_out, account_gone or unsupported means the person removes it on the platform themselves; only platform_refused is retriable. delivery_id still takes down one delivery; a post id passed there answers is_post_id with the post's deliveries.

NameRequiredDescriptionDefault
post_idNoThe post id from create_post or list_posts
platformNoOnly take it down here, e.g. `x`. Omit for every platform it is live on.
delivery_idNoOne delivery's `id` from get_delivery_receipt, instead of post_id

Output Schema

NameRequiredDescription
idNo
okNoPresent and false only on a refusal.
dataNoThe receipt after the take-down.
errorNoWhat was refused, in a sentence, when `ok` is false.
post_idNo
retriableNoFalse when asking again cannot change the answer.
deliveriesNoEach live delivery's own answer; one platform refusing does not stop the others.
error_codeNoMachine reason for a refusal.
taken_downNoGone from the platform — true, or how many deliveries came down. No undo.
post_statusNo
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.
preview_linkNo
approval_linkNo

TDQS

A4.8/5.0
Behavior5/5

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

The description goes far beyond basic documentation by detailing the operational semantics of error codes (e.g., distinguishing between 'user removed it' vs. 'platform refused'). This is highly valuable behavioral context not found 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.

Conciseness4/5

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

The description is dense and covers many complex operational facets, making it effective, though it is quite lengthy. Every sentence, however, adds critical functional information.

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 the high complexity (multi-platform, multiple ID options, irreversible nature, detailed failure logic), the description is extremely complete, leaving very little for the agent to infer about the tool's constraints and operational flow.

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?

Although schema coverage is 100%, the description adds crucial semantic context explaining the functional relationship between `post_id` and `delivery_id`, which helps the agent choose the correct identifier based on its available data.

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 purpose is explicitly clear: to delete a live post. It specifies the action and the resource, and uses 'take down' which clearly differentiates it from update or create siblings.

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 provides vital workflow guidance, stating there is 'no need to call get_delivery_receipt first' (direct contrast to a sibling tool) and clearly outlines the irreversible nature of the action ('no undo').

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

update_postEdit a postA
Destructive
Inspect

Change a post that has not gone out — caption, media, time, per-platform options; anything left out is kept. The reply is a NEW post with a new id and a new link; replaced names the old one, which is gone. add_media_ids and files append to what the post holds; media_ids replaces it. A picture the person added in the approval card is already on the post. Editing an approved or rejected post puts it back in the approval queue, and message says which of the two happened. A post already tried is not editable: retry_delivery handles the delivery that failed. Send a draft with is_draft: false — creating it again instead posts the words twice.

NameRequiredDescriptionDefault
filesNoFiles the user attached to this conversation, appended after what the post holds.
captionNoThe new text. It must still fit every target's own limit — X is 280 as X counts it — or the edit is refused and the post keeps its old words.
post_idYesThe post to change — an id list_posts returned, never one built from memory. Every edit gives the post a NEW id (the answer's `id`); use that one next time. An id an edit retired is refused with `error_code: replaced` and `replaced_by`, the current id. An id this project does not hold is refused with `error_code: not_found`; read the list again rather than trying another id.
is_draftNo`false` sends a draft: it leaves the drawer and goes out at its time, or now, or to the approval queue — whichever the project does. This is how a draft is finished; creating the post again instead leaves the draft behind and publishes the words twice. `true` puts a post that has not gone out back into the drawer. Omit to keep it as it is.
media_idsNoReplaces the attachments; omit to keep them.
scheduled_atNoNew time (Z or an offset); "next_slot" hands it to the project's queue; null clears it, and it goes out now — or once approved, on a project that holds agent posts.
add_media_idsNoAppended after what the post already holds.
platform_configurationsNoReplaces the per-platform options; omit to keep them.

Output Schema

NameRequiredDescription
idNo
okNoPresent and false only on a refusal.
errorNoWhat was refused, in a sentence, when `ok` is false.
shownNoWhere this post is already on screen, and that a receipt call now would show it a second time.
statusNopending_approval | scheduled | processing | draft
captionNo
messageNoAbout this post, written to be passed on: why it is held, or that a draft goes nowhere until someone sends it.
missingNoWhat the post still lacks before it can go out.
repeatedNoThis idempotency_key was already used — `id` is that earlier post, nothing new was written.
replacedNoupdate_post: the id of the post this one replaced. That post and its approval link are gone; this post's link stands in for them.
timezoneNo
plans_urlNoPublic page explaining what the plans include. Sent with free_first_post, with publishing_needs_plan, and on a refusal with error_code needs_plan.
publishesNoWhat has to happen before it goes out. Null on a draft or a rejected post.
retriableNoFalse when asking again cannot change the answer.
attach_nowNoThis host cannot send the file: the person adds it in the card, which offers its drop zone straight away.
created_atNo
error_codeNoMachine reason for a refusal.
plans_linkNoThe same page as a ready-made Markdown link. On a refusal with error_code needs_plan, include it in the reply as-is — it is where the person activates a plan.
upload_urlNoOn a held post: where a picture is POSTed as multipart form-data with a `file` field, no key needed. An environment that holds the file can run `upload_curl`; the person's card uses the same door.
connect_urlNoWhere an account is connected. On a refusal about an account that is not there.
needs_mediaNoA draft with no picture or video for a destination that needs one; `missing` names them. It cannot be sent as it stands — attach media with update_post, or the person adds it in xpost.
release_urlNoAfter POSTing every file to upload_url, POST this once and the post goes out. In the card the person presses it instead.
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.
upload_curlNoThe upload as one shell command, YOUR_FILE replaced by the path.
preview_linkNoA post nobody has to approve, as a ready-made Markdown link to it — the post as each network will draw it, its slot if it has one, and the receipt per account once it has gone. A DRAFT gets one too: it has no slot and nothing is waiting, and the link is the only way the person can see what was written without going to look for it. Give it to the person.
queued_postsNoHow many posts are scheduled, none of them going anywhere beyond the free first one. Sent with publishing_needs_plan on a scheduled post.
scheduled_atNoThe slot it got. NULL when it waits on approval — never a stand-in time.
approval_linkNoA ready-made Markdown link to the post as a page, with Approve and Reject on it.
free_post_nowNoRefused only because it was scheduled. The same call with no scheduled_at publishes now, free.
pace_warningsNoAccounts getting more posts in one day than the network likes — it may treat that as spam. Nothing is held. Mention it to the person once and offer to spread the rest out; don't stop to ask on every post.
awaiting_mediaNoCreated without its picture (media_pending). It cannot be approved until one is on it.
drafts_waitingNoHow many drafts are now waiting, none of them on its way anywhere. Sent with publishing_needs_plan.
free_post_rideNoWith free_first_post: this post reached another of their accounts as part of the same free first post, sent in the same reply. One free delivery per account, within a few minutes of the first.
replaced_draftNoThis post FINISHED a draft that held the same words for the same accounts: that draft is gone and this post stands in for it. Say there is one copy.
connect_messageNo
free_first_postNoThis post is the user's one free post — no plan was needed for it.
upload_max_bytesNoThe most `upload_url` takes in one request; bigger files go through the card.
releases_on_mediaNoHeld for its picture only: it goes out on its own once every picture is on it. Nothing to approve.
first_post_messageNoAbout that, written to be passed on; it carries the next step.
x_trial_link_limitNoX will not receive this post: the trial's posts with a link on X are used up. Every other account still gets it. Without the link, X gets it as usual.
x_monthly_link_limitNoX will not receive this post: this month's posts with a link on X are used up on their plan. Every other account still gets it. Without the link, X gets it as usual.
publishing_needs_planNoNothing here can publish beyond the one free post: sending needs an xpost subscription. Nothing REFUSES a draft or a scheduled post any more — a queue may be filled without one — so this is the only warning, and it is worth passing on as it is written rather than discovered one slot at a time.
free_post_awaiting_approvalNoRefused because their free first post is already waiting for their approval; approval_link opens it. Nothing needs buying.

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: it discloses that the response is a NEW post with a new id, that the old id is retired (`replaced`, error_code: replaced / not_found), that editing an approved or rejected post re-enters the approval queue with `message` reporting which, and that an over-limit caption is refused while keeping the old words. These are exactly the consequences destructiveHint=true and idempotentHint=false imply but do not spell out.

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 id-replacement consequence, and most sentences carry non-obvious information. However, the draft double-post warning appears nearly verbatim twice, and the description is long enough that some density could be trimmed without losing meaning.

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 explained, and the description nonetheless previews the meaningful response fields (`replaced`, `id`, `message`) and the error codes an agent must handle. For a destructive, non-idempotent, nested-parameter edit tool, nothing needed for correct invocation 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 baseline is 3; the description still adds real semantics by contrasting the three media paths (`add_media_ids`/`files` append, `media_ids` replaces) and by noting that a picture added in the approval card is already on the post. `scheduled_at` and `platform_configurations` are only gestured at, so it stops short of full parameter coverage.

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 ("Change a post") plus the crucial qualifier "that has not gone out", and enumerates the editable facets (caption, media, time, per-platform options). It also implies the boundary against create_post and retry_delivery so an agent can tell it apart 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?

Explicitly routes away from this tool in two cases and names the sibling to use instead: a failed post goes to retry_delivery, and finishing a draft must be done with `is_draft: false` rather than calling create_post again ("posts the words twice"). Both the when and the when-not are stated.

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

upload_mediaAttach a picture, video or PDFAInspect

Attach an image, video or PDF and get a media_id for create_post. Sources: file (an attachment from this conversation, as the host provides it), a public https url, base64 data with mime_type. Instagram, TikTok, YouTube and Pinterest need media; a PDF becomes a LinkedIn document post. When an attached file cannot be provided from here, create the post with media_pending: true instead and the person adds it in the approval card. Formats and caps: https://xpost.to/docs/api#media.

NameRequiredDescriptionDefault
urlNoPublic https URL
dataNoThe bytes of a small image, video or PDF generated here, base64-encoded, with `mime_type`. A file the user attached travels as `file`, or through the post's `upload_url`, not here.
fileNoA file the user attached to this conversation, as the host hands it over. Absent when the host has no such object.
alt_textNoImages: accessibility alt text (max 1000 chars). Applied natively on X and Bluesky
mime_typeNoMIME type for `data`, e.g. image/png, video/mp4
thumbnail_timestamp_msNoVideos: cover-frame time in ms into the video

Output Schema

NameRequiredDescription
idNoPass in create_post's media_ids.
okNoPresent and false only on a refusal.
kindNo
errorNoWhat was refused, in a sentence, when `ok` is false.
retriableNoFalse when asking again cannot change the answer.
error_codeNoMachine reason for a refusal.
people_tagsNo
replaced_byNoThe id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on.

TDQS

A4.7/5.0
Behavior4/5

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

Annotations declare the mutation/safety profile (readOnly=false, destructive=false, idempotent=false, openWorld=true), so the description needn't restate that; it adds real context instead — the media_id return, per-platform media requirements, and the graceful degradation path. Only gap is that format/size caps are offloaded to an external URL rather than summarized.

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 core action and return value are front-loaded in the first sentence, with source details, platform rules and the fallback ordered by decision relevance. Every clause carries information; nothing is restated from the title or 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?

Despite six parameters, a nested file object and an output schema, the description covers what an agent needs: which source to pick, what platforms require media, what comes back, and what to do when the file is unreachable. Return-value detail is correctly delegated 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 already 100%, so the baseline is 3; the description goes further by explaining source selection semantics — that host attachments travel as `file` (or the post's upload_url), and that base64 `data` requires a matching `mime_type`. It doesn't explain alt_text or thumbnail_timestamp_ms, but those are self-documenting in 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 and resource ('Attach an image, video or PDF') and names the payoff ('get a media_id for create_post'), which also anchors it to the sibling it feeds. An agent can distinguish this from create_post or bulk_post 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 Guidelines5/5

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

Explicitly enumerates the three input sources (`file`, https `url`, base64 `data` + `mime_type`), states platform conditions (Instagram/TikTok/YouTube/Pinterest need media; PDF becomes a LinkedIn document), and gives the fallback alternative (`media_pending: true` on the post) when a file cannot travel from here.

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. 17 tool updates
    • Changedbulk_post1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
    • Changedcreate_post1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
    • Changeddelete_post1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
    • Changedget_best_times1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
    • Changedget_delivery_receipt1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
    • Changedget_insights1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
    • Changedget_post_metrics1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
    • Changedget_posting_rules1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
    • Changedget_project1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
    • Changedget_top_posts1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
    • Changedlist_accounts1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
    • Changedlist_connection_issues1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
    • Changedlist_posts1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
    • Changedretry_delivery1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
    • Changedtake_down_post1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
    • Changedupdate_post1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
    • Changedupload_media1 field changed
      • changedOutput schema / properties / replaced_by / description
        Previous value: -"With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one."New value: +"The id the post has now, when you asked with one an edit retired. An edit gives a post a new id: get_delivery_receipt and get_post_metrics answer for this current version (and `asked_for` is the id you sent); update_post and delete_post refuse with error_code `replaced`. Use this id from here on."
  2. 2 tool updates
    • Changedcreate_post1 field changed
      • addedOutput schema / properties / x_monthly_link_limit
        Added value: +{
        +  "description": "X will not receive this post: this month's posts with a link on X are used up on their plan. Every other account still gets it. Without the link, X gets it as usual.",
        +  "type": "boolean"
        +}
    • Changedupdate_post1 field changed
      • addedOutput schema / properties / x_monthly_link_limit
        Added value: +{
        +  "description": "X will not receive this post: this month's posts with a link on X are used up on their plan. Every other account still gets it. Without the link, X gets it as usual.",
        +  "type": "boolean"
        +}
  3. 2 tool updates
    • Changedget_delivery_receipt1 field changed
      • addedOutput schema / properties / data / items / properties / retry_helps
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "boolean"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "On a failure: false means retry_delivery fails the same way — do what `plain_reason` says instead."
        +}
    • Changedtake_down_post1 field changed
      • addedOutput schema / properties / data / items / properties / retry_helps
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "boolean"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "On a failure: false means retry_delivery fails the same way — do what `plain_reason` says instead."
        +}
  4. 3 tool updates
    • Changedbulk_post2 fields changed
      • addedOutput schema / properties / message
        Added value: +{
        +  "description": "About the whole batch, written to be passed on — today, accounts it puts past a day's worth of posts.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / pace_warnings
        Added value: +{
        +  "description": "Accounts getting more posts in one day than the network likes — it may treat that as spam. Nothing is held. Mention it to the person once and offer to spread the rest out; don't stop to ask on every post.",
        +  "items": {
        +    "additionalProperties": {},
        +    "properties": {
        +      "account_id": {
        +        "type": "string"
        +      },
        +      "new_account": {
        +        "type": "boolean"
        +      },
        +      "platform": {
        +        "type": "string"
        +      },
        +      "posts_within_a_day": {
        +        "type": "number"
        +      },
        +      "same_site": {
        +        "additionalProperties": {},
        +        "properties": {
        +          "domain": {
        +            "type": "string"
        +          },
        +          "posts": {
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "suggested_per_day": {
        +        "type": "number"
        +      },
        +      "username": {
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedcreate_post1 field changed
      • addedOutput schema / properties / pace_warnings
        Added value: +{
        +  "description": "Accounts getting more posts in one day than the network likes — it may treat that as spam. Nothing is held. Mention it to the person once and offer to spread the rest out; don't stop to ask on every post.",
        +  "items": {
        +    "additionalProperties": {},
        +    "properties": {
        +      "account_id": {
        +        "type": "string"
        +      },
        +      "new_account": {
        +        "type": "boolean"
        +      },
        +      "platform": {
        +        "type": "string"
        +      },
        +      "posts_within_a_day": {
        +        "type": "number"
        +      },
        +      "same_site": {
        +        "additionalProperties": {},
        +        "properties": {
        +          "domain": {
        +            "type": "string"
        +          },
        +          "posts": {
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "suggested_per_day": {
        +        "type": "number"
        +      },
        +      "username": {
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedupdate_post1 field changed
      • addedOutput schema / properties / pace_warnings
        Added value: +{
        +  "description": "Accounts getting more posts in one day than the network likes — it may treat that as spam. Nothing is held. Mention it to the person once and offer to spread the rest out; don't stop to ask on every post.",
        +  "items": {
        +    "additionalProperties": {},
        +    "properties": {
        +      "account_id": {
        +        "type": "string"
        +      },
        +      "new_account": {
        +        "type": "boolean"
        +      },
        +      "platform": {
        +        "type": "string"
        +      },
        +      "posts_within_a_day": {
        +        "type": "number"
        +      },
        +      "same_site": {
        +        "additionalProperties": {},
        +        "properties": {
        +          "domain": {
        +            "type": "string"
        +          },
        +          "posts": {
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "suggested_per_day": {
        +        "type": "number"
        +      },
        +      "username": {
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
  5. 1 tool update
    • Changedget_delivery_receipt3 fields changed
      • addedOutput schema / properties / held_for_picture
        Added value: +{
        +  "description": "Created with media_pending and not released yet.",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / picture_on_it
        Added value: +{
        +  "description": "The picture has landed; only the release call is missing.",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / release_url
        Added value: +{
        +  "description": "POST once, after every picture is on the post, and it goes out on its own.",
        +  "type": "string"
        +}
  6. 1 tool update
    • Removedcheck_guardrails
  7. 3 tool updates
    • Changedcreate_post1 field changed
      • removedInput schema / properties / skip_signature
        Removed value: -{
        -  "description": "Leave the project's signature off this post. Only when the user asked for that in words.",
        -  "type": "boolean"
        -}
    • Changedget_posting_rules2 fields changed
      • changedOutput schema / properties / data / items / properties / limits / properties / caption_chars_available / description
        Previous value: -"Caption room left once the project's signature is added."New value: +"Caption room left for your words."
      • addedOutput schema / properties / data / items / properties / posts_left_today
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Absent where the account has no such daily allowance.",
        +  "properties": {
        +    "limit": {
        +      "type": "number"
        +    },
        +    "remaining": {
        +      "type": "number"
        +    },
        +    "resets_at": {
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedlist_accounts2 fields changed
      • changedOutput schema / properties / data / items / properties / limits / properties / caption_chars_available / description
        Previous value: -"Caption room left once the project's signature is added."New value: +"Caption room left for your words."
      • addedOutput schema / properties / data / items / properties / posts_left_today
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Absent where the account has no such daily allowance.",
        +  "properties": {
        +    "limit": {
        +      "type": "number"
        +    },
        +    "remaining": {
        +      "type": "number"
        +    },
        +    "resets_at": {
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
  8. 2 tool updates
    • Changedcreate_post1 field changed
      • changedOutput schema / properties / free_post_ride / description
        Previous value: -"With free_first_post: this post reached another of their accounts as part of the same free first post, written minutes earlier. One free delivery per account, within half an hour of the first."New value: +"With free_first_post: this post reached another of their accounts as part of the same free first post, sent in the same reply. One free delivery per account, within a few minutes of the first."
    • Changedupdate_post1 field changed
      • changedOutput schema / properties / free_post_ride / description
        Previous value: -"With free_first_post: this post reached another of their accounts as part of the same free first post, written minutes earlier. One free delivery per account, within half an hour of the first."New value: +"With free_first_post: this post reached another of their accounts as part of the same free first post, sent in the same reply. One free delivery per account, within a few minutes of the first."
  9. 18 tool updates
    • Changedbulk_post1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changedcheck_guardrails1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changedcreate_post1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changeddelete_post1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changedget_best_times1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changedget_delivery_receipt1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changedget_insights1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changedget_post_metrics1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changedget_posting_rules1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changedget_project1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changedget_top_posts1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changedlist_accounts1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changedlist_connection_issues1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changedlist_posts1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changedretry_delivery1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changedtake_down_post1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changedupdate_post2 fields changed
      • changedInput schema / properties / post_id / description
        Previous value: -"The post to change — an id list_posts returned, never one built from memory. An id this project does not hold is refused with `error_code: not_found`; read the list again rather than trying another id."New value: +"The post to change — an id list_posts returned, never one built from memory. Every edit gives the post a NEW id (the answer's `id`); use that one next time. An id an edit retired is refused with `error_code: replaced` and `replaced_by`, the current id. An id this project does not hold is refused with `error_code: not_found`; read the list again rather than trying another id."
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
    • Changedupload_media1 field changed
      • addedOutput schema / properties / replaced_by
        Added value: +{
        +  "description": "With error_code `replaced`: the id the post has now. An edit gives a post a new id; use this one.",
        +  "type": "string"
        +}
  10. 2 tool updates
    • Changedcreate_post3 fields changed
      • changedOutput schema / properties / drafts_waiting / description
        Previous value: -"How many drafts this project now holds, none of them on its way anywhere. Sent with publishing_needs_plan."New value: +"How many drafts are now waiting, none of them on its way anywhere. Sent with publishing_needs_plan."
      • changedOutput schema / properties / publishing_needs_plan / description
        Previous value: -"Nothing on this project can publish beyond its one free post: sending needs a plan. Nothing REFUSES a draft or a scheduled post any more — a queue may be filled without one — so this is the only warning, and it is worth passing on as it is written rather than discovered one slot at a time."New value: +"Nothing here can publish beyond the one free post: sending needs an xpost subscription. Nothing REFUSES a draft or a scheduled post any more — a queue may be filled without one — so this is the only warning, and it is worth passing on as it is written rather than discovered one slot at a time."
      • changedOutput schema / properties / queued_posts / description
        Previous value: -"How many posts are scheduled on this project, none of them going anywhere beyond the free first one. Sent with publishing_needs_plan on a scheduled post."New value: +"How many posts are scheduled, none of them going anywhere beyond the free first one. Sent with publishing_needs_plan on a scheduled post."
    • Changedupdate_post3 fields changed
      • changedOutput schema / properties / drafts_waiting / description
        Previous value: -"How many drafts this project now holds, none of them on its way anywhere. Sent with publishing_needs_plan."New value: +"How many drafts are now waiting, none of them on its way anywhere. Sent with publishing_needs_plan."
      • changedOutput schema / properties / publishing_needs_plan / description
        Previous value: -"Nothing on this project can publish beyond its one free post: sending needs a plan. Nothing REFUSES a draft or a scheduled post any more — a queue may be filled without one — so this is the only warning, and it is worth passing on as it is written rather than discovered one slot at a time."New value: +"Nothing here can publish beyond the one free post: sending needs an xpost subscription. Nothing REFUSES a draft or a scheduled post any more — a queue may be filled without one — so this is the only warning, and it is worth passing on as it is written rather than discovered one slot at a time."
      • changedOutput schema / properties / queued_posts / description
        Previous value: -"How many posts are scheduled on this project, none of them going anywhere beyond the free first one. Sent with publishing_needs_plan on a scheduled post."New value: +"How many posts are scheduled, none of them going anywhere beyond the free first one. Sent with publishing_needs_plan on a scheduled post."
  11. 3 tool updates
    • Changedcreate_post1 field changed
      • addedOutput schema / properties / plans_link
        Added value: +{
        +  "description": "The same page as a ready-made Markdown link. On a refusal with error_code needs_plan, include it in the reply as-is — it is where the person activates a plan.",
        +  "type": "string"
        +}
    • Changedget_project1 field changed
      • addedOutput schema / properties / publishing / properties / plans_link
        Added value: +{
        +  "description": "The plans page as a ready-made Markdown link. Where `needs_plan` is true, include it as-is.",
        +  "type": "string"
        +}
    • Changedupdate_post1 field changed
      • addedOutput schema / properties / plans_link
        Added value: +{
        +  "description": "The same page as a ready-made Markdown link. On a refusal with error_code needs_plan, include it in the reply as-is — it is where the person activates a plan.",
        +  "type": "string"
        +}
  12. 3 tool updates
    • Changedcreate_post2 fields changed
      • changedInput schema / properties / media_pending / description
        Previous value: -"The picture is still to come: the person adds it in the approval card. Lets a post for Instagram, TikTok, YouTube or Pinterest be created without media; it cannot be approved until the media is on it."New value: +"The picture is still to come: the person adds it in the approval card. Lets a post for Instagram, TikTok, YouTube or Pinterest be created without media; it goes out once the media is on it (or, on a project that holds agent posts, can be approved then)."
      • changedInput schema / properties / scheduled_at / description
        Previous value: -"ISO 8601 with Z or an offset, or \"next_slot\" for the project's own posting schedule (get_project shows `queue`). Omit to go out on approval."New value: +"ISO 8601 with Z or an offset, or \"next_slot\" for the project's own posting schedule (get_project shows `queue`). Omit to publish now — or, on a project that holds agent posts, as soon as it is approved."
    • Changedget_delivery_receipt1 field changed
      • addedOutput schema / properties / made_by_you_just_now
        Added value: +{
        +  "description": "You created this post minutes ago; its card is already on screen.",
        +  "type": "boolean"
        +}
    • Changedupdate_post1 field changed
      • changedInput schema / properties / scheduled_at / description
        Previous value: -"New time (Z or an offset); \"next_slot\" hands it to the project's queue; null clears it so it goes out once approved."New value: +"New time (Z or an offset); \"next_slot\" hands it to the project's queue; null clears it, and it goes out now — or once approved, on a project that holds agent posts."
  13. 2 tool updates
    • Changedcreate_post1 field changed
      • addedOutput schema / properties / shown
        Added value: +{
        +  "description": "Where this post is already on screen, and that a receipt call now would show it a second time.",
        +  "type": "string"
        +}
    • Changedupdate_post1 field changed
      • addedOutput schema / properties / shown
        Added value: +{
        +  "description": "Where this post is already on screen, and that a receipt call now would show it a second time.",
        +  "type": "string"
        +}
  14. 18 tool updates
    • First observedbulk_post
    • First observedcheck_guardrails
    • First observedcreate_post
    • First observeddelete_post
    • First observedget_best_times
    • First observedget_delivery_receipt
    • First observedget_insights
    • First observedget_post_metrics
    • First observedget_posting_rules
    • First observedget_project
    • First observedget_top_posts
    • First observedlist_accounts
    • First observedlist_connection_issues
    • First observedlist_posts
    • First observedretry_delivery
    • First observedtake_down_post
    • First observedupdate_post
    • First observedupload_media

Publisher details

Operator
xpost (Digital Abstracts SL, Barcelona) · Publisher source
Vendor relationship
First-party · Publisher source
Restrictions
Needs an xpost account: sign in with OAuth when your client asks, or use an API key from Settings. Every plan includes the MCP server and API; 7-day free trial, then from $12/month. No admin approval, no regional limits, no custom OAuth app needed. · Publisher source

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    One prompt, a native post per network, published or scheduled by your agent: TikTok, Instagram, Facebook, YouTube, LinkedIn, Bluesky, Mastodon, Telegram, Discord, Slack, Nostr, X, WordPress, Dev.to, Hashnode. 22 tools incl. plan_week, bulk_schedule, analytics and TikTok video quality check. Priced per brand, not per channel; API + MCP on the free plan. Hosted: postwire.io/api/mcp
    22
    414 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Social media scheduling and publishing for AI agents. 17 validation-first tools to post to X, LinkedIn, Instagram, TikTok, YouTube, Reddit, Discord, Telegram, and more through one connected workspace.
    175 npm
    103
    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.