# FeedSquad MCP changelog

Each entry is one tool catalogue. The catalogue version is its release date. The `capabilities` tool reports the catalogue the server runs (`catalog_version`). Your AI client may still hold an older copy of the tools. If a tool named here is missing, or behaves differently, remove FeedSquad from your AI client and add it again once, so the client loads the current tools and descriptions.

Parameters are never removed or renamed. A deprecated name keeps working for 90 days.

## 2026.10.23 (server 1.2.4)

Tool descriptions rewritten to describe only each tool, with usage guidance moved to get_help, plus fixes found on a fresh account and in review.

- Each tool's description now says what that tool does, what it takes and returns, what it changes and its limits. Advice on which tool to use when, and in what order, is in `get_help`: `overview` says where to start, `posting` says which tool handles which job (including images and brand memory), `campaigns` and `scheduling` cover the rest.
- `find_next_slot` now says that it does not apply your posting window or campaign mode, so the slot FeedSquad picks when it creates a post without a time can differ from the slots it lists.
- No tool or parameter is renamed or removed. If your AI client cached the older descriptions, it keeps working; reconnect to load the new wording.
- `get_brain_gaps` works on a new account with nothing in brand memory yet: it lists every gap and shows nothing waiting for review, instead of an error.
- You can approve and schedule posts before connecting LinkedIn, X or Threads. The answer says the platform is not connected yet (`connection`, or `connections` for a campaign) and links to the connections page. A scheduled post publishes at its time if the platform is connected by then; if the time passes first, it does not publish and comes back as a draft once you connect. Publishing a post right now still needs the platform connected.
- Paid plans have no limit on how many campaigns you create. Campaign drafts count toward the same daily draft ceiling as other drafts. On the free plan, creating a campaign answers that campaigns are not included in your plan. `get_usage` no longer reports `campaigns_per_day`.
- A limit that no plan raises (posting cadence, burst guards) no longer offers an upgrade.
- When FeedSquad stops picking times for you (300 dated posts in a month), the answer no longer offers an upgrade: no plan raises that limit. Give the post a time, or wait for the next month.
- A failed publish says what kind of failure it was (the connection, the platform's rate limit, the platform refusing the content, or unknown) in a fixed sentence; the platform's own reason comes separately (`platform_error`, at most 200 characters).
- `adapt_for_platform` answers within the request's time limit: a platform whose version takes too long comes back as `generation_timeout`, and you can try again.
- Downloading a video or image from a link now stops after 40 seconds (was 60), so the request stays inside its time limit. A very large file from a slow host that used to arrive can now time out; link it from a faster host.
- `upload_asset` is marked as reaching outside FeedSquad, because with the Pixel asset shelf the image is sent to FeedSquad's AI provider for a caption.
- Scheduling uses your browser's timezone when you haven't set one in Settings. FeedSquad notes it when you open FeedSquad or approve the connection, and the answer says so (`timezone_source: browser`). A timezone you choose in Settings always wins.

## 2026.10.22 (server 1.2.3)

Scheduling without clock math, and one clear account of limits.

- Times: the calendar and every scheduling answer now say what time it is for you (`server_now`, with your offset), in which timezone (`timezone`), and each post's time on your clock (`scheduled_local`) next to the UTC time. The timezone is the one in your FeedSquad Settings; the answer says when it is using your account's default zone or UTC instead, and the daily posting caps count days in the same timezone. `get_calendar` takes `date`: `today`, `tomorrow` or a date, read in your timezone.
- A time sent without an offset, such as `2026-10-22T08:45`, is read in your timezone, and the answer says so (`time_input`). A time with an offset is used exactly as sent. So "move today's post to 8.45" is one calendar read and one reschedule.
- Your AI keeps the exact time you name. When you name none, FeedSquad proposes a slot and says why. The old advice to pick "human-looking" minutes is gone.
- Limits: `capabilities` and `get_usage` return the same `limits`, with four parts kept apart: what your plan publishes and queues, the daily posting cadence on every plan, the rules FeedSquad uses when it picks the time for you (including the 300 dated posts a month after which it stops picking times, which is not a publishing limit), and the characters each platform allows. X allows 280 characters per post; longer single posts need the X long-post setting on an account that supports it.
- Approval: every change to a post reports `status_before`, `status_after` and `approval_required`. `get_help` with the topic `scheduling` has the full list of what each action does to approval. Moving a scheduled post keeps it scheduled; editing the text or media of an approved post sends it back for approval.
- The calendar lists each post once: `days` now holds each date's post ids, and the posts themselves are in `posts`. If your client read posts inside `days`, read `posts` instead.
- Published posts show when they went out and their link (`published_at`, `published_url`); a failed publish shows a short reason (`publish_error`).

Brand memory comes with Stash:

- The four Stash tools (`get_brand_context`, `get_brain_gaps`, `tell_stash`, `propose_stash_items`), the brand voice resource and the build-my-brain prompt are offered to every account whose plan includes Stash: Stash itself, the FeedSquad Bundle or Chief. They work the same in Claude, ChatGPT and other MCP clients. Access ends when the plan is cancelled or lapses. Accounts already in the Stash beta keep their access.
- A Stash tool called after access ended says the feature is not included in your current plan, instead of a private-beta notice.

## 2026.10.21 (server 1.2.2)

Plans and limits are stated plainly. When something is not included in your current plan, the answer says so and links to the page that describes each plan. In ChatGPT, FeedSquad no longer lists or compares plans: it describes your own account's limits, and your usage shows what your plan includes. In Claude, the visual tool that can draw AI illustrations is not offered. The `capabilities` answer adds `plan_limits`, a short description of what each plan includes.

## 2026.10.19 (server 1.2.1)

Candidate update: more reliable connector responses, complete campaign-post calendar and follow-up access, safer editing and scheduling, and clearer retry and permission information. Posts keep their existing identifiers. Client verification is still in progress.

## 2026.10.09 (server 1.2.0)

Reading your brand context:

- `get_brand_context` now says how to use your tone examples and signature phrases: as a style reference to imitate, never as sentences to copy. Your AI client sees this note next to the examples.

Performance insights:

- `get_performance_insights` returns less internal data. Each ranked post keeps its platform, text preview, publish date and numbers, and no longer includes the platform's own post id, the time the numbers were read, or our internal record fields.
- Each ranked post now has `post_id`, FeedSquad's id for the post, so you can open it with `get_post` or adapt it with `adapt_for_platform`. It is empty when the numbers could not be matched to a FeedSquad post.
- The recent winners resource matches: each winner's `id` is the FeedSquad post id, or empty, and never the platform's post id.

Connecting accounts:

- `connect_platform` tells you when a platform is already connected instead of sending a new sign-in link, and it agrees with `list_accounts`. If a connection has expired, you still get a link to reconnect. An already-connected answer names the connected accounts and links to the connections page, which is where you add a second X account, such as a brand account.

Looking up a lint hit:

- `get_ai_tell` opens the entry behind a `lint_post` hit when you pass the hit's `ai_tell_id`, and now also when you pass the hit's own id (for example `pointing_emoji`). The response says which id it resolved from.
- Every `lint_post` response with a hit says to call `get_ai_tell` with the hit's `ai_tell_id`.
- The short-sentence rhythm check ("Staccato tricolon") no longer points at the "Staccato fragment run" entry, which describes a different pattern. Its hit carries no `ai_tell_id`, because no entry describes it.

Posting media to X:

- Images, carousels and videos publish to X again. X stopped accepting the upload method we used, so videos failed and images were dropped from the post.
- If any image or video in an X post fails to upload, the post is not published with media missing. It fails with a clear error so you can try again.

Seeing a post's media:

- `get_post`, `get_calendar` and `search_posts` show each post's media as `media`: its type (none, image, carousel or video), how many items, and the alt text when one was set. Before, a post with a video looked like a text post. Links to the files are not included, because they expire.
- A `publish_post` dry run shows the post's text and its media. Before, the text came back empty.

Searching posts:

- `search_posts` matches your query exactly as typed. A percent sign, comma, underscore, quote, parenthesis or backslash now matches that character. Before, a percent sign or comma was ignored, an underscore matched any character, and a parenthesis made the search fail. An asterisk is treated as a space. Queries longer than 100 characters are shortened to the first 100.

Video and image formats:

- `set_post_video` works. Attach an MP4 or MOV video up to 200 MB. Before this fix every video attach failed at upload.
- `set_post_image` and `set_post_carousel` accept WebP and GIF image links as well as JPEG and PNG. They are stored as JPEG or PNG so every platform can publish them; only the first frame is kept, so an animated GIF loses its animation. Any attached image over 3 MB is downscaled on the server, as with `upload_asset`. Before this fix a WebP or GIF failed at upload.
- A video or image in a format we can't store (for example WebM or SVG) is refused before anything is downloaded, with a message that lists the supported formats. `dry_run: true` gives the same answer.

Sign-in for ChatGPT:

- Two new identity scopes, `openid` and `email`. A client gets them only when it asks for them by name. They grant no tool. The consent screen describes them as "Confirm who you are" and "Your email address".
- New OpenID Connect discovery at `/.well-known/openid-configuration`, with the same issuer as the OAuth metadata.
- New UserInfo endpoint at `/api/oauth/mcp/userinfo`. With `openid` it returns your account id. With `email` it adds your email address, and `email_verified` is true only for a confirmed address.
- Every authorization response now carries `iss`.
- ChatGPT can register only its two documented redirect addresses on chatgpt.com.
- A new domain-verification endpoint for OpenAI at `/.well-known/openai-apps-challenge`.

The FeedSquad plugin:

- One plugin package for Claude and ChatGPT. It connects this server and ships six skills: `setup`, `plan-week`, `write-campaign`, `repurpose`, `clear-backlog` and `check-ai-tells`.
- The skills approve, save a rewrite or publish only after a clear yes from you. `archive_posts` and `create_posts` run as a dry run first.

Directory addresses:

- The server also answers at `https://feedsquad.com/api/mcp/chatgpt`, the address listed in ChatGPT, and `https://feedsquad.com/api/mcp/claude`, the address listed in Claude. They offer the same tools. `https://feedsquad.com/api/mcp` keeps working for every client, and an existing connection works at all three addresses.

Images:

- `upload_asset` accepts images up to 10 MB. Over 3 MB the server downscales them (longest edge 2048 pixels, photo orientation kept, location and camera metadata removed), so you never resize first. Images are stored as JPEG or PNG; a GIF or WebP is converted, keeping its first frame. Images over about 2.5 MB are sent in chunks: the first call with `chunk_index: 0` and `total_chunks` returns an `upload_session_id` for the rest. An upload session lasts 24 hours, and you can have up to 3 open at once.
- `upload_asset` no longer needs a post. Without `post_id` it stores the image and returns an `asset_id`. Attach it to any number of posts with `set_post_image` and `asset_id`, with no second upload. An image that is never attached is deleted after 30 days.
- `set_post_image` takes `asset_id` as an alternative to `image_url`. A post still holds one kind of media at a time, and `replace: true` swaps it.
- `upload_asset` takes `dry_run: true` to check an image without storing it.
- An image error now says what went wrong and how to fix it, in a machine-readable code and a recovery instruction. A post that is already published is refused as an error instead of a result that says it failed.

FeedSquad Studio, a sidebar app for ChatGPT:

- On ChatGPT, where it is switched on, a new `open_studio` tool opens FeedSquad Studio from the sidebar or the conversation panel. It changes nothing. Claude and other clients do not see it, and the public tool count stays at 30.

Tool changes:

- `adapt_for_platform` keeps your wording and no longer adds a question, a call to action or hashtags your draft didn't have. Every platform, X included, keeps only your own hashtags. Each version is checked the same way as `lint_post` and reports a `lint_verdict`, and lists anything the check removed. A thread's part breaks are not counted as dividers.
- `archive_posts` takes an optional `only_status: "draft"`. With `post_ids`, a post is archived only while it is still a draft. A post approved or scheduled since is skipped as `changed`.
- `get_calendar` pages no longer skip or repeat a post when one is archived or added between pages. Cursors from before still work for one release. A malformed cursor is refused as `validation_failed`.

Bluesky and Mastodon:

- Publishing to Bluesky and Mastodon isn't available yet, so `capabilities` now lists only X, LinkedIn and Threads. `create_post`, `create_posts`, `create_campaign`, `find_next_slot` and `adapt_for_platform` answer a Bluesky or Mastodon request with a clear error instead of saving a draft or proposing a time that could never publish. The platform values are still accepted, so nothing that names them breaks.

## 2026.10.07 (server 1.1.1)

Tool annotations:

- `publish_post` is marked destructive. It publishes at once and cannot be taken back.
- `update_post` and `reschedule_post` are marked destructive. Each overwrites the post.
- `set_post_image`, `upload_asset`, `set_post_video` and `set_post_carousel` are marked destructive. Each replaces the post's media.
- `adapt_for_platform` is marked read-only. It returns text and saves nothing.
- `get_calendar` is no longer marked open world. It reads FeedSquad's own records only.
- `tell_stash` (Stash beta) is marked open world. Its text goes to FeedSquad's model provider to be classified.
- `connect_platform` is no longer marked idempotent. Each call returns a new sign-in link.

Other changes:

- The `delete_post` description says that published posts, and posts whose publish has not finished or been confirmed, cannot be deleted.
- On ChatGPT, purchase links in tool results point to `https://feedsquad.com/plans`, and `get_plans` shows only what you hold. Claude and other clients are unchanged.
- Post statuses in tool output can be `deleted` and `cancelled`. `confirm_post` with `cancel` reports `cancelled`.
- Cadence refusals arrive as `cadence_conflict` instead of `internal_error`. Their `data` names the rule and the posts already on that day.
- `delete_post` refuses a post whose publish is unsettled and points to `get_post`.
- The error table in the MCP cookbook lists every code the server sends.

## 2026.10.06 (server 1.1.0)

New tool:

- `archive_posts` archives up to 50 named posts, or up to 100 stale drafts selected by criteria. Dry run is the default. Published posts are never archived. An archived post stays in the dashboard under Archived, where you can restore it to drafts. The GA tool count goes from 29 to 30.

Safer deletes:

- `delete_post` refuses a post that is being published right now (`publish_in_progress`), or whose publish could not be confirmed.
- `delete_post` on a published post returns `already_published`. Remove the live post in the platform's own app.
- A successful `delete_post` reports `status: "deleted"`.

Discovery and help:

- `capabilities` returns `server_version`, `catalog_version` and per-platform posting rules under `platforms`.
- `get_help` has the topics `connection` and `platforms`, and its overview prints the server and catalogue versions.
- A `scope_insufficient` error carries `recovery_hint` with `action: "reconnect"`.
- Each resource description names the tool it mirrors, so a client without resource support loses nothing.

Shorter responses:

- `get_calendar_health` and `get_brand_context` (Stash beta) take `response_format`. The default `concise` returns every count and the first entries of each list. `detailed` returns everything, as before.
- `get_calendar` counts every post that matches the filters and adds `page` and `counts.scope`.
- `search_posts` rows carry `published_date` and `created_at`.
- `get_calendar` and `search_posts` leave archived posts out unless the status filter names `archived`.

Plans and usage:

- `get_plans` lists Handler Free, each agent on sale, the Bundle, Chief and the Pixel Pro add-on, and marks what you hold.
- `get_usage` returns the same plan summary.
- `billing:read` is in the default scopes. A connection made before this needs one reconnect to call `get_plans`.
- The pricing widget shows prices of 100 euros or more correctly.

Linting:

- `lint_post` checks the banned-pattern registry and the AI Tells Index in one pass. Its result is `kind: "lint"` with a declared output schema. This is the one change in this release that is not additive.
- `lint_post` takes `response_format`. Each hit names its source, evidence and rationale, and links its AI Tells Index page when there is one. AI Tells hits are advisory and never change the verdict.
- `lint_post` returns writing metrics only for drafts of 300 words or more.
