# VHGENGINE MCP server

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

## Links
- Registry page: https://www.getdrio.com/mcp/app-railway-up-engine-production-3bdc-vhgengine
- Website: https://engine-production-3bdc.up.railway.app/llms.txt

## Install
- Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- Auth: Not captured

## Setup notes
- Remote endpoint: https://engine-production-3bdc.up.railway.app/mcp

## Tools
- signup - 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.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- getting_started - The 5-step agent quickstart: modes, wait guidance, links. Free, no auth.

        Written to be parsed and acted on. Returns {what_this_is, five_steps, modes
        (cost + live latency + when to use), wait_guidance (expected_wait, estimates,
        progressToken, jobs), links}.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- list_archetypes - List the hook archetypes with psychology, platforms, and templates. Free, no auth.

        Returns {archetypes:[{id, name, description, psychological_trigger, best_for,
        templates}]}. Use an id for generate_hooks(archetypes=[...]) or
        remix_hook(target_archetype=...).
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- pricing - The machine-readable price list, with per-mode expected_wait. Free, no auth.

        Returns {unit, usd_per_credit (0 while credits are free), operations,
        pricing_modes:{instant:{base:0,per_hook:1},smart:{base:0,per_hook:2},
        research:{base:10,per_hook:4}} each with a formula, expected_wait, signup_grant,
        low_balance_threshold}. A generate charge is base + per_hook * hooks_returned;
        these are the exact constants the charge path uses.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- get_estimates - The measured/expected wait per generation mode. Free, no auth.

        Size a call before spending. Returns {op, modes:{instant|smart|research:
        {p50_ms, p90_ms, samples, source ("measured" once enough samples, else
        "default"), advice}}}.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- health - Deep health: DB read+write probe, worker/queue, backup + integrity. Free.

        Same db.write_probe/backup.status/backup.offsite_status/integrity.status calls
        GET /health makes, so the two can never disagree. status is "ok" only when the
        DB both reads AND writes. Returns {status, version, time, llm_configured,
        outcomes_reported_total, job_worker_alive, job_queue_depth, last_backup_at,
        backup_count, offsite, integrity}. llm_configured never calls an LLM; CHECK
        job_worker_alive before start_generate_job (false: a queued job never runs).
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- get_account - Return this account's state + remaining rate-limit budget. Free read.

        `rate_limit` carries {limit, remaining, reset_epoch, reset_at, window_seconds} for
        the per-account window, the same budget REST clients read from X-RateLimit-* headers.
        Pace a fleet off `remaining` instead of discovering the ceiling by taking a
        rate_limited mid-run; this read itself consumes one of those calls. No API key is
        ever echoed back. Errors: unauthorized, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- get_usage - Return the credit balance, per-operation totals, and recent ledger. Free.

        Args: recent_limit (1-200, default 50), offset (>=0, pages `recent` past the newest
        rows), request_id (scope recent to that call's charges), tag + key_prefix (WP-J
        fleet filters), api_key. Returns {credits, totals:{by_operation}, recent:[...]}
        (each row carries key_prefix; tags in metadata).
        Errors: unauthorized, invalid_request, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- export_usage - Export EVERYTHING this account owns in ONE body: ledger, hooks, outcomes. Free.

        The take-it-with-you call; make it BEFORE delete_account. Same body as GET
        /v1/usage/export?format=json (csv is a download shape with no MCP carrier and its
        columns are a subset of `events`). UNBOUNDED, no paging: on a big account prefer
        get_usage / list_hooks / list_outcomes. `email` is masked without the admin scope.
        Returns {account_id, email, count, events, hooks, outcomes}; tag/key_prefix narrow events.
        Errors: unauthorized, forbidden (key lacks the read scope), rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- list_runs - Every call this account was charged for, newest first. Free read.

        Recover a lost response in two calls, never re-charged: list_runs(request_id=...)
        for the receipt, then follow `hooks_url` for the hooks it produced. Page with
        `cursor` (one pass total) or `offset`; stop only when `exhausted` is true, never
        on a short page. Same composed read GET /v1/runs makes, so the two can never
        disagree. Errors: unauthorized, invalid_request, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- quote - Price and time a generate BEFORE you commit to it, without spending. Free.

        Answers what you cannot otherwise learn without paying: which engine will BILL
        (mode=auto resolves here), credits_max, expected_wait, and whether this key can
        afford it now (balance AND any daily account/key cap, spelled out in `blocker`).
        Same validation as generate_hooks, so a bad topic/archetype/mode fails HERE.
        credits_max is a CEILING (you pay per hook RETURNED) and nothing is reserved.
        Errors: unauthorized, invalid_request, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- add_credits - Top up your credit balance (1-10000). Self-serve by default.

        When VHGENGINE_ADMIN_KEY is configured on the deployment this requires a
        matching admin_key argument; otherwise it stays self-serve (unless
        VHGENGINE_FREE_CREDITS is off). Idempotent on idempotency_key (replay does NOT
        grant twice). Returns {credits (new balance), granted}. Errors: unauthorized
        (missing/wrong admin key or self-serve disabled), invalid_request (amount range
        / balance ceiling), idempotency_conflict, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- list_billing_events - Recent billing events (usage.recorded, credits.granted, credits.low). Free.

        Newest first, paged with limit/offset like list_hooks and list_outcomes. Returns
        {events:[{id, event_type, payload, created_at}], limit, offset, total}.
        Errors: unauthorized, invalid_request, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- create_checkout - Get a Stripe hosted-checkout link for a credit pack. You never touch a card (WP-PAY).

        Hand the returned checkout_url to your human; the webhook credits you after they pay.
        Args: pack (a credits amount from pricing.credit_packs), success_url/cancel_url
        (optional), api_key (spend scope). Returns {checkout_url, pack, credits, usd_cents,
        expires_at}. Errors: unauthorized, forbidden, invalid_request (bad pack),
        payments_disabled (503; use add_credits), rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- create_key - Mint a new named API key; the plaintext is returned ONCE. Requires admin scope.

        Delegate safely (WP-SCOPE): optional scopes (subset of read|spend|admin; omit for
        full power) + daily_credit_cap (credits/day; omit for uncapped) hand a sub-agent a
        key that can only do what you allow. Args: name (1-100), api_key (an admin-scoped
        key). Returns {api_key (store it), prefix, name, scopes, daily_credit_cap,
        created_at}. Errors: unauthorized, forbidden, invalid_request, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- list_keys - List this account's API keys as PREFIXES only (never the raw key). Admin scope.

        Returns {keys:[{prefix, name, scopes, daily_credit_cap, spent_today, created_at,
        revoked_at}]}, oldest first; revoked_at is null for an active key, scopes lists the
        key's grant (WP-SCOPE), spent_today is its credits spent since UTC midnight. Your
        signup key shows as name "default". Errors: unauthorized, forbidden, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- revoke_key - Revoke the key with `prefix` (from list_keys): it stops working, others keep working.

        Use to kill a leaked or old key. Args: prefix (the 12-char key prefix, e.g.
        vhg_sk_ab12), api_key (a DIFFERENT active key to authenticate this call).
        Returns {prefix, name, revoked, revoked_at, already_revoked}. You cannot revoke
        your LAST active key (create a replacement first). Requires the admin scope. Errors:
        unauthorized, forbidden, invalid_request (last key), not_found, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- delete_account - Permanently delete this account. TERMINAL, not reversible. Admin scope (WP-LIFE).

        Pass confirm="delete" (guards an accidental call). Revokes ALL your keys, deletes
        your hooks, webhook, deliveries, jobs and idempotency rows, KEEPS the immutable
        financial ledger, and ANONYMIZES your outcomes into the shared corpus. Take what
        you still want FIRST: export_usage returns the ledger, every hook and every outcome
        in ONE call (get_usage / list_hooks / list_outcomes are the paged alternative).
        Errors: unauthorized, forbidden, invalid_request, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- generate_hooks - Generate ranked, scored viral hooks for a topic. Charged by mode.

        Cost = base + per_hook * hooks_returned (instant 0+1, smart 0+2, research 10+4,
        ~50 at count=10); a pre-flight gate never bills a broke account. Deterministic
        only in instant; a progressToken streams stages; the hook id is `hooks[].id`.
        CANCELLING DOES NOT REFUND: a timeout cannot stop the engine thread, so the call
        still charges and persists. Send idempotency_key, or recover via list_hooks.
        Errors: unauthorized, invalid_request, llm_unavailable, insufficient_credits.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- generate_hooks_batch - Generate hooks for many topics in ONE call, charged all-or-nothing.

        One transaction: over-balance charges nothing; each item bills base + per_hook *
        hooks_returned for the engine that ran (divergent tiers -> pricing_mode "mixed").
        One mode + idempotency_key + tags cover the batch; a progressToken streams item i/n;
        hook ids are results[i].hooks[j].id. CANCELLING DOES NOT REFUND: a timeout cannot
        stop the engine thread, so the batch still charges and persists. Send idempotency_key.
        Errors: unauthorized, invalid_request, llm_unavailable, insufficient_credits.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- score_hook - Score any hook text on 5 dimensions with rewrite tips. 1 credit.

        Deterministic heuristic scorer (no LLM). Args: text (3-300), platform, topic
        (optional, reproduces generate's score via the verbatim-echo penalty), tags (1-5
        fleet slugs, WP-J), verbosity (full keeps per-dimension attribution), api_key,
        idempotency_key (replay not re-charged). Returns {score:{...,total}, verdict,
        suggestions, confidence, disclaimer, credits_charged, credits_remaining, request_id}.
        Errors: unauthorized, invalid_request, insufficient_credits, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- score_hooks_batch - 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.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- remix_hook - Rewrite an existing hook into a target archetype. 2 credits per variant.

        Args: EXACTLY one of text or hook_id; target_archetype OR its alias archetype
        (disagreeing spellings are a 400); count, tags, verbosity, api_key, idempotency_key.
        Deterministic; billed only for variants returned. Returns {original:{text, score},
        remixes:[{id, text, archetype, score, rank}], topic_core, reason, score_disclaimer,
        credits_charged, credits_remaining, request_id}. Errors: unauthorized,
        invalid_request, not_found, insufficient_credits, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- list_hooks - List the hooks this account has bought, newest first. Free (WP-G).

        Retrievable for 90 days. Args: mode (instant|smart|research|remix, or a generate
        alias such as template/search), since (ISO timestamp), tag (exact fleet-tag match),
        topic (substring), request_id (recover one charged call's hooks), unreported (only
        hooks a first outcome report can reward), limit (1-100), offset, api_key. Returns
        {hooks:[{hook_id, text, archetype, mode, score_total, created_at, request_id}],
        limit, offset, total}. Errors: unauthorized, invalid_request, rate_limited. Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- get_hook - Fetch one bought hook in full, including its parsed score. Free (WP-G).

        Account-scoped: a foreign or unknown id is not_found (no existence leak). Args:
        hook_id (from a generate/batch/remix response or list_hooks), api_key. Returns
        {hook_id, text, archetype, claim_type, mode, platform, topic, score_total, score,
        prompt_version, request_id, created_at, outcomes:[...], outcome_summary:{count,
        max_views, avg_views}}. Report results with report_outcome. Errors: unauthorized,
        not_found, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- list_outcomes - List the posted outcomes THIS account has reported, newest first. Free (WP-LIFE).

        Retrieve your own submitted telemetry in bulk (per-hook it rides get_hook). Args:
        platform (tiktok|instagram|youtube|x|other), since (ISO timestamp), hook_id (one
        hook), limit (1-200, default 50), offset (>=0), api_key. Each row carries the outcome
        plus its snapshot (hook_text, topic, mode, archetype, claim_type, score_total,
        score_source, prompt_version, tags). Returns {outcomes:[...], limit, offset, total}.
        Errors: unauthorized, invalid_request, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- report_outcome - Report what a bought hook actually did once posted. FREE (WP-H).

        Honest telemetry feeding the outcome corpus (no view prediction claimed). Args:
        hook_id, platform (tiktok|instagram|youtube|x|other), posted_at (ISO, not >48h
        future), views/likes (0..1e11), retention_pct? (0-100), url? (http(s)+host),
        api_key, idempotency_key. Caps 20/hook, 500/day; an exact duplicate is a conflict.
        Returns {outcome, aggregate, reward_credits, credits_remaining?}. Errors:
        unauthorized, not_found, invalid_request, conflict, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- start_generate_job - 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. Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- get_job - Poll an async job: status, real engine stage, progress, ETA, result/error.

        Poll after poll_after_seconds until status is "succeeded" (result holds the full
        generate body) or "failed" (error holds the typed envelope). Only the owning
        account can read a job; a foreign/unknown id is not_found (no existence leak).
        Returns {job_id, status, stage, progress_pct, eta_seconds, elapsed_ms,
        poll_after_seconds, result, error}. Errors: unauthorized, not_found, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- wait_for_job - 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.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- cancel_job - Cancel a job that is STILL QUEUED. Free, repeatable, never refunds.

        ALWAYS branch on `cancelled`; reason + next_action say what to do. A queued job
        was never charged (the worker charges), so credits_refunded is always 0. A RUNNING
        job cannot be stopped: it finishes, CHARGES and persists. Cancelled reads as
        status "failed" with error.error.details.cancelled true; to re-run, resubmit with
        a FRESH idempotency_key (reusing the cancelled one replays the cancelled result).
        Errors: unauthorized, forbidden (key lacks the spend scope), not_found, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- list_jobs - List this account's jobs, newest first (summaries without the result blob).

        Args: limit (1-200, default 50), offset (>=0), api_key. Returns {jobs:[{job_id,
        status, stage, progress_pct, created_at, started_at, finished_at}], limit,
        offset, total}. Errors: unauthorized, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- set_webhook - 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}.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- get_webhook - This account's webhook (url + last delivery status; never the secret). Free read.

        Args: api_key (read scope). Cost=free. Returns {url, created_at, last_delivery_status,
        last_delivery_at, events}. Errors: unauthorized, not_found (none registered),
        rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- delete_webhook - Remove this account's webhook (WP-M). Admin scope.

        Args: api_key (admin scope). Cost=free. Returns {deleted: true}. Errors: unauthorized,
        forbidden, not_found (none registered), rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- list_webhook_deliveries - List this account's webhook deliveries, newest first. Free read (WP-HOOKS).

        Verify your receiver end-to-end (a webhook.test ping is enqueued at registration) and
        diagnose failures without waiting out a real event. Args: status (pending|retrying|
        delivered|dead|retired), limit (1-200, default 50), offset (>=0), api_key. Each row has
        {delivery_id, event_type, status, attempts, last_status_code, error, timestamps,
        next_attempt_at, payload_preview (200 chars; the full body is never returned)}. Dead
        rows are kept 7 days. Errors: unauthorized, invalid_request, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- redrive_webhook_delivery - Requeue a dead-lettered webhook delivery: reset to pending, due now. Admin scope.

        Valid ONLY on a `dead` delivery (a live receiver that exhausted its retries); any other
        status is a 409 conflict and a delivery you do not own is not_found. It re-attempts
        through the normal pipeline and, if it dies again, dead-letters normally. Args:
        delivery_id (from list_webhook_deliveries), api_key. Returns the refreshed row. Errors:
        unauthorized, forbidden, not_found, conflict, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp
- get_activity - See what this account's agents are doing: in-flight ops + recent ops. Free.

        `in_flight` merges the live-ops registry (real stage/pct/eta mid-run) with your
        queued/running jobs; `recent` is the last completed charged ops. Every row has a
        human-readable message. The REST surface also offers an SSE feed at
        GET /v1/activity/stream. Args: recent_limit (1-100, default 20), api_key.
        Errors: unauthorized, rate_limited.
         Endpoint: https://engine-production-3bdc.up.railway.app/mcp

## Resources
- vhgengine://llms.txt - VHGENGINE agent guide MIME type: text/plain
- vhgengine://getting-started - Getting started (5-step quickstart) MIME type: application/json
- vhgengine://sample - Real response envelopes (zero-spend eval) MIME type: application/json
- vhgengine://scoring - Open scoring rubric MIME type: application/json
- vhgengine://pricing - Price list MIME type: application/json
- vhgengine://stats - Public stats MIME type: application/json
- vhgengine://benchmark - Public bake-off (blind craft-preference) MIME type: application/json
- vhgengine://legal.md - Terms, data retention, and refunds MIME type: text/markdown
- vhgengine://clients/chatgpt - ChatGPT (developer mode) Setup guide for chatgpt. MIME type: text/markdown
- vhgengine://clients/claude-code - Claude Code (CLI) Setup guide for claude-code. MIME type: text/markdown
- vhgengine://clients/claude-desktop - Claude Desktop Setup guide for claude-desktop. MIME type: text/markdown
- vhgengine://clients/codex - Codex CLI Setup guide for codex. MIME type: text/markdown
- vhgengine://clients/cursor - Cursor Setup guide for cursor. MIME type: text/markdown
- vhgengine://clients/rest - Plain REST / curl Setup guide for rest. MIME type: text/markdown

## Prompts
Not captured

## Metadata
- Owner: app.railway.up.engine-production-3bdc
- Version: 2.3.0
- Runtime: Streamable Http
- Transports: HTTP
- License: Not captured
- Language: Not captured
- Stars: Not captured
- Updated: Jul 22, 2026
- Source: https://registry.modelcontextprotocol.io
