@planifyapps/mcp
Model Context Protocol server for Planify. Lets an AI assistant schedule and publish social posts — Twitter/X, Facebook, Instagram, Bluesky, Pinterest, Threads, LinkedIn, Mastodon, YouTube — on your behalf.
Setup
You need a Planify API key. Create one in the dashboard under Settings → API. It is shown once.
Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"planify": {
"command": "npx",
"args": ["-y", "@planifyapps/mcp"],
"env": { "PLANIFY_API_KEY": "plfy_live_..." }
}
}
}
Claude Code
claude mcp add planify --env PLANIFY_API_KEY=plfy_live_... -- npx -y @planifyapps/mcp
Anything else that speaks MCP
Run npx -y @planifyapps/mcp with PLANIFY_API_KEY in the environment. It communicates over stdio.
Tools
planify_me | Plan, scopes the key holds, quota remaining |
planify_list_channels | Connected accounts and their channel ids |
planify_channel_settings | Read this before writing a post — character limit, media rules, settings schema, available lookups |
planify_channel_trigger | Fetch values you can't guess (Pinterest boards, Twitter communities) |
planify_next_slot | Next free slot from the user's own weekly schedule |
planify_upload_media_from_url | Hand over a URL; Planify downloads it |
planify_create_post | Create a draft, schedule it, or publish now |
Why it's shaped this way
The obvious design is one post_to_social tool. That fails, because every platform has different rules — 280 characters on Twitter, media required on Instagram, an unguessable board id on Pinterest — and a single tool either ignores them or restates them in a description that goes stale.
So these tools mirror the API's own discovery path. planify_channel_settings returns the real limits, prose rules, and a JSON Schema for that specific channel, generated server-side from the types the publishing code actually reads. The assistant is told the constraints before it writes, instead of learning them by being rejected.
Publishing safety
planify_create_post defaults to a draft.
Publishing immediately requires all three of:
type: "now" — never the default
- a key holding the
posts:publish scope — not granted by default
- your confirmation — the server's instructions tell the assistant to ask
Publishing is irreversible and public. An assistant acting on a misread instruction should not be one call away from a bad post on a real audience. If you want an assistant that can never publish, create a key without posts:publish — everything else still works, and it can prepare drafts for you to approve.
Configuration
PLANIFY_API_KEY | — | Required. From Settings → API. |
PLANIFY_API_URL | https://planifyapps.com/api/v1 | Override for self-hosted or staging. |
Without a key the server still starts and every tool explains what's missing rather than failing opaquely.
Releasing
Two places have to move together. The registry lists metadata only — it fetches the
npm package and checks that its package.json carries an mcpName matching the
name in server.json. Publish to the registry before npm and it fails validation.
Bump the version in three places (package.json, VERSION in src/index.ts, and
both version fields in server.json), then:
npm publish --access public
mcp-publisher login http --domain planifyapps.com \
--private-key "$(openssl pkey -in .mcp-registry-key.pem -noout -text | grep -A3 'priv:' | tail -n +2 | tr -d ' :\n')"
mcp-publisher publish
Domain authentication is what lets the server be named com.planifyapps/planify
rather than sitting under a personal GitHub namespace. The proof is the public key
at /.well-known/mcp-registry-auth, served from public/ in the web app; the
matching private key is .mcp-registry-key.pem, gitignored and kept out of the
repo. Lose it and you regenerate the pair and redeploy the proof file.
Links
License
MIT