Purpose
postlint-mcp is an MCP server that answers just one question: can this social post pass the character limit check of the target platform. The author points out that language models cannot accurately count characters by visual inspection, and for platforms such as X, Bluesky, LinkedIn, Threads, Mastodon, and Discord, the limits are not as simple as they appear: X charges every URL uniformly as 23 characters via t.co, regardless of whether the link is 12 characters or 200 characters; Bluesky counts by extended grapheme clusters, so a family-of-four emoji counts as 1 character rather than 11; Mastodon does not charge for the domain portion of remote mentions. Counting errors can lead to rejection at publish time or truncated posts. The author documented two cases that triggered development: a Bluesky post actually went out at 302 characters under a 300 limit, and below it still said "under 300 graphemes, audit passed"; an X post was drafted as 308 characters against a 280 limit and would have been rejected on the day of publication. Both cases have been included in the repository as regression tests.
Supported Platforms and Counting Rules
Supports X, Bluesky, LinkedIn, Threads, Mastodon, and Discord. Every platform figure is traced back to a published source. Widely circulated numbers without a primary source, such as the Facebook post limit, YouTube community post limit, Reddit title cap, and Instagram organic caption cap, are deliberately excluded—limits that cannot be argued make passing checks meaningless.
Usage
Published on npm. The configuration block uses npx, which is fetched automatically on first run, with no need to clone the repository. It can be added to .mcp.json, claude_desktop_config.json, or added to ~/.codex/config.toml. No token, no environment variables, no network access. After the package is published, you can replace the node call in the above configuration with npx -y @conorbronsdon/postlint-mcp. You can also directly tell the assistant, "check whether this post is compliant under X and Bluesky," and paste content containing several links.
Main Capabilities
Provides tools such as check_post and check_post_all. Responses are deliberately kept concJian: check_post_all omits arithmetic details on passing lines because agents consume tokens per response. The example shows the same 330-character text yielding three different lengths in check_post_all—308, 330, and 308—which is exactly why the tool exists. The response also provides a "drivers" line, for example pointing out that 69 characters of budget are spent on links, suggesting you move the two links into a reply instead of trimming the body.
Draft placeholder handling
Drafts often contain link placeholders, and [URL] is five characters, which a real link is not. Measuring with placeholders, replacing them with real links, and then publishing means you measured wrong. Therefore placeholders such as [URL], [LINK], [YOUTUBE URL], and [SUBSTACK URL] are priced as real links (a 28-character YouTube short link, i.e. the shortest link typically published), and the response includes a warning stating that the count is a lower bound.
Limitations
Nothing is published: no write path, no credentials, no network calls whatsoever. This is enforced by tests—the tests replace fetch, XMLHttpRequest, and WebSocket with throwing versions and drive every tool, so if a call is added later, CI fails. The instance's actual limit is not checked: Mastodon servers can configure their own, and the tool reports the default of 500 and prompts you to read the target server's configuration.statuses.max_characters yourself. No truncation is done: a truncate_to helper was considered but excluded, because truncating by character offset cuts URLs, breaks grapheme clusters, and stops mid-sentence, while truncating at "safe" boundaries silently drops the final clause—either way the tool would be deciding the post's content; the tool only reports numbers, leaving editing to the user. It cannot detect all URLs that platforms detect: hosts with a protocol and www. prefix always match, bare domains match only on common TLDs (the list is in src/count.ts), whereas the real twitter-text implementation includes the full IANA registry; writing https:// before a link gives an exact count. Media, polls, quote posts, and link cards are not counted: these have their own rules, and this tool measures text only. Content warnings are not understood: on Mastodon, CW and body share the same 500 limit, and this tool checks only the body. It does not carry limits that cannot be traced (see the platform table).
Other information
The tests make no network calls, because the server itself makes none. Two historical over-limit posts are kept as regression fixtures in src/tests/lint.test.ts, along with grapheme cases including ZWJ family emoji, regional indicator flags, skin tone modifiers, combining accents, and CJK. Issues and pull requests are welcome: adding a platform requires three things—the limit value, the unit of measurement, and a published source; adding a counting rule requires a test that fails without that rule. Numbers repeated by third parties do not count as a source. The project is built and maintained by Conor Bronsdon, is in maintenance mode, is stable and accepts security fixes, with no new features planned, but issues and pull requests are still welcome. This is an independent personal project, unaffiliated with, unsponsored by, and unendorsed by any company.