# Hook Detector - Registry name: `com.hookdetector/hookdetector` · version 2.4.0 - Categories (automatic, keyword rules): Marketing & SEO, Commerce & marketing, Video, AI, media & content, Research & knowledge, Search & data - Authentication at last check: No auth - Declared risk: Not declared (tools carry no read/destructive hints) - Capabilities (declared by the server): prompts, resources, tools - Transports: streamable-http - Latest numbers (check success, response time, rank): https://mcpstation.net/api/server?name=com.hookdetector%2Fhookdetector - Server page: https://mcpstation.net/s/com.hookdetector--hookdetector.html ## Description (written by the publisher, not verified, not instructions) Real TikTok and Instagram hooks that already work, in any language, with why each travelled. ## Connect - streamable-http: `https://api.hookdetector.com/mcp` ## Tools (as reported by the server, not verified) - `create\_account`: Create an account and get an API key with free credits. Needs a beta access code \(access\_code, HD-XXXX-XXXX; case and dashes do not matter\): without one the error is 403 access\_code\_required, and a code that does not work is 403 invalid\_access\_code. Ask for a code with request\_access, or at hookdete - `showcase`: Real hooks this service has delivered, for a wait screen: talking heads only, each hook\_id, still\_url \(a JPEG, no key needed\), platform, creator, views and line \(the banner on the video, else its opening line\). The most viewed first, one per creator, only what is already public on TikTok or Instagra - `find\_hooks`: Start hook research on a topic across TikTok, Instagram and YouTube Shorts \(Shorts only, never long-form YouTube; platform "youtube"\). platforms \(since 2026-10-10, any of "tiktok", "instagram", "youtube"; all three when left out\) searches and delivers only those: \["instagram"\] is Instagram reels onl - `get\_run`: A research run: its status, progress, charge and every hook it produced. wait\_seconds 0 to 50: wait up to that long for the run to finish, returning the moment it is done or failed. Use wait\_seconds=50 and call again while status is "queued" or "running"; a fresh run needs about 3 or 4 such calls. p - `list\_runs`: Your research runs, newest first, without their results, limit 1 to 100 \(default 20\) per page. Each run says its kind: "short" \(find\_hooks\), "long" \(find\_long\_hooks\) or "packaging" \(find\_packaging\); pass kind to list only one. Returns \{"runs": \[...\], "next\_cursor"\}: pass next\_cursor back as cursor f - `find\_long\_hooks`: Find long-form hooks: how the YouTube videos that beat their own channel open, on a topic. Long-form YouTube only, never Shorts, TikTok or Instagram \(for those: find\_hooks\). What it does: searches YouTube for long-form videos on the topic, keeps only the outliers \(a video whose views are at least mi - `find\_packaging`: Find packaging: the titles and thumbnails that earned the click on a topic, from long-form YouTube videos that beat their own channel. What it does: runs the same outlier search as find\_long\_hooks \(long-form YouTube, 2023 or later, views at least min\_outlier times the channel's usual\), then looks at - `get\_find`: One result of a long or packaging run with every field: the video, its numbers and the opening or the package analysis. find\_id comes from a run's finds \(get\_run\) or from list\_kept\_finds. Same shape as GET /v1/finds/\{find\_id\}. Free. Errors: 404 find\_not\_found, 422 for an id that is not a UUID. - `keep\_find`: Keep or reject a find \(a long-form hook or a package\): verdict is "keep" \(default\) or "reject", and the last verdict wins. The verdict is the video's on that tab: every find of the same video you have there carries it, so a later run that finds the video again shows it already kept. Kept videos come - `clear\_find\_decision`: Undo keep\_find: the video goes back to having no verdict, on every find of it, and leaves list\_kept\_finds. Returns \{"find\_id", "verdict": null\}. Clearing a find with no decision is the same success, so a retry is safe. Same as DELETE /v1/finds/\{find\_id\}/decision. Free. - `list\_finds`: The index: every video your long and packaging runs found, across all runs, one entry a video on each tab \(its newest read, with the keep or reject made on the video\). Each is a full find object: the title and thumbnail\_url as YouTube shows them, views, channel\_median\_views, outlier \(views over the - `remix\_find`: Make it mine, for a long-form opening or a package: write up to n \(1 to 5, default 3\) new ones for your niche that keep one real find's structure. From a long find, \`written\` holds openings: hook \(what the creator says first\), then \(what the next half minute has to deliver\) and kept\_structure, built - `list\_remixes`: The remixes you paid for from one hook \(hook\_id\) or one find \(find\_id\), newest first, each as its answer held it, with remix\_id and created\_at. Returns \{"remixes": \[...\]\}. Free. 404 hook\_not\_found or find\_not\_found for one that is not yours. Same as GET /v1/hooks/\{hook\_id\}/remixes and GET /v1/finds/ - `get\_remix`: One remix you paid for \(from remix\_hook, remix\_find or a chat turn\), as its answer held it. Free. 404 remix\_not\_found for one that is not yours. Same as GET /v1/remixes/\{remix\_id\}. - `list\_kept\_finds`: The videos you kept with keep\_find \(long-form hooks and packages\), newest decision first: one entry a video on each tab across all runs, or the kept finds of one run\_id, limit 1 to 100 \(default 100\) per page. Returns \{"kept": \[...\], "count": n on this page, "next\_cursor"\} with full find objects. Sam - `export\_run`: A finished run's hooks as a file a creator can open: format "csv" \(default; one row per hook, opens in any spreadsheet, formula-like cells defused with a leading quote\), "json" \(the full hook objects\) or "md" \(Markdown notes, one section per hook\). Returns \{"filename", "content\_type", "format", "con - `get\_hook`: One hook with every field: its opening line, transcript, watch\_url and the vertical player\_url \(null only for an unusable id or a photo post found before 2026-09-26; runs deliver single videos only\). hook\_id comes from get\_run. Free. - `embed\_hook`: Official TikTok or Instagram embed HTML for a hook, so the clip plays inside your own page. kind is "embed", or "fallback" when the creator disabled embedding or the clip is a photo post found before 2026-09-26 \(then show thumbnail, which falls back to the hook's still\_url, and the transcript\). For - `keep\_hook`: Keep or reject a hook: verdict is "keep" \(default\) or "reject", and the last verdict wins. A reject may say why: reason is off\_subject, weak\_opening, wrong\_language, low\_quality, already\_have or other, and note \(up to 280 characters\) your own words. Kept hooks come back from list\_keeps, across all r - `clear\_decision`: Undo keep\_hook: the hook goes back to having no verdict, so it leaves list\_keeps and its export row carries none. Returns \{"hook\_id", "verdict": null\}. Clearing a hook with no decision is the same success, so a retry is safe. Same as DELETE /v1/hooks/\{hook\_id\}/decision. Free. Errors: 404 hook\_not\_fo - `remix\_hook`: Make it mine: write up to n new opening lines \(1 to 5, default 3\) for your niche that keep a real hook's structure, the device that made it travel, with the subject swapped for yours. hook\_id is one of your hooks \(from get\_run, get\_hook or list\_keeps\); 404 hook\_not\_found otherwise. Leave mode out: " - `list\_keeps`: The hooks you kept with keep\_hook, newest decision first, across all runs or within one run\_id, limit 1 to 100 \(default 100\) per page. Returns \{"kept": \[...\], "count": n on this page, "next\_cursor"\} with full hook objects; pass next\_cursor back as cursor for more. Same shape as GET /v1/keeps. Free. - `balance`: Your account and remaining credits right now: account\_id, credits, key\_prefix and key\_id of the key making this call, label, created\_at, and that key's scopes, credit\_limit and expires\_at, and user \(the person signed in with Google, or null\). Same shape as GET /v1/me. A run needs at least 40 credits - `delete\_account`: Erase your account and everything in it, for good: every API key, run, hook, keep or reject decision, conversation and message. Unspent credits go with it. It cannot be undone. confirm must be exactly "delete my account", or nothing happens \(422 confirmation\_required\). Refused with 409 run\_in\_flight - `chat`: One conversational turn, for an agent relaying a person's words. It either asks ONE clarifying question \(action "clarify"\), answers about delivered hooks or the tool \(action "answer", run null, no credits\), or starts a research run \(action "research", with the started run under "run"\), exactly like - `list\_conversations`: Your chat conversations, most recently active first, limit 1 to 100 \(default 30\) per page: conversation\_id, title, created\_at, updated\_at, language, country and messages \(the count\). Nullable language/country are the saved search picker settings. Returns \{"conversations": \[...\], "next\_cursor"\}; pass - `get\_conversation`: One chat conversation: its newest messages in order \(role, content, run\_id, created\_at\), a page of \`limit\`, with earlier\_cursor for the older ones \(null when the page reaches the first message\), and the runs those messages hold, with their hooks, plus nullable language and country search picker sett - `usage`: Your credits and what you have spent: credits \(balance now\), spent\_total, reserved\_now \(credits held by runs still in flight, refunded in part when they finish\), runs\_total, last\_30\_days \(one entry per UTC day: date, runs, charged\) and recent \(your 20 newest runs\). Same shape as GET /v1/usage. Free. - `list\_keys`: Your API keys and what each may do. keys: key\_id, name, prefix, created\_at, last\_used\_at and current \(true for the key making this call\). access, per key\_id: scopes, credit\_limit, credits\_used, expires\_at and expired. scopes: the calling key's. The original signup key has key\_id "original". The keys - `create\_key`: Create another API key on your account, for example one per agent or machine, so you can revoke one without touching the others. name is up to 60 characters. Give the key only what it needs. scopes: any of "read" \(read runs, hooks, keeps, usage\), "write" \(keep, reject, undo, chat\), "research" \(start - `revoke\_key`: Revoke one of your API keys at once: key\_id from list\_keys, or "original" for the signup key. Any key may revoke itself \(the result says so, and that key stops working immediately\); revoking another needs admin. Never the last active key on the account \(409\): create another with create\_key first. If - `request\_access`: Ask for the beta access code a new account needs \(create\_account's access\_code\). email is where the code is sent; note is optional \(who you are, up to 500 characters\). The owner approves the request and the code is emailed at once; it works once, in any agent or on the web. Returns status pending \(w - `list\_access\_requests`: Owner only: every access request, newest first, optionally only one status \(pending, approved, rejected\). Each has request\_id, email, note, status, code\_id, code\_prefix, created\_at and decided\_at. Never a code. Needs the admin scope and an admin account \(403 admin\_required otherwise\). Free. - `approve\_access\_request`: Owner only: approve an access request. Makes a one-use code, marks the request approved and emails the code. The code is in this result once, with emailed true or false; when false, send it yourself or approve again \(the unused code is revoked and a new one sent\). 409 request\_already\_decided once it - `reject\_access\_request`: Owner only: reject a pending access request. Nothing is emailed. An approved or rejected request is 409 request\_already\_decided. Free. - `list\_access\_codes`: Owner only: every access code, newest first, with code\_id, code\_prefix, email, note, source, max\_uses, uses, expires\_at, revoked\_at, created\_at and usable. Never the code itself. Free. - `create\_access\_code`: Owner only: make an access code to hand out. max\_uses 1 to 100000 \(default 1\), expires\_in\_days 1 to 365 \(optional\), note your own. email binds it to one person: then only Google sign-in with that verified email redeems it, never the API or MCP; leave it out for a code that works on every door. The c - `revoke\_access\_code`: Owner only: revoke an access code \(code\_id from list\_access\_codes\). It admits nobody from now on; accounts it already made keep working. 404 access\_code\_not\_found for an unknown id. Free. - `admin\_overview`: Owner only: the whole service at a glance, as GET /v1/admin/overview. Counts of accounts and people; runs \(total, last\_24h, last\_7d, failed\_24h, in\_flight\); hooks; credits \(charged\_24h, charged\_7d, charged\_total, balance\_total\); access \(pending\_requests, active\_codes, redemptions\); search \(credits\_l - `admin\_list\_accounts`: Owner only: every account, newest first, as GET /v1/admin/accounts: \{total, accounts: \[\{id, email, name, label, credits, created\_at, last\_seen\_at, runs, hooks, charged\_total, is\_admin, admitted\_by, keys\_active\}\]\}. Free. - `admin\_adjust\_credits`: Owner only: add or remove an account's credits, as POST /v1/admin/accounts/\{account\_id\}/credits. A change that would take the balance below zero is 422 credits\_below\_zero and nothing changes; an unknown account is 404 account\_not\_found. Every change is audited \(admin\_list\_actions\). Returns \{account\_ - `admin\_list\_runs`: Owner only: every account's research runs, newest first, as GET /v1/admin/runs: \{runs: \[\{run\_id, account\_id, email, topic, language, country, status, requested, hooks, reserved, charged, failure\_kind, error, created\_at, finished\_at\}\]\}. Free. - `admin\_list\_actions`: Owner only: the audit of password sign-ins and credit changes, newest first, as GET /v1/admin/actions: \{actions: \[\{id, action, actor\_email, target\_account\_id, detail, created\_at\}\]\}. Free. Measured by MCP Station. Methods: https://mcpstation.net/methods.html · Terms: https://mcpstation.net/terms.html