
Postlint MCP Server
io.github.conorbronsdonPublished by GitHub account conorbronsdonv1.1.0Updated Oct 24, 2026
Check a social post against a platform's real character limit: X, Bluesky, LinkedIn, Threads.
Overview
Checks a drafted social post against the real character limits of X, Bluesky, LinkedIn, Threads, Mastodon, and Discord.
- What you can do
- Exposes tools that measure a post the way each platform actually counts it: check_post returns a verdict for one platform with counted length, limit, headroom, and what drove the count; check_post_all returns one row per platform; platform_limits lists each limit, its counting unit, and its source. It accounts for rules such as X pricing every URL at 23 characters and Bluesky counting grapheme clusters. It only measures text and reports numbers; it never edits or posts.
- When to use it
- Useful when drafting or scheduling posts for several networks and you need to know whether a draft fits before publishing, especially with links, emoji, or non-Latin text where eyeballing the count fails. Less useful if you only post to one platform or never hit limits.
- Requirements
- Runs locally over stdio, installed from npm with npx or built from source with Node.js. No account, token, environment variable, or network access is needed.
Installation
In SourceWeft
- Open Postlint MCP Server in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
postlint-mcp
Maintenance mode. This project is stable and receives security fixes. New features aren't planned, but issues and pull requests are still welcome.
Check a social post against a platform's real character limit before it ships. X, Bluesky, LinkedIn, Threads, Mastodon, Discord. Pure compute — no API, no auth, no network.
[npm version] [License: Apache 2.0] [Node] [Glama score] [Podcast] [X]
[Three drafts checked in a terminal: an X post at 308 of 280 with three URLs billed at 23 each, a Bluesky post at 302 of 300, and that same draft with its link still a [URL] placeholder, which a length check reads as 277 but the server prices at exactly 300 of 300]Recorded from docs/demo.tape with vhs. The posts and counts come from scripts/fixtures.mjs, which the regression tests import too.
An MCP server that answers one question: does this post fit?
A language model cannot count characters by inspection, and on these platforms neither can you. The limits are not what they look like. X bills every URL at 23 characters through t.co whether the link is 12 characters or 200. Bluesky counts extended grapheme clusters, so a four-person family emoji is 1 and not 11. Mastodon charges nothing for the domain on a remote mention. Getting any of that wrong shows up as a rejected post, or a truncated one, at publish time.
Counting is what a tool call is for. The model cannot do it by inspection, and a deterministic function can do it exactly.
Why this exists. Two posts went out of a podcast promo workflow over the limit. A Bluesky post shipped at 302 against 300, with the line "Under 300 graphemes. Audit clean." sitting directly beneath it. An X post was drafted at 308 against 280 and would have been rejected on launch morning. Both were invisible to eyeballing, because in both cases the count was a claim and not a measurement. Both are regression tests in this repo.
Tools
Responses are small on purpose. check_post_all omits the arithmetic on passing rows because agents pay tokens per response.
How each platform counts
Every number above traces to a published source. Widely repeated figures that no primary source states — the Facebook post limit, the YouTube community post limit, Reddit's title cap, Instagram's organic caption cap — are deliberately absent. A limit that cannot be defended makes a passing check worth nothing.
Setup
Published on npm. The config blocks below use npx, which fetches it on first run; no clone required.
Claude Code
Add to your .mcp.json:
Claude Desktop
Same block, in claude_desktop_config.json.
Codex
Add to ~/.codex/config.toml:
No token, no environment variables, no network access. Once the package is published, npx -y @conorbronsdon/postlint-mcp replaces the node invocation everywhere above.
Verify
Ask your assistant: "Check this post for X and Bluesky," and paste something with a couple of links in it.
A worked example
The X post that started this, run through check_post with platform: "x":
The drivers line is the useful part. 69 of the budget went to links before a word was written, which tells you to move two of them into a reply rather than trimming prose.
The same post through check_post_all:
One post, three different lengths — 308, 330, and 308 again — from the same 330 characters of text. That gap is the whole reason this exists.
Draft placeholders
Drafts carry link placeholders, and [URL] is five characters while a real link is not. A post measured with the placeholder in place and posted with the link filled in is a post measured wrong; one draft came in at 264 that way and posted at 282.
So [URL], [LINK], [YOUTUBE URL], [SUBSTACK URL], and similar are priced as a real link (a 28-character YouTube short link, the shortest thing normally posted) and the response carries a warning saying the count is a floor.
What it does not do
- It does not post anything. There is no write path, no credential, and no network call of any kind. That last one is enforced rather than asserted: a test replaces
fetch,XMLHttpRequest, andWebSocketwith throws and drives every tool, so a call added later fails CI instead of quietly making this sentence false. - It does not check an instance's actual limit. Mastodon servers configure their own; this reports the 500 default and tells you to read
configuration.statuses.max_charactersfrom the target server yourself. - It does not truncate. A
truncate_tohelper was considered and left out. Cutting a post at a character offset splits URLs, breaks grapheme clusters, and lands mid-sentence, and cutting it at a "safe" boundary silently drops whichever clause happened to be last. Either way the tool would be deciding what the post says. It reports the number and leaves the edit to you. - It does not detect every URL a platform would. Links with a scheme and
www.-prefixed hosts always match. A bare domain matches only on a common TLD (src/count.tsholds the list), where the real twitter-text implementation carries the full IANA registry. Writehttps://in front of a link and the count is exact. - It does not count media, polls, quote posts, or link cards. Those have their own rules and this measures text.
- It does not know about content warnings. On Mastodon a CW counts toward the same 500. This checks the body alone.
- It does not carry limits it cannot source. See the platform table.
Development
Tests make no network calls, because the server makes none. The two historical over-limit posts are regression fixtures in src/__tests__/lint.test.ts, alongside grapheme cases for ZWJ family emoji, regional-indicator flags, skin-tone modifiers, combining accents, and CJK.
Contributing
Issues and pull requests are welcome. A new platform needs three things: the limit, the unit it is measured in, and a published source. A new counting rule needs a test that fails without it. Numbers repeated by third parties are not sources.
About
Built and maintained by Conor Bronsdon. I host the Chain of Thought podcast, which covers AI infrastructure, developer tools, and how practitioners actually use this stuff. I built this after shipping two over-limit posts in a workflow that was supposed to catch them.
Companion tools:
- op3-mcp: podcast analytics through OP3 — downloads, geography, apps, per-episode breakdowns.
- podcastindex-mcp: the Podcast Index MCP server, search by person or topic, trending shows, feed health.
- substack-mcp: read posts and manage drafts on Substack, safe for agent workflows.
- Transistor MCP: Transistor.fm's official MCP server. Episodes, publishing, and analytics.
- ai-tools-for-creators: a curated list of AI skills and MCP servers for people who ship ideas for a living.
More at chainofthought.show and on X.
Disclaimer
This is an independent personal project, not affiliated with, sponsored by, or endorsed by any company. All views expressed are my own.
License
Apache-2.0
Source: README.md at commit 6622dba
Tools
0Version history
1- v1.1.0LatestSep 16, 2026
Score
50% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts