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

VHGENGINE

REMOTE · ENGINE-PRODUCTION-3BDC.UP.RAILWAY.APP · SCANNED AUG 3

Agents-first viral-hook engine: generate, score, and remix short-form hooks over MCP.

+13 this week 65 Trust /100
Trust breakdown (6 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 →

Endpoint Security63
Transport & Reachability100
Schema Quality & AI Usability53
  • 43% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Partial
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 14279 tokens (~274/item across 52 items; 38 tools + 14 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 Management27
  • Stability observed for 8 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage100
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 100% of tool parameters carry a description.Pass
  • Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Install

Add this component to your MCP client. Where a client-specific snippet is available, pick your client below and copy it straight into your config; otherwise use the connection detail shown.

remote · engine-production-3bdc.up.railway.app

# add to Claude Code
claude mcp add --transport http app-railway-up-engine-production-3bdc-vhgengine https://engine-production-3bdc.up.railway.app/mcp
# ~/.codex/config.toml
[mcp_servers.app-railway-up-engine-production-3bdc-vhgengine]
url = "https://engine-production-3bdc.up.railway.app/mcp"
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "app-railway-up-engine-production-3bdc-vhgengine": {
      "type": "remote",
      "url": "https://engine-production-3bdc.up.railway.app/mcp",
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add app-railway-up-engine-production-3bdc-vhgengine --url https://engine-production-3bdc.up.railway.app/mcp --transport streamable-http
# ~/.hermes/config.yaml
mcp_servers:
  app-railway-up-engine-production-3bdc-vhgengine:
    url: "https://engine-production-3bdc.up.railway.app/mcp"
// mcp.json
{
  "mcpServers": {
    "app-railway-up-engine-production-3bdc-vhgengine": {
      "type": "http",
      "url": "https://engine-production-3bdc.up.railway.app/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.

  • 3 Aug 26 +6
    • The server rewrote its instructions, which are the text every model session reads security
    • New tool “cancel_job”, which the server declares destructive security
    • Tool “delete_account” rewrote its description, which is the text the model reads security
    • Tool “generate_hooks” rewrote its description, which is the text the model reads security
    • Tool “generate_hooks_batch” rewrote its description, which is the text the model reads security
    • Tool “get_account” rewrote its description, which is the text the model reads security
    • Tool “get_usage” rewrote its description, which is the text the model reads security
    • Tool “health” rewrote its description, which is the text the model reads security
    • Tool “list_hooks” rewrote its description, which is the text the model reads security
    • Tool “remix_hook” rewrote its description, which is the text the model reads security
    • Tool “score_hook” rewrote its description, which is the text the model reads security
    • Tool “signup” rewrote its description, which is the text the model reads security
    • Tool “start_generate_job” rewrote its description, which is the text the model reads security
    • Schema quality: 138 → 274 functional
    • Schema quality: 0% → 43% functional
    • Tool coverage: 0% → 100% functional
    • Schema quality: good → excellent functional
    • New resource “client-guide-claude-desktop” functional
    • New resource “client-guide-codex” functional
    • New resource “client-guide-cursor” functional
    • New resource “client-guide-rest” functional
    • New resource “sample” functional
    • New resource “client-guide-chatgpt” functional
    • New resource “client-guide-claude-code” functional
    • New tool “quote” functional
    • New tool “export_usage” functional
    • New tool “list_billing_events” functional
    • New tool “list_runs” functional
    • New tool “wait_for_job” functional
    • “get_usage” added an optional parameter “offset” cosmetic
    • “remix_hook” added an optional parameter “archetype” cosmetic
    • “remix_hook” added an optional parameter “hook_id” cosmetic
    • “remix_hook” added an optional parameter “platform” cosmetic
    • “remix_hook” added an optional parameter “topic” cosmetic
    • “score_hook” added an optional parameter “topic” cosmetic
    • “score_hooks_batch” added an optional parameter “topic” cosmetic
    • “add_credits” reworded the description of “admin_key” cosmetic
    • “add_credits” reworded the description of “amount” cosmetic
    • “add_credits” reworded the description of “api_key” cosmetic
    • “add_credits” reworded the description of “idempotency_key” cosmetic
    • “create_checkout” reworded the description of “api_key” cosmetic
    • “create_checkout” reworded the description of “cancel_url” cosmetic
    • “create_checkout” reworded the description of “pack” cosmetic
    • “create_checkout” reworded the description of “success_url” cosmetic
    • “create_key” reworded the description of “api_key” cosmetic
    • “create_key” reworded the description of “daily_credit_cap” cosmetic
    • “create_key” reworded the description of “name” cosmetic
    • “create_key” reworded the description of “scopes” cosmetic
    • “delete_account” reworded the description of “api_key” cosmetic
    • “delete_account” reworded the description of “confirm” cosmetic
    • “delete_webhook” reworded the description of “api_key” cosmetic
    • “generate_hooks” reworded the description of “api_key” cosmetic
    • “generate_hooks” reworded the description of “archetypes” cosmetic
    • “generate_hooks” reworded the description of “count” cosmetic
    • “generate_hooks” reworded the description of “deadline_ms” cosmetic
    • “generate_hooks” reworded the description of “idempotency_key” cosmetic
    • “generate_hooks” reworded the description of “mode” cosmetic
    • “generate_hooks” reworded the description of “platform” cosmetic
    • “generate_hooks” reworded the description of “style” cosmetic
    • “generate_hooks” reworded the description of “tags” cosmetic
    • “generate_hooks” reworded the description of “topic” cosmetic
    • “generate_hooks” reworded the description of “verbosity” cosmetic
    • “generate_hooks_batch” reworded the description of “api_key” cosmetic
    • “generate_hooks_batch” reworded the description of “idempotency_key” cosmetic
    • “generate_hooks_batch” reworded the description of “mode” cosmetic
    • “generate_hooks_batch” reworded the description of “platform” cosmetic
    • “generate_hooks_batch” reworded the description of “requests” cosmetic
    • “generate_hooks_batch” reworded the description of “tags” cosmetic
    • “generate_hooks_batch” reworded the description of “verbosity” cosmetic
    • “get_account” reworded the description of “api_key” cosmetic
    • “get_activity” reworded the description of “api_key” cosmetic
    • “get_activity” reworded the description of “recent_limit” cosmetic
    • “get_hook” reworded the description of “api_key” cosmetic
    • “get_hook” reworded the description of “hook_id” cosmetic
    • “get_job” reworded the description of “api_key” cosmetic
    • “get_job” reworded the description of “job_id” cosmetic
    • “get_usage” reworded the description of “api_key” cosmetic
    • “get_usage” reworded the description of “key_prefix” cosmetic
    • “get_usage” reworded the description of “recent_limit” cosmetic
    • “get_usage” reworded the description of “request_id” cosmetic
    • “get_usage” reworded the description of “tag” cosmetic
    • “get_webhook” reworded the description of “api_key” cosmetic
    • “list_hooks” reworded the description of “api_key” cosmetic
    • “list_hooks” reworded the description of “limit” cosmetic
    • “list_hooks” reworded the description of “mode” cosmetic
    • “list_hooks” reworded the description of “offset” cosmetic
    • “list_hooks” reworded the description of “since” cosmetic
    • “list_hooks” reworded the description of “tag” cosmetic
    • “list_hooks” reworded the description of “topic” cosmetic
    • “list_hooks” reworded the description of “unreported” cosmetic
    • “list_jobs” reworded the description of “api_key” cosmetic
    • “list_jobs” reworded the description of “limit” cosmetic
    • “list_jobs” reworded the description of “offset” cosmetic
    • “list_keys” reworded the description of “api_key” cosmetic
    • “list_outcomes” reworded the description of “api_key” cosmetic
    • “list_outcomes” reworded the description of “hook_id” cosmetic
    • “list_outcomes” reworded the description of “limit” cosmetic
    • “list_outcomes” reworded the description of “offset” cosmetic
    • “list_outcomes” reworded the description of “platform” cosmetic
    • “list_outcomes” reworded the description of “since” cosmetic
    • “list_webhook_deliveries” reworded the description of “api_key” cosmetic
    • “list_webhook_deliveries” reworded the description of “limit” cosmetic
    • “list_webhook_deliveries” reworded the description of “offset” cosmetic
    • “list_webhook_deliveries” reworded the description of “status” cosmetic
    • “redrive_webhook_delivery” reworded the description of “api_key” cosmetic
    • “redrive_webhook_delivery” reworded the description of “delivery_id” cosmetic
    • “remix_hook” reworded the description of “api_key” cosmetic
    • “remix_hook” reworded the description of “count” cosmetic
    • “remix_hook” reworded the description of “idempotency_key” cosmetic
    • “remix_hook” reworded the description of “tags” cosmetic
    • “remix_hook” reworded the description of “target_archetype” cosmetic
    • “remix_hook” reworded the description of “text” cosmetic
    • “remix_hook” reworded the description of “verbosity” cosmetic
    • “report_outcome” reworded the description of “api_key” cosmetic
    • “report_outcome” reworded the description of “hook_id” cosmetic
    • “report_outcome” reworded the description of “idempotency_key” cosmetic
    • “report_outcome” reworded the description of “likes” cosmetic
    • “report_outcome” reworded the description of “platform” cosmetic
    • “report_outcome” reworded the description of “posted_at” cosmetic
    • “report_outcome” reworded the description of “retention_pct” cosmetic
    • “report_outcome” reworded the description of “url” cosmetic
    • “report_outcome” reworded the description of “views” cosmetic
    • “revoke_key” reworded the description of “api_key” cosmetic
    • “revoke_key” reworded the description of “prefix” cosmetic
    • “score_hook” reworded the description of “api_key” cosmetic
    • “score_hook” reworded the description of “idempotency_key” cosmetic
    • “score_hook” reworded the description of “platform” cosmetic
    • “score_hook” reworded the description of “tags” cosmetic
    • “score_hook” reworded the description of “text” cosmetic
    • “score_hook” reworded the description of “verbosity” cosmetic
    • “score_hooks_batch” reworded the description of “api_key” cosmetic
    • “score_hooks_batch” reworded the description of “compare” cosmetic
    • “score_hooks_batch” reworded the description of “idempotency_key” cosmetic
    • “score_hooks_batch” reworded the description of “platform” cosmetic
    • “score_hooks_batch” reworded the description of “sets” cosmetic
    • “score_hooks_batch” reworded the description of “tags” cosmetic
    • “score_hooks_batch” reworded the description of “texts” cosmetic
    • “score_hooks_batch” reworded the description of “verbosity” cosmetic
    • “set_webhook” reworded the description of “api_key” cosmetic
    • “set_webhook” reworded the description of “url” cosmetic
    • “signup” reworded the description of “email” cosmetic
    • “signup” reworded the description of “idempotency_key” cosmetic
    • “signup” reworded the description of “name” cosmetic
    • “start_generate_job” reworded the description of “api_key” cosmetic
    • “start_generate_job” reworded the description of “archetypes” cosmetic
    • “start_generate_job” reworded the description of “count” cosmetic
    • “start_generate_job” reworded the description of “idempotency_key” cosmetic
    • “start_generate_job” reworded the description of “mode” cosmetic
    • “start_generate_job” reworded the description of “platform” cosmetic
    • “start_generate_job” reworded the description of “style” cosmetic
    • “start_generate_job” reworded the description of “tags” cosmetic
    • “start_generate_job” reworded the description of “topic” cosmetic
    • “start_generate_job” reworded the description of “topics” cosmetic
    • “remix_hook” made “target_archetype” optional cosmetic
    • “remix_hook” made “text” optional cosmetic
  • 1 Aug 26 +1

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

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

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

  • 28 Jul 26 +1

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

  • 27 Jul 26 0
    • We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
  • 26 Jul 26 52

    First indexed and scored.

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 3 Aug 2026 · Probed https://engine-production-3bdc.up.railway.app/mcp

TLS valid

Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .

Subject Issuer Valid from Valid until Key Signature Serial
CN=*.up.railway.app CN=YE1,O=Let's Encrypt,C=US 29 Jul 2026 27 Oct 2026 ECDSA 256 ECDSA-SHA384 6da79bb561da3efeb0e751ca21abd3999fe
SANs: *.up.railway.app, up.railway.app
CN=YE1,O=Let's Encrypt,C=US (CA) CN=Root YE,O=ISRG,C=US 3 Sept 2025 2 Sept 2028 ECDSA 384 ECDSA-SHA384 5ddd70dd31f801c85c186a7a04b80afe
CN=Root YE,O=ISRG,C=US (CA) CN=ISRG Root X2,O=Internet Security Research Group,C=US 13 May 2026 2 Sept 2032 ECDSA 384 ECDSA-SHA384 872165fc34b6e5fba8add5b3705fb53a
CN=ISRG Root X2,O=Internet Security Research Group,C=US (CA) CN=ISRG Root X1,O=Internet Security Research Group,C=US 13 May 2026 2 Sept 2032 ECDSA 384 SHA256-RSA 6c8f1dc727c7117f7baf853ac980f9cd
DNSSEC insecure

Validation of engine-production-3bdc.up.railway.app. Not signed

Zone DS Keys Algorithms Outcome
. trust_anchor 20326, 38696 8, 8 Verified
app. present 23684 8 Verified
railway.app. absent Unsigned (proven) parent-signed NSEC/NSEC3 proves an unsigned delegation
Authentication No authorisation required

The endpoint answered without asking for a token. Anyone who knows the URL can reach it.

Result No authorisation required
HTTP status 200
Header Value
strict-transport-security max-age=31536000
x-content-type-options nosniff
Transports 2 probes
Transport URL Outcome Status Location
streamable-http https://engine-production-3bdc.up.railway.app/mcp Verified 200
http (plaintext) http://engine-production-3bdc.up.railway.app/mcp HTTPS enforced 301 https://engine-production-3bdc.up.railway.app/mcp
MCP tools — 38 exposed · ~12,802 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.

Tool Tokens
score_hooks_batch ~688

Score many hooks ranked with `best`, or compare named SETS. 1 credit per text. All-or-nothing charge. Plain: texts (1-25, each 3-300 chars). Self-test (E13): compare=true + sets (2-4 named lists, <=25 texts total) INSTEAD of texts -> per-set rankings + avg_score + winner + an honest winner_summary (same heuristic scorer on every set, never view prediction). Also: platform, tags, verbosity, api_key, idempotency_key. Returns {results, best, ...} or {sets, winner, winner_summary, ...}. Errors: unauthorized, invalid_request, insufficient_credits, rate_limited.

NameTypeReqDescription
api_keyAPI key for this call. Omit to fall back to the Authorization: Bearer / X-API-Key request header (streamable-HTTP only), then the VHGENGINE_API_KEY env var (the stdio default). No key resolvable -> u…
comparebooleanSwitch on compare mode, which requires `sets` and returns per-set rankings + a winner instead of one flat ranking. Leave false for the ordinary texts ranking.
idempotency_keyCaller-chosen replay key (any string, unique per intended effect). A repeat call with the SAME key returns the stored result and is NEVER charged twice; the same key with different arguments is an id…
platformstringTarget platform, which selects the length/format conventions the hooks are written and scored against. Defaults to tiktok when omitted.
setsCompare mode input: 2-4 NAMED variant lists, e.g. {"curiosity": ["..."], "contrarian": ["..."]}, each 1-25 texts and <=25 texts across all sets. Requires compare=true and excludes `texts`. Every set…
tags1-5 lowercase slug tags ([a-z0-9_-], <=40 chars) stamped on this call's usage event so a fleet can attribute spend per campaign. Omit for no tagging. Filter later with get_usage(tag=...) / list_hooks…
texts1-25 hook lines (3-300 chars each) to score and rank. Use this OR sets, never both: texts is the plain ranked mode, sets is the compare mode. 1 credit per text either way.
topicWhat the hooks are about, 3-200 chars. Supply it to score these lines the way they were generated: the scorer penalises a line that only echoes its own topic back, and it cannot apply that penalty to…
verbositystringHow much of the response envelope to return: minimal (ids/text/totals only), standard (the default), full (adds per-dimension score attribution and timings). Shapes the RESPONSE only, never what is g…
NameTypeReqDescription
bestPlain mode: the highest-scoring entry.
credits_chargednumber|nullCredits this call actually cost.
credits_remainingnumber|nullYour balance AFTER this charge.
replayedboolean|nulltrue when an idempotency_key replayed a stored result, so nothing was charged again. The credits_charged below is what the ORIGINAL call cost.
replayed_at_chargeboolean|nulltrue when the replay was detected at the charge boundary rather than up front; either way you are billed exactly once.
request_idstring|nullId of this call. Keep it: get_usage(request_id=...) itemises exactly what it charged, and it identifies the call in a support question.
resultsarray|nullPlain mode: one scored entry per text, ranked.
setsobject|nullCompare mode: per-set rankings and avg_score, keyed by your set names.
winnerstring|nullCompare mode: the winning set name.
winner_summarystring|nullCompare mode: an honest reading of the win. The same heuristic scorer runs on every set, so this is a craft comparison, never a view prediction.

No examples provided.

set_webhook ~264

Register (or replace) this account's webhook; the secret is returned ONCE. Admin scope. VHGENGINE POSTs signed job.succeeded/job.failed/credits.low (WP-M). `url` https, no creds, public host; re-registering ROTATES the secret (a repeat call is not a no-op). Verify via X-VHG-Signature: sha256=HMAC_SHA256(secret, raw_body); a webhook.test pings. Args: url (1-2048), api_key (admin). Cost=free. Errors: unauthorized, forbidden, invalid_request, rate_limited. Returns {url, secret, created_at, events, note, test_delivery_id}.

NameTypeReqDescription
api_keyAPI key for this call. Omit to fall back to the Authorization: Bearer / X-API-Key request header (streamable-HTTP only), then the VHGENGINE_API_KEY env var (the stdio default). No key resolvable -> u…
urlstringyeshttps:// endpoint that will receive signed event POSTs. Must be a public host with no embedded credentials. Re-registering ANY url rotates the signing secret, so this is not safe to blind-retry.
NameTypeReqDescription
created_atstring|nullRegistration time, ISO-8601 UTC.
eventsarray|nullEvent types that will be delivered.
notestring|nullHuman-readable summary, including the rotation warning.
secretstring|nullHMAC signing secret, shown exactly once. Verify deliveries with X-VHG-Signature: sha256=HMAC_SHA256(secret, raw_body).
test_delivery_idstring|nullA webhook.test ping enqueued immediately; look it up with list_webhook_deliveries to prove your receiver works.
test_notestring|nullWhat that test delivery is and how to check it.
urlstring|nullThe endpoint now registered.

No examples provided.

signup ~241

Create an account and return your API key exactly once. No auth needed. The entry point: an agent with nothing calls this and is productive immediately (no CAPTCHA); new accounts get 500 credits. An idempotent replay returns the SAME account with replayed:true and a NULL api_key (the plaintext is never stored), so branch on `replayed`, never on the empty key. Cost: free. Errors: invalid_request, idempotency_conflict, rate_limited.

NameTypeReqDescription
emailOPTIONAL contact address. Never required, never verified, and never used to authenticate; the api_key is the only credential.
idempotency_keyCaller-chosen replay key (any string, unique per intended effect). A repeat call with the SAME key returns the stored result and is NEVER charged twice; the same key with different arguments is an id…
namestringDisplay name for the account, 1-100 chars. Purely a label (it is never checked for uniqueness); defaults to 'agent'.
NameTypeReqDescription
account_idstring|nullYour account id. Not a credential.
api_keystring|nullThe plaintext key, returned EXACTLY once. NULL on an idempotent replay (the plaintext is never stored), so store it on first sight: it cannot be re-read.
api_key_prefixstring|nullFirst 12 chars of the key, safe to log and to pass to revoke_key.
created_atstring|nullAccount creation time, ISO-8601 UTC.
creditsnumber|nullStarting balance (500 on a fresh account).
docsobject|nullWhere to read more, keyed by topic.
memory_cardA compact block worth persisting into your own memory.
next_stepsarray|nullOrdered suggestions for what to call next.
notestring|nullHuman-readable summary of the above.
replayedboolean|nulltrue when this response replays an earlier signup with the same idempotency_key (and therefore carries no api_key); false on a fresh one.

No examples provided.

start_generate_job ~667

Submit a generate as an async job; poll get_job for the result. Same args as generate_hooks (tags persist); charge runs on the worker; results are always full-verbosity; prefer for research. EITHER topic OR topics (1-20 subjects, ONE job + one atomic charge, result = the batch envelope); both or neither is invalid_request. A job only runs where a job worker runs: when none does the response carries worker_alive:false + a warning, so call generate_hooks instead. Errors: unauthorized, invalid_request, insufficient_credits, idempotency_conflict.

NameTypeReqDescription
api_keyAPI key for this call. Omit to fall back to the Authorization: Bearer / X-API-Key request header (streamable-HTTP only), then the VHGENGINE_API_KEY env var (the stdio default). No key resolvable -> u…
archetypesRestrict generation to these archetype ids (see list_archetypes). Omit to let the engine spread across archetypes, which is what you want unless you are deliberately narrowing a deck.
countintegerHooks per topic, 1-25. With `topics` this applies to every subject, so the job's cost scales with count * len(topics).
idempotency_keyCaller-chosen replay key (any string, unique per intended effect). A repeat call with the SAME key returns the stored result and is NEVER charged twice; the same key with different arguments is an id…
modeGeneration engine and therefore the price: instant (0 base + 1/hook, deterministic templates, sub-second), smart (0 + 2/hook, one LLM call, seconds), research (10 + 4/hook, brief->draft->judge, tens…
platformstringTarget platform, which selects the length/format conventions the hooks are written and scored against. Defaults to tiktok when omitted.
styleVoice/tone to match, <=200 chars. Honored as a real instruction by smart and research; on instant it only varies which deterministic template fillers are drawn, so it cannot change the voice there. O…
tags1-5 lowercase slug tags ([a-z0-9_-], <=40 chars) stamped on this call's usage event so a fleet can attribute spend per campaign. Omit for no tagging. Filter later with get_usage(tag=...) / list_hooks…
topicSingle subject for the job, 3-200 chars. Pass EITHER this or `topics`, never both and never neither.
topics1-20 subjects run as ONE job with ONE atomic charge; the result is the batch envelope instead of a single generate body. Pass EITHER this or `topic`.
NameTypeReqDescription
estimated_secondsnumber|nullQueue-aware estimate of total time to a result.
expires_atstring|nullWhen an unexecuted job is abandoned, ISO-8601 UTC.
job_idstring|nullPass this to get_job.
poll_after_secondsnumber|nullWait at least this long before the first get_job. Honor it.
replayedboolean|nulltrue when an idempotency_key returned an EXISTING job rather than queuing a new one. Poll the returned job_id either way.
requeuedboolean|nulltrue when an idempotent resubmit revived an existing job.
statusstring|nullLifecycle state; 'queued' immediately after submit.
status_urlstring|nullREST URL for the same status (HTTP clients only).
warningstring|nullPresent only alongside worker_alive:false; says what to do instead.
worker_aliveboolean|nullPresent and FALSE only when no job worker will ever run this job. Then read `warning` and use generate_hooks instead of polling.

No examples provided.

wait_for_job ~312

Block until a job is terminal, then return it. Free, bounded, no poll loop. Returns the EXACT get_job body plus timed_out, waited_ms and polls, so branch on `status` exactly as you would with get_job. timed_out:true is NOT a failure, it means the budget ran out: call again with the SAME job_id. Waiting neither cancels nor charges; the worker charges when it runs the job either way. It returns IMMEDIATELY with worker_alive:false + `warning` when no worker exists here. Errors: unauthorized, not_found (unknown or foreign job_id), rate_limited.

NameTypeReqDescription
api_keyAPI key for this call. Omit to fall back to the Authorization: Bearer / X-API-Key request header (streamable-HTTP only), then the VHGENGINE_API_KEY env var (the stdio default). No key resolvable -> u…
job_idstringyesThe job to wait on, as returned by start_generate_job (or by a generate_hooks call that auto-jobbed on deadline_ms). Account-scoped: an id you do not own reads as not_found.
timeout_secondsintegerHow long to block, 1-300 seconds. Keep it BELOW your own MCP client's request timeout, or the client gives up before this tool answers. Running out is not an error: you get timed_out:true plus the jo…
NameTypeReqDescription
elapsed_msnumber|nullMilliseconds since the job started running.
errorobject|nullOn failure: the same typed error envelope a synchronous call returns. details.cancelled true means YOU cancelled it with cancel_job, not a fault.
eta_secondsnumber|nullEstimated seconds still remaining.
job_idstring|nullThe job waited on.
poll_after_secondsnumber|nullHow long to wait before polling again; 0 once finished.
pollsnumber|nullHow many get_job reads this call made on your behalf.
progress_pctnumber|null0-100 progress within the run.
resultobject|nullOn success: the FULL generate (or batch) body, always full-verbosity.
stagestring|nullThe real engine stage reached (e.g. brief, draft, judge).
statusstring|nullqueued, running, succeeded (see `result`) or failed (see `error`). With timed_out:false this is always succeeded or failed unless worker_alive is false.
timed_outboolean|nulltrue when timeout_seconds elapsed before the job finished. NOT a failure: call wait_for_job again with the SAME job_id, or poll get_job.
waited_msnumber|nullHow long this call actually blocked.
warningstring|nullPresent only alongside worker_alive:false; says what to do instead.
worker_aliveboolean|nullPresent and FALSE only when the wait returned immediately because no job worker will ever run this job. Then read `warning`.

No examples provided.