markpost
Publishes Markdown content as threaded posts on Threads, automatically splitting long content into separate posts respecting platform character limits.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@markpostpreview this markdown as a Twitter thread"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Markpost
An MCP server that takes Markdown content and syndicates it to Twitter/X, Threads, and a static blog on S3. Designed to be used by AI agents like Claude Code — write a post in Markdown, and Markpost handles the formatting and publishing for each platform.
What it does
Formats per platform — Strips Markdown to plain text for social media, renders full HTML for blog
Auto-splits into threads — Long content is split at
---separators or sentence boundaries, respecting each platform's character limit (280 for Twitter, 500 for Threads)Previews before publishing — Dry-run tool shows exactly how content will be formatted and split
Syndicates everywhere at once — Publish to all platforms with a single tool call, or pick specific ones
Related MCP server: Markdown-To-Notion
Tools
Tool | Description |
| Format and publish Markdown to one or more platforms |
| Preview formatting and thread splits without publishing |
| Health check |
Quick start
1. Install
git clone <this-repo> && cd markpost
uv venv && uv pip install -e ".[dev]"2. Configure API keys
Copy the example config and fill in your credentials:
mkdir -p ~/.markpost
cp config.example.toml ~/.markpost/config.tomlEdit ~/.markpost/config.toml:
[twitter]
consumer_key = "your-consumer-key"
consumer_secret = "your-consumer-secret"
access_token = "your-access-token"
access_token_secret = "your-access-token-secret"
[threads]
access_token = "your-long-lived-access-token"
user_id = "your-threads-user-id"
[blog]
s3_bucket = "my-blog-bucket"
s3_prefix = "posts/"
base_url = "https://blog.example.com"
[blog.aws]
region = "us-east-1"You can also set a custom config path via the MARKPOST_CONFIG environment variable.
3. Connect to an MCP client
See the sections below for your specific client.
Running the server
stdio mode (default)
stdio is the standard transport for local MCP clients. The server reads JSON-RPC messages from stdin and writes responses to stdout.
uv run python src/markpost/server.pyOr using the FastMCP CLI:
uv run fastmcp run src/markpost/server.pyHTTP mode (remote / SSE)
For remote access or web-based clients, run in HTTP mode:
uv run fastmcp run src/markpost/server.py --transport http --host 0.0.0.0 --port 9000The server will be available at http://localhost:9000. Clients connect via the Streamable HTTP transport.
Client setup
Claude Code
Register the server with the claude CLI:
claude mcp add markpost -- uv run --directory /path/to/markpost fastmcp run src/markpost/server.pyVerify it's registered:
claude mcp listThe publish_post and preview_post tools will now be available in Claude Code sessions.
Claude Desktop
Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"markpost": {
"command": "uv",
"args": [
"run",
"--directory", "/path/to/markpost",
"fastmcp", "run", "src/markpost/server.py"
]
}
}
}Restart Claude Desktop after saving.
Other MCP clients (HTTP)
Start the server in HTTP mode (see above), then point your client at http://localhost:9000.
Getting API keys
Twitter/X
Go to the Twitter Developer Portal
Create a Project and App
Set app permissions to Read and Write
Generate your Consumer Key (API Key), Consumer Secret (API Secret), Access Token, and Access Token Secret
If you changed permissions after generating tokens, regenerate them
The free tier allows 1,500 tweets/month.
Threads
Go to the Meta Developer Dashboard
Create a new app and add the Threads API product
Your Threads account must be public
Complete the OAuth flow to get an access token:
Authorize at
https://threads.net/oauth/authorize?client_id={app_id}&redirect_uri={uri}&scope=threads_basic,threads_content_publish&response_type=codeExchange the code for a short-lived token at
https://graph.threads.net/oauth/access_tokenExchange for a long-lived token (60 days) at
https://graph.threads.net/access_token?grant_type=th_exchange_token&client_secret={secret}&access_token={short_token}
Get your user ID:
GET https://graph.threads.net/v1.0/me?access_token={token}
S3 Blog
Create an S3 bucket configured for static website hosting
Configure your AWS credentials via the standard methods (
~/.aws/credentials, environment variables, or IAM role)Set
s3_bucket,s3_prefix, andbase_urlin your config
The base_url should be the public URL where your blog is served (e.g., your CloudFront distribution or S3 website endpoint).
Thread splitting
Long content is automatically split into threads. You control splits two ways:
Explicit separators — Use --- in your Markdown to force a split:
Here is the first tweet in my thread.
---
And here is the second one.Auto-splitting — If any section exceeds the platform's character limit, it's split at sentence boundaries. If a single sentence is too long, it falls back to word boundaries.
The preview_post tool lets you see exactly how content will be split before publishing.
Development
# Install dev dependencies
uv pip install -e ".[dev]"
# Run tests
uv run pytest tests/ -v
# Run a specific test file
uv run pytest tests/test_formatter.py -vProject structure
src/markpost/
server.py # FastMCP server — ping, publish_post, preview_post
config.py # TOML config loading
formatter.py # markdown_to_plain, split_into_thread, markdown_to_html
publishers/
twitter.py # Twitter/X via tweepy
threads.py # Threads via httpx (async)
blog.py # S3 upload via boto3License
Apache 2.0
Available Tools
3 toolspingB
Health check tool.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries full responsibility for behavioral disclosure. It only states that the tool performs a health check, but does not explain what it returns, whether it makes network calls, what success/failure looks like, or any side effects. This leaves the agent with incomplete expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: 'Health check tool.' It is front-loaded and contains no filler. While it could include a bit more context without harming conciseness, for a zero-parameter tool this brief phrase is appropriately sized and easy to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple health check tool with no parameters, the description provides the essential purpose, but it lacks details about expected output or behavior. The presence of an output schema helps, but the description alone does not tell the agent what a healthy or unhealthy result looks like. It is minimally adequate but not complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, and the schema is trivially fully covered. With no parameters, the baseline is 4, and there is nothing the description needs to add about parameter meaning. The description adds no parameter details, but none are required.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'Health check tool,' which clearly identifies the tool's function as a health/connectivity check. It is distinct from the sibling tools publish_post and preview_post, which involve different resources. The phrasing is a noun phrase rather than verb+resource, but it is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided about when to use this tool versus alternatives. The description does not mention contexts such as pre-flight checks, monitoring, or verifying service availability. The sibling tools are clearly different, but no explicit usage direction is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
preview_postA
Preview how content will be formatted for each platform.
Returns the formatted text and thread splits without actually publishing. Use this to verify formatting before calling publish_post.
| Name | Required | Description | Default |
|---|---|---|---|
| title | No | Post title (for blog preview) | |
| content | Yes | Markdown-formatted content to preview | |
| platforms | No | Platforms to preview for: 'twitter', 'threads', 'blog'. Defaults to all. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full responsibility for behavioral disclosure. It does well by stating the tool is non-publishing and returns formatted text plus thread splits. It could mention whether any changes or side effects occur, but 'without actually publishing' covers the most important behavioral trait.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loaded with the core purpose, and adds only relevant operational details. Every sentence contributes either the scope, return behavior, or when to use the tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists (context signal) and full parameter schema coverage, the description is largely complete. It explains the purpose, return content, non-publishing nature, and recommended usage. Minor gaps like platform-specific behavior details are covered by the output schema or are unnecessary for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all three parameters. The description adds context about content being markdown and platforms being selectable, but largely recaps what the schema states. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool's job: preview content formatting per platform. It explicitly contrasts with publishing via 'without actually publishing' and is distinct from sibling publish_post, making the tool's purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Direct usage guidance is provided: 'Use this to verify formatting before calling publish_post.' This explicitly names the alternative and the appropriate sequence, telling an agent when to choose this tool rather than publish_post.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
publish_postA
Publish Markdown content to social media and/or a static blog.
Formats content appropriately for each platform:
Twitter/X: Converts to plain text, auto-splits into threads at 280 chars
Threads: Converts to plain text, auto-splits into threads at 500 chars
Blog: Renders full HTML and uploads to S3
| Name | Required | Description | Default |
|---|---|---|---|
| slug | No | URL slug for blog post (e.g. 'my-first-post') | |
| title | No | Post title (used for blog HTML <title>) | |
| content | Yes | Markdown-formatted content to publish | |
| platforms | No | Platforms to publish to: 'twitter', 'threads', 'blog'. Defaults to all. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden and does disclose meaningful traits: plain-text conversion, character-based auto-threading for Twitter/X and Threads, and HTML rendering with S3 upload for blog. It does not mention error/auth/rollback behavior, but the main platform-specific behavior is transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loaded with the core action, and uses a scannable bullet list for platform-specific details. There is no filler or repetition of schema fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a multi-platform publish tool with an output schema present, the description covers the key transformations and destinations well. The main completeness gap is the absence of any explicit note about previewing alternatives or side effects such as irreversible public posting, though these are partly covered by other dimensions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, and the description adds real value beyond the schema by explaining the platform-specific consequences of the platforms parameter (280/500-char thread splitting, S3 upload). The slug and title parameters remain covered by schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb+resource ('Publish Markdown content to social media and/or a static blog') and then enumerates platform-specific output behaviors, so an agent immediately knows what the tool does. It does not explicitly name or contrast the sibling preview_post, but the publish-vs-preview distinction is clear from the wording.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given on when to use this tool versus the sibling preview_post, and there are no conditions, exclusions, or caveats about when publishing would be inappropriate. The usage context must be inferred entirely from the word 'publish.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
3 tool updates
v0.1.0- First observed
ping - First observed
preview_post - First observed
publish_post
TDQS
publish_post and preview_post are cleanly separated as actual publishing vs. dry-run preview, and ping is an obvious health check. No two tools overlap in purpose.
publish_post and preview_post follow a consistent verb_noun pattern, but ping breaks that pattern. The naming is still readable and predictable overall.
Three tools is a tight, well-scoped set: health check, preview, and publish. Each tool earns its place with no redundancy.
The preview-then-publish workflow covers the server's stated purpose well. Minor gaps like listing platforms or managing existing posts exist, but they fall outside the core publish/preview flow.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
FastMCP server for posting formatted content to X (Twitter) — Tollbooth-monetized, DPYC-native
Markdown-based note-taking with a hosted MCP server. Your notes serve you and your AI.
MCP server for QPost — lets AI agents publish video and image posts to YouTube, TikTok, Instagram.
Publish and share access-controlled Markdown documents from any MCP-enabled AI tool.
Related MCP Servers
- AlicenseBqualityDmaintenanceAn MCP server that allows Claude to create, manage and publish X/Twitter posts directly through the chat interface.561MIT
- AlicenseCqualityDmaintenanceAn MCP server that converts Markdown content to Notion API-compatible formats, suitable for content management and development integration.11Apache 2.0
- FlicenseNot gradedqualityNot gradedmaintenanceAn MCP server that repurposes text or URL content into platform-optimized posts for Twitter, LinkedIn, Instagram, and newsletters using AI. It enables users to automatically transform articles and blog posts into engagement-ready social media threads and professional captions.-
- AlicenseAqualityDmaintenanceMCP server for publishing threads to Threads and Twitter/X simultaneously from Claude Code. Journal your thoughts, convert them to viral threads, and post everywhere at once.13MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/nsmith/markpost'
If you have feedback or need assistance with the MCP directory API, please join our Discord server