Google Search Console integration for Model Context Protocol (MCP)
flayr is installed from its publisher's own source and answers where it runs, so this marketplace is not in the path of a single call. There is no address here to send one to, and a panel that pretended otherwise would be showing you an answer we made up. Install it and call it from your own client — the Installation tab has the entry for each one.
What it does
Create, schedule and publish social posts to 13 platforms for your brands.
Quickstart
# 1 — add it to Claude Code
claude mcp add --scope user --transport http flayr-mcp https://flayr.social/api/mcp
# 2 — ask your agent for something these tools do
# whoami, list_brands, list_connected_accounts and 54 more
flayr costs nothing on mcprush: there is no plan to choose here, no cap to set and nothing mcprush can bill you for.
Collected from a public index. Nobody has claimed this account, so nothing here was written by its author — claim it if it is yours.
Where are you running it?
Every route below installs the same thing and ends at the same approval screen. Nothing here runs on your machine and nothing runs on ours: this server answers at its publisher’s own address, and what you install is the connection straight to it.
This is a public server: it answers at its publisher’s own address and this marketplace is not in the path. Claude Code registers it in one command; --scope user makes it available in every project. The transport below is http, as the publisher's own manifest declares it.
claude mcp add --scope user --transport http flayr-mcp https://flayr.social/api/mcpReconnect, or start a new session, and the tools appear in the model’s tool list.
One config entry pointing straight at the publisher’s own address — this marketplace is not in the path, and nothing from this listing executes on your machine.
57 tools, with what each one reads, writes and reaches shown before you agree — the same list on every route above. Read the tool surface.
Tool surface
What the model actually sees. Descriptions are diffed on every release — see version history.
[read-only] Returns who this connection (an OAuth sign-in or an API key) belongs to: userId, the account's current plan tier, and brandId/brandName when the connection is bound to one brand (null = account-wide). Call this first to learn what the connection can reach. (Wraps GET /api/v2/ping.)
No parameter schema on file.
[read-only] Lists the brands this connection can file content into and publish through. Use an id as brandId on create_content, publish, queues and analytics tools; "personal" means the account owner's personal accounts. A connection bound to one brand sees only that brand (and personal is null). (Wraps GET /api/v2/brands.)
No parameter schema on file.
[read-only] The social accounts a brand can post to — the same set publish would use for that brandId: platform, handle, display name, health (healthy, needs_reauth, disconnected) and whether flayr can post there right now (postable; Reddit is paused because Reddit closed its API to third-party apps). Call this before publish to pick platforms, and tell the user to reconnect any account that i
| Parameter | Type | Required | Notes |
|---|---|---|---|
| brandId | string | no | An id from GET /api/v2/brands, or "personal". Omitted → the key's bound brand, else the owner's personal accounts. |
[read-only] Playlists of the YouTube channel(s) a brand publishes to. Use a playlist id as youtube.playlistId on create_content or publish. (Wraps GET /api/v2/youtube/playlists.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| brandId | string | no | An id from GET /api/v2/brands, or "personal". Omitted → the key's bound brand, else the owner's personal accounts. |
[read-only] Boards of the Pinterest account(s) a brand publishes to. Use a board id as pinterest.boardId on publish. A board is required; the one you pick is remembered as the brand's default for next time, and a publish that uses the default says so (defaultBoardApplied). (Wraps GET /api/v2/pinterest/boards.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| brandId | string | no | An id from GET /api/v2/brands, or "personal". Omitted → the key's bound brand, else the owner's personal accounts. |
[writes flayr data · write scope] Step 1 of attaching a LOCAL file (video or image) to a draft. Returns a single-use, short-lived uploadUrl. Step 2: POST the raw file bytes to it with the file's Content-Type, e.g. curl -X POST -H "Content-Type: video/mp4" --data-binary @clip.mp4 "<uploadUrl>" — the JSON response has a storageId. Step 3: pass it as videoStorageId or imageStorageId on cr
No parameter schema on file.
[read-only] Lists content items (drafts), newest first. Each carries postState ("posted" / "scheduled" / null) and posts[] (up to 5): where it went out, per platform, with status, live URL and failure reason. (Wraps GET /api/v2/content.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| limit | integer | no | — |
| includeArchived | boolean | no | — |
| brandId | string | no | A brand id from GET /api/v2/brands. Omitted: the key's brand (brand-bound key) or the owner's active brand. |
[read-only] One content item plus its live posting status: postState and posts[] (up to 20, newest first) with each post's status (scheduled · publishing · published · partial · failed · review_held · held), scheduledAt, and per-platform status, live URL and error. The item's own status stays "draft" after publishing — read posts to know whether it is live. Use this to confirm a publish la
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
[writes flayr data · write scope] Creates a DRAFT content item. Nothing is posted. Give text plus optional media (videoUrl / imageUrl, or videoStorageId / imageStorageId from upload_media), target platforms, brandId (from list_brands; omitted → the brand last active in the dashboard), per-platform captions (platformText), creator credits, labels and YouTube options. Returns t
| Parameter | Type | Required | Notes |
|---|---|---|---|
| text | string | no | — |
| copyFromContentId | string | no | COPY TO BRAND (staff and the Agency plan): the id of an existing item (GET /api/v2/content) to copy into brandId as a new draft. Images, video, slides, documents and thumbnails are copied into new s |
| platforms | array | no | — |
| contentType | string | no | — |
| imageUrl | string | no | — |
| videoUrl | string | no | — |
| imageStorageId | string | no | — |
| videoStorageId | string | no | — |
| brandId | string | no | An id from GET /api/v2/brands, or "personal". |
| sourceLabel | string | no | — |
| youtube | object | no | Stored on the draft and used when it is published (POST /api/v2/publish with contentId). YouTube upload options, applied to YouTube targets only. madeForKids is always sent to YouTube (default false). |
| referralFooter | boolean | no | Caption watermark: appends "Posted with flayr.social — try it: flayr.social/r/<code>/<ch>" to each platform's text (<code> is your referral code — your custom one if you claimed it; <ch> names the pla |
| credits | array | no | Creator credits for work this post uses. Added to the published caption above the flayr footer, one line each: model → "Print your own: <url> (model by <author>)"; other kinds → "Credit: <title> by <a |
| labels | array | no | Normalized "key:value" labels (keys and values are lower-cased, spaces become "-"). Linked keys: campaign:<media campaign id>, experiment:<experiment id> (+ variant:<name> or the experiment's compareK |
| platformText | object | no | Per-platform captions: platform id → the caption that platform gets instead of text, e.g. { "twitter": "short version" }. Each must fit its platform: X 280 (a link counts 23, an emoji 2), Bluesky 30 |
[writes flayr data · write scope] Edits a draft in place; only the fields you pass change. Any media field replaces the draft's media as a set (keeps the id, so queue items still point at it). Refused (409) for archived or already-published items, and a media swap is refused once a queue booked it. labels, opus and videoWatermarked may be changed on published items too. A video draft's cus
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
| text | string | no | — |
| platforms | array | no | — |
| youtube | object | no | Merged into the stored YouTube options. YouTube upload options, applied to YouTube targets only. madeForKids is always sent to YouTube (default false). A missing title is derived from the first senten |
| title | string | no | Shorthand for youtube.title (the video title). No < or >. |
| credits | array/null | no | Creator credits for work this post uses. Added to the published caption above the flayr footer, one line each: model → "Print your own: <url> (model by <author>)"; other kinds → "Credit: <title> by <a |
| platformText | object/null | no | Per-platform captions: platform id → the caption that platform gets instead of text, e.g. { "twitter": "short version" }. Each must fit its platform: X 280 (a link counts 23, an emoji 2), Bluesky 30 |
| labels | array/null | no | Replaces the labels ([] or null clears). Allowed on published items too. Normalized "key:value" labels (keys and values are lower-cased, spaces become "-"). Linked keys: campaign:<media campaign id>, |
| opus | object/null | no | Link this row to an Opus Clip clip (owner only; allowed on published rows) so an Opus project import skips it instead of creating a duplicate. null unlinks. |
| videoWatermarked | object/null | no | The item's own video already has the "Posted by flayr.social" watermark: publish it as-is. null clears. |
| videoStorageId | string | no | storageId from uploading to POST /api/v2/media/upload-url's uploadUrl. Not with videoUrl. Another account's upload is refused (422). |
| videoUrl | string | no | http(s) URL of the new video. Not with videoStorageId. |
| imageStorageId | string | no | Uploaded image storageId: the video's thumbnail, or on its own the post's single image. Not with imageUrl. |
| imageUrl | string | no | http(s) image URL: the video's thumbnail, or on its own the post's single image. Not with imageStorageId. |
| images | array | no | Carousel image URLs. Cannot be combined with the other media fields. |
| thumbnailStorageId | string/null | no | Custom video thumbnail: an image storageId from POST /api/v2/media/upload-url. Not with thumbnailUrl. null clears. |
| thumbnailUrl | string/null | no | Custom video thumbnail: an http(s) image URL. Not with thumbnailStorageId. null clears. |
| thumbnailFrameOffsetMs | integer | no | Use this frame of the video (ms from the start) as the cover. Instagram and TikTok get the offset; YouTube/Facebook/LinkedIn need an image, so pass the captured frame as thumbnailStorageId / thumbnail |
[DESTRUCTIVE] DESTRUCTIVE: permanently deletes a content item from the library. Posts already live on a platform are not removed. Needs the write scope. Ask the user before calling. (Wraps DELETE /api/v2/content/{id}.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
[writes flayr data · write scope] Extends a video draft (id) with more clips and image cards into ONE finished video, rendered by flayr and saved as a NEW linked draft (same brand, caption copied, credits merged, labelled variant:combined). Nothing is posted and the original is unchanged. Use it to show a finished print with painting/assembly clips before or after it. segments (2-8, in order
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | The video to extend. |
| segments | array | yes | In playback order. Must include this video ({ "kind": "clip", "contentId": "<id>" }). |
| transition | string | no | — |
| crossfadeMs | integer | no | Crossfade overlap per join. |
| audio | string | no | — |
[read-only] Status of an async job (combine_clips, or an API video generation): pending, processing, completed or failed. For a combine, resultContentId is the new draft once completed; a failed combine is refunded automatically. Poll every 10-30 s — renders take about a minute. (Wraps GET /api/v2/generate/status/{jobId}.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| jobId | string | yes | — |
[PUBLISHES to social accounts · publish scope] PUBLISHES TO REAL SOCIAL ACCOUNTS. Posts now, or at scheduledAt (ISO-8601, future). Prefer contentId (a draft from create_content: its text and media become the post) over inline content. The post goes out through the target brand's own connected accounts. Always pass an idempotencyKey so a retry never double-posts. The same safety gates as
| Parameter | Type | Required | Notes |
|---|---|---|---|
| content | string | no | Post text. Required unless contentId is given. |
| contentId | string | no | An existing content item id (GET /api/v2/content/{id} access rules). Cannot be combined with imageUrl / videoUrl. |
| platforms | array | yes | — |
| imageUrl | string | no | — |
| videoUrl | string | no | — |
| brandId | string | no | An id from GET /api/v2/brands, or "personal". With contentId it must match the item's brand. |
| scheduledAt | string | no | Must be in the future. Omitted → publish now. |
| mediaCampaignId | string | no | Link to a media campaign; with a brand target it must belong to that brand. |
| requiresApproval | boolean | no | — |
| aiGenerated | boolean | no | Label the post as AI-generated / synthetic media: YouTube containsSyntheticMedia, Instagram isAiGenerated, TikTok videoMadeWithAi, X madeWithAi, and the disclosure line (default "#AIgenerated") on pla |
| idempotencyKey | string | no | Unique per API key. A retry with the same key never posts twice. |
| allowDuplicateBooking | boolean | no | A contentId that is already scheduled (a live booking still ahead) on one of these platforms is refused with 409 { code: "already_booked", bookedAt, bookedPlatforms }. Pass true only to book the same |
| labels | array | no | Labels for this post on top of the draft's own (the draft wins for type/cut/variant). Normalized "key:value" labels (keys and values are lower-cased, spaces become "-"). Linked keys: campaign:<media c |
| youtube | object | no | Overrides the content item's stored YouTube options field by field. YouTube upload options, applied to YouTube targets only. madeForKids is always sent to YouTube (default false). A missing title is d |
| object | no | Facebook post type. "reel" posts a Reel (exactly one video, no images; anything else is a 422 with code content_type_invalid), "story" a Page Story, "feed" a regular post. Omitted → the content item's | |
| object | no | Instagram post type, same rules: "reel" (exactly one video — a single video is posted as a Reel), "story", or "feed". Omitted → the content item's stored platformSpecificData.instagram.contentType. | |
| object | no | FFE-428: Pinterest pin options for every Pinterest target. Overrides the content item's stored platformSpecificData.pinterest field by field. A board is required. boardId omitted → the brand's last-pi | |
| poll | object | no | A native poll. Only on twitter (X), linkedin and discord, and with no media: any other platform or media is a 422 (code poll_invalid), never a plain post. X: 2-4 choices of at most 25 characters, 5 mi |
| referralFooter | boolean | no | Caption watermark: appends "Posted with flayr.social — try it: flayr.social/r/<code>/<ch>" to each platform's text (<code> is your referral code — your custom one if you claimed it; <ch> names the pla |
| reshare | object | no | Share/repost another post: a flayr post id (postId) or a pasted link (url). Per platform: linkedin a native reshare with your text on top (not with media or a poll); twitter a quote of your own X |
[read-only] A post (id = convexPostId from publish, or posts[].id from get_content): status, slot, platforms, and while it is scheduled the first comment each platform will publish and whether it can be changed now. (Wraps GET /api/v2/posts/{id}.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | The post: convexPostId from POST /api/v2/publish, or posts[].id from GET /api/v2/content/{id}. |
[PUBLISHES to social accounts · publish scope] CHANGES WHAT A SCHEDULED POST WILL PUBLISH on real accounts, keeping its slot, accounts, options, labels and draft. firstComment sets per-platform first comments (linkedin, facebook, instagram, threads, youtube; null removes; X/Bluesky have none); text / platformText change the caption; applyAutoFirstComment: true adds the brand's auto first
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | The post: convexPostId from POST /api/v2/publish, or posts[].id from GET /api/v2/content/{id}. |
| text | string | no | The caption (every platform without its own). |
| platformText | object/null | no | Per-platform captions, merged into the draft's: { "linkedin": "…" } sets one, null / "" clears it; null clears them all. |
| firstComment | object | no | The first comment the post publishes, per platform: a string sets it, null or "" removes it; platforms not named keep theirs. X and Bluesky have no first comment at the platform scheduler and are refu |
| applyAutoFirstComment | boolean | no | Add the brand's auto first comment where the post has none. |
| removePlatforms | array | no | Platform ids to drop from this booking (e.g. a duplicate ["tiktok"]). Each must be on the post; dropping every platform is refused (use DELETE). The booking is rebuilt from the draft. |
[PUBLISHES to social accounts · publish scope] Takes a SCHEDULED post off the platform schedule and marks it cancelled (the draft stays, so it can be published again). Safe to repeat. Refused within 5 minutes of the slot, and when the platform will not remove it (some YouTube uploads). Needs the publish scope (or admin) and the Pro plan or higher; each publish counts against the plan's direct
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | The post: convexPostId from POST /api/v2/publish, or posts[].id from GET /api/v2/content/{id}. |
[read-only] Scheduled posts waiting for (or given) a human sign-off, oldest slot first. canApprove tells whether THIS connection may approve each one. (Wraps GET /api/v2/reviews.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| status | string | no | — |
| brandId | string | no | — |
| window | string | no | — |
[PUBLISHES to social accounts · publish scope] decision "approve" sends a held post to the platform for its slot (GOES LIVE) — needs the explicit review scope (admin does not include it) and never works on a post the same connection created. decision "hold" takes a scheduled post off the platform schedule — needs review or publish. Agency plan. id is a reviewId or a convexPostId. (Wraps
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | A convexPostId or a review id. |
| decision | string | yes | — |
| note | string | no | — |
| pastSlot | no | Only for a held post whose slot passed: "now", or { at: ISO-8601 future time }. | |
| collabSide | string | no | FFE-501 collab posts only: which brand this decision is for ("owner" = the shared character's brand, "grantee" = the brand that made the post). Needed only when the key's owner approves for both brand |
[read-only] Content held for approval that waits on the account owner's decision, newest first: posts filed with publish requiresApproval: true, drafts submitted for review, and workflow runs parked at an approval gate. kind is "manual" or "workflow". Needs the explicit approve scope (admin does not include it). Agency plan. (Wraps GET /api/v2/approvals.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| status | string | no | — |
| brandId | string | no | — |
[PUBLISHES to social accounts · publish scope] Same rules as the dashboard: only the assigned approver may decide. On a "workflow" approval, decision "approve" resumes the parked run, whose next steps may publish (GOES LIVE); "reject" cancels it. On a "manual" approval, "approve" only marks the content approved — nothing is posted until you call publish with its contentId — and "reject" returns
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | An approval id. |
| decision | string | yes | — |
| note | string | no | — |
[read-only] Posting (drip) queues of one brand. A queue posts one item every cadenceHours at timeOfDay in its timezone, keeping lookahead items booked at the platform. (Wraps GET /api/v2/queues.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| brandId | string | no | Account-wide keys: "personal" or an id from GET /api/v2/brands (omitted → the brand last active in the dashboard). A brand-bound key always uses its own brand. |
[read-only] A queue and its items in order, with each item's state (queued · publishing · scheduled · posted · failed · skipped), booked or projected slot, and attribution status. (Wraps GET /api/v2/queues/{id}.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
| brandId | string | no | Account-wide keys: "personal" or an id from GET /api/v2/brands (omitted → the brand last active in the dashboard). A brand-bound key always uses its own brand. |
[PUBLISHES to social accounts · publish scope] Creates a posting queue. Once items are added it BOOKS REAL POSTS on the given platforms on its cadence (default daily 19:00 America/Chicago, 2 booked ahead). Use startsAt to hold everything until a date. Needs the publish scope (or admin) on the Agency plan or higher. (Wraps POST /api/v2/queues.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| name | string | yes | — |
| platforms | array | yes | — |
| cadenceHours | integer | no | 1, 2, 3, 4, 6, 8, 12, or whole days (24, 48, …, 720). |
| timeOfDay | string | no | 24-hour "HH:MM" local time. |
| timezone | string | no | IANA timezone. Slots keep their local time across DST. |
| lookahead | integer | no | How many upcoming items are scheduled at the platform at once. |
| startsAt | string | no | ISO 8601 with an offset (or Z). Nothing is booked before it; the first slot is the first timeOfDay (in the queue's timezone) at or after it, so a startsAt that is itself a slot is the first slot. A pa |
| youtube | object | no | Queue-wide YouTube defaults (a draft's own options win; titles are per item). YouTube upload options, applied to YouTube targets only. madeForKids is always sent to YouTube (default false). A missing |
| brandId | string | no | — |
[PUBLISHES to social accounts · publish scope] status: "paused" stops new bookings (already-booked posts stay booked); "active" resumes. Other fields (platforms, cadenceHours, timeOfDay, lookahead, startsAt, name) apply from the next booking. Needs the publish scope (or admin) on the Agency plan or higher. (Wraps PATCH /api/v2/queues/{id}.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
| brandId | string | no | — |
| status | string | no | — |
| name | string | no | — |
| platforms | array | no | Replaces the queue's platforms for items booked from now on. Already-booked items keep theirs; items with their own platforms keep using them. |
| cadenceHours | integer | no | 1, 2, 3, 4, 6, 8, 12, or whole days (24, 48, …, 720). |
| timeOfDay | string | no | 24-hour "HH:MM" local time. |
| lookahead | integer | no | — |
| startsAt | string/null | no | ISO 8601 with an offset (or Z). Nothing is booked before it; the first slot is the first timeOfDay (in the queue's timezone) at or after it, so a startsAt that is itself a slot is the first slot. A pa |
[DESTRUCTIVE] DESTRUCTIVE: deletes the queue (its drafts stay in the library). With posts booked at the platform it is refused (409) unless unschedule: true, which first deletes those platform posts. Needs the publish scope (or admin) on the Agency plan or higher. Ask the user before calling. (Wraps DELETE /api/v2/queues/{id}.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
| brandId | string | no | Account-wide keys: "personal" or an id from GET /api/v2/brands (omitted → the brand last active in the dashboard). A brand-bound key always uses its own brand. |
| unschedule | boolean | no | true: delete every booked post at the platform first (the dashboard's "Unschedule"), then delete. Without it a booked post is a 409 — nothing is ever left booked at the platform without its queue item |
[PUBLISHES to social accounts · publish scope] Appends drafts (content ids) to the end of a queue — they will be BOOKED AND POSTED on the queue's schedule. Use contentIds, or items for a per-item YouTube title or platforms. Drafts of another brand, duplicates, archived drafts and drafts without a video for a video platform come back in rejected. Needs the publish scope (or admin) on the
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
| contentIds | array | no | — |
| items | array | no | — |
| brandId | string | no | — |
[PUBLISHES to social accounts · publish scope] action: "skip" passes over a queued item; "retry" puts a failed/skipped item back in line; "unschedule" deletes a booked platform post and puts the item back in line. Also youtubeTitle, per-item platforms, and position (0-based among waiting items). Needs the publish scope (or admin) on the Agency plan or higher. (Wraps PATCH /api/v2/queue
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
| itemId | string | yes | — |
| brandId | string | no | — |
| action | string | no | — |
| youtubeTitle | string/null | no | null or "" → back to the draft's stored title. |
| platforms | array/null | no | This item's own platforms, used when it is booked; null → back to the queue's. Only before the item is booked (queued / failed / skipped). |
| position | integer | no | 0-based index among the waiting (queued) items. |
[DESTRUCTIVE] DESTRUCTIVE: removes an item (the draft stays in the library). A booked (scheduled) item is refused (409) unless unschedule: true, which deletes its platform post first. Needs the publish scope (or admin) on the Agency plan or higher. (Wraps DELETE /api/v2/queues/{id}/items/{itemId}.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
| itemId | string | yes | — |
| brandId | string | no | Account-wide keys: "personal" or an id from GET /api/v2/brands (omitted → the brand last active in the dashboard). A brand-bound key always uses its own brand. |
| unschedule | boolean | no | true: delete the booked post at the platform first (the dashboard's "Unschedule"), then delete. Without it a booked post is a 409 — nothing is ever left booked at the platform without its queue item. |
[PUBLISHES to social accounts · publish scope] Send every waiting (queued) item id exactly once, in the new order. Booked, posted, failed and skipped items keep their places. Needs the publish scope (or admin) on the Agency plan or higher. (Wraps POST /api/v2/queues/{id}/items/reorder.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
| itemIds | array | yes | — |
| brandId | string | no | — |
[read-only] Engagement overview for the last 7, 30 or 90 days. Pro plan or higher. (Wraps GET /api/v2/analytics.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| range | string | no | — |
[read-only] Read-only analytics query: one metric aggregated (median by default) over posts, broken down by up to a few dimensions (platform, weekday, hour, brand, campaign, postType, label:<key>, arm), at a fixed post age window (48h / 7d / 30d / lifetime) so posts are compared fairly. Every row carries its sample size n; platforms that do not report the metric are listed in availability, n
| Parameter | Type | Required | Notes |
|---|---|---|---|
| format | string | no | csv = the result as a spreadsheet-safe CSV attachment (UTF-8 BOM, CRLF, cells starting with = + - @ are prefixed with '). Without format, Accept: text/csv also selects CSV. Errors are always JSON. |
| metric | string | no | — |
| aggregation | string | no | Default median; pooled for the rates engagementRate, ctr and completionRate. A rate is pooled (Σ numerator ÷ Σ denominator), mean, median or count, never sum or p90. Pooled applies to rates only. |
| breakdown | array | no | Up to 2 of: platform, brand, campaign, experiment, arm, weekday, hour, postType, or label:<key> (e.g. label:cut, label:line, label:source, label:hook, label:series). The multi-valued format key also s |
| window | string | no | Snapshot age: the metric as it stood 48h / 7d / 30d after publish, or the latest refresh. |
| interval | string | no | Adds a time series bucketed by publish date. |
| filters | object | no | — |
| dateFrom | string | no | ISO date or epoch ms (publish time). Default: 90 days ago; ranges are capped at 400 days. |
| dateTo | string | no | ISO date or epoch ms. Default: now. |
| tzOffsetMinutes | integer | no | Offset from UTC for weekday / hour / day buckets (e.g. -300). |
| brandId | string | no | A brand id, or "all" (default: every profile you can see). A brand-bound key is always its own brand. |
| formula | object | no | Optional (needs the Advanced insights feature): combine up to three series. Each series is a metric + aggregation over the same breakdown, window, interval, filters and range. expression (≤ 80 chara |
[read-only] Splits every labelled post by the values of one label key (e.g. key "cut" → cut:opus vs cut:raw) and reports medians with n per group at the 48h / 7d snapshot. Descriptive, not a significance test. Pro plan or higher. (Wraps GET /api/v2/analytics/experiments.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| key | string | no | — |
| brandId | string | no | A brand id, or "all" (default: every profile you can see). A brand-bound key is always its own brand. |
| window | string | no | — |
| metric | string | no | Which metric "leading" ranks by. |
| include | string | no | — |
[read-only] A/B experiments. Content joins one by carrying the label experiment:<id> plus <compareKey>:<variant>. (Wraps GET /api/v2/experiments.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| brandId | string | no | A brand id, or "all" (default: every profile you can see). A brand-bound key is always its own brand. |
| allBrands | boolean | no | true: every brand of the organizations you own or administer, plus your personal brands. Refused (403) for a plain member and for a brand-bound key. |
[read-only] One experiment: hypothesis, variants, compareKey, window and status. (Wraps GET /api/v2/experiments/{id}.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
[writes flayr data · write scope] Creates an A/B experiment. Then tag drafts with its label (experiment:<id>) and <compareKey>:<variant> via update_content labels, publish them, and read get_experiment_results. (Wraps POST /api/v2/experiments.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| name | string | yes | — |
| hypothesis | string | no | — |
| compareKey | string | no | — |
| variants | array | no | — |
| startAt | string/null | no | — |
| endAt | string/null | no | — |
| status | string | no | — |
| primaryMetric | string | no | — |
| notes | string | no | — |
| brandId | string | no | A brand id, or "personal" (default). |
[writes flayr data · write scope] Changes an experiment's fields (e.g. status "running" / "done", endAt, notes). Only the fields you pass change. (Wraps PATCH /api/v2/experiments/{id}.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
| name | string | no | — |
| hypothesis | string | no | — |
| compareKey | string | no | — |
| variants | array | no | — |
| startAt | string/null | no | — |
| endAt | string/null | no | — |
| status | string | no | — |
| primaryMetric | string | no | — |
| notes | string | no | — |
[DESTRUCTIVE] DESTRUCTIVE: deletes the experiment record (content keeps its labels). Ask the user before calling. (Wraps DELETE /api/v2/experiments/{id}.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
[read-only] The experiment's posts split by its compareKey, with the leading variant by its primary metric and n per arm. Small samples: read medians with their n. (Wraps GET /api/v2/experiments/{id}/results.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
| window | string | no | — |
| include | string | no | — |
[read-only] Reusable text shapes per brand: sections, length targets, hook patterns, CTA slots and guardrails. Use one to shape a draft's text before create_content. (Wraps GET /api/v2/text-templates.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| brandId | string | no | A brand id (GET /api/v2/brands), "personal", or "all" (default: everything the key owner can see). A brand-bound key is always pinned to its brand; any other value is 403. |
| includeArchived | boolean | no | — |
[read-only] One format (text template) with its full structure and example. (Wraps GET /api/v2/text-templates/{id}.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
[writes flayr data · write scope] Creates a reusable format (text template) in a brand. (Wraps POST /api/v2/text-templates.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| name | string | yes | — |
| format | string | yes | — |
| platform | string/null | no | e.g. "linkedin"; null = any platform. |
| useFor | string/null | no | One line: when to pick this format. |
| length | object | yes | — |
| sections | array | no | In order. "Start from a format" writes one [you fill: Label — guidance] placeholder per section. |
| hookPatterns | array | no | "[slot]" placeholders are kept as written. |
| ctaSlots | array | no | — |
| guardrails | array | no | — |
| maxHashtags | integer/null | no | — |
| defaultLabels | array | no | "key:value" labels every draft started from this format gets (plus the format's own label). |
| example | string/null | no | — |
| source | string/null | no | Where the shape came from, e.g. an import path. |
| brandId | string | no | — |
[writes flayr data · write scope] Changes a format; only the fields you pass change. archived: true hides it. (Wraps PATCH /api/v2/text-templates/{id}.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
| name | string | no | — |
| format | string | no | — |
| platform | string/null | no | e.g. "linkedin"; null = any platform. |
| useFor | string/null | no | One line: when to pick this format. |
| length | object | no | — |
| sections | array | no | In order. "Start from a format" writes one [you fill: Label — guidance] placeholder per section. |
| hookPatterns | array | no | "[slot]" placeholders are kept as written. |
| ctaSlots | array | no | — |
| guardrails | array | no | — |
| maxHashtags | integer/null | no | — |
| defaultLabels | array | no | "key:value" labels every draft started from this format gets (plus the format's own label). |
| example | string/null | no | — |
| source | string/null | no | Where the shape came from, e.g. an import path. |
| archived | boolean | no | — |
[DESTRUCTIVE] DESTRUCTIVE: deletes a format (drafts started from it keep their text). Ask the user before calling. (Wraps DELETE /api/v2/text-templates/{id}.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
[read-only] The brand's "posts like this must carry a credit" rules and its mode (flag / push_down). In push_down mode publish refuses or holds a post missing a required credit — add credits with update_content first. (Wraps GET /api/v2/attribution-rules.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| brandId | string | no | Account-wide keys: "personal" or an id from GET /api/v2/brands (omitted → the brand last active in the dashboard). A brand-bound key always uses its own brand. |
[read-only] The brand's share rules: "when <account> publishes, reshare to <accounts> (or comment on it) after N minutes with text T", each with its approval mode. (Wraps GET /api/v2/automations/reshare-rules.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| brandId | string | no | Account-wide keys: "personal" or an id from GET /api/v2/brands (omitted → the brand last active in the dashboard). A brand-bound key always uses its own brand. |
[PUBLISHES to social accounts · publish scope] Creates a rule that reshares (or comments on) every new post of the source accounts. Defaults to needs_approval: each fire waits for approve in act_on_publish_action. Only LinkedIn (native reshare) and X (quote own / retweet) really repost; other platforms get a link share. Confirm with the user first. Needs the publish scope (or admin) on the Age
| Parameter | Type | Required | Notes |
|---|---|---|---|
| name | string | yes | — |
| enabled | boolean | no | — |
| kind | string | no | reshare: share the post to targets. comment: comment on the post itself through the source account. |
| sourceAccountIds | array | yes | Fires when a post goes live through any of these connected accounts. |
| sourceLabel | string/null | no | Only posts carrying this label. |
| targets | array | no | — |
| template | string | no | The reshare commentary or comment text. Tokens, resolved only once the URL exists: {{postUrl}} (this post, on the comment's platform), {{postUrl:<platform>}}, `{{parentPostUrl:<post or draft id>}} |
| delayMinutes | integer | no | — |
| approval | string | no | needs_approval (default): each fire waits for a person (POST …/actions/{id} approve). auto: runs on its own. |
| brandId | string | no | — |
[read-only] Pending, sent and failed comments-after-publish and reshares of the brand (filter by status, e.g. needs_approval or failed), with what each waits on. (Wraps GET /api/v2/automations/actions.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| brandId | string | no | Account-wide keys: "personal" or an id from GET /api/v2/brands (omitted → the brand last active in the dashboard). A brand-bound key always uses its own brand. |
| status | string | no | — |
[PUBLISHES to social accounts · publish scope] approve lets a rule's reshare / comment go out at its time; retry re-sends a failed one (same idempotency key); reject / cancel stop it. Confirm with the user before approving. Needs the publish scope (or admin) on the Agency plan or higher. (Wraps POST /api/v2/automations/actions/{id}.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
| op | string | yes | — |
[PUBLISHES to social accounts · publish scope] Schedules comments on a post, sent once after it is live on that platform and its tokens resolve ({{postUrl}}, {{parentPostUrl:<post id>}}, {{youtubeUrl:<post id>}}), optionally at sendAt. Confirm with the user first. Needs the publish scope (or admin) on the Agency plan or higher. (Wraps POST /api/v2/posts/{id}/comments.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
| comments | array | yes | — |
[read-only] A post's comments-after-publish and reshares, with status (waiting, needs_approval, sent, failed) and the resolved text. (Wraps GET /api/v2/posts/{id}/comments.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
[read-only] The brand's frames (borders, overlays, lower thirds, corner tags, quote-card frames, ribbons) plus the built-in flayr frames in the brand colors. Each has a ref to pass to apply_frame. (Wraps GET /api/v2/frames.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| kind | string | no | — |
| aspect | string | no | — |
| includeArchived | boolean | no | — |
[read-only] One library frame with its sizes and content areas. (Wraps GET /api/v2/frames/{id}.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| id | string | yes | — |
[writes flayr data · write scope] Copy a flayr frame into the brand library (defaultKey, optional colors/texts), or add uploaded PNG/SVG art (upload_media first; variants of storageIds, the content area is detected from transparency). (Wraps POST /api/v2/frames.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| defaultKey | string | no | A defaults[].ref without "default:". |
| paletteOverride | object | no | Colors that win over the brand kit. |
| texts | object | no | Texts some frames print (ribbon/tag label, lower-third title/subtitle). |
| name | string | no | — |
| kind | string | no | Default: guessed from the name. |
| tags | array | no | — |
| variants | array | no | One per aspect ratio. |
| rights | string | no | Who holds the rights to the art. Optional; a frame without it shows a reminder. |
[writes flayr data · write scope] Draws a frame over an image and returns a new image URL (the original is untouched). Use the URL in create_content, or pass contentId + platform so that post publishes the framed image on that platform. Free by default; the same inputs again are free. (Wraps POST /api/v2/frames/apply.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| sourceUrl | string | yes | https image URL (flayr/Convex storage or a stock host). |
| frameRef | string | yes | default:<key> or brand:<id> from GET /api/v2/frames. |
| aspect | string | no | Default: nearest to the source image. |
| fit | string | no | — |
| zoom | number | no | — |
| offsetX | number | no | — |
| offsetY | number | no | — |
| paletteOverride | object | no | Colors that win over the brand kit. |
| texts | object | no | Texts some frames print (ribbon/tag label, lower-third title/subtitle). |
| platform | string | no | Platform this framed image is for ("all" by default). |
| slideIndex | integer | no | Image position in the post. |
| contentId | string | no | A content id: its publish swaps this framed image in for platform. |
[read-only] Which frame each platform's images get automatically when a post is published or scheduled. (Wraps GET /api/v2/frames/settings.)
No parameter schema on file.
[writes flayr data · write scope] Frame every image posted to a platform automatically (frameRef), or stop (frameRef null). Applies to posts published or scheduled from now on. Confirm with the user first. (Wraps POST /api/v2/frames/settings.)
| Parameter | Type | Required | Notes |
|---|---|---|---|
| platform | string | yes | — |
| frameRef | string/null | yes | — |
| aspect | string | no | — |
- Every tool — any call limit is its publisher’s, not ours
- No card, and mcprush charges nothing for it
- Runs at its publisher’s own address — this marketplace is not in the path
- Nothing to cap, because mcprush bills nothing
What counts against your monthly calls
| Tool | Unit | Calls used | Out of the allowance |
|---|
Nothing here is billable: mcprush charges nothing to install flayr or to call it, at any volume.
Two independent axes, because powerful and malicious are different questions. The grade is threat only. The capability level is blast radius, and it is never a penalty on the grade — it is priced as one subtract-only term in the score, where you can see it.
| Term | Level | What it prices | Points |
|---|---|---|---|
| capability-exposure | moderate | capability blast radius (moderate) — client exposure if the model is manipulated | −3 |
| coverage-honesty | manifest | inspection depth (manifest) — how much of the target the scan could see | −4 |
What the scan could actually read
A grade is only as meaningful as its coverage, so the scanner publishes its own depth before it publishes its result.
The scan read each tool’s name, description, input schema and annotations exactly as the server listed them the last time it answered us; no code was reviewed. We ask the server again about once a month, and a list that changed is graded again.
The implementation source was not read — this reflects the declared tool metadata only.
Capability — what it could do if the model were manipulated
Tags derived from each tool’s schema and the implementation, not from what the tool calls itself. moderate is the level these add up to.
| Tool | Capability tags | Why the tag was assigned |
|---|---|---|
| whoami | no tags | |
| list_brands | no tags | |
| list_connected_accounts | no tags | |
| list_youtube_playlists | no tags | |
| list_pinterest_boards | no tags | |
| upload_media | state-write | state-write: declares readOnlyHint: false |
| list_content | no tags | |
| get_content | no tags | |
| create_content | state-write | state-write: declares readOnlyHint: false |
| update_content | state-write | state-write: declares readOnlyHint: false |
| delete_content | state-write | state-write: declares readOnlyHint: false, destructiveHint: true |
| combine_clips | state-write | state-write: declares readOnlyHint: false |
| get_job_status | no tags | |
| publish | external-sink | external-sink: declares readOnlyHint: false, destructiveHint: true, openWorldHint: true |
| get_post | no tags | |
| update_scheduled_post | external-sink | external-sink: declares readOnlyHint: false, destructiveHint: true, openWorldHint: true |
| cancel_scheduled_post | external-sink | external-sink: declares readOnlyHint: false, destructiveHint: true, openWorldHint: true |
| list_reviews | no tags | |
| decide_review | external-sink | external-sink: declares readOnlyHint: false, destructiveHint: true, openWorldHint: true |
| list_approvals | no tags | |
| decide_approval | external-sink | external-sink: declares readOnlyHint: false, destructiveHint: true, openWorldHint: true |
| list_queues | no tags | |
| get_queue | no tags | |
| create_queue | external-sink | external-sink: declares readOnlyHint: false, destructiveHint: true, openWorldHint: true |
| update_queue | external-sink | external-sink: declares readOnlyHint: false, destructiveHint: true, openWorldHint: true |
| delete_queue | state-write | state-write: declares readOnlyHint: false, destructiveHint: true |
| add_queue_items | external-sink | external-sink: declares readOnlyHint: false, destructiveHint: true, openWorldHint: true |
| queue_item_action | external-sink | external-sink: declares readOnlyHint: false, destructiveHint: true, openWorldHint: true |
| remove_queue_item | state-write | state-write: declares readOnlyHint: false, destructiveHint: true |
| reorder_queue_items | external-sink | external-sink: declares readOnlyHint: false, destructiveHint: true, openWorldHint: true |
| get_analytics | no tags | |
| query_insights | no tags | |
| compare_labels | no tags | |
| list_experiments | no tags | |
| get_experiment | no tags | |
| create_experiment | state-write | state-write: declares readOnlyHint: false |
| update_experiment | state-write | state-write: declares readOnlyHint: false |
| delete_experiment | state-write | state-write: declares readOnlyHint: false, destructiveHint: true |
| get_experiment_results | no tags | |
| list_text_templates | no tags | |
| get_text_template | no tags | |
| create_text_template | state-write | state-write: declares readOnlyHint: false |
| update_text_template | state-write | state-write: declares readOnlyHint: false |
| delete_text_template | state-write | state-write: declares readOnlyHint: false, destructiveHint: true |
| list_attribution_rules | no tags | |
| list_share_rules | no tags | |
| create_share_rule | external-sink | external-sink: declares readOnlyHint: false, destructiveHint: true, openWorldHint: true |
| list_publish_actions | no tags | |
| act_on_publish_action | external-sink | external-sink: declares readOnlyHint: false, destructiveHint: true, openWorldHint: true |
| add_post_comments | external-sink | external-sink: declares readOnlyHint: false, destructiveHint: true, openWorldHint: true |
| list_post_comments | no tags | |
| list_frames | no tags | |
| get_frame | no tags | |
| create_frame | state-write | state-write: declares readOnlyHint: false |
| apply_frame | state-write | state-write: declares readOnlyHint: false |
| get_frame_settings | no tags | |
| update_frame_settings | state-write | state-write: declares readOnlyHint: false |
Toxic-flow graph
The lethal trifecta, checked as a graph rather than as a checklist: untrusted input, a sensitive source and an external sink have to meet before there is a path worth worrying about.
The public result for this release does not print the flow graph, so there is nothing to show here. That is not the same as "no paths were found": what the scan did read is above, under coverage.
Supply chain and provenance
This is the first scan of this surface here, so there is nothing yet to compare it against.
Every result on this tab comes from one deterministic pass over the published package — offline, rule by rule, and auditable line by line above. Same methodology version, same bytes, same score.
Release history
This is an address its publisher runs: which release it serves is theirs to choose, so there is nothing here to pin. The history below is for reading; the current release on file is 1.2.0.
No release note was published with this version.
One review per account, from a signed-in account that does not publish this listing. Nothing else is asked — you can say what you think before you install it. Publishers can reply once per review, and a review can be edited or deleted by whoever wrote it.
Any signed-in account that does not publish flayr can review it, once — before installing it or after. A review from an account that has installed it is marked as one.
Nobody has reviewed this listing. The rating on the card is the mean of the reviews written here and nothing else, so there is no rating until somebody writes the first — which takes a signed-in account that does not publish it, and nothing else.