MCP server
Connect Claude and other AI assistants to the full PostZen API through the Model Context Protocol.
The PostZen MCP server connects AI assistants to the full PostZen API through the Model Context Protocol (MCP). Once connected, an assistant like Claude can create and schedule posts, manage profiles, and connect accounts across all 9 supported platforms — all from natural language, without you leaving the conversation.
The server is hosted at https://mcp.postzen.dev/mcp — there is nothing to install or run locally. Its tools are generated from the same OpenAPI spec that powers the API reference, so they stay in sync with the API. It works with claude.ai, Claude Desktop, Claude Code, Cursor, and any MCP client that supports remote servers.
Use PostZen in your AI client
Point your client at the server URL:
https://mcp.postzen.dev/mcpThis is a remote server that speaks Streamable HTTP. Interactive clients can sign in with OAuth — no key to paste. Headless clients can send a PostZen API key in an Authorization header instead. Setup differs slightly per client.
In claude.ai or Claude Desktop, open Settings → Connectors → Add custom connector, set the URL to https://mcp.postzen.dev/mcp, and click Connect. You'll be sent to the PostZen dashboard to approve access, then bounced back automatically. No API key required — see Authentication for what the consent screen offers.
Add the server, then authenticate from a session:
claude mcp add --transport http postzen https://mcp.postzen.dev/mcp
# then, in a session:
/mcp # select "postzen" -> AuthenticateTo skip OAuth and use a PostZen API key directly, pass it as a header when adding the server:
claude mcp add --transport http postzen https://mcp.postzen.dev/mcp \
--header "Authorization: Bearer pzn_live_..."Add PostZen to your .cursor/mcp.json. Cursor connects over remote HTTP, so pass your PostZen API key in an Authorization header:
{
"mcpServers": {
"postzen": {
"url": "https://mcp.postzen.dev/mcp",
"headers": {
"Authorization": "Bearer pzn_live_..."
}
}
}
}Any MCP client that supports remote servers can connect. Point it at https://mcp.postzen.dev/mcp and either run the OAuth flow (if the client supports it) or send a PostZen API key as an Authorization: Bearer pzn_live_... header. Legacy clients that only speak Server-Sent Events can use https://mcp.postzen.dev/sse instead.
After changing MCP configuration, restart or reload your client so it reconnects to the server and picks up the tools.
What you can do
Once connected, you can ask your assistant to work with PostZen in plain language. The examples below map onto the real tools the server exposes:
- "Post 'Shipping day 🚀' to my X account right now."
- "Schedule this to LinkedIn tomorrow at 9am."
- "List the social accounts I have connected."
- "Cross-post this announcement to X, LinkedIn, and Instagram at the same time."
- "Attach this image URL to the post and publish it."
- "Create a new profile called 'Acme Marketing' for this client."
- "Give me a link to connect a new Instagram account."
- "Save this as a draft so I can finish the wording later."
Authentication
The server accepts two ways to authenticate. Interactive clients should use OAuth; scripts and headless clients should send an API key.
OAuth (interactive clients)
When a client such as Claude connects without a key, the server runs an OAuth 2.1 flow. The client sends you to a PostZen consent screen at app.postzen.dev/connect/mcp, where you approve access while signed in to your account. On the consent screen you choose:
- Permission — Read Only (the default) or Read & Write. Creating or scheduling posts, connecting accounts, and uploading media all require Read & Write; a Read Only connection can only fetch data.
- Profile access — full access to all profiles (the default), or a specific set of profiles you select.
Approving mints a PostZen API key named MCP: <client name> that the connection uses from then on. You can revoke it at any time from the API Keys page. The pending consent request expires after 10 minutes, so complete the approval promptly.
API key (automation)
For scripts and headless clients, create a key on the API Keys page and send it directly, skipping OAuth. A key looks like pzn_live_ followed by 64 hexadecimal characters and is passed as an Authorization: Bearer pzn_live_... header. A token starting with pzn_ is recognized verbatim and bypasses the OAuth flow.
Choose Read & Write when creating the key if the assistant needs to publish posts, connect accounts, or upload media. Read Only is enough for listing profiles, accounts, and other fetch-only work.
Your API key is shown only once at creation — PostZen stores only a SHA-256 hash and can never recover it. Treat it like a password: keep it in a secret manager or environment variable, never commit it to source control, and never expose it client-side. If you lose it, create a new one and revoke the old.
Available tools
The server exposes 12 tools — 11 generated from the PostZen OpenAPI spec, plus one custom verifyApiKey tool. They are grouped by API area below.
Profiles
| Tool | Description |
|---|---|
listProfiles | List the profiles the key can access. |
createProfile | Create a profile (name required, 1–80 chars; optional description, color). |
getProfile | Fetch a single profile by id. |
updateProfile | Update a profile's name, description, color, or default flag. |
deleteProfile | Delete a profile (the default profile can't be deleted; disconnect its accounts first). |
Accounts
| Tool | Description |
|---|---|
listAccounts | List connected social accounts, with optional filters and pagination. |
disconnectAccount | Disconnect an account; cancels its pending scheduled targets. |
Connect
| Tool | Description |
|---|---|
createConnectUrl | Start an OAuth flow and return a URL to connect a new account. |
completeConnect | Exchange an OAuth code and finish connecting an account. |
Media & posts
| Tool | Description |
|---|---|
createMediaPresign | Get a presigned URL for uploading an image, video, GIF, or PDF. |
createPost | Create a draft, scheduled, or immediate post across one or more platforms. |
Utility
| Tool | Description |
|---|---|
verifyApiKey | Check that the connection's key works; returns how many profiles it can access. |
Because the generated tools come from the OpenAPI spec, their inputs match the corresponding API endpoints exactly. See the API reference for the underlying request and response shapes.
Tool reference
createPost
Creates a draft, a scheduled post, or an immediate post across one or more platforms.
| Field | Type | Notes |
|---|---|---|
content | string | Shared post text. Defaults to "". Each platform's own validation still applies. |
title | string | Internal title. YouTube uses it as the fallback video title. |
mediaItems | array | Up to 10 items of { url, title? }. url is a PostZen publicUrl or an external image/video URL (see Working with media). title is optional alt text. |
platforms | array | Targets of { platform, accountId, customContent?, settings? }. accountId is required; customContent overrides content for that target; settings holds platform-specific options. |
publishNow | boolean | Publish immediately. |
scheduledFor | string | ISO-8601 timestamp, at least 60 seconds in the future. |
isDraft | boolean | Save as a draft. platforms is optional for drafts. |
timezone | string | Metadata stored on the post. Defaults to "UTC". |
tags | string[] | Optional tags. |
Set exactly one of publishNow, scheduledFor, or isDraft. Use isDraft to capture content now and choose targets later, scheduledFor to publish at a future time, and publishNow to publish immediately. Setting none — or combining publishNow with either of the others — returns a 400.
Pass an x-request-id value to make a create idempotent: repeating the same value returns the original post instead of creating a duplicate.
settings is a per-platform object; unknown keys are ignored. Highlights by platform: Instagram — postType (feed, story, reel, carousel), collaborators, userTags, firstComment; TikTok — privacyLevel, and duet/stitch/comment toggles; YouTube — title, privacyStatus, tags, categoryId, madeForKids; LinkedIn — visibility (PUBLIC or CONNECTIONS); X — replySettings; Threads — replyControl; Facebook — link, firstComment; Pinterest — boardId, title, link, altText; Bluesky — no extra settings; links, @mentions, and #hashtags become clickable rich-text facets automatically; Telegram — parseMode (html or markdownv2; plain text by default), disableNotification, disableLinkPreview, protectContent.
createMediaPresign
Returns a presigned URL for uploading a file to PostZen-hosted storage.
| Field | Type | Notes |
|---|---|---|
filename | string | Required. Original file name; PostZen sanitizes it. |
contentType | enum | Required. One of the supported image, video, or PDF MIME types (jpeg/jpg/png/webp/gif, mp4/mpeg/quicktime/avi/webm/m4v, or PDF). |
size | integer | Optional. File size in bytes, up to 5368709120 (5 GB). |
profileId | string | Optional profile scope. |
The response includes an uploadUrl (where you PUT the raw bytes) and a publicUrl (which you reference in mediaItems). This tool requires a Read & Write key.
listAccounts
Lists connected social accounts available to the key.
| Field | Type | Notes |
|---|---|---|
profileId | string | Filter to a profile. |
platform | enum | Filter to a platform. |
status | enum | connected for healthy accounts, disconnected for accounts needing reconnection. |
page | integer | 1-based page number. Must be paired with limit. |
limit | integer | Page size, 1–100. Must be paired with page. |
createConnectUrl
Starts an OAuth flow to connect a new social account and returns a URL to redirect to.
| Field | Type | Notes |
|---|---|---|
platform | enum | Required. Platform to connect. |
profileId | string | Required. Profile to attach the account to. |
redirectUrl | string | Optional URL PostZen sends the user to after connecting. |
The returned OAuth state expires after 10 minutes, so start the connection promptly.
Supported platforms
The platform value (used in createPost, listAccounts, and createConnectUrl) is one of:
| Platform | Value |
|---|---|
| X | x (or twitter) |
instagram | |
| TikTok | tiktok |
linkedin | |
facebook | |
| YouTube | youtube |
| Threads | threads |
pinterest | |
| Bluesky | bluesky |
| Telegram | telegram |
twitter is accepted as an alias for x. In responses, the platform is normalized to twitter.
Working with media
There are two ways to attach an image or video to a post.
External URL — simplest. Pass a publicly reachable image or video URL directly in mediaItems. PostZen downloads and re-hosts it. External items must resolve to an image or video (PDF is not supported) of at most 100 MB.
Presigned upload — programmatic. Call createMediaPresign to get an uploadUrl and publicUrl, HTTP PUT the raw file bytes to uploadUrl, then reference the publicUrl in mediaItems. Presigned uploads accept jpeg/jpg/png/webp/gif images, mp4/mpeg/quicktime/avi/webm/m4v video, and PDF, up to 5 GB.
You can attach up to 10 media items per post. For AI-assistant use, passing an external URL is usually the easiest path since it needs no separate upload step.
Example conversations
You: Post "We just shipped MCP support 🎉" to my X account right now.
Assistant: Done — published to your X account (@acme). Post ID
jh72r5nqk9wx3v8m1t4cz6bs0fy5dg3e.
You: Schedule that same announcement to LinkedIn for tomorrow at 9am.
Assistant: Scheduled for 2026-07-04 09:00 UTC on your LinkedIn account. Post ID
kp83s6mrl0xy4w9n2u5da7ct1gz6eh4f. Want me to add an image?
You: What accounts do I have connected?
Assistant: You have 2 connected accounts: X (@acme, connected) and LinkedIn (Acme Inc, connected).
Troubleshooting
- Invalid API key. The key is wrong, revoked, or missing. Confirm it on the API Keys page, or run the
verifyApiKeytool to check the connection. Create a new key if needed. - OAuth consent expired. The consent request is only valid for 10 minutes. If approval times out or the connection stops working, remove and re-add the connector (or re-run
/mcp→ Authenticate in Claude Code) to start a fresh consent flow. - "No accounts connected." Connect an account at app.postzen.dev, or ask the assistant to create a connect URL with
createConnectUrland open it to authorize the account. - Can't connect a third (or X) account. The Free plan includes 2 connected accounts and does not allow extras, so connecting a third returns a
402. Connecting an X account requires a payment method on file. Upgrade or add a card on the dashboard as the error directs. - Tools don't appear after a config change. Restart or reload your MCP client so it reconnects and re-reads the tool list.