Bowmark AI
@bowmark-ai
About Bowmark AI
Pre-computed navigation recipes for public websites. Your AI agent skips the explore-and-click phase and goes straight to the answer.
Config
Add this server to your MCP-compatible client using the configuration below.
{
"mcpServers": {
"bowmark": {
"url": "https://api.bowmark.ai/mcp"
}
}
}Tools
3**Use this whenever a task touches a live website.** It answers, definitively and cheaply, whether Bowmark can already DO the thing: look up current prices, check real availability or stock, search a site, get a quote or a fare, drive a configurator, start a booking, or pull anything that only exists behind a form, a filter, or a login. **Checking is cheap, so check.** One read-only call, no site is touched, and an unrecognized query returns a one-line index instead of an error, so the check never dead-ends and never costs you an attempt. If nothing fits, you have lost one cheap call and can use your normal approach. What comes back is the callable **function library** you write against: the runtime globals (`log`) PLUS, for each capability your query named, its namespace, TypeScript types, functions, and worked examples. Everything listed is real and callable. The language rules and how to run a script are on the `run` tool description. Pass `query` — what you want to DO (`"flights"`, `"price a GPU"`) or, if you have one in mind, the COMPANY or site (`"Kayak"`, `"newegg.com"`). A phrase in the user's own words is fine; it is matched against the whole library. **You get what you asked about and nothing else.** If nothing matches — or you send no query — you get instead a one-line index: pick whichever entry fits and CALL AGAIN with its name to get the types and examples you need to write a script. **Every response is bounded, and it says so when it is a slice.** A broad query can match more than one response carries; when that happens the answer opens with a partial-answer line naming what it left out. **Read it before concluding anything** — absence from a sliced list means nothing, and the fix is one narrower query (a single task, or a single company by name), which always returns that entry in full. Only an answer that does NOT say it is a slice supports the conclusion that a task is uncovered. **Two tiers come back.** CAPABILITIES (`bowmark.flights.search(...)`) are the default and usually what you want: one call fans out across several sites, dedupes, ranks, and routes around a site that's failing. PROVIDERS (`bowmark.providers.kayak.search(...)`) are the individual sites, callable directly — they appear only when your query NAMED a company, or when the capability has just one provider behind it. A direct provider call gets that site's own raw shape and no failover, so prefer the capability unless you specifically want that site. Loop: call `get_library` → write a JS script against the `bowmark` global → send it to `run`.
**Executes the task on the real websites** (the search, the price check, the availability lookup, the configurator, the booking flow) and returns what came back. Runs a script you authored against the `get_library` vocabulary, on the live sites, and returns `{ ok, result, logs, error, ms }`. Call `get_library` FIRST — it gives the exact function names, argument shapes, and return types; this description is the LANGUAGE + how-to (get_library is just the vocabulary). THE LANGUAGE — plain async JavaScript: • `bowmark` is a ready global (no import). Call capabilities off it — `await bowmark.<capability>.<method>(...)` — always `await`, they're async. • Individual sites are callable too, at `await bowmark.providers.<provider>.<fn>(...)`. Use one when you specifically want THAT site; otherwise prefer the capability, which fans out across sites and routes around failures. • Real control flow: `await`, `if`, loops, array methods (`map`/`filter`/`sort`/`slice`), and `Promise.all` for fan-out. • `return` a value to get it back (JSON-serialized). `log(...)` for progress lines. • `bowmark` is the ONLY I/O — no `fetch`, `process`, filesystem, or `import`/`require`. Write a plain async body, not a wrapping function. • Keep scripts small and deterministic — no infinite loops. Runs in a hard sandbox with CPU + memory + wall-clock limits. SENDING IT: pass the script text as `run({ script })` — `script` is the only argument (there is no `site` argument; the library exposes every capability under `bowmark`). `result` is whatever you returned; `logs` are your `log()` lines in order; on a throw/timeout `ok:false` and `error` is set. CHECK `status` BEFORE `ok`. It is `ok` | `error` | `partial` | `needs_user`. • `partial` means the script RAN and `result` is real and usable, but some of what it called never answered — so the result is narrower than what you asked for. `ok` is still `true`; this is not a failure. `incomplete.summary` says what happened in one sentence, `incomplete.failures` names each call that threw and what the site said, and `incomplete.degraded` names each call that answered while reporting its OWN results thin. You MUST say so when you present the result: name what was missed, and do not describe it as complete, exhaustive, or 'all' of anything. A `partial` you report as whole is a wrong answer, not a slightly smaller right one. • Before you conclude a `partial` is final, check `incomplete.failures[].fixable`. `fixable: true` means YOUR ARGUMENT was rejected, not the site — the error text names what that function actually takes, so re-read it in `get_library`, fix the argument and run again; that recovers the whole answer. For any other failure re-running usually returns the same thing. • `needs_user` means a site needs the USER signed in — it is NOT a failure and NOT something you can fix by editing the script. `needs` lists the sites; `meta.handoff.url` is a single-use link that expires (`meta.handoff.expiresAt`). Give the user that URL, say which sites it covers, and WAIT. When they tell you they're done, send the SAME script again unchanged. Do NOT retry before then — it will stop at the same place and cost another run. Do NOT try to log in yourself, ask them for a password, or work around it with a different site. • Logged-in runs need a Bowmark API key on the connection; if you get `needs_user` saying so, tell the user to add one rather than retrying. `trace` is the execution trace — every capability you called and the providers it fanned out to under the hood: `[{ kind:'capability', capability:'flights', method:'search', ms }, { kind:'provider', capability:'flights', provider:'google_flights', fn:'search', results, status, ms }, …]`. The script never visits websites — it calls capabilities that route to providers, and the trace is the receipt. Composition is the point — call a method MULTIPLE times and combine results. To sweep a date range, call the search per date inside `Promise.all` and sort/filter the merged arr…
**Creates a free Bowmark account and returns an API key.** Call it when a `run` is refused for hitting the anonymous limit, when you expect to make more than a handful of calls, or any time the user says they want an account. **Every argument is optional. `register({})` is a complete, valid call** and returns a working key. Do NOT stop to ask the user for anything before calling this — there is nothing required to ask for. WHAT IT BUYS: anonymous callers share one small daily allowance per IP address with everything else behind it. A registered account gets its own monthly allowance, an order of magnitude larger. The response says both numbers. Where the connection allows it the new allowance applies IMMEDIATELY, with no configuration change — `activeNow: true` in the response means your very next `run` is already on it. `email` is OPTIONAL and no key depends on it — it is not a credential, and nothing you do with the API authenticates with it. **But passing one CREATES A BOWMARK SIGN-IN for that address**, so the person can sign in at bowmark.ai with an emailed code and manage the account without keeping any link. Pass it only if the user actually gave you one. **Never invent one and never pass a placeholder** — that creates a sign-in for somebody else's mailbox. **IF YOU PASS AN `email`, TELL YOUR USER THIS:** that address is subscribed to occasional Bowmark product and changelog email by default. Pass `newsletter: false` to decline, and say so plainly rather than deciding for them — every message carries a one-click unsubscribe either way. With no `email` there is nothing to subscribe and nothing to mention. `promotions` is a SEPARATE consent and is OFF unless you set it. **Only set it if the user has actually said yes to promotional email.** Do not infer consent from enthusiasm, and do not set it to be helpful. AFTER IT RETURNS: show the user `apiKey`. It is returned exactly once and cannot be recovered — tell them to save it and to add it to their Bowmark MCP config as `Authorization: Bearer <key>` so it works from every future session. Do not put the key in a file, a commit, or anywhere it outlives the conversation. **HOW THEY REACH THE ACCOUNT AS A PERSON.** If `signInUrl` came back, that is the way in: they sign in there with the email you passed, Bowmark sends a code, and they land in this account. Nothing to save. `claimUrl` is then only a backup for a wrong address. If `signInUrl` is null, `claimUrl` is the ONLY door — show it, and say `claimExpiresAt` is the date it stops working, because after that they can use the key but never manage or revoke the account. Re-registering is not how you get a second key: an address that already has an account is refused, and there is a per-network cap. If you already hold a key, present it instead.
Overview
What is Bowmark AI?
Bowmark AI is an MCP server that serves a continuously-refreshed cheatsheet for known websites. It provides either a parameterized URL (fastest_path) or a tight UI sequence (ui_procedure) so that browser agents can skip guessing and go straight to the answer. It is intended for use with AI agents in any MCP-aware host.
How to use Bowmark AI?
Configure Bowmark AI as an MCP server in your host by pointing it to api.bowmark.ai/mcp. No authentication is required. It is free during the beta period. Once connected, your agent can query the server for known websites to receive optimized navigation paths or UI procedures.
Key features of Bowmark AI
- Continuously-refreshed cheatsheet for known websites
- Provides parameterized URL (
fastest_path) or UI sequence (ui_procedure) - Works with Claude Code, Claude.ai, Cursor, OpenCode, and other MCP hosts
- No authentication required
- Hosted at
api.bowmark.ai/mcp - Free during beta
Use cases of Bowmark AI
- Quickly retrieving the fastest URL pattern for a known website
- Getting a step‑by‑step UI procedure to perform a task on a known site
- Reducing guesswork for browser‑based AI agents
- Streamlining agent workflows across multiple supported MCP hosts
FAQ from Bowmark AI
What does Bowmark AI do that alternatives don’t?
The README does not mention alternatives. Bowmark AI focuses on serving a pre‑computed, continuously‑refreshed cheatsheet of known websites rather than relying on agents to blindly parse the DOM.
What runtime or dependencies are required?
Bowmark AI requires only an MCP‑aware host (e.g., Claude Code, Claude.ai, Cursor, OpenCode). No additional dependencies or authentication setup are needed.
Where does Bowmark AI’s data live?
The server is hosted at api.bowmark.ai/mcp. The cheatsheet is continuously refreshed server‑side.
Are there any known limits?
The service is free during beta and only covers known websites; it does not dynamically discover new sites. The README does not specify any other limits.
What transport or authentication does Bowmark AI use?
Bowmark AI uses the standard MCP transport via an HTTP endpoint (api.bowmark.ai/mcp). No authentication is required.
Frequently asked questions
What does Bowmark AI do that alternatives don’t?
The README does not mention alternatives. Bowmark AI focuses on serving a pre‑computed, continuously‑refreshed cheatsheet of known websites rather than relying on agents to blindly parse the DOM.
What runtime or dependencies are required?
Bowmark AI requires only an MCP‑aware host (e.g., Claude Code, Claude.ai, Cursor, OpenCode). No additional dependencies or authentication setup are needed.
Where does Bowmark AI’s data live?
The server is hosted at `api.bowmark.ai/mcp`. The cheatsheet is continuously refreshed server‑side.
Are there any known limits?
The service is free during beta and only covers known websites; it does not dynamically discover new sites. The README does not specify any other limits.
What transport or authentication does Bowmark AI use?
Bowmark AI uses the standard MCP transport via an HTTP endpoint (`api.bowmark.ai/mcp`). No authentication is required.
Basic information
More Other MCP servers
🚀 Model Context Protocol (MCP) Curriculum for Beginners
microsoftThis open-source curriculum introduces the fundamentals of Model Context Protocol (MCP) through real-world, cross-language examples in .NET, Java, TypeScript, JavaScript, Rust and Python. Designed for developers, it focuses on practical techniques for building modular, scalable,
Nginx UI
0xJackyYet another WebUI for Nginx

Figs, Relationship Expert
Figs O'Sullivan, LMFTCouples therapist Figs O'Sullivan (LMFT, 17 years, endorsed by Sue Johnson, creator of EFT) inside your AI. Ask relationship questions answered from his clinical writing, name the pattern in a fight, get a three-step rep
Awesome Mlops
visengerA curated list of references for MLOps
IDA Pro MCP
mrexodiaAI-powered reverse engineering assistant that bridges IDA Pro with language models through MCP.
Comments