Repliz MCP Server
Use this hosted MCP server to manage a Repliz social-media workspace through an AI assistant.
Connect and manage social accounts across Facebook, Instagram, Threads, TikTok, LinkedIn, YouTube, and more.
Read, reply to, update, and delete comments, and send DMs to commenters.
Create, update, retry, delete, and bulk-delete scheduled posts, including text, image, video, reel, album, link, and story posts.
Browse chats and messages, send text or media messages, and mark conversations as read.
Review published content, comments, and engagement statistics.
Research Threads posts, user content, and public profiles.
Use add-ons such as TikTok trending music, Shopee products, and link metadata previews.
Manage automations, templates, contacts, storage/uploads, reports, and account connections as part of the full 119-tool Repliz API surface.
Allows scheduling posts to Instagram and managing Instagram content, including listing, getting, and commenting on posts.
Allows searching products on Shopee.
Enables researching Threads content and user profiles, including search and retrieval of posts and user info.
Provides access to TikTok trending music data.
Click on "Deploy 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., "@Repliz MCP Server list my pending comments"
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.
Repliz MCP Server
A hosted Model Context Protocol server for the Repliz Public API. It gives an AI assistant 119 tools for managing a Repliz workspace in plain language: listing and replying to comments, scheduling posts, handling DMs, browsing content and stats, researching Threads, managing automations and templates, and more.
Users connect by pointing their MCP client at one URL — then either click "Connect" and sign in with their Repliz Access Key and Secret Key (OAuth), or send those keys as headers. There is nothing for them to install, build, or keep updated.
https://mcp.repliz.com/mcpThis repository is the server that serves that URL.
How it works
One process serves everyone. It holds no credentials of its own — each request carries the caller's keys, which are verified against the Repliz API and bound to that caller's session. A session owns its own API client, so no two users ever share one.
MCP client ──(URL + keys)──► this server ──(Basic auth)──► api.repliz.comUsers authenticate in one of three ways. Keys come from the Repliz dashboard under Settings > API.
OAuth — for Claude.ai, ChatGPT, and any client with a "Connect" button.
The user adds https://mcp.repliz.com/mcp as a connector, a sign-in page opens,
and they paste their keys there once. Enabled when REPLIZ_OAUTH_SECRET is set;
see OAuth.
Headers — for API integrations (the Anthropic Messages API, the OpenAI Responses API) and clients with custom-header support (Cursor and most desktop clients):
Authorization: Basic base64(accessKey:secretKey)X-Repliz-Access-Key: <accessKey>
X-Repliz-Secret-Key: <secretKey>Related MCP server: RecurPost MCP Server
Running it
Requires Node.js 18+ (Node 20.12+ to auto-load .env).
npm ci
npm run build
cp .env.example .env
npm startThe endpoint is POST/GET/DELETE /mcp, plus GET /health for monitoring.
With OAuth on, the server also answers /.well-known/oauth-protected-resource/mcp,
/.well-known/oauth-authorization-server, /register, /authorize, /token,
and /oauth/login (the sign-in form). Serve it over HTTPS in production, behind
a reverse proxy or platform TLS.
Configuration
Everything is optional; the defaults suit a 1 GB VPS.
Variable | Default | Description |
|
| Port to listen on |
|
| Repliz API base URL |
|
| Cap on concurrent sessions; beyond it new connects get |
|
| Close a session after this long without a request |
|
| Requests allowed per IP per minute |
|
| Which proxies may set |
|
| Timeout for outbound calls to the Repliz API |
|
| How long a verified credential pair is cached |
|
| Largest file |
| — | Browser origins allowed to call |
| R2 + Repliz storage | Hosts accepted as presigned-upload targets |
| — | Turns OAuth on; seals every token. At least 32 characters |
| — | Public origin, e.g. |
|
| Access token lifetime |
|
| How long an unused connection stays signed in |
There is deliberately no variable for the server's own Repliz credentials. A fallback like that would quietly lend the operator's workspace to any caller who omitted their keys.
OAuth
The Repliz API has no OAuth of its own, so this server acts as the authorization server and wraps the user's keys:
Claude.ai ──► /mcp: 401 ──► discovery ──► /register ──► /authorize (sign-in page)
◄── code ◄── keys checked against Repliz ◄── user pastes keys
──► /token (PKCE) ──► access + refresh token ──► /mcp with BearerTo turn it on, add two lines to .env and restart:
REPLIZ_PUBLIC_URL=https://mcp.repliz.com
REPLIZ_OAUTH_SECRET=<output of: openssl rand -base64 32>There is no token database. Every client id, authorization code, and token
is the user's keys (plus expiry and client binding) encrypted with AES-256-GCM
under REPLIZ_OAUTH_SECRET. Only this server can open them, they survive a
restart, and nothing new needs deploying or backing up. What follows from that:
Keep
REPLIZ_OAUTH_SECRETstable and private. Changing it signs every OAuth user out — which is also the emergency switch if it leaks.One token cannot be revoked early. Instead, access tokens live an hour; each tool call still presents the sealed keys to Repliz, so a key rotated in the Repliz dashboard stops working at once; and a refresh re-checks the keys, sending the client back to the sign-in page. No revocation endpoint is advertised, because it could only pretend.
Refreshing extends the connection. Each refresh issues a new refresh token, so a connection in regular use stays signed in; one left unused for
REPLIZ_OAUTH_REFRESH_TOKEN_DAYShas to sign in again.
Clients identify themselves in either of two ways, and need no setup on this side for either:
Client ID Metadata Documents (what Claude and ChatGPT prefer). The
client_idis an HTTPS URL, such ashttps://chatgpt.com/oauth/client.json, serving a JSON document that names the client and its redirect URIs. The server fetches it on first use and caches it as itsCache-Controlsays (between one minute and a day; an hour without the header). Only public clients are accepted: the document must allowtoken_endpoint_auth_methodnone, as both Claude's and ChatGPT's do.Dynamic Client Registration (RFC 7591), for everything else. The client id it hands out is the registration itself, sealed.
Accepted redirect URIs are any https:// URL, http:// on localhost only, and
a native app's own scheme such as cursor://. Every authorization response
carries the issuer (iss, RFC 9207), which ChatGPT needs to use its stable
redirect URI. Header authentication keeps working alongside OAuth.
PM2 + Nginx on a VPS
npm ci && npm run build
cp .env.example .env # PORT and the limits live here
pm2 start dist/index.js --name repliz-mcp
pm2 save && pm2 startup # survive a rebootDo not add -i / --instances. PM2's default fork mode is what you want.
Sessions live in this process's memory, so cluster mode would spread a user's
requests across workers that know nothing about each other, and every follow-up
request would be told its session does not exist. Scale by raising
REPLIZ_MAX_SESSIONS on a bigger box, not by adding instances.
Nginx needs two non-default settings, because the transport holds a Server-Sent Events stream open and Nginx would otherwise buffer it and cut it after 60 seconds:
location /mcp {
proxy_pass http://127.0.0.1:5301;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s; # keep above REPLIZ_SESSION_IDLE_MINUTES
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# OAuth discovery, sign-in, and token endpoints live at the root.
location / {
proxy_pass http://127.0.0.1:5301;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}$proxy_add_x_forwarded_for is correct here: the server trusts only loopback,
so it reads the rightmost untrusted entry and a client cannot forge its way into
a fresh rate-limit bucket. It matters even more with OAuth on: /register allows
20 registrations per IP per hour, and without X-Forwarded-For every user looks
like 127.0.0.1 and shares that one budget.
What a restart does
pm2 restart drops every live session — they exist only in this process's
memory. Nothing is queued or half-written, since every tool call is a single
synchronous call to the Repliz API, so the cost is small:
Mid-request | That one call fails; retrying works. |
Idle | The next request gets |
After reconnecting | Normal. One extra verification call, because the auth cache is empty again. |
OAuth users | Stay signed in. Their tokens are sealed, not stored, so they open again after a restart. |
Shutdown on SIGTERM closes sessions and stops listening in about 0.1s, well
inside PM2's default kill_timeout.
Sizing
The server is a thin proxy — every tool call is one outbound HTTPS request with no computation in between — so CPU is effectively idle and memory is the only thing to plan for. Measured:
Live sessions | Process RSS |
0 (baseline) | ~96 MB |
10 | ~103 MB |
100 | ~122 MB |
300 | ~173 MB |
1000 | ~356 MB |
That is roughly 0.26 MB per live session on top of a ~96 MB baseline. The 119 tool schemas are built once and shared by every session; only the MCP server object, the transport and the Repliz client — which holds that user's credentials — are per session. The default cap of 300 fits easily on a 1 GB VPS. Sessions are only live while a client is connected and idle ones are reclaimed after 30 minutes, so the steady-state number is far below the total user count.
GET /health reports live sessions, the cap, RSS, and uptime.
Security
Because /mcp is open to the internet:
Credentials are verified before a session exists. On
initializethe server callsGET /public/account/countwith the supplied keys and returns401if Repliz rejects them, so an anonymous caller cannot make the server allocate memory. Successes are cached briefly so reconnects stay cheap.Sessions are bound to the credentials that opened them. Every later request is re-checked against a fingerprint of those keys, in constant time. The session id travels as a plain header and can end up in a proxy access log or a client's debug output; without this check, replaying it would hand over the owner's workspace with no credentials at all. A mismatch gets
403, a request with no credentials gets401.Sessions expire and are capped. Idle sessions are swept, because MCP clients routinely disappear without sending
DELETE— the SDK's ownclient.close()does not send one. At capacity the server sweeps first, then evicts the least recently used session if it has been quiet for over a minute, so dead sessions cannot lock out real users; if every session is genuinely active, the new connect gets503rather than cutting someone off.Requests are rate limited per IP, counted against the address chosen by
REPLIZ_TRUST_PROXY.The OAuth sign-in page guards the keys typed into it. It cannot be framed (
frame-ancestors 'none',X-Frame-Options: DENY), so a clickjacking overlay cannot trick a user into submitting. Any client can register itself, so the page escapes the client's chosen name and states where the user will be sent next — a client calling itself "Claude" still cannot hide its own redirect host. The form carries the authorization request sealed, so its redirect target cannot be altered, and there is no session cookie for a cross-site request to ride. Sign-in attempts are limited to 10 per IP per minute, and PKCE (S256) is mandatory. For a client identified by a metadata document, the page also names the host that published it.Client metadata documents are fetched like untrusted URLs — because the
client_idis whatever the caller sends. The fetch refuses private and loopback addresses and redirects, times out after 5 seconds, and reads at most 5 KB. A document whoseclient_iddiffers from its URL, that carries a client secret, or that lists a disallowed redirect URI is refused, and nothing fetched is ever relayed back to the caller.Outbound calls time out, so a stalled Repliz request cannot pin a session.
Uploads never touch the host's disk. See File uploads.
Clean shutdown on
SIGTERM/SIGINT.
Two things to be aware of:
Credentials are verified when a session opens, not on every call. A revoked key keeps working until its session goes idle; shorten
REPLIZ_SESSION_IDLE_MINUTESif that matters.Sessions live in memory, so this is a single-instance server. Horizontal scaling needs a shared session store — see Roadmap.
File uploads
Uploading is three steps: repliz_init_file returns a one-time presigned URL,
repliz_upload_file sends the bytes, repliz_complete_file finalizes.
The middle step takes a sourceUrl, never a local path. This server is
shared, so its filesystem belongs to the operator: a path parameter would let
any connected user read the server's own files and ship them anywhere. Two
guards apply:
the presigned PUT target must be a Repliz storage host (
REPLIZ_UPLOAD_HOSTS)sourceUrlmust resolve to a public address — loopback, private LAN ranges, and cloud metadata endpoints such as169.254.169.254are refused, as are redirects
Clients that would rather not route media through the server can PUT straight
to the presigned URL themselves and then call repliz_complete_file.
Tools
119 tools across the Repliz Public API:
Group | Count | Tools |
Accounts | 6 | list, count, get, statistics, update automation, delete |
Account Connect | 42 | OAuth authorize / exchange / list / connect / reconnect for Facebook, Instagram, Threads, YouTube, LinkedIn, TikTok, Shopee, Twitter/X, Pinterest; QR session / connect / reconnect for WhatsApp; QR session / two-step password / connect / reconnect for Telegram |
Comments | 5 | list, get, reply, update status, delete |
Contacts | 10 | list, count, list tags, get, get by comment, get by chat, update, set follow-up, remove follow-up, delete |
Schedule | 7 | list, get, create, update, retry, delete, bulk delete |
Chat | 5 | list, get, list messages, send message, mark read |
Content | 9 | list, get, list comments, comment, statistics, DM commenter, like comment, delete comment, delete content |
Automation | 5 | list, get, create, update, delete |
Templates | 5 | list, get, create, update, delete |
Storage | 8 | statistics, list, get, init upload, upload, complete, delete, bulk delete |
Reports | 3 | list, get, retry |
Research | 3 | Threads content, user content, user profile |
Add-ons | 11 | TikTok trending music, Shopee products, WhatsApp and Telegram channels & groups, Pinterest boards (list, create, update, delete), Instagram profile (follow check), link metadata, addon allocation |
Tool availability follows the caller's Repliz plan; calling one above your tier returns a clear error.
Every tool declares what it does, as MCP tool annotations: 53 only read
(readOnlyHint), 45 create or send something without touching what exists
(destructiveHint: false), and 21 change or delete (destructiveHint: true).
Clients use these to decide what to confirm first; ChatGPT asks before any tool
not marked read-only. A new tool must state its effect to compile.
Development
npm run dev # run from TypeScript source, no build step
npm test # unit tests (no network, no credentials)
npm run smoke # end-to-end: boots the real server against a stub Repliz API
npm run build # compile to dist/npm test covers the parts where a quiet mistake becomes a security hole: the
SSRF and upload-host guards, credential parsing, the session credential binding,
the limits that bound memory, and OAuth token sealing, single-use codes, and
client binding. npm run smoke covers the wiring — that two users stay apart,
that a session id alone opens nothing, that the full OAuth flow works over HTTP,
and that the upload guards are reachable through the tool surface. Neither needs
credentials or network access, and CI runs both.
src/
index.ts # entry point: load .env, start the server
http.ts # the HTTP transport, auth, and request lifecycle
session.ts # session store, credential fingerprints, rate limiter, auth cache
server.ts # createReplizServer(client)
config.ts # env config + per-request credential parsing
client.ts # Repliz API client (Basic auth, timeouts, errors)
oauth.ts # OAuth provider: sealed clients, codes, and tokens
oauth-page.ts # the sign-in page and its security headers
net.ts # upload-host allowlist and SSRF guards
tools/ # one module per API domain, registered via tools/index.ts
test/ # unit tests for config, session, oauth, and net
scripts/
smoke-test.mjs # end-to-end check against a stub API
api.json # the source OpenAPI spec, kept as referenceRoadmap
Shared session store (Redis) so several replicas can run behind a load balancer without sticky sessions.
License
MIT — see LICENSE.
Available Tools
33 toolsrepliz_count_accountsCount AccountsA
Get the total number of accounts connected to your Repliz workspace.
Inputs: no named parameters.
repliz_create_content_commentComment on ContentC
Post a comment on a piece of content, or reply to an existing comment by passing commentId.
Inputs: text (required), accountId (required), contentId (required), commentId.
repliz_create_scheduleCreate Scheduled PostA
Schedule a post to be published to a connected account at a specific time.
Post type support by platform:
text: Facebook, Threads
image: Facebook, Instagram, Threads, TikTok, LinkedIn
video: Facebook, Instagram, Threads, TikTok, YouTube, LinkedIn
reel: Facebook
album: Facebook, Instagram, Threads, TikTok, LinkedIn
link: Facebook (provide
metafor the link preview)story: Facebook, Instagram
For media posts, attach medias. For threaded/multi-part posts, attach replies. scheduleAt must be a future ISO 8601 timestamp (UTC).
Inputs: type (required), accountId (required), scheduleAt (required), description (required), +7 more.
repliz_delete_accountDelete AccountA
Disconnect and remove an account from your Repliz workspace. This is irreversible — confirm with the user before calling.
Inputs: accountId (required).
repliz_delete_content_commentDelete Content CommentA
Delete a comment on a piece of content. Irreversible — confirm before calling.
Inputs: accountId (required), commentId (required), contentId (required).
repliz_delete_scheduleDelete Scheduled PostA
Delete a single scheduled post by id. Irreversible — confirm before calling.
Inputs: scheduleId (required).
repliz_delete_schedulesDelete Multiple Scheduled PostsA
Delete several scheduled posts at once by their ids. Irreversible — confirm before calling.
Inputs: scheduleIds (required).
repliz_get_accountGet AccountA
Get details of a single connected account by its Repliz account id.
Inputs: accountId (required).
repliz_get_chatGet ChatB
Get the details of a single conversation by its chat id.
Inputs: chatId (required).
repliz_get_commentGet CommentB
Get the full details of a single comment by its id.
Inputs: commentId (required).
repliz_get_contentGet ContentB
Get the details of a single piece of content.
Inputs: accountId (required), contentId (required).
repliz_get_content_commentsGet Content CommentsA
List comments on a piece of content. Pass commentId to fetch replies to a specific comment. Uses cursor pagination via nextToken.
Inputs: accountId (required), contentId (required), commentId, nextToken.
repliz_get_content_statisticGet Content StatisticsC
Get engagement statistics/insights for a piece of content.
Inputs: accountId (required), contentId (required).
repliz_get_scheduleGet Scheduled PostB
Get the full details of a single scheduled post by its id.
Inputs: scheduleId (required).
repliz_link_metadataGet Link MetadataA
Fetch Open Graph / link-preview metadata (title, description, image) for a URL. Useful for building the meta field of a 'link' post.
Inputs: url (required).
repliz_list_accountsList AccountsA
List the social accounts connected to your Repliz workspace. Returns each account's id, platform, username, picture, and status. Supports pagination and filtering by platform type or search term.
Inputs: page, limit, types, search.
repliz_list_chatsList ChatsA
List direct-message conversations across connected accounts. Supports pagination and filtering by status (unread/unreplied), account(s), and search.
Inputs: page, limit, search, status, +1 more.
repliz_list_commentsList CommentsA
List comments in your Repliz inbox across connected accounts. Supports pagination and filtering by status, account(s), and search term.
Inputs: page, limit, search, status, +1 more.
repliz_list_contentList ContentA
List published content (posts/media or stories) for a connected account. Uses cursor pagination via nextToken.
Inputs: accountId (required), type, nextToken.
repliz_list_messagesList Chat MessagesA
List the messages within a conversation, paginated (newest first).
Inputs: chatId (required), page, limit.
repliz_list_schedulesList Scheduled PostsA
List scheduled and published posts. Supports pagination and filtering by account(s), status, and date range.
Inputs: page, limit, status, toDate, +2 more.
repliz_message_content_commentSend DM to Content CommenterB
Send a private message (DM) to the author of a comment on your content. Provide text and/or a button payload.
Inputs: accountId (required), commentId (required), contentId (required), text, +1 more.
repliz_read_chatMark Chat as ReadB
Mark a conversation as read.
Inputs: chatId (required).
repliz_reply_commentReply to CommentB
Post a public reply to a comment. The reply is published to the original platform (Facebook, Instagram, etc.).
Inputs: text (required), commentId (required).
repliz_retry_scheduleRetry Scheduled PostB
Retry publishing a scheduled post that previously failed (status 'error').
Inputs: scheduleId (required).
repliz_search_threads_contentSearch Threads ContentA
Search public Threads posts by keyword. Requires a connected Threads account id (used to authorize the search). Uses cursor pagination via nextToken.
Inputs: search (required), accountId (required), nextToken.
repliz_search_threads_userGet Threads User ProfileB
Look up the public profile of a Threads user by username. Requires a connected Threads account id.
Inputs: username (required), accountId (required).
repliz_search_threads_user_contentGet Threads User ContentA
Fetch public Threads posts authored by a specific username. Requires a connected Threads account id. Uses cursor pagination via nextToken.
Inputs: username (required), accountId (required), nextToken.
repliz_send_messageSend Chat MessageB
Send a message in a conversation. Set type and provide the matching field:
text: provide
textimage: provide
image{ url, mimetype, thumbnail? }video: provide
video{ url, duration, mimetype, thumbnail? }audio: provide
audio{ url, duration, mimetype }document: provide
document{ url, name, size, mimetype }button: provide
button{ text, buttons:{ title, url }, image? }
Inputs: type (required), chatId (required), text, audio, +4 more.
repliz_shopee_productsList Shopee ProductsA
List Shopee products for a connected Shopee account. Useful for tagging products on posts. Uses cursor pagination via nextToken.
Inputs: accountId (required), nextToken.
repliz_tiktok_trending_musicTikTok Trending MusicA
Get trending TikTok music for a given genre, country, and time window. Useful for picking a music track when scheduling a TikTok post.
Inputs: countryCode (required), genre, dateRange.
repliz_update_comment_statusUpdate Comment StatusA
Update the handling status of a comment in your Repliz inbox (pending, resolved, or ignored).
Inputs: status (required), commentId (required).
repliz_update_scheduleUpdate Scheduled PostA
Update an existing scheduled post. The account cannot be changed; provide the new content fields. scheduleAt must be a future ISO 8601 timestamp.
Inputs: type (required), scheduleAt (required), scheduleId (required), description (required), +7 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 33 tools
Each tool targets a distinct resource and action (e.g., get_comment vs get_content_comments, list_chats vs get_chat). Descriptions clearly differentiate similar-sounding tools, leaving no ambiguity.
All tools follow a consistent 'repliz_verb_noun' pattern with lowercase and underscores. Actions like create, get, list, delete, update are used uniformly across resources.
33 tools is slightly high but appropriate for a comprehensive social media management server covering accounts, scheduling, content, comments, messaging, and search. Each tool has a clear purpose.
The tool set covers major workflows: account management, scheduling (CRUD + retry), content/comments, messaging, and platform-specific searches. Minor gaps like immediate publishing (vs scheduling) exist but are not critical.
Related MCP Connectors
Draft, schedule, and publish social posts for your workspace straight from your AI.
Let AI agents draft, schedule and publish posts to 17 social platforms, read analytics and reply.
Draft, schedule and publish social media posts from your AI assistant.
Draft, schedule and publish social media posts from AI agents, under workspace approval rules.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceManage Threads and Bluesky social media from AI assistants. Schedule posts, check analytics, and automate follow-up replies.3MIT
- AlicenseAqualityBmaintenanceProvides AI assistants with access to the RecurPost API to manage social media accounts, schedule posts, and organize content libraries. It enables users to automate recurring posts, track engagement metrics, and generate social media content through natural language.1015 npm1MIT
- AlicenseAqualityDmaintenanceEnables AI assistants to manage social media accounts and CRM operations, including posting, analytics, inbox management, and customer management.2214 PyPIApache 2.0

PostMCP MCP Serverofficial
AlicenseAqualityBmaintenanceEnables AI assistants to manage social media publishing across platforms like LinkedIn, Twitter, Facebook, Instagram, Threads, and Bluesky.748 npmMIT