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.

VarynForge

REMOTE · APP.VARYNFORGE.COM · SCANNED SEP 20

SEO research SaaS exposed as 30+ MCP tools. Forge niche analysis, plans, and writer-ready briefs.

0 this week 83 Trust /100
Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →

Endpoint Security94
Transport & Reachability100
Schema Quality & AI Usability67
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 9371 tokens (~164/item across 57 items; 57 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 Management50
  • Stability check failed: schema churn in the 30 days we've observed: 0 tool removals, 57 breaking changes, 0 auth/transport breaks, 0 additions. See how to fix → Fail
Tool Coverage75
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 26% of tool parameters carry a description.Partial
Tool Safety100
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • All 2 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
  • An AI judge read all 57 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
Install

How do I install the VarynForge MCP server?

VarynForge is a hosted endpoint at https://app.varynforge.com/api/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

remote · app.varynforge.com

# add to Claude Code
claude mcp add --transport http com-varynforge-server 'https://app.varynforge.com/api/mcp'
// .cursor/mcp.json
{
  "mcpServers": {
    "com-varynforge-server": {
      "url": "https://app.varynforge.com/api/mcp"
    }
  }
}
// .vscode/mcp.json
{
  "servers": {
    "com-varynforge-server": {
      "type": "http",
      "url": "https://app.varynforge.com/api/mcp"
    }
  }
}
# ~/.codex/config.toml
[mcp_servers.com-varynforge-server]
url = "https://app.varynforge.com/api/mcp"
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "com-varynforge-server": {
      "type": "remote",
      "url": "https://app.varynforge.com/api/mcp",
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add com-varynforge-server --url 'https://app.varynforge.com/api/mcp' --transport streamable-http
# ~/.hermes/config.yaml
mcp_servers:
  com-varynforge-server:
    url: "https://app.varynforge.com/api/mcp"
// ~/.netclaw/config/netclaw.json
{
  "McpServers": {
    "com-varynforge-server": {
      "Transport": "http",
      "Url": "https://app.varynforge.com/api/mcp"
    }
  }
}
# add to Vellum
assistant mcp add com-varynforge-server -t streamable-http -u 'https://app.varynforge.com/api/mcp'
// mcp.json
{
  "mcpServers": {
    "com-varynforge-server": {
      "type": "http",
      "url": "https://app.varynforge.com/api/mcp"
    }
  }
}

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

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 Sept 26 −7
    • Stability: pass → fail security
    • Tool “send_feedback” rewrote its description, which is the text the model reads security
    • Schema quality: 134 → 164 functional
    • “accept_idea” added a required parameter “context”, so existing callers break functional
    • “add_article_suggestion” added a required parameter “context”, so existing callers break functional
    • “add_competitor_by_domain” added a required parameter “context”, so existing callers break functional
    • “add_destination” added a required parameter “context”, so existing callers break functional
    • “add_radar_topic” added a required parameter “context”, so existing callers break functional
    • “check_idea” added a required parameter “context”, so existing callers break functional
    • “create_article_suggestion_with_input” added a required parameter “context”, so existing callers break functional
    • “create_content_plan_from_opportunities” added a required parameter “context”, so existing callers break functional
    • “create_project” added a required parameter “context”, so existing callers break functional
    • “delete_article_suggestion” added a required parameter “context”, so existing callers break functional
    • “download_brief_markdown” added a required parameter “context”, so existing callers break functional
    • “expand_idea” added a required parameter “context”, so existing callers break functional
    • “expand_radar_topic” added a required parameter “context”, so existing callers break functional
    • “generate_article_brief” added a required parameter “context”, so existing callers break functional
    • “get_account_status” added a required parameter “context”, so existing callers break functional
    • “get_article_brief” added a required parameter “context”, so existing callers break functional
    • “get_article_suggestion” added a required parameter “context”, so existing callers break functional
    • “get_changelog” added a required parameter “context”, so existing callers break functional
    • “get_competitor_detail” added a required parameter “context”, so existing callers break functional
    • “get_draft_status” added a required parameter “context”, so existing callers break functional
    • “get_instructions” added a required parameter “context”, so existing callers break functional
    • “get_keyword_detail” added a required parameter “context”, so existing callers break functional
    • “get_lint_rubric” added a required parameter “context”, so existing callers break functional
    • “get_onboarding_guide” added a required parameter “context”, so existing callers break functional
    • “get_opportunity_detail” added a required parameter “context”, so existing callers break functional
    • “get_page_dossier” added a required parameter “context”, so existing callers break functional
    • “get_pitch_report_payload” added a required parameter “context”, so existing callers break functional
    • “get_project” added a required parameter “context”, so existing callers break functional
    • “get_project_asset” added a required parameter “context”, so existing callers break functional
    • “get_project_overview” added a required parameter “context”, so existing callers break functional
    • “get_research_status” added a required parameter “context”, so existing callers break functional
    • “get_starting_point_report” added a required parameter “context”, so existing callers break functional
    • “get_write_handoff” added a required parameter “context”, so existing callers break functional
    • “get_writer_system_prompt” added a required parameter “context”, so existing callers break functional
    • “lint_draft” added a required parameter “context”, so existing callers break functional
    • “list_article_suggestions” added a required parameter “context”, so existing callers break functional
    • “list_competitors” added a required parameter “context”, so existing callers break functional
    • “list_destinations” added a required parameter “context”, so existing callers break functional
    • “list_keywords” added a required parameter “context”, so existing callers break functional
    • “list_opportunities” added a required parameter “context”, so existing callers break functional
    • “list_organizations” added a required parameter “context”, so existing callers break functional
    • “list_pages” added a required parameter “context”, so existing callers break functional
    • “list_projects” added a required parameter “context”, so existing callers break functional
    • “list_radar_topics” added a required parameter “context”, so existing callers break functional
    • “mark_article_published” added a required parameter “context”, so existing callers break functional
    • “register_derived_asset” added a required parameter “context”, so existing callers break functional
    • “remap_asset” added a required parameter “context”, so existing callers break functional
    • “resync_asset_profile” added a required parameter “context”, so existing callers break functional
    • “send_feedback” added a required parameter “context”, so existing callers break functional
    • “set_competitor_importance” added a required parameter “context”, so existing callers break functional
    • “set_excluded_terms” added a required parameter “context”, so existing callers break functional
    • “set_opportunity_status” added a required parameter “context”, so existing callers break functional
    • “set_posting_cadence” added a required parameter “context”, so existing callers break functional
    • “start_research_run” added a required parameter “context”, so existing callers break functional
    • “update_article_status” added a required parameter “context”, so existing callers break functional
    • “update_asset_profile” added a required parameter “context”, so existing callers break functional
    • “update_niche” added a required parameter “context”, so existing callers break functional
    • Tool coverage: 0% → 26% functional
    • Server version: 1.20.0 → 1.21.0 functional
  • 2 Sept 26 0
    • Stability: 0.97 → pass security
  • 1 Sept 26 +1

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

  • 30 Aug 26 +1

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

  • 28 Aug 26 +1

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

  • 26 Aug 26 +2
    • We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
  • 25 Aug 26 +1

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

  • 23 Aug 26 +1

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

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 20 Sept 2026 · Probed https://app.varynforge.com/api/mcp

TLS valid

Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .

Subject Issuer Valid from Valid until Key Signature Serial
CN=*.varynforge.com CN=YR1,O=Let's Encrypt,C=US 4 Sept 2026 3 Dec 2026 RSA 2048 SHA256-RSA 5a0e6dde94cf4b6bc611294928c43932df2
SANs: *.varynforge.com, varynforge.com
CN=YR1,O=Let's Encrypt,C=US (CA) CN=Root YR,O=ISRG,C=US 3 Sept 2025 2 Sept 2028 RSA 2048 SHA256-RSA a20253f15f2691c05dc1ce13b9bcca4e
CN=Root YR,O=ISRG,C=US (CA) CN=ISRG Root X1,O=Internet Security Research Group,C=US 13 May 2026 2 Sept 2032 RSA 4096 SHA256-RSA f24b6d17f9d9ad7cb1c9fea78782699f

Background: What to check on a remote MCP endpoint →

DNSSEC insecure

Validation of app.varynforge.com. Not signed

Zone DS Keys Algorithms Outcome
. trust_anchor 20326, 38696 8, 8 Verified
com. present 19718 13 Verified
varynforge.com. absent Unsigned (proven) parent-signed NSEC/NSEC3 proves an unsigned delegation
Authentication Enforced and verified

The endpoint asked for a token and published valid RFC 9728 metadata describing how to get one.

Result Enforced and verified
Enforced On tool calls
HTTP status 200

WWW-Authenticate challenge Bearer resource_metadata="https://app.varynforge.com/api/auth/.well-known/oauth-protected-resource"

Bearer resource_metadata="https://app.varynforge.com/api/auth/.well-known/oauth-protected-resource"
Header Value
strict-transport-security max-age=63072000; includeSubDomains; preload
x-content-type-options nosniff
x-frame-options DENY
referrer-policy strict-origin-when-cross-origin
permissions-policy camera=(), microphone=(), geolocation=(), interest-cohort=()

Protected resource metadata

Document https://app.varynforge.com/api/auth/.well-known/oauth-protected-resource
Retrieved Yes
Resource https://app.varynforge.com
Authorisation server https://app.varynforge.com

Background: How OAuth 2.1 works in the 2026 MCP spec →

Transports 2 probes
Transport URL Outcome Status Location
streamable-http https://app.varynforge.com/api/mcp Verified 200
http (plaintext) http://app.varynforge.com/api/mcp HTTPS enforced 308 https://app.varynforge.com/api/mcp
MCP tools · 57 exposed · ~9,371 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
accept_idea ~166

Commit an expanded idea (from expand_idea) to the content plan as a brief-ready article suggestion. Stores the verbatim idea as provenance, lands the suggestion in generating_brief, and forges its brief automatically (free tier: queues past the daily cap). Returns the new suggestionId.

NameTypeReqDescription
anglestringyes
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
demandEstimatestring
ideaTextstringyes
nicheFitinteger
projectIdstringyes
reasoningstring
relatedQueriesarray
searchIntentstringyes
titlestringyes

No output schema declared.

No examples provided.

add_article_suggestion ~112

Add a bare article suggestion to a content plan (title + optional intent and reasoning). For richer input that produces a brief-ready suggestion, use create_article_suggestion_with_input.

NameTypeReqDescription
contentPlanIdstringyes
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
intentstring
projectIdstringyes
reasoningstring
titlestringyes

No output schema declared.

No examples provided.

add_competitor_by_domain ~88

Add a competitor to a project by domain (e.g. example.com). Marks the competitor as important or ignored on creation.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
domainstringyes
importancestringyes
projectIdstringyes

No output schema declared.

No examples provided.

add_destination ~209

Add a destination to a project — where the operator publishes. Pass `type` (website | youtube_channel | instagram | tiktok | x | linkedin | local_business) and `name` with `state: 'detected'` for a destination that already exists and belongs to the operator (website name = the domain like yourdomain.com; social types = the handle, @ optional), or `state: 'planned'` for one they intend to build (name is held, no live URL yet). Confirm the type and name with the operator before adding — this shapes where briefs, drafts, and lint formats anchor. A project holds up to 10 destinations; manage or remove them in the web UI.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
namestring
projectIdstringyes
statestringyes
typestring

No output schema declared.

No examples provided.

add_radar_topic ~188

Add selected angles from a radar topic to the content plan as radar-born article suggestions (provenance preserved; exact-title duplicates skipped). Angles come from expand_radar_topic; call list_radar_topics first to get signalObservationId + topicIndex. Auto-creates the content plan when the project has none. Each added suggestion lands in generating_brief and its brief forges automatically (free tier: queues past the daily cap and forges at reset) — do not also call generate_article_brief. Returns the created suggestionIds.

NameTypeReqDescription
anglesarrayyes
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
projectIdstringyes
signalObservationIdstringyes
topicAngleTotalinteger
topicIndexintegeryes

No output schema declared.

No examples provided.

check_idea ~185

Attach real search data to one article idea that is already in the project — runs one live Google search per target keyword and returns volume bands and the pages currently ranking for each. Use after create_article_suggestion_with_input, or on any existing suggestion the operator wants judged on data instead of instinct. Opportunity score and cluster placement are returned only when the project has a completed research run to compare against; on a project without one they are absent, and start_research_run is what produces them. Do not use to find new ideas or map a niche — that is start_research_run. Consumes no credits; daily- and monthly-capped per account.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
projectIdstringyes
suggestionIdstringyes

No output schema declared.

No examples provided.

create_article_suggestion_with_input ~159

Create a brief-ready article suggestion from the operator's own input. Auto-resolves a default content plan; creates/links search-query rows for the keywords; returns suggestionId + contentPlanId. Free-tier compatible (no research run required).

NameTypeReqDescription
anglestring
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
primaryKeywordstringyes
projectIdstringyes
reasoningstring
searchIntentstring
secondaryKeywordsarray
targetAudiencestring
titlestringyes
wordCountTargetinteger

No output schema declared.

No examples provided.

create_content_plan_from_opportunities ~130

Create a content plan by harvesting the top-30 opportunity clusters from a completed research run. Auto-creates article suggestions linked to each cluster. Left out of the harvest: dismissed clusters (set_opportunity_status), keywords matching the project exclusion terms (set_excluded_terms), and clusters the site already covers (>=80% of keywords covered — refresh work on existing pages surfaces via editorial scores, not here).

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
projectIdstringyes

No output schema declared.

No examples provided.

create_project ~211

Create a new project — pass either a website URL or a niche description (or both). Returns projectId immediately; niche analysis and asset mapping run async. Poll get_project until niche.analysisStatus is ready. When the operator says whose site this is, pass siteRelation: mine (their own), client (an existing client), or prospect (a site they are pitching) — ask only if it is ambiguous, never guess. Optionally pass organizationId (see list_organizations) to create the project in a specific organization; it defaults to the personal organization.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
extrasarray
nicheDescriptionstring
organizationIdstring
originDescriptionstring
originInputstring
originTypestring
siteRelationstring
websitestring

No output schema declared.

No examples provided.

delete_article_suggestion ~63

Delete an article suggestion and its associated brief. Cascades to keyword and cluster links.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
idstringyes

No output schema declared.

No examples provided.

download_brief_markdown ~147

Get a brief as inline markdown the host agent can use as a writing prompt. Pass format=markdown_inline, and `channel` (article default) to pick which of the suggestion’s per-channel briefs to render. Returns the brief assembled into a single markdown string capped at ~8K chars — markdown only; the structured fields are get_article_brief’s job and are omitted here.

NameTypeReqDescription
channelstring
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
formatstringyes
projectIdstringyes
suggestionIdstringyes

No output schema declared.

No examples provided.

expand_idea ~115

Score a raw article idea against the project's niche without writing anything to the plan. Returns a title, angle, search intent, related queries, a coarse demand estimate, and a 0-100 niche-fit score. Pass the returned fields to accept_idea to commit the idea as a brief-ready suggestion.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
ideaTextstringyes
projectIdstringyes

No output schema declared.

No examples provided.

expand_radar_topic ~151

Expand one radar topic (by signalObservationId + topicIndex from list_radar_topics) into 3-6 candidate article angles with title, intent, and editorial positioning; each angle is flagged when a near-duplicate already exists in the content plan. Optionally pass customPov for angles from a specific point of view. No writes — pass chosen angles to add_radar_topic.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
customPovstring
projectIdstringyes
signalObservationIdstringyes
topicIndexintegeryes

No output schema declared.

No examples provided.

generate_article_brief ~312

Forge a writer-ready brief from an article suggestion. `channel` picks the brief template: article (default, SEO article outline), reels (hook/beats/shot list), youtube (retention beats/chapters), x (thread posts), linkedin (carousel slide deck: cover hook, one-idea slides, recap, CTA). A suggestion holds one brief per channel — generating a second channel adds a brief without touching the others. When the suggestion already has an article brief, channel briefs DERIVE from it (its key points, hook, and keyStats flow into the channel shape) and are free — they do not consume a daily brief slot. Idempotent per channel: if that channel already has a brief, returns it without consuming a slot; pass `force: true` to regenerate it. When regenerating, pass `guidance` — corrective direction the forge must follow (e.g. the angle the operator actually wants, a section to drop, an audience correction) — instead of re-rolling blind and hoping. Free tier: 10/day for article briefs and non-derived channel briefs. Returns `{ entitlement }` when the daily cap is reached.

NameTypeReqDescription
articleSuggestionIdstringyes
channelstring
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
forceboolean
guidancestring
projectIdstringyes

No output schema declared.

No examples provided.

get_account_status ~202

Get the operator account status — the organization whose plan/credits/limits this payload describes (plans and usage limits are per-organization; see list_organizations), current plan, available credits, brief quota state, the lint_draft daily verification cap (applies on every tier; check lint_drafts_remaining_today before a verification loop), the idea_checks allowance (check_idea is daily- AND monthly-capped on every tier; check remaining before a check loop), locked paid tools, the upgrade URL, and next_actions: the ranked cross-project queue of what to do next. Defaults to the personal organization; pass organizationId when working a project that belongs to a different organization — its shared caps are the ones project actions consume. Read on session start and after a wall hit.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
organizationIdstring

No output schema declared.

No examples provided.

get_article_brief ~232

Get the full content brief for an article suggestion. A suggestion holds one brief per channel — pass `channel` (article default | reels | youtube | x | linkedin) to pick which. Every brief carries hookStatement (one verbatim-usable hook sentence naming the reader payoff); article briefs also carry keyStats (a stat bank of { claim, value, source, sourceUrl } entries for evidence blocks and data slides). Pass compact=true to drop referenceArticles (informational only). internalLinks, curatedTargetQueries, and targetKeywords always populate. When the requested channel's brief does not exist yet, returns { hasBrief: false, briefStatus: 'queued' | 'forging' | 'none', queuedUntil } — 'queued' means the forge is waiting for the free daily cap to reset at queuedUntil; poll after that moment.

NameTypeReqDescription
channelstring
compactboolean
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
suggestionIdstringyes

No output schema declared.

No examples provided.

get_article_suggestion ~124

Get article suggestion details — metadata, cluster context, brief availability, registered derived assets (carousels, social posts), target keywords with volumes. Call get_article_brief for the full brief. Status semantics: generating_brief with briefQueuedAt set means the brief is QUEUED behind the free daily cap (forges automatically at reset); briefQueuedAt null means actively forging.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
suggestionIdstringyes

No output schema declared.

No examples provided.

get_changelog ~90

Get the URL of the VarynForge product changelog — what shipped, newest first, in plain markdown. Fetch it when the operator asks what is new, and in the days after a send_feedback report to check whether the gap they hit has been closed.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.

No output schema declared.

No examples provided.

get_competitor_detail ~87

Get a competitor company detail in a project context — domain, name, importance, top pages in the project SERPs, and top keywords they rank for.

NameTypeReqDescription
companyIdstringyes
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
projectIdstringyes

No output schema declared.

No examples provided.

get_draft_status ~207

Re-read an article suggestion's verification state without re-linting: the suggestion's single pipeline status plus, per destination `format`, the stored draft and the latest gate receipt (verdict, per-check detail, thresholds) from its last lint_draft submission. Free and uncapped — always use this instead of lint_draft to recover a known verdict. Pass `format` to read one destination including the stored draft text; omit it for the per-destination overview (receipts only, no draft bodies). Status-ownership model: ONE suggestion status drives the pipeline while verdicts are per-destination (N receipts), and status transitions are forward-only — a later flagged submission on one destination never demotes a suggestion another destination already moved to ready_to_publish.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
formatstring
suggestionIdstringyes

No output schema declared.

No examples provided.

get_instructions ~71

Get the VarynForge agent guide — workflow paths (free vs paid), token-economy rules, walls and upgrade conversation conventions. Read this at session start.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.

No output schema declared.

No examples provided.

get_keyword_detail ~77

Get a keyword detail — pages ranking for it with positions and ownership, plus related keywords already tracked in the project.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
projectIdstringyes
queryHashstringyes

No output schema declared.

No examples provided.

get_lint_rubric ~164

Get the verification rubric for an article suggestion: the submission format for the channel (markdown | --- separated thread | post-with-slides | production script), required vs advisory checks, the exact numeric limits each check grades against (checkParams), plus the brief fields lint_draft reads (keywords, outline, FAQ, channel payload). Pass `channel` to read the rubric of that channel's brief (article default) — use the same channel you will pass to lint_draft. Fetch this before writing so the draft passes on the first submission.

NameTypeReqDescription
channelstring
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
suggestionIdstringyes

No output schema declared.

No examples provided.

get_onboarding_guide ~141

Diagnose where the operator is in their VarynForge journey and get a guided setup path. Call when the operator asks to set up VarynForge, get started, or seems unsure what to do next — and always when list_projects returns empty. Returns the server-derived stage, a stage-tailored pitch to relay to the operator, a setup checklist with done/pending status per step, and the ranked next_actions queue. Diagnose before prescribing: never run the welcome pitch on an operator whose stage says producing.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.

No output schema declared.

No examples provided.

get_opportunity_detail ~106

Get a cluster detail — top-20 keywords by score, top-10 ranked pages by position, top-5 competitor podium, linked article suggestions, and rawOpportunityScore (un-normalized; list_opportunities returns the 0-100 normalized version).

NameTypeReqDescription
clusterIdstringyes
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
projectIdstringyes

No output schema declared.

No examples provided.

get_page_dossier ~93

Get a page dossier — URL, title, project rankings, ownership. `headingOutline`, `targetKeywords`, and `contentAnalysis` populate for owned (asset-mapped) pages only.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
pageIdstringyes
projectIdstringyes

No output schema declared.

No examples provided.

get_pitch_report_payload ~350

Assemble the client-ready pitch report payload for a completed research run — niche + solution profile, competitor landscape, ranked opportunity map holding GAPS ONLY (0-100 normalized; demand sized as volumeBucket buckets, no search-volume numbers by design; each entry carries overlapStatus net_new|partial plus siteOverlap — covered-keyword share + closest owned pages), coveredOpportunities as a separate defend-and-refresh list (topics the site already covers — never pitch these as new work), and a derived 90-day content sequence sized to the project posting cadence (postsPerWeek, up to 12 weeks; planned articles first, then gap topics marked type: topic — topics to develop, not article titles; covered clusters never enter the sequence; entries may carry advisory notes — near-duplicates, already-published near-matches, working titles needing a rewrite — keep the notes visible when rendering). assetProfile reports when the profile facts were last synced; when assetProfile.syncedBeforeRun is true, offer the operator the choice between resync_asset_profile first and rendering with the profile as-is, and always render the "Asset profile last synced <date>" stamp. renderGuide carries the full report structure with an explicit branding slot: render it in the operator’s own template (Docs, Slides, Notion, or PDF) under the operator’s name. Included with every run, no extra cost. Pass the runId from get_research_status; a run that is not completed returns { runStatus, report: null }.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
runIdstringyes

No output schema declared.

No examples provided.

get_project ~128

Get one project — its canonical name (operator-set, falling back to site brand then niche name), niche profile, target audience, current research status, and postsPerWeek (the operator’s publishing cadence, settable via set_posting_cadence; sizes the pitch report’s 90-day sequence). Address the project by `name`; `niche.name` is the market niche, not the project name.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
projectIdstringyes

No output schema declared.

No examples provided.

get_project_asset ~67

Get the asset (website/product) associated with a project — URL, name, description, solution profile.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
projectIdstringyes

No output schema declared.

No examples provided.

get_project_overview ~181

Get the at-a-glance read on a project — niche summary, keyword stats, nextActions (the ranked queue of what to do next in this project — offer its first entry when the operator asks "what now?"), and topPriorities: the ranked queue of article suggestions (best first — priorityScore desc; radar-born suggestions carry no score until briefed and rank oldest-first below scored ones; source tells you why score/cluster may be null). Entries already at ready_to_publish or published are done, not next — "do the next piece" = the first entry whose status still needs work (planned, brief_ready, drafting, draft_ready, reviewing).

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
projectIdstringyes

No output schema declared.

No examples provided.

get_research_status ~188

Poll the latest research run for a project — runId, status, current pipeline phase, progress percent, elapsed seconds, and structured failure diagnostics when failed. failure carries failureClass (upstream_timeout | upstream_rate_limited | invalid_input | internal | unknown), the phase the run died in, retryable (true = transient upstream issue, safe to retry; false = retrying will fail again — fix inputs or report it; null = unknown, retry at most once before reporting), and the raw message. A running run with phase "initializing" and large elapsedSeconds is stalled, not queued — report it instead of waiting. Token-light: returns a small fixed shape, no step payloads.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
projectIdstringyes

No output schema declared.

No examples provided.

get_starting_point_report ~175

Get the free starting-point report for a project — a client-facing document assembled from setup-time data: positioning (niche + market profile), the site and its current content inventory, the curated competitor set, and early rising-topic signals. Free on every plan, no research run required. markdown is the ready-to-send render; the structured fields are the same data for custom rendering. lockedSections names the sections a research run adds (full opportunity map, 90-day sequence, competitor gap analysis) — absent here, not previewed. Once the project has a completed run, prefer get_pitch_report_payload: that is the full report.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
projectIdstringyes

No output schema declared.

No examples provided.

get_write_handoff ~150

One-call writer handoff: returns a compact writing payload for an article suggestion (brief essentials, keywords, acceptance criteria, lint instructions). Compact by design — FAQs cap at 6 and long sections degrade to fit a deep-link budget; the FULL brief is get_article_brief and the full check list is get_lint_rubric, so verify against those, not this. deepLinks (ChatGPT/Claude URLs embedding the payload) is null over MCP — it exists for web users without a connected agent.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
suggestionIdstringyes

No output schema declared.

No examples provided.

get_writer_system_prompt ~182

Get the writer system prompt for drafting one content type from its brief. The writer works with your Varyn account context: every channel prompt binds to the brief, its acceptance rubric, and the opportunity behind the brief fetched from the account, and degrades to generic writing advice without them. Pass `channel` (article | x | linkedin | reels | youtube) — each channel has its own methodology: article covers voice adaptation, structure rules, and the acceptance checklist; x covers thread mechanics; linkedin covers post + carousel slides; reels and youtube cover the production script (brief -> script -> video). Load the prompt for the channel you are about to draft; article is the default.

NameTypeReqDescription
channelstringyes
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.

No output schema declared.

No examples provided.

lint_draft ~529

Submit a draft for verification against its brief. Returns a pass/flag verdict with per-check detail. Pass moves the article to ready_to_publish; flag moves it to draft_ready for revision. `channel` (article | reels | youtube | x | linkedin) declares WHICH of the suggestion's per-channel briefs the draft is graded against AND the submission shape — always pass it for non-article content; when omitted, the channel is inferred from `format`. Submission shapes (get_lint_rubric returns the same spec + the numeric limits): article = markdown draft; x = thread text with one post per --- separated section, NO links in post bodies (put links in a reply); linkedin = post/caption text first, optional --- separated carousel slides after, NO links in the body (put links in the first comment); reels/youtube = the production SCRIPT — the process is brief -> script -> video, this gate validates the script, and the video is produced after it passes (published URL is recorded at publish time, not here). `format` labels the storage destination: prefer one of the project's destination type ids (see list_destinations) so receipts and drafts group per destination — re-submitting the same `format` replaces that destination's draft, a different `format` keeps both. The response reports the suggestion's post-lint `status` and a `nextAction` hint; `thresholds` is the article ratio block on the article channel and null otherwise (channel limits live in get_lint_rubric checkParams). `waiveChecks` marks check ids the OPERATOR deliberately deviates from (e.g. a brief section they dropped on purpose): waived checks still run and are recorded as waived in the receipt, but no longer fail the verdict — only pass ids the operator explicitly waived, never waive on your own initiative. Verdicts and drafts are stored per `format` and re-readable any time via get_draft_status (free — never re-lint to recover a lost verdict). Status transitions are forward-only: a flagged re-submit never demotes a sugge…

NameTypeReqDescription
channelstring
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
draftstringyes
formatstring
suggestionIdstringyes
waiveChecksarray

No output schema declared.

No examples provided.

list_article_suggestions ~218

List article suggestions for a project — title, status, priority, cluster, intent, source, publishedAt, scheduledFor, and a per-channel distributions rollup ({ channel, count, latestAt, scheduledFor } per channel the content went out on). Use distributions to spot gaps from the list alone — e.g. items with no linkedin entry have no LinkedIn post yet — without per-item reads. Page through suggestions; call get_article_suggestion for the full record. Status semantics: generating_brief with briefQueuedAt set means the brief is QUEUED behind the free daily cap and forges automatically at cap reset (get_article_brief returns queuedUntil); generating_brief with briefQueuedAt null means it is actively forging — re-check within a minute.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
cursor
limitnumberyes
projectIdstringyes
status

No output schema declared.

No examples provided.

list_competitors ~116

List companies for a project — marked competitors (important / default / ignored) and SERP-discovered companies (unmarked). Sorted important → default → unmarked → ignored, then by domain. Pass `importance` to filter to one bucket. Capped at 100.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
importancestring
limitnumberyes
projectIdstringyes

No output schema declared.

No examples provided.

list_destinations ~218

List the project's destinations — where the operator publishes (website, youtube_channel, tiktok, instagram, x, linkedin, local_business). Destination type ids are the `format` labels lint_draft stores drafts under. Each row carries its capabilities so you never cross-reference other tools: `briefChannel` is the brief/lint channel the type maps onto (null for open slots), `verifiable` says lint_draft can grade drafts for it, `publishable` says it is live and its published URLs can be recorded, and `publishVia` names the recording tool (mark_article_published for article-channel destinations, register_derived_asset for social/video; null while planned). An empty list means the operator has not configured destinations — add one with add_destination, or fall back to the brief channel name as the lint_draft `format` label.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
projectIdstringyes

No output schema declared.

No examples provided.

list_keywords ~107

List keywords tracked for a project — text, difficulty, intent, volume bucket (no_traffic | long_tail | average | high). Paginated; supports sorting and intent filter.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
cursor
filtersobject
limitnumberyes
projectIdstringyes
sortingarray

No output schema declared.

No examples provided.

list_opportunities ~275

List content opportunity clusters sorted by opportunity score. Goal filters: fast_wins, high_intent, authority_building, competitor_gap. coverage filters by site-coverage status and defaults to ["gap","partial"] — clusters the site already COVERS (ranks top-10 for a cluster keyword) are hidden unless "covered" is included (refresh candidates). Dismissed clusters (set_opportunity_status) are hidden, and keywords matching the project exclusion terms (set_excluded_terms) down-weight their cluster scores. Clusters flagged by the asset-fit assessment (fitFlag unservable_feature | off_catalog, with fitReason explaining why) are down-weighted rather than hidden — treat them as comparison-content candidates at best, never headline opportunities. Scores are normalized 0-100 against the highest-scoring visible cluster, so coverage filtering, dismissing, excluding, or fit-flagging can shift the relative numbers of other clusters.

NameTypeReqDescription
activeMetaCluster
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
coveragearray
cursor
excludeInContentPlanboolean
goal
limitnumberyes
projectIdstringyes

No output schema declared.

No examples provided.

list_organizations ~129

List the organizations this account belongs to — id, name, your role (owner | admin | member), is_personal, plan, and member_count — plus pending invitations awaiting a response (accept them in the web app). Plans, credits, and usage limits are per-organization, and a project belongs to exactly one organization. Pass an organizationId to create_project to target a specific organization, or to get_account_status to read that organization’s caps.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.

No output schema declared.

No examples provided.

list_pages ~97

List ranked pages tracked for a project — URL, title, company, query count, ownership. Filter by ownership or company domain.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
cursor
filtersobject
limitnumberyes
projectIdstringyes
sortingarray

No output schema declared.

No examples provided.

list_projects ~158

List all projects for the authenticated operator — paginated, sortable by createdAt, niche, or industry. `name` is the canonical project name (operator-set, falling back to site brand then niche name) — match operator references against it; `niche.name` is the market niche, distinct metadata. lastActivityAt is the most recent change to the project or any of its content pieces — when the operator says "my project" without naming one, the highest lastActivityAt is the right pick.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
cursor
limitnumberyes
sortingarray

No output schema declared.

No examples provided.

list_radar_topics ~114

List the latest emergent-topic radar snapshot for a project: rising narrative topics (label, summary, momentum, novelty, drivers, evidence) with per-topic index and how many article suggestions were already added from each. Returns null when the project has no radar snapshot yet. Use expand_radar_topic to turn a topic into article angles.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
projectIdstringyes

No output schema declared.

No examples provided.

mark_article_published ~295

Record that an article went live at a URL. Flips the suggestion to published, writes the distribution ledger row, stamps the Passport, and pings IndexNow. Call it only once the URL actually resolves — the IndexNow ping fires immediately, and a ping for a dead URL is wasted (search engines crawl, hit the 404, drop it; nothing re-pings later). For a CMS-scheduled article, set scheduledFor via update_article_status and stay in ready_to_publish: publish auto-detect attests it (and pings IndexNow) when it appears. Use this instead of update_article_status for the published transition — a status flip alone records no URL, and without a URL the article is invisible to Search Console outcome tracking (clicks/impressions on the Earnings page). Also works on an already-published suggestion to attach a missing or corrected URL. Pass `publishedAt` (ISO datetime, must not be in the future) when the article went live EARLIER than this call — e.g. attesting after the fact or matching a CMS publish date — so the record carries the real go-live moment instead of the call time.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
idstringyes
publishedAtstring
publishedUrlstringyes

No output schema declared.

No examples provided.

register_derived_asset ~231

Register a derived asset (LinkedIn carousel PDF, social post, video, image) produced from an article suggestion. Appends a distribution-ledger row so the suggestion shows everything it produced — the article plus its derivatives — for content-ROI reporting (get_article_suggestion returns them as derivedAssets). Pass `channel` (reels | youtube | x | linkedin) so the app can show per-channel distribution status; register again with a new URL for repeat posts on the same channel — every registration is kept. `scheduledFor` records a future post date from an external scheduler (Buffer etc.) for display only — VarynForge never posts on your behalf. Derivative rows never affect publish status or Search Console attribution; use mark_article_published for the article itself.

NameTypeReqDescription
channelstring
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
kindstringyes
scheduledForstring
suggestionIdstringyes
urlstringyes

No output schema declared.

No examples provided.

remap_asset ~94

Re-crawl the project website and refresh its owned pages. Use when get_project_asset shows mappingStatus "error" or owned pages look stale. Rate-limited per site; returns an error naming the wait time if the cooldown is active.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
projectIdstringyes

No output schema declared.

No examples provided.

resync_asset_profile ~165

Re-read the project website and re-infer the asset profile (name, description, primary offer, benefits, differentiators, use cases) from its current content. Use before rendering a report when get_pitch_report_payload flags assetProfile.syncedBeforeRun — the stored profile facts may have drifted since they were written. Overwrites the profile facts (fields the site no longer supports inferring are left unchanged, never nulled) and stamps profileSyncedAt; the niche is not touched. Rate-limited per site; returns an error naming the wait time if the cooldown is active.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
projectIdstringyes

No output schema declared.

No examples provided.

send_feedback ~233

File a note to the VarynForge team: a bug, a missing capability, a friction point, or an operator idea. Call when you hit something VarynForge cannot do, a confusing tool result, or the operator voices frustration or a wish. Whenever the task would benefit from a capability this tool list does not offer, file a missing_capability BEFORE you settle for a workaround with existing tools, even if they could work as a fallback. Do NOT file entitlement walls (PAYMENT_REQUIRED / RATE_LIMITED / FEATURE_LOCKED payloads) — those are working as designed. Feedback is a note to the team, never a ticket: do not promise the operator it will be fixed. There is no reply — read get_changelog over the following days to see whether the gap closed.

NameTypeReqDescription
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
detailstring
kindstringyes
projectIdstring
summarystringyes
toolContextstring

No output schema declared.

No examples provided.

set_competitor_importance ~158

Mark a competitor important, default, or ignored. Important applies a 1.25× boost on opportunity scores for clusters where the competitor ranks top-10. Scores are then normalized 0-100 against the highest-scoring cluster, so other clusters may appear to drop in relative ranking even when their absolute (raw) scores did not change — cross-check via get_opportunity_detail.rawOpportunityScore. Ignored hides the competitor from competitor surfaces and the editorial-score pipeline.

NameTypeReqDescription
companyIdstringyes
contextstringyesOne sentence: what is the operator trying to achieve right now? Describe their goal, not this tool's purpose.
importancestringyes
projectIdstringyes

No output schema declared.

No examples provided.

Common questions

What is the VarynForge MCP server?

VarynForge is an MCP server listed in the public MCP registry as com.varynforge/server. SEO research SaaS exposed as 30+ MCP tools. Forge niche analysis, plans, and writer-ready briefs. This page covers its hosted endpoint (https://app.varynforge.com/api/mcp).

Is the VarynForge MCP server safe to use?

VarynForge scores 83 out of 100 on VerifyMCP. 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 VarynForge MCP server expose?

VarynForge exposes 57 tools: get_instructions, get_changelog, get_writer_system_prompt, get_account_status, list_organizations, and 52 more. Their descriptions and schemas cost roughly 9,371 tokens of context every time the server is loaded.

Does the VarynForge MCP server require authentication?

Yes. VarynForge asked us for credentials when we connected, so you will need to authorise it in your MCP client before it can do anything.

Is the VarynForge MCP server still maintained?

VarynForge is still listed as active in the MCP registry. We last reached this channel on 20 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.