Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

io.github.rodvan/viralhunt-mcp

NPM · VIRALHUNT-MCP

Trending content on 12 networks, best time, hashtags, templates, drafts and review, publish to 11.

Available components

−1 this week 73 Trust /100

Last scanned (21 hours ago)

Scores higher than 45% of npm servers

Category Marketing and SEO

Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →

Supply Chain Security81
  • No malware found by supply-chain analysis.Pass
  • CVE check failed: a known high-severity CVE affects zod 3.25.76, a direct dependency. A fixed version is available. View diagnostics → Fail
  • No install/post-install scripts declared.Pass
  • 30 of 93 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency45
Schema Quality & AI Usability59
  • AI-judged instruction clarity (good).Pass
  • Context-footprint check failed: tool/resource definitions use about 10795 tokens (~220/item across 49 items; 49 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management93
  • Stability observed for 28 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage90
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 71% of tool parameters carry a description.Partial
Tool Safety75
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • 0 of 1 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "viralhunt_delete_post" implies "delete" and declares no destructiveHint at all, which the MCP spec reads as destructive by default. See how to fix → Fail
  • An AI judge read all 49 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 4 Nov 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 90 to 93. That category is still filling its 30-day observation window: 27 days of observed history at the previous scan, 28 at this one. The score rises as the window fills, whether or not the server changes.

  • 3 Nov 26 −2
    • Stability: pass → 0.90 functional
  • 31 Oct 26 0
    • Security disclosure: unverified → fail ▼ functional
  • 29 Oct 26 0
    • Security disclosure: fail → unverified ▼ functional
  • 27 Oct 26 0
    • Package version: 0.1.2 → 1.1.27 functional
  • 25 Oct 26 +1
    • Stability: 0.97 → pass security
  • 24 Oct 26 +9
    • CVE-2023-54404 affects this package: high ▼ security
    • Known CVEs: pass → fail ▼ security
    • Malware scan: unverified → pass ▲ security
    • Stability: pass → 0.97 functional
  • 23 Oct 26 −15
    • Malware scan: pass → unverified ▼ security
    • Package version: 1.1.25 → 1.1.27 functional
Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 4 Nov 2026 · Analysed npm/viralhunt-mcp@1.1.27

Provenance No attestation

The registry publishes no build provenance for this version, so there is nothing to verify.

Result No attestation
Ecosystem npm

Background: How many MCP packages publish verified provenance →

Vulnerabilities 1 finding
ID CVE Severity Vector Fix available
GHSA-mrhx-c7xc-m3w5 CVE-2023-54404 high CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H yes

Background: What a vulnerability scan can and cannot prove →

Dependencies 93 packages
Packages resolved 93
Stale 30
Tree resolution Complete

Background: SBOMs and build attestations, explained →

MCP tools · 49 exposed · ~10,795 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
viralhunt_account ~109

Who this key is: plan (free/creator/studio/agency), requests per hour, whether it can publish, today's daily content-query quota (free plan: 24 shared across trending, search, best-time, hashtags, sounds, communities), credits balance, and per-endpoint rules. Call it once at the start and again on a 429 or 402, and set expectations from it (free plan: trending is 72h delayed and numbers are withheld, never print 0).

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

viralhunt_approve_draft ~98

Send a draft (owner or admin token only, and never without the user's explicit yes). A draft blocked by its last review cannot be approved until it is fixed and reviewed again. `translations` makes the translated draft in each linked project in the same call (see viralhunt_translate_post). Returns {status, results, warnings, translations[]}.

NameTypeReqDescription
idintegeryesThe draft id.
translationsarray––

No output schema declared.

No examples provided.

viralhunt_archive_card ~42

Take a card off the board (archive). Nothing is deleted: a person restores it from the board's Archived view.

NameTypeReqDescription
card_idintegeryes–

No output schema declared.

No examples provided.

viralhunt_assign_card ~82

Hand a card to a member (id, name as the Team page shows it, or email); null unassigns. The member is notified. The answer carries the card with assigned_to_user_id and assigned_to_name read back.

NameTypeReqDescription
assigned_to–yesMember id, name or email; null to unassign.
card_idintegeryes–

No output schema declared.

No examples provided.

viralhunt_assign_template ~86

Assign (or unassign) a content template to a project, so that project's agents see it via viralhunt_list_templates with assigned=true. Owner/admin only.

NameTypeReqDescription
actionstring–add (default) or remove.
project_idintegeryesProject id (from viralhunt_targets).
template_idintegeryesTemplate id (from viralhunt_list_templates).

No output schema declared.

No examples provided.

viralhunt_best_communities ~336

Where to post a topic: the best subreddits (network=reddit) or Bluesky custom feeds (network=bluesky) from our own measurements. Reddit rows are ranked by peak_per_1k, the best score we hold per 1,000 members (upside relative to size); no average score is published because a swept community's sample is its greatest hits. Each row carries members, sample.posts and the window of post dates. Pass `subreddit` for one community: timing (best UTC hours/day the climbing posts were posted), pace, flairs, type mix, top posts and similar communities. Bluesky rows carry posts, authors, avg_likes; pass `feed` (slug) for its top posts, authors, tags.

NameTypeReqDescription
feedstring–bluesky: one feed by slug for its full detail.
max_membersinteger–reddit: only communities with at most this many members (smaller rooms are easier to climb).
min_membersinteger–reddit: only communities with at least this many members.
networkstring–reddit (default) or bluesky.
pageinteger––
per_pageinteger––
qstring–Topic words matched against the community name (and, on Bluesky, the feed description).
sortstring–reddit: upside (default), members, peak, posts. bluesky: posts (default), avg_likes, top_likes, feed_likes.
subredditstring–reddit: one community by name for its full detail.

No output schema declared.

No examples provided.

viralhunt_best_time ~237

Best time to post on a network, measured on the posts that went viral there in the last 365 days (their OWN publish time). Returns best_slots (weekday + hour, ranked by average engagement, each with its sample size and hit_rate_pct = share of that slot's posts that reached the network's top 10%), worst_slot, today's best hours, by_hour and by_weekday tables, proof_posts, and sample {posts, window, from, to}. Read `confidence` (high >= 500 posts, medium >= 200, low) before quoting an hour. Hours are rotated to `timezone`; weekday aggregates stay UTC. With `keyword`, slots are recomputed on posts whose caption contains it; if that sample is under 200 posts the response says fallback:true and returns the network-wide slots instead.

NameTypeReqDescription
keywordstring–Optional niche word; slots recomputed on posts whose caption contains it (falls back when thin).
networkstringyesWhich network.
timezonestring–IANA zone to express hours in, e.g. America/Mexico_City (default UTC).

No output schema declared.

No examples provided.

viralhunt_board_context ~54

The team's Editorial Board in one call: organization, members (people and agents, with ids to assign cards to), columns (with is_default / is_done flags) and categories. Call this before creating or moving cards.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

viralhunt_brand_alerts ~139

What a brand was alerted about (each thread once), newest first; or, with mark_read_ids, mark alerts as taken so unread=true shows only what is left. Poll with since = your last read every 10 to 30 minutes, or set a webhook with viralhunt_brand_webhook.

NameTypeReqDescription
limitinteger––
mark_read_idsarray–Mark these alert ids as taken (a POST instead of the list).
project_idintegeryes–
sincestring–ISO 8601: only alerts after this.
unreadboolean–true = only alerts not yet marked read.

No output schema declared.

No examples provided.

viralhunt_brand_hot ~183

The discussions about a brand heating up RIGHT NOW: posts of the last window that mention one of its keywords and whose comments grew by delta in the last hours (or were born loud), each with title, url, author, comments_from/to, delta, hours, alerted_at. The answer to 'where should I comment today': hand the user the biggest deltas with their links and a proposed comment. Never post the comment yourself.

NameTypeReqDescription
hoursinteger–The span the comments grew in (default 8).
min_deltainteger–Minimum comments gained (default 10).
networksarray–reddit, quora, x, instagram, tiktok, bluesky (default: all).
project_idintegeryes–
windowinteger–How far back a post may be, in hours (default 24).

No output schema declared.

No examples provided.

viralhunt_brand_keywords ~230

Read a brand's keywords (what the always-on extension searches on X, Quora, Pinterest, Instagram, TikTok, Facebook, and the server on Reddit), or REPLACE the list (owner/admin token): keywords = product names, ingredients, the problems its buyers search for, #hashtags; up to 40; every keyword is machine time on every network. The answer carries the sweep state per network.

NameTypeReqDescription
categorystring–The brand's niche, e.g. Hair care.
keywordsarray–Send to REPLACE the whole list (owner/admin). Omit to read.
networksarray–With keywords: x, quora, pinterest, reddit, instagram, tiktok, facebook (default: the server's set).
project_idintegeryesThe brand (project).
runboolean–true = 'search now' (owner/admin): every keyword of the brand is marked asked; the always-on machine picks them up within five minutes, Reddit within 30. The answer's machine.extension_alive says whe…

No output schema declared.

No examples provided.

viralhunt_brand_status ~113

Every brand (project) of the organization and whether it is being watched: keywords count, category, webhook set, alerts in the last 7 days, and per network when the extension (or the Reddit cron) last searched its keywords (last_run, never_run, found). keywords: 0 = not watched, offer to set them; never_run with an old last_run = the always-on machine is off, tell the owner.

NameTypeReqDescription
project_idinteger–One brand only (default: all).

No output schema declared.

No examples provided.

viralhunt_brand_webhook ~135

Read, set or clear the webhook where a brand's alerts are POSTed the minute the cron writes them (owner/admin to change it): JSON body {event: brand.alerts, project, alerts[], radar_url}, header X-VH-Signature = sha256=<hex HMAC-SHA256 of the raw body with the secret returned here>. Answer 2xx within 8 s; no retry (alerts stay readable). url null clears it.

NameTypeReqDescription
project_idintegeryes–
urlstring|null–https URL on a public host to set; null to clear; omit to read.

No output schema declared.

No examples provided.

viralhunt_calendar ~389

The calendar base: the international days (UN, UNESCO, WHO) and the anniversaries of science, technology, space, health, the environment and civilization in a window of days, each with `why` (what is celebrated or what happened, and why it matters: write the caption FROM it, never from memory), kind (observance repeats every year; event, birth, death carry year and years_ago), category, origin, importance (3 = most brands can post about it, 2 = worth it inside its category, 1 = niche), image_url (a free Wikipedia thumbnail when there is one), source_url. Use days=7 or 31 to plan ahead; post on the day. The vh-ephemeris template fits an event or a birth; the news frame fits an observance. mark_used=true with calendar_id records what you posted.

NameTypeReqDescription
calendar_idinteger––
categorystring–One or several: science,technology,space,health,environment,humanity,civilization,education,culture,economy.
datestring–YYYY-MM-DD or today (default today, UTC).
daysinteger–How many days from date (default 1).
kindstring––
langstring––
mark_usedboolean–true with calendar_id = record that you posted about it this year.
min_importanceinteger–3 = the big days only, 2 = worth a post (recommended), 1 = everything.
notestring––
qstring–Keyword in the title, the text or the tags.
statsboolean–true = how many rows per category and kind instead of the rows.
unusedboolean–true = leave out what this organization already posted about this year.

No output schema declared.

No examples provided.

viralhunt_cancel_post ~92

Cancel the not-yet-published targets of a scheduled post, or with account_id stop ONE network (a pending retry, a timed-out create, a not-yet-published PostProxy post). A published target answers 409: use viralhunt_delete_post.

NameTypeReqDescription
account_idinteger–One connected account to stop; omit for the whole post.
idintegeryesThe post id.

No output schema declared.

No examples provided.

viralhunt_card_comments ~71

Read the comments on a card, or add one (comment set). New comments notify the assignee and appear in the team chat's #board channel.

NameTypeReqDescription
card_idintegeryes–
commentstring–When given, posts this comment; when omitted, lists the card's comments.

No output schema declared.

No examples provided.

viralhunt_create_card ~308

Create a card on the Editorial Board: a piece of content to curate, with an optional post URL (title/description/image are filled from the URL's metadata when omitted), assignee, priority, due date, category and column. Returns the card with its id. Use it to hand a trending post to a teammate instead of publishing it directly.

NameTypeReqDescription
assigned_to––Who takes the card: a member id from viralhunt_board_context, the member's name as the Team page shows it, or their email. The answer carries assigned_to_user_id and assigned_to_name read back from t…
assigned_to_user_idinteger–Same as assigned_to, by id.
board_column_idinteger–Target column (default: the board's default column).
card_typestring–Post, Note, Article, Video… (the org's card types).
category_idinteger––
descriptionstring––
due_datestring–YYYY-MM-DD.
image_urlstring––
notesstring––
platformstring–tiktok, instagram, x, facebook, pinterest, rss… (detected from post_url when omitted).
post_urlstring–The post/article this card is about; metadata is fetched when title/image are missing.
prioritystring––
titlestring–Card title (required unless post_url is given).

No output schema declared.

No examples provided.

viralhunt_delete_post ~73

Owner, admin or a member marked 'Their OK publishes': take a PUBLISHED target down from its network through PostProxy (the cleanup of a duplicate). Confirm on the network afterwards. Without account_id every published target of the post goes.

NameTypeReqDescription
account_idinteger––
idintegeryes–

No output schema declared.

No examples provided.

viralhunt_drafts ~233

List the posts not yet sent (this project, or every project with all=true): stage 'draft' = being worked on, 'review' = complete and dated, waiting for an owner or admin. Each carries stage, body, media, targets, scheduled_at, overrides, card_id, submitted_via (api = from an agent), design, lang, translated_from_id, assigned_to and assigned_to_name (the member it is assigned to), review {score, verdict, reviewed_at, entries[]}, needs_review (no verdict on its current content), valid_verdict, content_hash and updated_at.

NameTypeReqDescription
allboolean–true = every project of the organization.
assigned_tointeger–Only the posts assigned to this member (a user id from viralhunt_members).
needs_reviewboolean–true = only posts with no verdict on their current content (the reviewer's queue).
projectstring–Project name (default: the org's first project).
project_idinteger––
stagestring–One stage only (default: both).

No output schema declared.

No examples provided.

viralhunt_edit_log ~140

What people changed in drafts after an agent left them: one row per field (body, media, targets, scheduled_at, first_comment, overrides, thread, design) with before, after, who and when, plus by_field counts. Drafts with submitted_via=api came from an agent: those edits are what the person did not like. Read it at the start of each batch and apply the pattern (shorter captions, another picture, another hour).

NameTypeReqDescription
idinteger–Only one draft's changes.
limitinteger––
sincestring–ISO-8601: only changes after this moment.

No output schema declared.

No examples provided.

viralhunt_get_card ~52

One card of the Editorial Board: title, column (name, is_done), status, assignee (id and name), priority, due date, notes, archived.

NameTypeReqDescription
card_idintegeryes–

No output schema declared.

No examples provided.

viralhunt_get_post ~291

Get the current status and per-network results (incl. permalinks) of a post you created. Also events[] (the delivery log: created, accepted by PostProxy, published with its link, refused with the reason, retried, canceled, reviewed, approved) and support_text, the text to hand the user when they ask what happened to a post. Statuses: scheduled (queued), processing (handed to the networks, or a target being retried), published (every target live), partial (some refused: each failed results[account].error carries the network's own words and error_message sums it up), failed, draft, canceled. The app retries a transient failure up to three times (results show retries, will_retry, retry_after); a final reason (dead connection, refused text, oversized video) is not retried: tell the user what to fix. The post carries the same fields as a viralhunt_drafts row whatever its status: stage, targets, media, overrides (what each account really sends: read it before an OK), thread, design (and render {html, css, format} on a draft or a post in review), card_id, kind, author_notes, lang, assigned_to, review {score, verdict, entries[]}, content_hash, needs_review.

NameTypeReqDescription
idintegeryesThe post id returned by viralhunt_schedule.

No output schema declared.

No examples provided.

viralhunt_get_template ~341

Get one template's full spec: html, css, the variable manifest (with hard rules per variable), formats, palette tokens, embedded fonts, render_tech, plus what is `static` (the owner fixed it: logo, frame, signature, fixed texts; never move, cover or restyle it), what is `dynamic` (the variables you fill: the picture, the headline, the caption that is the post body), what it `suits` (news, photo, quote, number, tip, on_this_day, meme, any) and the owner's `instructions` (they override any general rule). Fill every dynamic {{variable}}, then render with headless Chrome at the chosen format's size and WAIT for [data-vh-ready='1'] before screenshotting .vh-card. With preview=true the answer is instead preview {document, html, css, format, variables}: a complete page with the example values (or `variables`) filled and the organization's design baked in, to open in a browser or render, so a template is seen before any post is made.

NameTypeReqDescription
formatstring–With preview: feed (default), story, square…
idinteger–Template id — alternative to slug.
previewboolean–true = how it looks: preview.document is a full HTML page with the example values filled (yours with `variables`).
slugstring–Template slug, e.g. vh-image-card.
variablesobject–With preview: your own values, {"text": "…", "highlight": "…"}; the rest take the manifest examples.

No output schema declared.

No examples provided.

viralhunt_list_cards ~86

The organization's cards, newest first (up to 200): filter by column, status, assignee (id, name or email), unassigned or archived.

NameTypeReqDescription
archivedboolean––
assigned_to–––
board_column_idinteger––
limitinteger––
statusstring––
unassignedboolean––

No output schema declared.

No examples provided.

viralhunt_list_posts ~159

What went out and what did not: posts of the project (or the organization with all) by status, newest first, each target with status, PostProxy id, permalink, error, will_retry, timed_out (may be live), reconciled.

NameTypeReqDescription
account_idinteger––
allboolean––
idstring–One post id or a csv: those posts whatever their status.
limitinteger––
offsetinteger––
project_idinteger––
sincestring––
statusstring–csv of draft, review, scheduled, processing, published, partial, failed, canceled; default published,partial,failed,processing,scheduled

No output schema declared.

No examples provided.

viralhunt_list_templates ~222

List ViralHunt content templates (layouts you fill and render yourself). Lean by design — no html/css — so use viralhunt_get_template for the one you'll actually render.

NameTypeReqDescription
assignedboolean–true = only the templates assigned to project_id.
categorystring–image | quote | video | top3 | …
favoritesboolean–true = only the templates the brand starred. Favourites come first in every list: prefer them when several fit.
media_typestring–Filter by what it renders to.
networkstring–Only templates suited to this network.
pageinteger––
per_pageinteger–Page size (default 20). The answer's meta says total and has_more.
project_idinteger–With assigned=true, the project whose allowed templates you want.
qstring–Search name/description.
scopestring–org = only the organization's own templates (they also come first in every list), global = only the library.

No output schema declared.

No examples provided.

viralhunt_mark_quote_used ~67

After scheduling a quote, mark it used for this organization so the next pick (unused=true) is a different one.

NameTypeReqDescription
notestring–e.g. 'scheduled 2026-09-20 09:00 instagram'.
quote_idintegeryes–

No output schema declared.

No examples provided.

viralhunt_move_card ~75

Move a card to another column (moving into the column flagged is_done completes it; a 'done' comment does not).

NameTypeReqDescription
board_column_idintegeryesTarget column id from viralhunt_board_context.
card_idintegeryes–
positioninteger–Position inside the column (0 = top).

No output schema declared.

No examples provided.

viralhunt_my_cards ~74

Cards assigned to the authenticated token's member (your own workload when you are an agent member of the team). Optional status filter.

NameTypeReqDescription
pageinteger––
per_pageinteger––
projectstring–Restrict to one project/brand by name.
statusstring––

No output schema declared.

No examples provided.

viralhunt_news_categories ~81

The categories of the news corpus (source rss), with how many feeds carry each and how many articles arrived in the last 7 and 30 days. Read it once before asking for news on a subject, then pass a name as category on viralhunt_trending (source rss). Not the Editorial Board categories. Technology and Artificial Intelligence are separate categories.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

viralhunt_policy ~170

The content rule a reviewer applies before any OK, kept on the platform so it changes without a release: what blocks a post (policy_* codes), what sends it back to Drafts (fix_* codes), the six scores (tos_risk, rights, fake_news, sensationalism, brand, grammar; 100 = clean) with the thresholds the server recalculates the verdict with, the extra readings every review carries (risk10 1 safe to 10 breaks a network's terms, image_match, ai_written), the kinds (fact, meme, quote, opinion, promo: a meme or a quote never gets a source or DOI demand), what changes per network, and the server rules an OK cannot bypass. Read it at the start of every review pass; never judge from memory.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

viralhunt_quotes ~260

Quotes ranked by our popularity score, for daily-quote series: text, author, author_context (description, born, died), work, categories, rights, popularity high|medium|low and author_image (portrait url, licence, credit). Default rights=public_domain (authors dead more than 70 years): keep it unless the user asks for a modern author, and with rights=any tell the user a quote is restricted before scheduling it under their brand. Write the caption's context FROM author_context and work, never from memory. categories_list=true lists the categories held. unused=true leaves out what this organization already used.

NameTypeReqDescription
authorstring–Part of an author's name.
categoriesstring–Several mixed: stoicism,leadership.
categories_listboolean–true = list the categories instead of quotes.
categorystring–One category, e.g. stoicism.
langstring–Language of the quote (default en).
max_charsinteger–Default 180: what the quote templates fit.
pageinteger––
per_pageinteger––
rightsstring––
sortstring––
unusedboolean––

No output schema declared.

No examples provided.

viralhunt_recipe_ran ~41

Stamp a recipe run so the person sees in the app that it happened.

NameTypeReqDescription
notestring––
recipe_idintegeryes–

No output schema declared.

No examples provided.

viralhunt_recipes ~184

The standing orders of a brand, saved by a person in the app: each recipe says what to post from (source quotes|trending|manual with source_params, and source_call = the exact request that fetches the content), which template (template.slug for viralhunt_get_template), format, networks, cadence (daily|weekdays|weekly|manual), post_time in the project's timezone (null = the network's best time), caption_brief and last_run_at. Nothing runs on the server: you do the loop (fetch, fill, render, schedule, mark the quote used, then viralhunt_recipe_ran). daily with last_run_at older than today = due. Never run a paused recipe (is_active false).

NameTypeReqDescription
activeboolean––
project_idinteger–One brand (default: every active recipe of the organization).

No output schema declared.

No examples provided.

viralhunt_review_draft ~536

Append your review to a post in Review: verdict ok|fix|block, a score 0-100, per-topic scores (tos_risk, rights, fake_news, sensationalism, brand, grammar; 100 = clean) plus risk10 (1 safe to 10 breaks a network's terms), image_match and ai_written (0-100), one warning per issue with the policy's code (policy_* / fix_*), the network it concerns and the severity, and a short note on how to fix it, in the post's language. Judge against viralhunt_policy (read it first), network by network; verify claims with viralhunt_search / trending rss. `fix` sends the post back to Drafts with your note (returned: true). The server recalculates the verdict from your scores and warnings with the policy thresholds and keeps the more severe one (verdict, verdict_requested, verdict_reason in the answer). An `ok` sends the post at its time only when the organization sends on OK AND this token may release (owner, admin, or 'their OK publishes' in Team); The note carries the fix (the corrected sentence, the exact link, the short version); say which problem decided the verdict. The server refuses to send on a self review (same USER, not token: the reviewer is its own agent member), a post with no time or under 15 minutes, one edited after the review, or one whose scores sit outside the policy's auto_send thresholds (risk10 > 5, fake_news < 70, image_match < 60: risk_threshold, a person decides), and says why in sent.skipped. Report `sent` as it is. Drafts rows carry project_lang: a post in another language is fix_language. Always pass content_hash from the row you read: if the post changed meanwhile the server answers 409 content_changed with the current hash and writes nothing; read it again.

NameTypeReqDescription
content_hashstring–The content_hash of the drafts row when you read the post. Always send it.
idintegeryesThe draft id.
notestring–How to fix it, and the source you verified against.
scoreinteger––
scoresobject–{"tos_risk": 90, "fake_news": 70, "sensationalism": 80, "grammar": 95, "risk10": 3, "image_match": 85, "ai_written": 40}
verdictstringyes–
warningsarray––

No output schema declared.

No examples provided.

viralhunt_review_queue ~80

The reviewer's queue: posts in Review, every project, with no verdict on their current content (never reviewed, or edited after the last verdict). Same rows as viralhunt_drafts. Read viralhunt_policy first, then one viralhunt_review_draft per post.

NameTypeReqDescription
project_idinteger–One project only (default: every project).

No output schema declared.

No examples provided.

viralhunt_review_stats ~129

Flags per collaborator (owner, admin, or a reviewer marked 'Their OK publishes'): for the last days (7 = week, 14 = fortnight, 30 = month), per person or agent who authored posts: reviews, ok / fix / block, flags (a fix or block, or any policy_* / fix_* warning), codes (how many of each rule, e.g. fix_doi), avg_risk10 and last_flag_at. The Team page shows the same table.

NameTypeReqDescription
daysinteger–7, 14 or 30 (default 30).

No output schema declared.

No examples provided.

viralhunt_schedule ~1,209

Publish now, schedule, or (default when the user did not ask to publish right now) leave a DRAFT of a post on a project's connected accounts. Ask the user before publishing or scheduling: it posts to real accounts. Verify content first: never fake news, copyrighted media or spam. Never use another page's text as the copy or its branded picture as the post's picture: the picture comes from the organization's templates (viralhunt_get_template), either rendered by you and passed in media, or passed as `design` with draft=true so the app renders it when a person approves. Returns {id, status, results, warnings, review_url}: status processing|scheduled|review|draft|partial|failed; results keyed by account id carry each network's own reason when it refused. Two stages sit before sending: Drafts (being worked on) and Review (complete, dated, waiting for an owner or admin). Say which one the post is in. The working agreement: a post the user asks for goes to Drafts COMPLETE (text, image, accounts, tentative time, the project they named; no picture with rights = the organization's template with text only), never to Review unless asked. Hand it over in one five-line message: id and project_name, the url the answer gives (never compose a link), the angle, what you verified and the source, the decision you need. Everything else goes in author_notes. The Drafts page shows one project at a time (name the project); media_removed after a week is retention. A picture made on a template is complete only with its design in the post (pass the PNG in media AND design): a PNG alone is a flat file nobody can edit in the app; the answer says picture_editable: false and viralhunt_update_post with design repairs it. Every picture is made on one of the organization's templates; when none fits, CREATE one (viralhunt_upsert_template, the owner's 'Creates templates' tick) and use it.

NameTypeReqDescription
assigned_tointeger–The member who takes this post over (an id from viralhunt_members; agents count): its board card is assigned to them and they get the notification. Also on viralhunt_update_post.
author_notesstring–For the reviewer, never published: the source link, the picture's origin, what you verified. Put the source link HERE, never in the body (the networks cut the reach).
bodystring–Caption/text. Optional if media or design is provided.
card_idinteger–The Editorial Board card this post comes from (optional).
carouselboolean–Only when the user asked for a carousel: allows several pictures in media. Without it a second picture answers 422 multiple_pictures.
designobject–ALWAYS when the picture was made from a ViralHunt template, even if you also rendered and uploaded the PNG (a PNG alone cannot be edited in the app; the design opens the editor on that template): {"t…
draftboolean–true = a working copy in Drafts you still mean to edit (viralhunt_update_post, then viralhunt_submit_draft). Every draft is also an Editorial Board card (card_id in the answer) that moves with the po…
first_commentstring–Optional first comment (link-in-comments).
kindstring–What the post IS. The reviewer applies only that kind's rules (a meme is never asked for a source). A post from a card takes the card's category when omitted.
mediaarray–Public image/video URLs. ONE picture per post (a post made on a template has exactly one, its render). Check media_limits (viralhunt_targets) before a big video.
networksarray–Post to every account on these networks, e.g. ["instagram","facebook"].
overridesobject–Per network (or per account id), only what that account needs to differ: {"bluesky": {"body": "the 300-character version", "thread": [{"body": "part 2"}]}, "12": {"media": ["…"], "first_comment": "it…
projectstring–Project name — REQUIRED if the org has more than one project.
project_idinteger–Project id — alternative to project name.
scheduled_atstring–ISO-8601 UTC, e.g. 2026-08-01T15:30:00Z. Omit = publish now (or, with draft, the tentative time is 'when approved').
stagestring–Where the post lands, in one word: draft = a working copy (same as draft: true), review = complete and waiting for an owner or admin, even from a token that could send.
target_account_idsarray–Exact account ids (from viralhunt_targets). Omit = all accounts in the project.

No output schema declared.

No examples provided.

viralhunt_search ~268

Search one keyword across every network at once (or a chosen subset) and get one merged, ranked list: each row normalized to platform, id, title, description, post_url, thumbnail_url, author_name, author_handle, engagement_score, stats, growth_24h, created_at, plus the network's full row under raw. sources[] says per network how many posts matched (total), so you can tell the user where the topic lives and where the corpus holds nothing (total 0 = say so, never invent posts). All words must appear, in any order. Use viralhunt_trending when the user wants ONE network with its own sorts and paging.

NameTypeReqDescription
keywordstringyesThe words to find (all must appear).
min_engagementinteger––
per_sourceinteger–Rows per network (default 10).
sortstring––
sourcesstring–all (default) or a comma list: pinterest,x,reddit,tiktok,instagram,facebook,bluesky,douyin,mastodon,tumblr,hackernews,rss.
time_rangestring–Window on the post's own date (default 30d): a number with a unit, a bare number of days, or all.

No output schema declared.

No examples provided.

viralhunt_stats ~114

Engagement of the published posts as the networks report it back: by_network, by_project and top_posts (with permalinks). ready=false means nothing collected yet. Use it to answer 'what worked' and to find more like the winners (viralhunt_search on the winning topic); never invent a number.

NameTypeReqDescription
daysinteger–Window in days (default 30).
limitinteger––
networkstring––
projectstring––
project_idinteger––

No output schema declared.

No examples provided.

viralhunt_submit_draft ~102

Move a draft to Review once it is complete (a body or media, and at least one account): it waits there for an owner or admin to authorize it. now=true clears the time (it goes out when authorized); scheduled_at sets one; neither keeps the draft's own. Nothing is sent.

NameTypeReqDescription
idintegeryesThe draft id.
nowboolean––
scheduled_atstring–ISO-8601 UTC.

No output schema declared.

No examples provided.

viralhunt_sync_post ~40

Refresh the status of this organization's posts from the networks (call before viralhunt_get_post when the answer matters). Returns how many rows were re-read.

Input schema present but exposes no named parameters.

No output schema declared.

No examples provided.

viralhunt_targets ~298

List the user's projects/brands and the connected social accounts you can publish to in each. Also returns needs_reconnect (expired connections: not targets until a person reconnects them in the app; name the network before publishing), media_limits per network (image bytes: bigger ones are re-encoded to fit; video bytes and seconds: a bigger or longer video is refused for that network only, with the numbers; text length), each project's lang and translates_to (linked projects in another language), and must_draft: '' = this token may publish directly; 'role' = a member or agent token: every post waits in Drafts for an owner or admin whatever draft says; 'review_mode' = the organization reviews every post. Read it before promising 'published'. Each project carries voice: the owner's playbook for that brand (audience, tone, hooks, structure, per-network versions, what it never says, verification). Read it before writing anything for that project and follow it over the general rules; when empty, offer to draft one from the brand's best posts for the owner to paste on the Projects page. And complete means every network's copy: for every account whose text_limit the body exceeds (X 280, Bluesky 300, Threads 500), its own short copy in overrides in the same create, never a cut.

NameTypeReqDescription
projectstring–Project name to scope the accounts to (optional).

No output schema declared.

No examples provided.

viralhunt_top_hashtags ~210

Top hashtags from the captions of the posts we hold, per network or across all, optionally filtered to tags containing a word. Each row carries posts (sample size), total_engagement and per_post (the number to compare: a tag used less but hitting harder). `window` is all-time over the corpus with updated_at (there is no per-day hashtag history; say so if asked for 'this week'). Pass `hashtag` to get one tag broken down by network with its top posts.

NameTypeReqDescription
hashtagstring–One hashtag (with or without #) for its per-network breakdown.
min_postsinteger–Minimum posts a tag needs to be listed (default 3).
networkstring–One network, or omit for all networks summed.
pageinteger––
per_pageinteger––
qstring–Only hashtags containing this word (niche filter).
sortstring–Ranking (default engagement).

No output schema declared.

No examples provided.

viralhunt_translate_post ~403

Make the translated draft of a post (a draft or one already sent) in a linked project that publishes in another language. The app adapts the copy, the first comment, the per-network copies, the thread and the TEXT variables of a design (hashtags in the new language; links, mentions, numbers and names kept): do not translate yourself. A design keeps its picture and the answer carries needs_png=true with render {html, css, format}: render it, store the PNG with viralhunt_update_post {id, png}, then approve if wanted. A plain picture (no template) stays unless `image` hands the translated one. The same translation twice is refused. The texts come back without em dashes, and for every network of the target project whose limit the translated body passes (X 280, Bluesky 300, Threads 500) a short copy is written as that network's override: `shortened` lists them (network, limit, full length, short length) and `overrides` carries the copies. One brand, two languages: link the projects once (Projects → Also publish translated in…), work in one project, and the other language comes out of this call or of `translations` on viralhunt_approve_draft. Never write the second language by hand.

NameTypeReqDescription
account_idsarray–Accounts of the target project (default: all postable).
idintegeryesThe source post id.
imagestring–https URL of the translated picture, for a post whose picture is not a template.
langstring–Override the target language (es, en, pt, fr, de, it…).
project_idintegeryesThe target project (from translates_to on viralhunt_targets).
send_modestring–draft (default) waits in the target project; send (owner/admin) goes out at once when there is nothing to render.

No output schema declared.

No examples provided.

viralhunt_trending ~684

Find trending/viral posts on a social network, ranked by viral score (engagement velocity). Sources: tiktok, instagram, x, facebook, pinterest, bluesky, douyin, reddit, mastodon, tumblr, hackernews, and rss (news articles from 230 feeds plus articles discovered through social links, each with Facebook/Reddit/Bluesky/Hacker News/comment signals). Each post carries growth_24h when we hold at least two readings of it: {from, to, delta, percent, hours, measured_at, samples}. Read it carefully: growth_24h null means 'we cannot say', NOT zero (Facebook and Pinterest never carry it); delta 0 with samples >= 2 means measured and unchanged (flat), not missing; `hours` is the REAL window between the two readings (the newest reading at least 20h older than the latest, or the oldest one when the post is younger than that), so it is often under 24: quote it, never assume 24, and say 'in 24h' only when `full_window` is true; `percent` is null when `from` is under 100 (from zero or from a handful of interactions a percentage is noise) while `delta` always holds the absolute change. A high delta over few hours is what 'going viral right now' looks like.

NameTypeReqDescription
authorstring–ONE page or account only (facebook page name, x handle or name, tiktok or instagram username; contains-match). 'The most viral posts of the page X in 2025' = source + author + time_range=1y.
categorystring–rss only: ONE news category, a name or id from viralhunt_news_categories (exact name, case-insensitive; unknown = 422 with the valid names). Technology and Artificial Intelligence are two categories:…
keywordstring–Filter by keyword/niche (matched in title, text, hashtags or author).
min_engagementinteger–Minimum engagement on the network's main metric.
pageinteger–Page number for more results.
per_pageinteger–How many results (max 100).
sortstring–viral (default), engagement, newest, oldest, plus per network: most_liked, most_viewed, most_commented (accepted on every network that counts comments: the threads to comment in), most_retweeted, mos…
sourcestringyesWhich network to pull trending from.
subredditstring–reddit only: restrict to one subreddit (with or without r/).
time_rangestring–Time window on the post's own publish date: any number with a unit (24h, 7d, 30d, 2w, 3m, 1y), a bare number of days, or all (default 7d). An unknown value is a 422. Tumblr's corpus fills slowly: use…

No output schema declared.

No examples provided.

viralhunt_trending_sounds ~220

Trending sounds/audio on TikTok, Instagram Reels and Douyin, ranked by the engagement of the posts that used them, cross-network sounds first. A sound is listed only when several different accounts used it (one account's audio is a voiceover, not a trend). Each sound carries networks{tiktok|instagram|douyin: posts, creators, eng, per_post}, cross (on more than one network) and stronger (tiktok|instagram|even, per post) when both sides are measured. Pass `slug` for one sound with the posts that used it. Window is all-time over the corpus.

NameTypeReqDescription
cross_onlyboolean–Only sounds trending on more than one network.
networkstring–One network or all (default all).
pageinteger––
per_pageinteger––
qstring–Filter by words in the title or artist.
slugstring–One sound's slug (from a previous result) for its detail and posts.

No output schema declared.

No examples provided.

viralhunt_update_post ~641

Edit a post. A DRAFT can be changed freely by its author, an owner or an admin (body, media, overrides, first_comment, targets, scheduled_at, design, and png: the a reviewer marked 'Their OK publishes' may change only overrides (a per-account short copy), kind, and the texts inside the image (design_fields {variable key: text}, never a picture variable or caption; with its png) on someone else's post). design_fields works on posts made on a template only (a flat picture answers no_design); without png the old render leaves (needs_png + render in the answer). overrides is MERGED per account: send only the accounts you change, a key set to null removes that account's copy, overrides_replace: true replaces the whole map; rendered picture of its design as a data:image/png;base64 URL, which becomes the post's first picture). A SCHEDULED post can be edited only while status is 'scheduled' and more than 5 min before publish. Only the fields you send change; the project cannot be changed. Check status with viralhunt_get_post first; on a 409 error re-fetch instead of retrying.

NameTypeReqDescription
assigned_to––Drafts and posts in review: the member who takes it over (a user id from viralhunt_members; agents count); null unassigns. Their board card, their notification. A trusted reviewer may assign on someo…
author_notesstring–Drafts: notes for the reviewer, never published (the source link goes here).
bodystring–New caption.
carouselboolean–Only when the user asked for a carousel: allows several pictures in media. Without it a second picture answers 422 multiple_pictures. A post made on a template always has ONE picture, its render.
designobject–The filled template of this post (see viralhunt_schedule): send it to repair a post that went out with a PNG only, so its image becomes editable.
design_fieldsobject–Drafts made on a template: {variable key: corrected text} for the texts inside the image (text variables only, never caption). Send the new png with it when you can render.
first_commentstring–Drafts: the first comment.
idintegeryesThe post id.
kindstring–Drafts: what the post is.
mediaarray–New media URLs (replaces the set).
networksarray–New network set (adds/removes targets).
overridesobject–Drafts: per network or per account id: body, media, first_comment, thread.
pngstring–Drafts: data:image/png;base64,… of the rendered design; stored as the post's ONE picture (it replaces any picture the post had).
scheduled_atstring–New ISO-8601 UTC time (must be in the future).
target_account_idsarray–New exact account-id set.

No output schema declared.

No examples provided.

viralhunt_upsert_template ~608

Create or edit a content template (layout HTML/CSS + variable manifest). Editing a curated/global template CLONES it into the org's own copy — the global is never modified. Every {{placeholder}} in the html must be declared in variables, or the call is rejected. Owners and admins, or a member/agent the owner ticked 'Creates templates' (they edit only the templates they created). A template is html, css and images, never code: scripts, iframes, forms, event handlers and javascript: URLs are removed and listed in `removed`; data:font/ and data:image/ are accepted. Coloured words and a headline that fits need no script: put data-highlight="{{highlight}}" on the headline (the listed words get <span class="hl">, your css styles .hl), data-fit="28" (or data-fit-lines="4") on a block whose text must shrink to fit, and the platform appends its runtime (runtime_added: true), which also sets data-vh-ready. On update you may send only the fields that change. Then viralhunt_get_template with preview=true shows how it came out.

NameTypeReqDescription
actionstring–create (default), update (send only what changes) or archive (retire one of your organization's templates; id or slug_ref).
aspectstring–Default format's aspect, e.g. 4:5.
canvas_hinteger––
canvas_winteger––
categorystring–image | quote | video | top3 | …
content_sourceobject–Optional curated-bank binding instead of generating values.
cssstring–Styles; reference palette tokens via CSS vars. Max 256KB.
descriptionstring––
fontsarray–[{family,weight,style,url_woff2}] — fonts must travel with the template.
formatsarray–[{name,w,h,aspect?,networks?,default?}] — the sizes this one layout ships.
htmlstring–Layout with {{variable}} placeholders. Max 256KB.
idinteger–On update: the template id to edit.
is_activeboolean––
media_typestring––
namestring–Human-readable name.
networkstring–Network it suits, or omit for any.
paletteobject–Design tokens → hex, e.g. {"cyan":"#1edbee"}.
render_techstring–How the agent turns this into a file.
slugstringyesStable kebab-case id for the template, e.g. my-quote-card.
slug_refstring–On update: the slug to edit, if you don't have the id.
variablesarray–The manifest: [{key,label,type,description,rules,example,fallback,required}].

No output schema declared.

No examples provided.

Install

How do I install the io.github.rodvan/viralhunt-mcp server?

io.github.rodvan/viralhunt-mcp runs locally as an npm package, launched with npx -y viralhunt-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

npm · viralhunt-mcp

# add to Claude Code
claude mcp add rodvan-viralhunt-mcp -- npx -y viralhunt-mcp
Common questions

What is the io.github.rodvan/viralhunt-mcp server?

io.github.rodvan/viralhunt-mcp is listed in the public MCP registry as io.github.rodvan/viralhunt-mcp. Trending content on 12 networks, best time, hashtags, templates, drafts and review, publish to 11. This page covers its npm package (viralhunt-mcp).

Is the io.github.rodvan/viralhunt-mcp server safe to use?

io.github.rodvan/viralhunt-mcp scores 73 out of 100 on VerifyMCP. We recorded 1 known advisory against it as of 4 November 2026. It declares no install or post-install scripts. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the io.github.rodvan/viralhunt-mcp server expose?

io.github.rodvan/viralhunt-mcp exposes 49 tools: viralhunt_trending, viralhunt_news_categories, viralhunt_account, viralhunt_search, viralhunt_targets, and 44 more. Their descriptions and schemas cost roughly 10,795 tokens of context every time the server is loaded.

Is the io.github.rodvan/viralhunt-mcp server still maintained?

io.github.rodvan/viralhunt-mcp is still listed as active in the MCP registry. We last reached this channel on 4 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

What licence is the io.github.rodvan/viralhunt-mcp server under?

io.github.rodvan/viralhunt-mcp declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.