Skip to main content
Glama

Do the task on the live websites and return the result

run
Destructive

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. • Standard JavaScript built-ins are there (JSON, Math, Date, RegExp, Intl, Promise), plus URL and URLSearchParams — use them to resolve a relative link against the page it came from and to build query strings. Nothing else from the Web platform exists: no fetch, setTimeout, TextEncoder or crypto. • 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.

Your own tool-call budget is tighter than you'd guess, and it decides how many calls fit in one script. Most MCP clients time a single tool call out at around 55 seconds, and ONE ordinary capability call already spends 30-55 seconds of that fanning out to live sites — see COMPOSITION below before calling a second capability in the same script.

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 MEANS PARALLEL, NOT SEQUENTIAL. Default to ONE capability call per script — most already spend 30-55 seconds of your own ~55-second tool-call budget on their own, so a second call made AFTER the first routinely never returns before your client gives up, and the script errors with nothing to show for either call. If you genuinely need several, run them TOGETHER inside Promise.all — in parallel they cost about what one call costs, not the sum of them — and never call them one after another. 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. If even one call will not fit your budget, narrow the query (fewer dates, a single site instead of a fan-out) or split the work across separate turns — do not compose more into one script to make it fit.

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.

Input Schema

TableJSON 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

TableJSON Schema
NameRequiredDescriptionDefault
msNo
okYes
logsNo
metaNo
errorNo
needsNo
runIdNo
resultNo
statusNo
incompleteNo

Schema Changelog

Changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. Changed1 schema field changed
    • addedOutput schema / properties / runId
      Added value: +{
      +  "format": "uuid",
      +  "type": "string"
      +}
  2. Changed2 schema fields changed
    • removedInput schema / $schema
      Removed value: -"http://json-schema.org/draft-07/schema#"
    • removedOutput schema / $schema
      Removed value: -"http://json-schema.org/draft-07/schema#"
  3. Changed2 schema fields changed
    • addedOutput schema / properties / incomplete
      Added value: +{}
    • changedOutput schema / properties / status / enum
      Previous value: -[
      -  "ok",
      -  "error",
      -  "needs_user"
      -]New value: +[
      +  "ok",
      +  "error",
      +  "partial",
      +  "needs_user"
      +]
  4. Changed1 schema field changed
    • changedInput schema / properties / script / description
      Previous value: -"The JavaScript script body to execute (async, against the `bowmark` global). e.g. `const f = await bowmark.flights.search({from:'SFO',to:'JFK',depart:'2026-09-01'}); return f.sort((a,b)=>a.price-b.price)[0];`"New value: +"The 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 };`"
  5. Added

TDQS

A5/5.0
Behavior5/5

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

The description discloses far beyond annotations: sandbox limits, no fetch/import/process, bowmark as only I/O, statuses (ok/error/partial/needs_user), fixable failures, handoff URLs, API key requirements, trace receipts, and warnings. The destructiveHint=true is consistent with executing real-site actions like booking flows.

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 tightly structured with bold headers and bullets, front-loading the core purpose and return shape. Each section addresses a real failure mode, budget constraint, or usage nuance, so every sentence earns its place.

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?

Given the complexity of executing arbitrary scripts against live sites, the description covers execution semantics, failure modes, output interpretation, warnings, and interaction with get_library. Nothing essential for correct invocation is missing.

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?

Schema coverage is 100%, and the description adds extensive meaning to the script parameter: it is the only argument, no site argument exists, the body must be async, bowmark is global, return values are JSON-serialized, and composition constraints apply. This far exceeds the schema description.

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 states a specific action: executing user-authored scripts against the bowmark capability vocabulary on live websites, and returns a defined object shape {ok, result, logs, error, ms}. It clearly distinguishes itself from get_library by framing get_library as the vocabulary and this tool as the execution runtime.

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 guidance is abundant: call get_library FIRST, default to one capability call per script, use Promise.all for parallel composition, narrow the query or split work if budget is tight, and how to handle partial/needs_user results. This leaves no ambiguity about when and how to invoke the tool.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

TDQS

A4.8/5.0
Disambiguation5/5

Each tool has a clearly distinct job: get_library returns capability documentation, run executes scripts against live sites, register creates credentials, and report captures feedback. There is no meaningful overlap or plausible misselection between them.

Naming Consistency4/5

All tool names are lowercase imperative verbs and follow a simple, readable style. The pattern is slightly inconsistent because get_library includes an object while register, report, and run are bare verbs, but the convention is still predictable enough.

Tool Count5/5

Four tools is well-scoped for this server's purpose: discover, execute, authenticate, and give feedback. Each tool earns its place and the count is within the ideal range for a focused MCP server.

Completeness5/5

The core workflow is fully covered: get_library and run form a complete discover-and-execute loop, register handles access and quotas, and report provides a path for missing capabilities. There are no obvious dead ends or missing lifecycle steps for the domain.