Skip to main content
Glama

Server Details

Do things on live websites: prices, availability, quotes, bookings, anything behind a form or login.

Status
Healthy
Last Tested
Transport
Streamable HTTP
URL
Repository
bowmark-ai/skill
GitHub Stars
0

Glama MCP Gateway

Connect through Glama MCP Gateway for full control over tool access and complete visibility into every call.

MCP client
Glama
MCP server

Full call logging

Every tool call is logged with complete inputs and outputs, so you can debug issues and audit what your agents are doing.

Tool access control

Enable or disable individual tools per connector, so you decide what your agents can and cannot do.

Managed credentials

Glama handles OAuth flows, token storage, and automatic rotation, so credentials never expire on your clients.

Usage analytics

See which tools your agents call, how often, and when, so you can understand usage patterns and catch anomalies.

100% free. Your data is private.
Tool DescriptionsA

Average 4.8/5 across 2 of 2 tools scored.

Server CoherenceA
Disambiguation5/5

The two tools have completely distinct roles: get_library is a read-only introspection lookup to discover capabilities, while run executes scripts against live websites. There is no overlap in purpose or potential for misselection, as the descriptions clearly reinforce the separation.

Naming Consistency4/5

Both names are short imperatives, but 'get_library' follows a verb_noun pattern while 'run' is a bare verb. This is a minor deviation; the names are still clear and predictable, and the inconsistency is not confusing given the small set.

Tool Count4/5

Only two tools is on the thin side, but each earns its place and they form a necessary two-stage workflow: discover then execute. The count feels appropriate for the server's narrow, well-defined purpose rather than insufficient.

Completeness5/5

The tool surface fully covers the intended workflow: get_library provides the vocabulary (including a fallback index when no query matches), and run executes with detailed statuses (ok, partial, needs_user) and trace information. There are no obvious gaps for the stated purpose.

Available Tools

3 tools
get_libraryCheck what can be done on a live website for this taskA
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryNoOptional, but pass one — it decides how much detail comes back. What the user wants to do, in their words ("flights", "price a GPU", "book a table", "check stock"), or a company/site if they named one ("Kayak", "newegg.com"). A rough guess is always safe: a value that matches nothing returns the one-line index rather than an error, and so does omitting it.
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, and the description reinforces this ('One read-only call, no site is touched'). It adds valuable behavioral context: sliced/partial responses are flagged, unrecognized queries return a one-line index instead of erroring, and the response opens with a partial-answer line when sliced. The main thing it doesn't disclose beyond that is fine.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Comprehensive but somewhat long. The content is dense and almost every sentence earns its place — the two-tier explanation, the 'absence from a sliced list means nothing' warning, and the payoff loop are all necessary. Could be tightened slightly but front-loads the key use-case.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a discovery/index tool with 1 optional parameter, no output schema, and good annotations, this is complete: it explains what comes back, how to avoid false negatives (slice warning), the two result tiers, and the interaction with the 'run' sibling. No meaningful gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already documents the query parameter thoroughly. The description adds semantic value by explaining what kinds of values work ('flights', 'price a GPU', company names) and what happens with no/mismatched query, going beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description is explicit: 'Use this whenever a task touches a live website' and enumerates concrete capabilities (prices, availability, search, quote, configurator, booking). It clearly differentiates from the sibling 'run' tool by stating this returns the function library while run executes scripts.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use ('whenever a task touches a live website'), emphasizes checking is cheap, explains the loop (call get_library → write script → send to run), and clarifies the two tiers (CAPABILITIES vs PROVIDERS) with guidance to prefer capabilities unless a specific site is wanted.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

registerCreate a free Bowmark account for more callsAInspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
agentNoOPTIONAL free-text name for this account, so the user can tell their keys apart later ("claude-code on my laptop", "research-bot"). Purely a label.
emailNoOPTIONAL contact address. It is NOT an API credential — no key depends on it — but passing one CREATES A BOWMARK SIGN-IN for that address, so the user can sign in with an emailed code and manage the account. Pass it only if the user supplied one; omit it entirely otherwise. Never invent, guess, or placeholder this — an address you made up is somebody else's mailbox.
newsletterNoOPTIONAL, and it DEFAULTS TO TRUE — occasional product and changelog email to the address you passed. Set false to decline. It does nothing at all when no `email` is given, since there is no address to reach. If you are passing an email, tell your user it subscribes them and that you can decline for them.
promotionsNoOPTIONAL, and a SEPARATE consent from `newsletter`. Set true ONLY if the user explicitly agreed to promotional email. Defaults to false. Do not infer this.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYes
emailNo
errorNo
apiKeyNo
reasonNo
messageNo
claimUrlNo
accountIdNo
activeNowNo
keyPrefixNo
newsletterNo
promotionsNo
freeCallsPerMonthNo
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only four false hint annotations, the description carries the full behavioral burden and handles it richly: the API key "is returned exactly once and cannot be recovered," passing an email creates a Bowmark sign-in for that address, `newsletter` defaults to true, `signInUrl`/`claimUrl`/`claimExpiresAt` semantics are explained, and re-registering is refused with a per-network cap. These disclosures add substantial context far beyond the annotations and do not contradict them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but every section earns its place for a tool with consent and security implications. It is front-loaded with the core purpose, then organized by bolded headers (WHAT IT BUYS, AFTER IT RETURNS, HOW THEY REACH THE ACCOUNT AS A PERSON) so an agent can quickly scan for the decision-relevant rules.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a side-effectful account-creation tool with consent traps, the description covers the full lifecycle: pre-call decision (when to call, all-optional params), consequences (allowance, activeNow), consent rules (newsletter, promotions), post-return handling (show apiKey, save it, add to MCP config), and account access (signInUrl vs claimUrl). Since an output schema exists, not explaining return values is acceptable, and even so the description references its key fields.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema coverage is 100% (baseline 3), the description adds decisive policy meaning: "Every argument is optional. `register({})` is a complete, valid call," never invent or placeholder an email "because that creates a sign-in for somebody else's mailbox," tell the user that passing an email subscribes them to the newsletter, and only set `promotions` when the user "has actually said yes." This turns parameter syntax into correct agent decision-making.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence, "Creates a free Bowmark account and returns an API key," names a specific action, resource, and output, and the title reinforces the benefit ("for more calls"). It also differentiates from the sibling `run` by explaining that this tool is the remedy when `run` is refused for hitting the anonymous limit, so an agent can clearly tell which tool to use.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use guidance is given: "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." It also provides when-not-to-use and an alternative: "Re-registering is not how you get a second key... If you already hold a key, present it instead," and instructs the agent not to stop and ask the user for anything before calling.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

runDo the task on the live websites and return the resultAInspect

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 array (each flight result carries its date, so you can tell the runs apart). See the get_library examples for the exact shape.

SOME capabilities return their rows alongside a warnings array — { flights, warnings }, { hotels, warnings }, { cars, warnings }. Others return a bare array. The signature in get_library tells you which; go by it rather than assuming. Where there IS a warnings array it names any site dropped from the fan-out, and the rows themselves look identical with or without it. Read it, and pass on anything it says rather than quoting a 'cheapest' that only ranks the sites that happened to answer. Dropping warnings from what you return does not hide it — the run comes back status: 'partial' regardless, because the runtime counts what your script CALLED, not what it chose to report.

ParametersJSON Schema
NameRequiredDescriptionDefault
scriptYesThe JavaScript script body to execute (async, against the `bowmark` global). e.g. `const { flights, warnings } = await bowmark.flights.search({from:'SFO',to:'JFK',depart:'2026-09-01'}); return { best: flights.sort((a,b)=>a.price-b.price)[0], warnings };`

Output Schema

ParametersJSON Schema
NameRequiredDescription
msNo
okYes
logsNo
metaNo
errorNo
needsNo
resultNo
statusNo
incompleteNo
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes far beyond the sparse annotations by disclosing sandbox limits (CPU/memory/wall-clock), the no-I/O rule (only bowmark), status semantics (partial, needs_user), trace, warnings, and the consequences of retrying needs_user runs. This is rich behavioral context that annotations only hint at.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured with bold headers, front-loaded purpose, and each section delivering necessary operational detail for a complex tool. It is not overly repetitive; the length is justified by the tool's power, though it could be tightened slightly without loss.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and one complex parameter, the description is comprehensive: it covers the scripting language, execution environment, status handling, partial and needs_user flows, trace, and warnings. It is fully self-contained and references get_library only for the exact function vocabulary.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema coverage is 100%, the description vastly enriches the script parameter: it explains the language syntax, the bowmark global, control flow, return values, and gives a concrete example. It also clarifies that script is the only argument and how to pass it via run({ script }).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific action: 'Executes the task on the real websites' and names the resource as a script against the bowmark vocabulary, returning a well-defined result object. It clearly distinguishes from the only sibling (get_library) by stating get_library is just the vocabulary while this tool runs the script.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says 'Call get_library FIRST' and explains the relationship between the two tools. It provides thorough when-to-use guidance for capabilities vs providers, and detailed handling rules for partial and needs_user statuses, including when to retry and when to wait.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Discussions

No comments yet. Be the first to start the discussion!

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Enables AI-powered web browsing automation using Google's Gemini 2.5 Computer Use API. Allows agents to navigate websites, click buttons, fill forms, and extract information through natural language commands with real-time progress tracking.
    7
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables autonomous AI agents to perform browser-based tasks like login, form filling, and data extraction via natural language, with pay-per-call billing and on-chain settlement.
    2

View all MCP Servers

Try in Browser

Your Connectors

Sign in to create a connector for this server.