HookovaHookova
Documentation

Hookova MCP server: setup guide

Your save library, as tools an assistant can call. Install it once and “save this page,” “what did I save about sourdough,” “tag those three as Recipes” and “summarise everything I saved this week” all become things you can just say. It takes about two minutes and needs no account beyond the one you already have.

Or don’t do any of it yourself: tell an assistant with a terminal install www.hookova.com/install/mcp and it fetches the commands and runs them. What that does.

What it is

MCP — the Model Context Protocol — is the standard way an AI client asks an outside system to do something. An MCP server is a small program that advertises a set of tools; the client reads that list and calls them when a conversation needs them. The Hookova server advertises seventeen: four to get itself signed in, six pointed at your save library, two at your projects, five at publishing to your channels.

In one line
A single TypeScript file that runs on your machine, holds one token, and translates between your assistant and the same Hookova API the iOS app and the Chrome extension already use.

Two consequences worth knowing before you install it. First, it is local: nothing is hosted, there is no Hookova process watching your conversations, and the only thing that leaves your machine is the API call a tool makes. Second, it is your account: one token, one library, no sharing — and saves made here count against the same daily allowance as everywhere else.

It works with any client that speaks MCP over stdio. The instructions below cover Claude Code, the Claude desktop app and Cursor; anything else follows the same shape.

The seventeen tools

You never call these by name — you ask for what you want and the client picks. They are listed here so you know what it’s allowed to do, which is the useful thing to know about any tool you hand an assistant. Four cover signing in; six cover the library; two cover projects.

Signing in

These exist so a token never has to arrive by config edit and restart. If you install the server with no token at all, everything else answers “Sign in to save.” and connectis the way out of it — from inside the conversation, in one turn, without a credential ever being typed into the chat.

connect(wait?, remember?)

Signs this server in through your browser — the way every other command-line tool does it.

Returns a link; you open it, approve the account you're already signed into, and the page hands the key back to this machine over 127.0.0.1. Call connect again to wait for the approval. The link lasts five minutes and works once. Use Chrome or Edge — Safari won't let a web page reach your own machine. This is the only self-service option for a Google account, and the key never appears in the conversation.

auth_status()

Whether there's a working token, whose account it is, and what that account can do today.

Plan, analysis credits left, saves used against the daily allowance — and where the token came from: the environment variable, a saved sign-in, or this session. Call it first whenever anything answers “Sign in to save.” It changes nothing and never returns the token.

sign_in(token?, email?, password?, remember?)

Signs this server in without editing config or restarting the client.

Pass a token — minted or a session cookie — or an email and password. The token is verified before it's kept, saved at mode 0600 so the next run starts signed in (remember: false keeps it to the session), and never echoed back.

sign_out()

Forgets the token here and deletes the saved file.

Not revocation: the token stays valid until its 30 days are up, because there is no endpoint to revoke one. If HOOKOVA_TOKEN is in your config it takes over again at the next restart, and the answer says so.

Prefer connect to all of this. Nothing is typed, nothing is pasted, and no credential enters the chat log at all. Failing that, prefer the token argument to a password: a password passed as a tool argument is written into the conversation transcript wherever your client keeps it, and a Google-linked account has no password to pass anyway. HOOKOVA_EMAIL/HOOKOVA_PASSWORD in the config do the same job without putting a credential in a chat log.

The library

save_link(url, title?)

Saves any public URL — a TikTok, Reel or Short, or an ordinary web page.

Returns immediately with status queued; the title, synopsis, takeaways and category are written by a background worker a few seconds later. Saving the same URL twice returns the existing save rather than a duplicate.

list_saves(q?, tag?, limit?, cursor?)

Browses and searches the library, newest first.

q searches title, synopsis, URL, notes and tags; tag filters to one category. Also returns every tag with a count and the day's remaining save allowance. Page with the returned nextCursor.

get_save(id)

One save in full: synopsis, excerpt, takeaways, tags, notes.

Also reports whether a shot-by-shot analysis exists for the same URL. Read this before update_save, because tags are written as a whole list.

update_save(id, tags?, notes?, title?, liked?)

Edits the fields you own on a save.

tags REPLACES the whole list — send the existing tags plus your addition, or the rest are deleted. Everything else on a save is the worker's and can't be set here.

delete_save(id)

Removes a save and its stored images.

Permanent. There is no undo and no trash to recover it from.

export_saves(limit?)

The library in bulk, newest first, with notes and takeaways.

For summarising or reorganising across many saves at once. Capped at 100 by default because the full export runs to thousands of rows — use list_saves to search instead.

Projects and the hook guide

A project is a board for one video in production. These two read it — and the second turns it into the material HyperFrames builds your own opening from. See From a board to a hook.

list_projects()

Every board you own: id, name, the brief in your words, how many saves are pinned.

A project is a board for one video in production. This is how a board is found by name; get_hook_guide takes the id. Cover images are dropped.

get_hook_guide(projectId, dir?, full?, overwrite?)

A board as HOOK-GUIDE.md — the material for building the opening of your own video.

The brief, every pinned save (synopsis, takeaways, a transcript excerpt), and for each pinned clip with a finished shot-by-shot analysis its hook pattern: the opening shot by shot — timing, shot size, camera, where the text lands, the technique each shot performs — plus reference stills. Pass dir and the server writes the file and downloads the stills into dir/refs/ itself. Free: it re-shapes analyses you already paid for and generates nothing. Nothing from the source clips is reused; the guide says so in its own text.

Publishing

The Publish page’s three steps as tools: which accounts are connected, post a video or photos to them, and see where each one landed. These are the tools that touch the outside world, and the assistant is told so in each description.

list_publish_accounts()

The social accounts connected on the Publish page: id, platform, handle.

YouTube, TikTok, Instagram, Facebook and X. Connecting one is a sign-in on the platform's own consent screen, so it happens on hookova.com/publish under Connections, not here.

publish_post(files, caption, accountIds?, platforms?, scheduledAt?, draft?, title?, youtubePrivacy?, tiktokPrivacy?)

Uploads one video or up to ten photos from your machine and posts them with one caption.

Now, at an ISO time with a timezone offset, or as a draft. The assistant is told to list your accounts and ask which ones, not assume all of them; a photo post skips YouTube. The file goes straight to the scheduler's storage, not through Hookova. This really posts, so the assistant is told to confirm the caption, the accounts and the time with you first. The queue's next slot lives in your browser, so the tool takes a time rather than picking one.

list_posts(status?)

Every post made through Hookova: drafts, scheduled, posting, done — and where each landed.

Per-account results ride along for the most recent done posts: the URL on each platform, or its error.

schedule_draft(id, scheduledAt?)

Sends a draft, now or at a time.

Only a draft, and only one with a file on it. Really posts.

cancel_post(id)

Withdraws a scheduled post before it goes out, or deletes a draft.

A post already sent is recalled on the platform, not here. No undo.

Pro tip
update_savereplaces the tag list wholesale. If you ask for “add Recipes to that one,” a good client reads the save first and sends the old tags back with the new one — but it’s worth saying “keep the existing tags” out loud the first few times.

Let the agent install it

If the assistant you’re installing this for can run shell commands — Claude Code, Cursor’s agent, anything with a terminal — you don’t have to read the rest of this page. Hand it one URL and it fetches the commands itself.

install www.hookova.com/install/mcp

That address serves this same install as plain text, written for whatever is holding the shell rather than for a reader: the zip to fetch, where to put it, the claude mcp add line with the path already absolute, the JSON block for every other client, and where to stop and ask you for a token. Read it yourself with curlif you’d rather see what you’re authorising first — it’s about two hundred lines and it does nothing on its own.

curl https://www.hookova.com/install/mcp

It will stop before signing in.The runbook tells the assistant to install and register the server and then ask you for a token, because that is the one step it can’t do on your behalf — and it says, in as many words, not to ask you for your password. See the runbook and step 1 below for the two token shapes.

Set it up in three steps

The manual path, for a client with no shell of its own — or for anyone who’d rather type it themselves.

You need Bun installed — the server is a TypeScript file run directly, with no build step. Everything else is copy-paste.

01

Get a token

Or skip this one — most people should
Registering with no token is a valid first run, and the better one. Do steps 2 and 3, then say “connect me to Hookova” — connect hands you a link, you approve it in the browser, and the key arrives on this machine without passing through the conversation. Nothing to edit, nothing to restart. The rest of this step is the manual route, for a headless machine with no browser or a token you already have.

Two things work, because the server tries both signing salts. Which one you need depends on how you sign in.

If your account has a password

curl -s https://www.hookova.com/api/auth/token \
  -H 'content-type: application/json' \
  -d '{"email":"you@example.com","password":"…"}' | jq -r .token

If you sign in with Google

Those accounts have no password, so there is nothing to mint with. connect exists precisely for this and needs none of what follows; copy the session cookie only if you have no browser on the machine. Sign in at hookova.com, open DevTools → Application → Cookies, and copy the value of __Secure-authjs.session-token. If the browser split it into .0, .1and so on, concatenate the values in order with nothing between them. It’s the same trick the Chrome extension plays.

Either way the token lasts 30 days. Step 3 shows how to make renewal automatic.

02

Unzip and install

Unzip it somewhere you intend to keep — your client will run the file from wherever it lands, so the Downloads folder is a bad choice.

unzip ~/Downloads/hookova-mcp.zip -d ~/hookova-mcp
cd ~/hookova-mcp
bun install

bun install fetches two dependencies: the MCP SDK and zod. Four files go in, nothing is compiled, and nothing is left running.

03

Register it

In Claude Code, one command does it. Use an absolute path — the client may not expand ~.

claude mcp add hookova \
  --env HOOKOVA_TOKEN=eyJ… \
  -- bun /Users/you/hookova-mcp/index.ts

If your account has a password, add it here instead of re-pasting a token every month — the server re-mints once on a 401, so expiry becomes invisible:

claude mcp add hookova \
  --env HOOKOVA_TOKEN=eyJ… \
  --env HOOKOVA_EMAIL=you@example.com \
  --env HOOKOVA_PASSWORD=… \
  -- bun /Users/you/hookova-mcp/index.ts

Restart the client, then check it took: /mcpin Claude Code lists the server and its seventeen tools. Or just ask — “am I signed in to Hookova?” runs auth_statusand comes back with the account, the plan and what’s left today. If you skipped step 1, say “sign in to Hookova” instead and paste the token when it asks.

Other MCP clients

Every other client wants the same three facts in JSON: the command, its arguments, and the environment. Put this in claude_desktop_config.json (Claude desktop app) or .cursor/mcp.json (Cursor), and the same block works in most editor integrations.

{
  "mcpServers": {
    "hookova": {
      "command": "bun",
      "args": ["/Users/you/hookova-mcp/index.ts"],
      "env": { "HOOKOVA_TOKEN": "eyJ…" }
    }
  }
}

If the client is a desktop app, give command an absolute path too — e.g. /opt/homebrew/bin/bun. A GUI application doesn’t inherit your shell’s PATH, which is the single most common reason a server registers fine and then shows no tools.

Environment variables

VariableWhat it does
HOOKOVA_TOKENOptionalA minted bearer token or your site session cookie — the server accepts either, and both expire after 30 days. Generate one on the MCP server page in Settings, or mint one with your password. Set here it wins over a saved sign-in at startup; leave it out and sign_in supplies the token instead.
HOOKOVA_EMAIL + HOOKOVA_PASSWORDOptionalRe-mints a token once on a 401, so expiry is invisible instead of a monthly re-paste. Does nothing on a Google-linked account, which has no password to mint with.
HOOKOVA_APIOptionalDefaults to https://www.hookova.com. Point it at http://localhost:3000 to work against a dev server.
HOOKOVA_TOKEN_FILEOptionalWhere sign_in saves its token. Defaults to ~/.hookova/mcp.json, written at mode 0600.

Troubleshooting

Every tool answers “Sign in to save.”

Ask for auth_status — it says whether a token is there at all, and if one is, why it was refused and which of the three places it came from. The fix is usually sign_in with a fresh token, which takes effect immediately. If you pasted a session cookie that DevTools had split into __Secure-authjs.session-token.0, .1 and so on, the values must be joined in order with nothing between them.

sign_in worked, but the next session is signed out again.

Either it ran with remember: false, or HOOKOVA_TOKEN is set in your client's config — the environment variable wins at startup, so a stale one there overrides the token sign_in saved. sign_in's answer warns about this when it applies. Remove it from the config and the saved sign-in takes over.

The client starts but lists no tools.

The command couldn't run. Check that bun is on the PATH the client uses (a GUI app doesn't inherit your shell's PATH — give the absolute path to bun, e.g. /opt/homebrew/bin/bun) and that the path to index.ts is absolute, not ~-relative, in JSON configs.

Cannot find package '@modelcontextprotocol/sdk'

bun install wasn't run in the unzipped folder, or was run somewhere else. cd into the folder that holds index.ts and run it there.

A save comes back with no title or synopsis.

That's expected — save_link returns as soon as the row exists. The worker fills in the rest a few seconds later; call get_save again to read it.

“Daily save limit reached.”

The allowance is per account and shared with the phone and the browser extension — there's no separate MCP quota. It resets daily.

From a board to a hook

A Hookova project is a board: a name, a brief in your words, and the saves you pinned to it — some of them clips Hookova has taken apart shot by shot. get_hook_guide writes that board out as HOOK-GUIDE.md, plus a folder of reference stills, and a Claude Code skill hands it to HyperFrames, which renders video from HTML, to build the opening seconds of your video.

The one rule
Pattern and subject are kept apart. What is borrowed from the analysed clips is the skeleton of their opening — timing, shot sizes, camera moves, where the text lands, which hook technique each shot performs. What the video is about comes only from your brief and your saves. Nothing from the source clips is reused, and the guide says so in its own text.

The skill ships inside the server folder, but Claude Code only reads skills from ~/.claude/skills, so link it once:

ln -sfn "$HOME/.hookova/mcp/skills/hook-from-project" "$HOME/.claude/skills/hook-from-project"

Then, in a fresh directory, say /hook-from-project <board name>. It lists your boards, runs hyperframes init, writes the guide and the stills into the project, asks which pattern to build on when a board has several, and hands the build to the hyperframes skills (npx hyperframes skills updateinstalls them). It spends no credit and never starts an analysis: a board with no analysed clip is told so, and the choice — analyse one first, or build a typographic hook from the subject alone — is yours.

What it can’t do

Stated plainly, because a tool list that overpromises wastes more of your time than one that’s short.

  • No separate quota. Saves made here draw on the same daily allowance as the phone and the extension. There is no MCP tier to raise.
  • Local only. Stdio, one process, one token, one account. A hosted server with OAuth is a different piece of work and nobody has asked for it yet.
  • No images or video in answers.Keyframes and source videos are auth-gated URLs a model can’t open, so get_save drops them rather than handing back links that 401. The one exception is on disk: get_hook_guide with a dir fetches the reference stills itself and writes them to refs/.
  • Bulk export has a floor. export_savesreads the Obsidian export route, which returns one page of at most 2,000 rows with no cursor. Past that, the oldest saves aren’t reachable through this tool — use list_saves with a search instead.
  • No starting an analysis. Shot-by-shot breakdowns are run in the web app; get_save tells you when one exists for a saved URL, and get_hook_guide reads the finished ones on a board.
  • No revocation. sign_out forgets a token; it cannot cancel one. There is no revocation endpoint behind it, so a token that has leaked stays usable until its 30 days run out.

Frequently asked questions

Can my assistant install this for me?

Yes, if it can run shell commands. Say "install www.hookova.com/install/mcp" — that URL serves the whole install as plain text written for an agent rather than a reader: the zip to fetch, where to put it, the claude mcp add line with the path already absolute, and the JSON block for other clients. It will install and register the server, then stop and ask you for a token, which is the only step it can't do for you. Read it first with curl if you'd rather see what you're authorising.

Does saving through MCP spend an analysis credit?

No. Credits are spent by shot-by-shot video analysis only. Saves count against your daily save allowance, which is shared with the iOS app and the Chrome extension — there is no separate MCP quota.

Do I need the Hookova source repository?

No. The zip is the whole server: one TypeScript file, a package.json, a tsconfig and a README. It calls the public API over HTTPS like any other client.

Where does my data go?

Nowhere new. The server is a local process on your machine that holds one token and talks to the same api.hookova.com routes the iOS app has used since it shipped. Your assistant sees what the tools return, and nothing else — no tool ever returns the token itself.

Is it safe to give my password to sign_in?

Prefer not to. A password passed as a tool argument goes into the conversation transcript wherever your client stores it, the same as anything else you type. Use the token argument instead, or put HOOKOVA_EMAIL and HOOKOVA_PASSWORD in the client's config — the server re-mints from those on a 401 without either value ever entering the conversation. The password path exists because it is sometimes the quickest way in, not because it is the best one.

Does sign_out revoke the token?

No. It forgets the token — clears it from the running server and deletes the saved file — but there is no revocation endpoint to call, so the token stays valid until its 30 days are up. Treat a token that has leaked as still live, and assume signing out does nothing to it.

My account signs in with Google. Can I still use it?

Yes. Google-linked accounts have no password, so there is nothing to mint a token with over curl — generate one on the MCP server page in Settings instead, and paste it into your config or the sign_in tool. It expires after 30 days, and generating a fresh one is the renewal.

Which clients does it work with?

Anything that speaks MCP over stdio: Claude Code, the Claude desktop app, Cursor, and most editor integrations. It is a local stdio server with one token and one account — there is no hosted, OAuth version of it.

Can it analyze a video, not just save it?

It can't start one — shot-by-shot analysis runs in the web app and spends a credit there. It can read the finished ones: get_save tells you whether an analysis exists for a URL you've saved, and get_hook_guide turns every analysed clip on a project board into a hook pattern, written out shot by shot.

Can it help me make the video, not just study other people's?

That is what the hook guide is for. Pin the clips you want to learn from to a project, give it a brief, and get_hook_guide writes the board out as HOOK-GUIDE.md with reference stills. The hook-from-project skill hands that to HyperFrames, which builds the opening seconds of your own video on the pattern of those clips — their timing, framing and technique — with your brief as the subject. Nothing from the source clips is reused, and no model runs inside Hookova to make the guide: it is your own analyses, re-shaped.

Two minutes, and your library starts answering questions.

Grab the zip, paste the three commands, and the next thing you read worth keeping can be saved without leaving the conversation you’re in.