Skip to main content
Glama
cameronrye

AT Protocol MCP Server

create_post

Create a public post on Bluesky with text, images, video, link cards, or quotes. Control who can reply and whether quoting is allowed.

Instructions

Create a new post on AT Protocol (Bluesky). The single rich post-creation tool: supports plain text with auto-detected mentions/links/#hashtags, explicit richtext facets, replies, image embeds, a video embed (from upload_video), an external link card, a quote (record) embed, language tags, reply controls (who can reply, via a threadgate record), and quote controls (quote policy, via a postgate record). Requires authentication (app password). SIDE EFFECT: publishes a public post visible to everyone. Subject to per-tool rate limiting. Use create_thread to publish a multi-post chain in one call, and reply_to_post to reply to an existing post; use this tool for a single standalone post (it can also reply via the reply field).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
textYesThe post body. Max 300 graphemes / 3000 bytes (emoji count as one grapheme). Mentions, links and #hashtags are auto-detected into richtext facets unless you supply `facets` explicitly.
replyNoSet to make this post a reply in an existing thread.
embedNoOptional media embed: images OR an external link card OR a video (at most one).
facetsNoOptional explicit richtext facets (byte-range annotations). For mentions, `value` is a handle or DID; for links, a URL; for hashtags, the tag without #. Omit to let the server auto-detect facets from the text.
quoteNoQuote another post (record embed). Mutually exclusive with the `embed.images`, `embed.external`, and `embed.video` embeds.
langsNoOptional BCP-47 language tags (e.g. en, en-US, pt-BR) declaring the languages of the post text.
replyControlsNoWho can reply to this post. Writes an app.bsky.feed.threadgate record (same rkey as the post) AFTER the post is created. Enabled options combine, up to 5 rules. Provide the object with NO rules enabled to let nobody reply; omit it entirely to leave replies open to everyone. If the gate write fails after the post succeeded, the call still succeeds with gateApplied:false and a warning instead of failing.
quoteControlsNoQuote (embed) policy for this post. Only allowQuotes:false writes an app.bsky.feed.postgate record, AFTER the post is created. If that write fails after the post succeeded, the call still succeeds with gateApplied:false and a warning instead of failing.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
uriYesAT-URI of the newly created post.
cidYesCID (content hash) of the newly created post.
successYesWhether the post was created successfully.
messageYesHuman-readable status message.
gateAppliedNoPresent only when replyControls and/or quoteControls were requested. True when every requested gate record (threadgate/postgate) is in effect. False when the post was created but a gate write failed — the post is LIVE without the requested controls (success stays true; see `warning` for which gate failed and how to retry).
warningNoPresent only when gateApplied is false: explains which gate record (threadgate and/or postgate) could not be written and how to retry. The post itself was created successfully.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed30 schema fields changedv0.6.2
    • removedInput schema / additionalProperties
      Removed value: -false
    • removedInput schema / properties / embed / additionalProperties
      Removed value: -false
    • removedInput schema / properties / embed / properties / external / additionalProperties
      Removed value: -false
    • removedInput schema / properties / embed / properties / external / properties / thumb / additionalProperties
      Removed value: -false
    • changedInput schema / properties / embed / properties / external / properties / thumb / properties / ref / anyOf
      Previous value: -[
      -  {
      -    "description": "CID of the uploaded blob as a flat string (e.g. \"bafkrei…\").",
      -    "minLength": 1,
      -    "type": "string"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "Lexicon blob-ref object wrapping the CID as { \"$link\": \"<cid>\" }.",
      -    "properties": {
      -      "$link": {
      -        "description": "CID of the uploaded blob (e.g. \"bafkrei…\").",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "$link"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "description": "CID of the uploaded blob as a flat string (e.g. \"bafkrei…\").",
      +    "minLength": 1,
      +    "type": "string"
      +  },
      +  {
      +    "description": "Lexicon blob-ref object wrapping the CID as { \"$link\": \"<cid>\" }.",
      +    "properties": {
      +      "$link": {
      +        "description": "CID of the uploaded blob (e.g. \"bafkrei…\").",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "$link"
      +    ],
      +    "type": "object"
      +  }
      +]
    • addedInput schema / properties / embed / properties / external / properties / thumb / properties / size / maximum
      Added value: +9007199254740991
    • removedInput schema / properties / embed / properties / images / items / additionalProperties
      Removed value: -false
    • removedInput schema / properties / embed / properties / images / items / properties / image / additionalProperties
      Removed value: -false
    • changedInput schema / properties / embed / properties / images / items / properties / image / properties / ref / anyOf
      Previous value: -[
      -  {
      -    "description": "CID of the uploaded blob as a flat string (e.g. \"bafkrei…\").",
      -    "minLength": 1,
      -    "type": "string"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "Lexicon blob-ref object wrapping the CID as { \"$link\": \"<cid>\" }.",
      -    "properties": {
      -      "$link": {
      -        "description": "CID of the uploaded blob (e.g. \"bafkrei…\").",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "$link"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "description": "CID of the uploaded blob as a flat string (e.g. \"bafkrei…\").",
      +    "minLength": 1,
      +    "type": "string"
      +  },
      +  {
      +    "description": "Lexicon blob-ref object wrapping the CID as { \"$link\": \"<cid>\" }.",
      +    "properties": {
      +      "$link": {
      +        "description": "CID of the uploaded blob (e.g. \"bafkrei…\").",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "$link"
      +    ],
      +    "type": "object"
      +  }
      +]
    • addedInput schema / properties / embed / properties / images / items / properties / image / properties / size / maximum
      Added value: +9007199254740991
    • removedInput schema / properties / embed / properties / video / additionalProperties
      Removed value: -false
    • removedInput schema / properties / embed / properties / video / properties / aspectRatio / additionalProperties
      Removed value: -false
    • addedInput schema / properties / embed / properties / video / properties / aspectRatio / properties / height / maximum
      Added value: +9007199254740991
    • addedInput schema / properties / embed / properties / video / properties / aspectRatio / properties / width / maximum
      Added value: +9007199254740991
    • removedInput schema / properties / embed / properties / video / properties / captions / items / additionalProperties
      Removed value: -false
    • removedInput schema / properties / embed / properties / video / properties / captions / items / properties / file / additionalProperties
      Removed value: -false
    • changedInput schema / properties / embed / properties / video / properties / captions / items / properties / file / properties / ref / anyOf
      Previous value: -[
      -  {
      -    "description": "CID of the uploaded blob as a flat string (e.g. \"bafkrei…\").",
      -    "minLength": 1,
      -    "type": "string"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "Lexicon blob-ref object wrapping the CID as { \"$link\": \"<cid>\" }.",
      -    "properties": {
      -      "$link": {
      -        "description": "CID of the uploaded blob (e.g. \"bafkrei…\").",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "$link"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "description": "CID of the uploaded blob as a flat string (e.g. \"bafkrei…\").",
      +    "minLength": 1,
      +    "type": "string"
      +  },
      +  {
      +    "description": "Lexicon blob-ref object wrapping the CID as { \"$link\": \"<cid>\" }.",
      +    "properties": {
      +      "$link": {
      +        "description": "CID of the uploaded blob (e.g. \"bafkrei…\").",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "$link"
      +    ],
      +    "type": "object"
      +  }
      +]
    • addedInput schema / properties / embed / properties / video / properties / captions / items / properties / file / properties / size / maximum
      Added value: +9007199254740991
    • removedInput schema / properties / embed / properties / video / properties / video / additionalProperties
      Removed value: -false
    • changedInput schema / properties / embed / properties / video / properties / video / properties / ref / anyOf
      Previous value: -[
      -  {
      -    "description": "CID of the uploaded blob as a flat string (e.g. \"bafkrei…\").",
      -    "minLength": 1,
      -    "type": "string"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "description": "Lexicon blob-ref object wrapping the CID as { \"$link\": \"<cid>\" }.",
      -    "properties": {
      -      "$link": {
      -        "description": "CID of the uploaded blob (e.g. \"bafkrei…\").",
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "$link"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "description": "CID of the uploaded blob as a flat string (e.g. \"bafkrei…\").",
      +    "minLength": 1,
      +    "type": "string"
      +  },
      +  {
      +    "description": "Lexicon blob-ref object wrapping the CID as { \"$link\": \"<cid>\" }.",
      +    "properties": {
      +      "$link": {
      +        "description": "CID of the uploaded blob (e.g. \"bafkrei…\").",
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "$link"
      +    ],
      +    "type": "object"
      +  }
      +]
    • addedInput schema / properties / embed / properties / video / properties / video / properties / size / maximum
      Added value: +9007199254740991
    • removedInput schema / properties / facets / items / additionalProperties
      Removed value: -false
    • removedInput schema / properties / facets / items / properties / features / items / additionalProperties
      Removed value: -false
    • removedInput schema / properties / facets / items / properties / index / additionalProperties
      Removed value: -false
    • addedInput schema / properties / facets / items / properties / index / properties / byteEnd / maximum
      Added value: +9007199254740991
    • addedInput schema / properties / facets / items / properties / index / properties / byteStart / maximum
      Added value: +9007199254740991
    • removedInput schema / properties / quote / additionalProperties
      Removed value: -false
    • removedInput schema / properties / quoteControls / additionalProperties
      Removed value: -false
    • removedInput schema / properties / reply / additionalProperties
      Removed value: -false
    • removedInput schema / properties / replyControls / additionalProperties
      Removed value: -false
  2. Changed26 schema fields changedv0.6.0
    • addedInput schema / properties / embed / description
      Added value: +"Optional media embed: images OR an external link card OR a video (at most one)."
    • addedInput schema / properties / embed / properties / external / description
      Added value: +"An external link card to attach. Mutually exclusive with `images`, `video`, and `quote`."
    • addedInput schema / properties / embed / properties / external / properties / description / description
      Added value: +"Description shown on the external link card (max 1000 characters)."
    • addedInput schema / properties / embed / properties / external / properties / thumb
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Optional thumbnail for the link card as a pre-uploaded blob descriptor: pass the `preview.thumb.blob` object from generate_link_preview (or the `image.blob` from upload_image) verbatim. Omit for a card without a thumbnail.",
      +  "properties": {
      +    "mimeType": {
      +      "description": "MIME type of the uploaded blob (e.g. \"image/jpeg\").",
      +      "minLength": 1,
      +      "type": "string"
      +    },
      +    "ref": {
      +      "anyOf": [
      +        {
      +          "description": "CID of the uploaded blob as a flat string (e.g. \"bafkrei…\").",
      +          "minLength": 1,
      +          "type": "string"
      +        },
      +        {
      +          "additionalProperties": false,
      +          "description": "Lexicon blob-ref object wrapping the CID as { \"$link\": \"<cid>\" }.",
      +          "properties": {
      +            "$link": {
      +              "description": "CID of the uploaded blob (e.g. \"bafkrei…\").",
      +              "minLength": 1,
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "$link"
      +          ],
      +          "type": "object"
      +        }
      +      ],
      +      "description": "CID reference of the uploaded blob: either the flat string returned by upload_image, or the lexicon { \"$link\": \"<cid>\" } object form."
      +    },
      +    "size": {
      +      "description": "Size of the uploaded blob in bytes.",
      +      "exclusiveMinimum": 0,
      +      "type": "integer"
      +    },
      +    "type": {
      +      "const": "blob",
      +      "description": "Discriminator emitted by upload_image; always \"blob\" when present. May be omitted.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "ref",
      +    "mimeType",
      +    "size"
      +  ],
      +  "type": "object"
      +}
    • addedInput schema / properties / embed / properties / external / properties / title / description
      Added value: +"Title shown on the external link card (max 300 characters)."
    • addedInput schema / properties / embed / properties / external / properties / uri / description
      Added value: +"The URL the external link card points to."
    • addedInput schema / properties / embed / properties / images / description
      Added value: +"Up to 4 images to attach. Mutually exclusive with `external` and `quote`."
    • addedInput schema / properties / embed / properties / images / items / properties / alt / description
      Added value: +"Accessibility alt text describing the image (max 1000 characters)."
    • addedInput schema / properties / embed / properties / images / items / properties / image / additionalProperties
      Added value: +false
    • addedInput schema / properties / embed / properties / images / items / properties / image / description
      Added value: +"Pre-uploaded image blob descriptor: pass the `image.blob` object from a prior upload_image call verbatim. The image must already be uploaded — this tool does not accept raw image data."
    • addedInput schema / properties / embed / properties / images / items / properties / image / properties
      Added value: +{
      +  "mimeType": {
      +    "description": "MIME type of the uploaded blob (e.g. \"image/jpeg\").",
      +    "minLength": 1,
      +    "type": "string"
      +  },
      +  "ref": {
      +    "anyOf": [
      +      {
      +        "description": "CID of the uploaded blob as a flat string (e.g. \"bafkrei…\").",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      {
      +        "additionalProperties": false,
      +        "description": "Lexicon blob-ref object wrapping the CID as { \"$link\": \"<cid>\" }.",
      +        "properties": {
      +          "$link": {
      +            "description": "CID of the uploaded blob (e.g. \"bafkrei…\").",
      +            "minLength": 1,
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "$link"
      +        ],
      +        "type": "object"
      +      }
      +    ],
      +    "description": "CID reference of the uploaded blob: either the flat string returned by upload_image, or the lexicon { \"$link\": \"<cid>\" } object form."
      +  },
      +  "size": {
      +    "description": "Size of the uploaded blob in bytes.",
      +    "exclusiveMinimum": 0,
      +    "type": "integer"
      +  },
      +  "type": {
      +    "const": "blob",
      +    "description": "Discriminator emitted by upload_image; always \"blob\" when present. May be omitted.",
      +    "type": "string"
      +  }
      +}
    • addedInput schema / properties / embed / properties / images / items / properties / image / required
      Added value: +[
      +  "ref",
      +  "mimeType",
      +  "size"
      +]
    • addedInput schema / properties / embed / properties / images / items / properties / image / type
      Added value: +"object"
    • changedInput schema / properties / embed / properties / images / items / required
      Previous value: -[
      -  "alt"
      -]New value: +[
      +  "alt",
      +  "image"
      +]
    • addedInput schema / properties / embed / properties / video
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "A video to attach (app.bsky.embed.video). Mutually exclusive with `images`, `external`, and `quote`.",
      +  "properties": {
      +    "alt": {
      +      "description": "Accessibility alt text describing the video (max 1000 characters).",
      +      "maxLength": 1000,
      +      "type": "string"
      +    },
      +    "aspectRatio": {
      +      "additionalProperties": false,
      +      "description": "Optional aspect ratio hint (e.g. {\"width\": 16, \"height\": 9}) clients use to reserve layout space before the video loads.",
      +      "properties": {
      +        "height": {
      +          "description": "Height component of the aspect ratio.",
      +          "minimum": 1,
      +          "type": "integer"
      +        },
      +        "width": {
      +          "description": "Width component of the aspect ratio.",
      +          "minimum": 1,
      +          "type": "integer"
      +        }
      +      },
      +      "required": [
      +        "width",
      +        "height"
      +      ],
      +      "type": "object"
      +    },
      +    "captions": {
      +      "description": "Up to 20 caption tracks, each pairing a language code with a pre-uploaded .vtt caption blob descriptor.",
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "file": {
      +            "additionalProperties": false,
      +            "description": "Pre-uploaded WebVTT caption blob descriptor: pass a `video.captions[].file` object from upload_video verbatim.",
      +            "properties": {
      +              "mimeType": {
      +                "description": "MIME type of the uploaded blob (e.g. \"image/jpeg\").",
      +                "minLength": 1,
      +                "type": "string"
      +              },
      +              "ref": {
      +                "anyOf": [
      +                  {
      +                    "description": "CID of the uploaded blob as a flat string (e.g. \"bafkrei…\").",
      +                    "minLength": 1,
      +                    "type": "string"
      +                  },
      +                  {
      +                    "additionalProperties": false,
      +                    "description": "Lexicon blob-ref object wrapping the CID as { \"$link\": \"<cid>\" }.",
      +                    "properties": {
      +                      "$link": {
      +                        "description": "CID of the uploaded blob (e.g. \"bafkrei…\").",
      +                        "minLength": 1,
      +                        "type": "string"
      +                      }
      +                    },
      +                    "required": [
      +                      "$link"
      +                    ],
      +                    "type": "object"
      +                  }
      +                ],
      +                "description": "CID reference of the uploaded blob: either the flat string returned by upload_image, or the lexicon { \"$link\": \"<cid>\" } object form."
      +              },
      +              "size": {
      +                "description": "Size of the uploaded blob in bytes.",
      +                "exclusiveMinimum": 0,
      +                "type": "integer"
      +              },
      +              "type": {
      +                "const": "blob",
      +                "description": "Discriminator emitted by upload_image; always \"blob\" when present. May be omitted.",
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "ref",
      +              "mimeType",
      +              "size"
      +            ],
      +            "type": "object"
      +          },
      +          "lang": {
      +            "description": "BCP-47 language code for the caption track (e.g. \"en\", \"fr\", \"pt-BR\").",
      +            "minLength": 2,
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "lang",
      +          "file"
      +        ],
      +        "type": "object"
      +      },
      +      "maxItems": 20,
      +      "type": "array"
      +    },
      +    "video": {
      +      "additionalProperties": false,
      +      "description": "Pre-uploaded PROCESSED video blob descriptor: pass the `video.blob` object from a prior upload_video call verbatim. The video must already have been uploaded and processed by the video service — this tool does not accept raw video data.",
      +      "properties": {
      +        "mimeType": {
      +          "description": "MIME type of the uploaded blob (e.g. \"image/jpeg\").",
      +          "minLength": 1,
      +          "type": "string"
      +        },
      +        "ref": {
      +          "anyOf": [
      +            {
      +              "description": "CID of the uploaded blob as a flat string (e.g. \"bafkrei…\").",
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            {
      +              "additionalProperties": false,
      +              "description": "Lexicon blob-ref object wrapping the CID as { \"$link\": \"<cid>\" }.",
      +              "properties": {
      +                "$link": {
      +                  "description": "CID of the uploaded blob (e.g. \"bafkrei…\").",
      +                  "minLength": 1,
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "$link"
      +              ],
      +              "type": "object"
      +            }
      +          ],
      +          "description": "CID reference of the uploaded blob: either the flat string returned by upload_image, or the lexicon { \"$link\": \"<cid>\" } object form."
      +        },
      +        "size": {
      +          "description": "Size of the uploaded blob in bytes.",
      +          "exclusiveMinimum": 0,
      +          "type": "integer"
      +        },
      +        "type": {
      +          "const": "blob",
      +          "description": "Discriminator emitted by upload_image; always \"blob\" when present. May be omitted.",
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "ref",
      +        "mimeType",
      +        "size"
      +      ],
      +      "type": "object"
      +    }
      +  },
      +  "required": [
      +    "video"
      +  ],
      +  "type": "object"
      +}
    • addedInput schema / properties / facets
      Added value: +{
      +  "description": "Optional explicit richtext facets (byte-range annotations). For mentions, `value` is a handle or DID; for links, a URL; for hashtags, the tag without #. Omit to let the server auto-detect facets from the text.",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "features": {
      +        "description": "One or more features applied to the annotated span.",
      +        "items": {
      +          "additionalProperties": false,
      +          "properties": {
      +            "type": {
      +              "description": "The kind of richtext feature this span represents.",
      +              "enum": [
      +                "mention",
      +                "link",
      +                "hashtag"
      +              ],
      +              "type": "string"
      +            },
      +            "value": {
      +              "description": "For a mention: a handle or DID (a leading @ is stripped); for a link: the URL; for a hashtag: the tag (a leading # is stripped).",
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "type",
      +            "value"
      +          ],
      +          "type": "object"
      +        },
      +        "type": "array"
      +      },
      +      "index": {
      +        "additionalProperties": false,
      +        "description": "UTF-8 byte range of the text span this facet annotates.",
      +        "properties": {
      +          "byteEnd": {
      +            "description": "End byte offset (UTF-8) of the annotated span, exclusive.",
      +            "minimum": 0,
      +            "type": "integer"
      +          },
      +          "byteStart": {
      +            "description": "Start byte offset (UTF-8) of the annotated span, inclusive.",
      +            "minimum": 0,
      +            "type": "integer"
      +          }
      +        },
      +        "required": [
      +          "byteStart",
      +          "byteEnd"
      +        ],
      +        "type": "object"
      +      }
      +    },
      +    "required": [
      +      "index",
      +      "features"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / langs / description
      Added value: +"Optional BCP-47 language tags (e.g. en, en-US, pt-BR) declaring the languages of the post text."
    • addedInput schema / properties / quote
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Quote another post (record embed). Mutually exclusive with the `embed.images`, `embed.external`, and `embed.video` embeds.",
      +  "properties": {
      +    "cid": {
      +      "description": "CID (content hash) of the quoted post.",
      +      "minLength": 1,
      +      "type": "string"
      +    },
      +    "uri": {
      +      "description": "AT-URI of the post to quote.",
      +      "minLength": 1,
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "uri",
      +    "cid"
      +  ],
      +  "type": "object"
      +}
    • addedInput schema / properties / quoteControls
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Quote (embed) policy for this post. Only allowQuotes:false writes an app.bsky.feed.postgate record, AFTER the post is created. If that write fails after the post succeeded, the call still succeeds with gateApplied:false and a warning instead of failing.",
      +  "properties": {
      +    "allowQuotes": {
      +      "description": "Set false to disable quoting/embedding of this post: writes an app.bsky.feed.postgate record (same rkey as the post) with a disableRule. true is the network default — quoting stays enabled and no postgate record is written.",
      +      "type": "boolean"
      +    }
      +  },
      +  "required": [
      +    "allowQuotes"
      +  ],
      +  "type": "object"
      +}
    • addedInput schema / properties / reply / description
      Added value: +"Set to make this post a reply in an existing thread."
    • addedInput schema / properties / reply / properties / parent / description
      Added value: +"AT-URI of the immediate parent post being replied to."
    • addedInput schema / properties / reply / properties / root / description
      Added value: +"AT-URI of the root post of the thread being replied to."
    • addedInput schema / properties / replyControls
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Who can reply to this post. Writes an app.bsky.feed.threadgate record (same rkey as the post) AFTER the post is created. Enabled options combine, up to 5 rules. Provide the object with NO rules enabled to let nobody reply; omit it entirely to leave replies open to everyone. If the gate write fails after the post succeeded, the call still succeeds with gateApplied:false and a warning instead of failing.",
      +  "properties": {
      +    "allowFollowers": {
      +      "description": "Allow replies from accounts that follow the author (threadgate followerRule).",
      +      "type": "boolean"
      +    },
      +    "allowFollowing": {
      +      "description": "Allow replies from accounts the author follows (threadgate followingRule).",
      +      "type": "boolean"
      +    },
      +    "allowListUris": {
      +      "description": "Allow replies from members of these moderation/curation lists (threadgate listRule). Each entry must be the AT-URI of an app.bsky.graph.list record (at://did/app.bsky.graph.list/rkey); anything else is rejected before the post is created.",
      +      "items": {
      +        "description": "AT-URI of an app.bsky.graph.list record whose members may reply.",
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "maxItems": 5,
      +      "type": "array"
      +    },
      +    "allowMentioned": {
      +      "description": "Allow replies from accounts @-mentioned in the post text (threadgate mentionRule).",
      +      "type": "boolean"
      +    }
      +  },
      +  "type": "object"
      +}
    • addedInput schema / properties / text / description
      Added value: +"The post body. Max 300 graphemes / 3000 bytes (emoji count as one grapheme). Mentions, links and #hashtags are auto-detected into richtext facets unless you supply `facets` explicitly."
    • changedInput schema / properties / text / maxLength
      Previous value: -300New value: +3000
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "properties": {
      +    "cid": {
      +      "description": "CID (content hash) of the newly created post.",
      +      "type": "string"
      +    },
      +    "gateApplied": {
      +      "description": "Present only when replyControls and/or quoteControls were requested. True when every requested gate record (threadgate/postgate) is in effect. False when the post was created but a gate write failed — the post is LIVE without the requested controls (success stays true; see `warning` for which gate failed and how to retry).",
      +      "type": "boolean"
      +    },
      +    "message": {
      +      "description": "Human-readable status message.",
      +      "type": "string"
      +    },
      +    "success": {
      +      "description": "Whether the post was created successfully.",
      +      "type": "boolean"
      +    },
      +    "uri": {
      +      "description": "AT-URI of the newly created post.",
      +      "type": "string"
      +    },
      +    "warning": {
      +      "description": "Present only when gateApplied is false: explains which gate record (threadgate and/or postgate) could not be written and how to retry. The post itself was created successfully.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "uri",
      +    "cid",
      +    "success",
      +    "message"
      +  ],
      +  "type": "object"
      +}
  3. Changed4 schema fields changedv0.3.0
    • removedInput schema / $schema
      Removed value: -"http://json-schema.org/draft-07/schema#"
    • removedInput schema / properties / langs / items / maxLength
      Removed value: -2
    • removedInput schema / properties / langs / items / minLength
      Removed value: -2
    • addedInput schema / properties / langs / items / pattern
      Added value: +"^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{2,8})*$"
  4. First observedv0.2.1

TDQS

A4.8/5.0
Behavior5/5

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

The description discloses important behavioral traits beyond annotations: the post is public, subject to rate limiting, requires auth, and creates additional records (threadgate, postgate) for reply/quote controls. It also explains side effects and error handling for gate write failures.

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 well-structured with a clear opening, a list of supported features, side effects, and alternatives. It is somewhat lengthy due to the tool's complexity, but every sentence contributes meaningful information. Slightly more conciseness could be achieved by reducing redundancy.

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 tool's complexity (8 parameters, nested objects, output schema present), the description covers all necessary aspects: main functionality, usage modes, side effects, preconditions, and error handling. It leaves no significant gaps for an agent to misinterpret.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3. The description adds value by explaining mutual exclusivity among embed types, auto-detection of facets, and the relationship between reply controls and threadgate records. This provides context that enriches the schema descriptions.

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

Purpose5/5

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

The description clearly states the tool's purpose: 'Create a new post on AT Protocol (Bluesky).' It explicitly distinguishes itself from sibling tools like create_thread and reply_to_post by stating when to use each.

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

Usage Guidelines5/5

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

The description provides explicit guidance on when to use this tool versus alternatives: 'Use create_thread to publish a multi-post chain... and reply_to_post to reply...; use this tool for a single standalone post.' It also mentions prerequisites (authentication, app password) and side effects.

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