Mmcp.market

Is uplika MCP server safe?

Probably. Read the findings first.

C57/100grade C

Use with care. Some checks failed or could not be verified.

What to know before installing
  • highWrite-action tools reachable without authentication

Public scan report

scanner v0.1.9 · 2026-09-23 · same rubric, same numbers if you re-run it

1 high2 low
  • Code scanremote-only server, no package to scann/a
  • Live reliabilityremote reachable in 1967ms20/20
  • Tool poisoning54 tool descriptions checked13/15
  • Auth qualityopen endpoint exposes 18 write-action tools with no auth3/15
  • Maintenanceno repository listed3/15
  • Maintainer identityverified namespace with website, no repo4/10

Findings (3)

  • highWrite-action tools reachable without authenticationauth.open-write
  • lowUnusually long tool description (over 2,000 characters)poison.long-description
    tool publish: …Post to social channels. Channels open today: threads, instagram, youtube, facebook, bluesky, telegram, naver_blog, tiktok. Get accountIds from select_channels — do not guess which channel the person meant. Naver Blog caps how many posts one ID publishes; when it does, this returns 429 naver_rate_limited with retryAfterSeconds. Do not call again before that, the draft is already in Naver. Naver Blog asks which form to publish with, every post: if options.naver_blog.form is missing this returns 400 naver_form_required with forms (id, name, when). The form is the house style to use when the person has no style of their own, so read the conversation first. If they dictated the structure or you laid it out yourself, pass options.naver_blog.layout: "as-is" and the markdown goes out unchanged. Otherwise show them the forms (naver_layout with forms: "all" lays every one out side by side) and call again with the one they pick. Do not pick for them. Naver Blog goes out through the user's browser extension. If the response carries a bridge object, read bridge.state: offline means that Chrome is closed and the post is queued (up to 7 days); logged_out means Chrome is on but not logged in to Naver. Either way relay bridge.userMessage to the person word for word, do not say it was published, and know that delete_post cancels a queued post and update_post rewrites it before it goes out. If the extension in that Chrome is too old for what you asked (update_post), this returns 422 extension_outdated with the installed and required versions; ask the person to update the extension. Text limits differ per channel: Threads 500 characters, Instagram 2200 characters, YouTube 5000 UTF-8 bytes, Facebook 63206 characters, Bluesky 300 graphemes and 3000 UTF-8 bytes, Telegram 4096 characters (1024 with media attached), Naver Blog 30000 characters, TikTok 2200 characters. Over the limit nothing goes out to any channel, so shorten it before calling. Images and video both work on the channels that take them. How several items sit in one post differs per channel: Threads groups up to 20 items in one post, Instagram groups up to 10 items in one post, YouTube takes 1 video and no images, Facebook groups up to 10 items in one post, Bluesky has no carousel and places up to 4 images in the post itself, Telegram groups up to 10 items in one post, Naver Blog has no carousel and places up to 40 images in the post itself, TikTok groups up to 35 items in one post. More than a channel takes is not refused: the first items up to its limit go out and that target's warning says what was left out. A channel that cannot mix images and video keeps the video. YouTube is different: it takes exactly one video, no images, and it needs options.youtube.title. Its description is measured in UTF-8 bytes, so Korean and Japanese cost three per character. Instagram cannot publish text alone: every post needs at least one image or video. A single video becomes a reel there. Set options.instagram.contentType to story for a story; stories show no caption. Non-JPEG images are converted for Instagram automatically. Facebook publishes to a Page, never a personal profile. options.facebook.link makes a link post (no media alongside), and a single video becomes a reel (3-90 seconds). Bluesky counts graphemes, not characters, and also caps UTF-8 bytes, so a post of 300 emoji can fail on the byte limit. Set options.bluesky.langs to the language of the text (1-3 BCP-47 codes like ["ko"]): without it the post never appears in language-scoped feeds, and Bluesky has no post editing to fix it later. Links, @mentions and #hashtags in the text are made clickable for you, and a link gets a preview card, so write the URL plainly. There are three ways to get a media id, pick by where the file is: media_from_url when it already has a public https address, media_upload_link when it is on the person's own device, media_presign plus media_complete when you can PUT the bytes yourself. Then pass the media ids here. On Naver Blog the body can also place media itself with ![alt](media:<id>) and @video(media:<id>), each on a line of its own. Ids you reference that way are picked up even if you leave them out of mediaIds, and media you pass but never reference goes at the end of the post. Those references only work when every target is Naver Blog: other channels would publish the markup as literal text, so we refuse instead. This publishes immediately unless you pass scheduledAt (we hold the post and send it at that time, on every channel) or draft: true (nothing goes out; the person or update_post finishes it later). scheduledAt needs a timezone offset, 10 minutes to a year out; ask the person which timezone they mean instead of guessing. A scheduled or draft post comes back with status scheduled or draft, can be changed with update_post, sent early with publish_now, and dropped with delete_post. Every channel also takes options.<channel>.content to send that channel a different text than the shared content, which is how Naver Blog Markdown and a 500-character Threads post fit in one call. On YouTube we pass privacyStatus through as you set it and report back what YouTube actually applied, so read the warning on the result instead of promising the person a visibility we did not confirm. Returns while the post is still publishing. The permalink is null at that moment. Call get_post with the returned id to see the final status and link. Pass wait: true to hold the response until it is really out — then you can tell the person it is posted instead of guessing. For a long post use threadItems instead of publish-then-reply: we keep the order and wait for each piece to land before sending the next one.…
  • lowNo source repository listedmaint.no-repo
Overall 57/100. Components that don't apply are left out of the denominator. Any critical finding is an F.RubricAppeal a findingJSON

Other servers that do what uplika does

  • Socialclaw
    Connect any AI agent to 11+ social platforms: schedule, publish & track posts via hosted MCP.
    A
  • Agent-Native Chat
    Minimal chat-first app with durable threads, actions, and the app-agent loop
    A
  • Godot MCP
    Agent-driven Godot playtesting: editor control, input injection, game-time stepping, live state.
    A

uplika reviews, tools and install