Skip to main content
Glama
606,552 tools. Updated 2026-09-24 08:47

"How to run a Python script in a sandboxed environment" matching MCP tools:

  • ⚡ ACTION: Execute source code in a sandboxed environment — 71 programming languages supported (Python, JavaScript, Java, C++, Go, Rust, C#, Bash, Ruby, PHP, and 60+ more). Returns stdout, stderr, execution time, and memory usage. Safe sandboxed execution with CPU/memory limits. Use code.languages to get language IDs (Judge0 CE)
    ConnectorNo auth
  • Use this when you need to run a script and check it compiles. Run a kernelCAD .kcad.ts script and report pass/fail + feature count + diagnostics. When the scene is assembly-built (assembly().part(...) → .model()/.solvedModel()), also returns a parts summary { count, names } AND runs the mechanism-truth gate by default: the `mechanism` field reports real/broken/unverified and a broken mechanism (disconnected components / mechanism.orphan-part, self-collision, fastened drift, dof-mismatch) makes ok:false with the failures in diagnostics — multi-body assemblies need connectors + mates/joints (axis+revolute for shafts/hinges/gears; frame+fastened for rigid; or arm.revolute/.prismatic/.ball/.fixed). Pass { skipMechanismCheck: true } to opt out. Pass either { file: "<path>" } or { code: "<inline source>" }. Set { dryRun: true } for fast validation while iterating: transpile + capture + capture-light checks WITHOUT OCCT lowering, DFM gates, or meshing — milliseconds instead of seconds (100x+ on boolean/fillet-heavy scripts). A dry run catches script throws, capture-time API misuse, and assembly validity-gate failures, but NOT lowering failures or dfmSpec diagnostics; it leaves the active session untouched, so finish with a full (non-dry) evaluate_script before using session-dependent tools.
    ConnectorNo auth
  • Turn a script into a finished 1080p video — narrated, cut to matched stock footage, subtitles burned in, audio normalized to −14 LUFS. Returns a job id; poll get_job, then fetch_video. Use when you need a publishable video and have only text. $0.60 per video in USDC on Solana — no account, no API key, no human in the loop. script: narration body to speak (plain text) title: optional intro title shown for ~4s at the top voice: voice id from list_voices(), e.g. female_warm subtitles: burn-in subtitles (default true) speed: narration speed multiplier, e.g. 1.0 seed: stock-selection seed for reproducible visuals, e.g. 7
    ConnectorNo auth
  • Save script text (your own draft, or an edited version of the generated one). Saving UPDATES the active version in place — the previous text is not kept, so show the user the current script (get_script) before overwriting it. New versions are created by generate_script runs, and activate_script_version switches between those. Run scan_script afterwards so assets and voice blocks reflect the new text. Three notations the script text carries, none of them ever spoken: SCENE DIRECTIONS — `[SCENE: <visual direction>]` as its OWN paragraph (blank line before and after; brackets inside a narration paragraph are never matched). It directs the storyboard for the narration that follows, until the next direction, and for that span OUTRANKS the director style's shot choices — say what is on screen, who is in frame, and any on-screen text to bake in verbatim. It does not constrain how many segments the span is cut into. scan_script extracts characters/places named only inside a direction too, under the exact name used. PAUSES — `<break time="1.5s" />` is the ONLY thing that makes the voice pause; ellipses, dashes and paragraph breaks produce no silence. Use ~0.5s between thoughts, ~1.0s at act seams, longer where a card needs reading time; write ONE tag with the total ("4.0s"), never two back to back. narrator_speed changes how fast words are said; breaks add the silence between them. SPEAKERS — a paragraph starting `Name: "..."` assigns that line to a character, who gets their own voice (set_character_voice) and their own shot. Narration with no prefix is the narrator's.
    ConnectorNo auth
  • **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. • `bowmark.files` keeps a file the run produces (a CSV, an image, a transcript) in the caller's Bowmark account and gives you a link to it: `save({ name, text | base64, contentType? })` → `{ id, url, expiresAt }` (25 MB from a script), `list()`, `get(id)`, `url(id, { expiresIn })`, `makePublic(id)` → `{ publicUrl }`, `makePrivate(id)`, `delete(id)`. Return the link rather than inlining the bytes. • 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. ONE EXIT IP FOR THE WHOLE SCRIPT: `await bowmark.egress.pin({ ttlMinutes: 120 })` before your first call, and every call the script makes afterwards leaves from ONE address. Reach for it when a site binds a cart, a token or a sign-in to the address that made the request, and the symptom is being logged out or asked to start over between steps. It is not a dedicated IP: the exit is a shared residential peer, `shared: true` says so, and the vendor can still replace it without telling us. **Pin FIRST** — a site you already called keeps the address it used, and the result says `pinnedAfterCalls: true` when you left it too late. Up to 7 days; anything longer comes back clamped, and the `ttlMinutes` you get back is the one that was granted. SAVED SECRETS: `savedSecrets` lists every secret the run stored in the user's Bowmark account, each as `{ name, type, viewUrl }`. An API key a key-making function returns is saved there automatically as `<vendor>_api_key`, and later runs that call that vendor use it with nothing to configure. When `savedSecrets` is present, tell the user what was saved and give them each `viewUrl`, where they can view or manage it. `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, AND THAT GOES FOR PROVIDER CALLS TOO — an `await` inside a `for` loop is the single slowest thing you can write here. Measured 2026-09-18 over 147 real runs: a script with one awaits a for-loop body ran a median of 49 seconds against 19 for the rest, and on YouTube transcripts specifically, three fetched one after another took 27.3s where six fetched together took 9.8s. Collect the ids first, then `Promise.all` over them; never walk a list awaiting each item. 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. A FAN-OUT OF FIVE THAT LOSES ONE SHOULD STILL HAND BACK FOUR: `Promise.all` rejects the whole thing the moment any leg does, so one refused request turns a finished answer into nothing. Use `Promise.allSettled` and keep the fulfilled legs. That is safe HERE and nowhere else, because Bowmark reports the dropped leg for you — the runtime counts what your script CALLED at the dispatch point, not what it chose to report, so a swallowed failure still comes back as `status: 'partial'` with the call named in `incomplete`. Say so when you present the result. 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. **`bowmark.browser_agent` is a one-shot live browser for ONE task on a site nothing in the library covers** (a lookup came back empty, or a function failed on it). It is billed per turn to the account, and it is not a watcher: it cannot poll on a schedule or run unattended, so a standing watch or daily job is not a fit — say so. When it fits and your user asked you to get the thing done, `start({ task })`; it returns `id` and `watchUrl` at once, and in the same reply tell them it is running, that it costs money, and give them `watchUrl`. A login only they hold does not stop it — they sign in themselves on the live browser through that link. If you hold off for any reason, still NAME it in your reply with its cost — never end on a manual workaround without mentioning it. In **later runs** call `status(id, { waitMs: 60000 })`. When status is `needs_input`, relay `question` to your user and `send(id, their_answer)`. When `idle`, read `result` and `stop(id)`. **Always `stop` a session when done** — idle browsers keep spending money. Your account holds max 3 concurrent sessions. One task = one goal: never bundle multiple queries into one task or the agent silently reuses results. Start separate sessions for each. A NORMAL task takes 1-4 poll cycles to reach `idle` — roughly 1-3 minutes total, not one. Each poll's `steps` shows the agent's current activity, and the SAME step name on back-to-back polls (or a run of DIFFERENT step names) is ordinary mid-task activity, not a stall — do not `stop` a run that is still inside that window just because progress looks repetitive. `get_library({ query: "browser agent" })` has full types and examples.
    Connector
    Destructive
    No auth
  • Day-of-year climate normals (NCEI 1991-2020 30-year averages) for a US location, from the nearest station with a record. Returns normal high, normal low, and normal mean for each date in the window, plus the station and how far away it is. Use this whenever a question needs a baseline rather than a forecast: "is this warm for October?", "what is a typical high here in January?", "how does this week compare to normal?". Pair it with get_forecast to say how far above or below normal the coming days run. Covers dates by day of year, so it answers for any date, past or future -- these are long-period averages, not a forecast and not observed history for a specific year.
    ConnectorNo auth

Matching MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables any MCP-compatible AI assistant to search, filter, and retrieve information from a local document collection using a hybrid search pipeline with vector, BM25, reranking, and LLM enrichment.
    4
    -

Matching MCP Connectors

  • Run Python code from natural language prompts, with optional PyPI package install.

  • AI agents hire a human to observe, log or film on site. Typed results, feasibility before payment.

  • Get the state and output of an edit run (edit group) — resume a status: "running" run or inspect a failed one. wait: true blocks until terminal or wait-budget expiry. Edit runs have no list endpoint — keep the run ID. While status is "running", call again with wait: true (same workspaceId and environment) until it is terminal; never re-submit the document. On UNAUTHORIZED or NOT_FOUND, re-call get_me for the granted targets. output.editedFile.presignedUrl expires in ~15 minutes (re-fetch with get_file). Output shape is documented at https://docs.extend.ai/editing/response-format.md (get_documentation).
    ConnectorOAuth
  • Requires an API key with the write scope or higher. Commit, at the START of a run, to the criteria by which THAT RUN will be judged when it closes — before you can see how it turns out. This is how a run stops grading itself: once declared, a success ping whose body does not satisfy every declared criterion is recorded as a FAILED run with cause 'assertion', regardless of the exit code or what the ping claims. Call this right after your run's /start ping, before doing any work — see the assertions argument for the full, immutable contract, and get_ping_instructions' expectations_how_to for a worked example.
    ConnectorNo auth
  • Validates a Python automation script that runs OUTSIDE the game, on three axes: Python syntax (using the real interpreter), Minecraft commands embedded in the script (against the official command index), and the shape of the /connect WebSocket message envelope. For behavior pack scripts use validate_script instead — Python does not run inside a pack. The embedded command check is the most valuable one: a command written from memory can look syntactically fine and still do nothing in the game. Only strings starting with / are treated as commands. If syntax could not be checked, syntaxChecked is false in the result; ok:true alone does not mean the syntax is valid.
    ConnectorNo auth
  • Get ONE test case's result inside a run: status code, timing, the response body and headers, every assertion outcome, extracted variables and any script output. This is the read to make when a run failed and you need to know why. The id comes from get_test_run's results[].id, not from get_test_results (run ids). Requires project context.
    ConnectorAPI key
  • Write a JavaScript program that calls this server's other tools. You have the whole language: loops, arithmetic, functions, conditionals, and values carried from one call into the next — all running next to the tools instead of across the conversation. Use it whenever code says the thing more directly than a sequence of separate calls would, which is often. COMPUTE, don't hand-write. Anything you would otherwise work out in your head and type as literals is better computed here — eased keyframe tracks, staggered start times, grid coordinates, derived palettes, positions from measured text widths. This is usually what makes motion look right: sample a curve at ten points and emit the values, rather than guessing four. DON'T COMMENT THE SCRIPT. Nobody reads it — it runs once and is gone. Comments, blank lines and explanatory names are pure cost here. Write it dense. The one thing to remember: inside a script you see only what you `return` or log, so a tool's own rich output (layout measurements, layout_qa, new ids) has to be surfaced deliberately. That also makes a single-call script worthwhile when a read is fat — `find` takes no projection argument, so logging the 200 characters you need is a real saving. A fat read is usually better narrowed at the source than filtered here: get_clip takes `select`, and get_element_schema takes `fields` (name what you're setting and a 15KB schema becomes ~200 bytes). get_element_schema returns TEXT by default, which you cannot index into — pass `format: 'json'` when you want to compute over the schema rather than log it. CALLING TOOLS Every tool except run_script and get_script_job is a global function taking exactly the arguments it takes normally, and returning its parsed result (those two are excluded so a script cannot recurse into itself or poll its own job). Calls are synchronous — do NOT use async/await, and there are no imports. `sleep(ms)` waits, synchronously like everything else here. Use it to poll a generation: `generate_media` and `voiceover_batch` return before their work lands, and `get_clip(select:['busy'])` says what is still being written. It is clamped to the script's remaining time, so a long sleep ends the run rather than overrunning it — and it holds one of the few concurrent script slots while it waits, so poll on the order of seconds, not milliseconds. const p = create_project({ title: "Launch" }); const made = add_clips({ project_id: p.projectId, kind: "blank", clips: [{ duration: 4 }] }); Use the BARE tool name. If your client shows these tools under a prefix, the prefixed form works too — mcp__clueso_connect__add_elements and clueso__add_elements both resolve to add_elements. `tools()` lists every callable name; `call(name, args)` invokes one by a name computed at runtime. WHY IT IS CHEAPER What you construct never passes through the conversation. Build an array in a loop and send it in ONE batched call — a 24x24 dot grid is six lines here versus 576 elements of JSON: const els = []; for (let r = 0; r < 24; r++) for (let c = 0; c < 24; c++) els.push({ x: c * 60, y: r * 60, width: 8, height: 8, type_data: { backgroundColor: "#C462F5" } }); add_elements({ project_id, defaults: { clip_index: 0, element_type: "rectangle" }, elements: els }); READ, THEN WRITE — this is how you edit in bulk: const clip = get_clip({ project_id, clip_index: 0, select: ["elements.name", "elements.y"] }); const captions = clip.elements.filter(e => e.name.startsWith("caption")); update_elements({ project_id, defaults: { clip_index: 0 }, updates: captions.map(e => ({ element_id: e.id, y: e.y + 40 })) }); WHAT COMES BACK `return` a value to hand it back, and `console.log` anything you want to see — that output is all you pay for, so log summaries, not payloads. `print_json(obj, maxBytes)` logs an object and truncates it for you, which is safer than hand-rolling JSON.stringify(...).slice(...) at every call site. You get `{ ok, calls, writes_applied, result, stdout }`. `writes_applied` matters because a script is NOT a transaction: if it throws on call nine, the first eight writes already landed, and that count is how you tell. A FAILED TOOL CALL THROWS. It does not return an error object, so a failure stops the script instead of letting it run on against bad state. Wrap a call in try/catch only when you genuinely intend to continue. You get every tool's normal result, so `succeeded`/`failed` counts, per-element `layout` (font_size_px, text_width_px, natural_width_px, line_count, fits_width/fits_height/fits plus `adjusted` when your height was replaced — widen to natural_width_px, not text_width_px) and `layout_qa` findings are all readable in the script. Check them and react. NO IMAGES are returned inside a script — a render in a loop would flood the reply. But you are not blind: `get_clip({..., render: { save: true }})` gives the script a `presigned_url` and `s3_key` for the rendered frame, so it can render many frames, keep the URLs, and hand them on (update_clueprint takes one as source_url). `_images_omitted` counts the frames withheld; when the reply would be a bare array it arrives as `{items, _images_omitted}`. Call get_clip yourself, outside a script, when YOU need to look at one. FINISHING Fast scripts return their result here. If one is still running after `wait_seconds` (default 45s) you get `{ job_id, status: "processing" }` and it keeps running — poll `get_script_job`. Set `idempotency_key` on anything that builds, so a retry cannot run it twice — a key that already ran is never re-executed, failed runs included. LIMITS: 200 tool calls, 45s of run time, 16KB each of logged output and returned value. `dry_run` runs reads for real and only records writes. Anything costing credits errors as it normally would.
    Connector
    Destructive
    No auth
  • Add, retarget, remove or dry-run one suppression rule of the caller's account, chosen by action. A matched issue keeps recording events and keeps its status while staying out of the default list and out of every notification. To silence a set of issues: call this with action=preview and the match and conditions, read the sample back to the person (call again with page=1 and the same match and conditions when issuesMatched is larger than one page), then call this with action=create and that same match and those same conditions, then call list_suppression_rules to see how much the new rule covers. A rule the account already holds is refused, so read the existing rules before adding one. To retarget a rule that is too wide, too narrow or simply wrong: call list_suppression_rules to read the rule ids, their conditions and their coverage, call this with action=preview and the match and conditions you mean to move it to, then call this with action=update, the id and that same match and those same conditions; a rule is replaced whole, so send every condition it should keep, and it keeps its id, its author and the day it was added. To remove a rule: call list_suppression_rules for the id, then call this with action=delete and that id. On update and delete, issues the old conditions hid return to the list at once and alert again on their next event; nothing is resent for issues that stay quiet, cards withheld while the rule was in force are not resent, and the answer reports how many issues are now waiting to alert again as rearmedIssues. A preview stores nothing and changes no issue: its answer holds how many issues the conditions match, how many of those were seen in the last day, and one page of matching issues, most recently seen first. To silence a single issue instead (the app calls this suppressing one issue), call set_issue_status with IGNORED. A rule holds one to five conditions and one operator: match="all" covers an issue only when every condition holds, match="any" covers it as soon as one does. A rule of one condition has nothing to join, so it is stored and answered as match="all" whichever operator you sent. A condition is a field and a value. Every field matches the whole value, case insensitive, and a star stands for any run of characters: service notifier names that one service, exceptionType java.net.* names every type under java.net, title *timed out* names every title carrying that phrase, level warn names every issue recorded at that severity. An ENVIRONMENT condition matches an issue that has been seen in a deployment environment matching the value, so a rule naming one environment covers the whole issue, not only that environment's rows. A value of only stars is refused. To narrow, write match="all" with conditions [{"field":"SERVICE","value":"notifier"},{"field":"ENVIRONMENT","value":"staging"},{"field":"LEVEL","value":"warn"}], which covers the notifier service's warnings in staging and nothing else. To widen, write match="any" with conditions [{"field":"EXCEPTION_TYPE","value":"com.slack.*"},{"field":"EXCEPTION_TYPE","value":"io.netty.*"}], which covers both libraries. A condition can be negated: to cover everything from payments except timeouts, write match="all" with conditions [{"field":"SERVICE","value":"payments"},{"field":"EXCEPTION_TYPE","value":"java.util.concurrent.TimeoutException","negated":true}], and an issue carrying no exception type at all counts as not a timeout.
    ConnectorAPI key
  • Get the connected user's profile, plan, onboarding state, team memberships, and note quota in a single call. Call this once at the start of a conversation so you can greet the user by first name, run the onboarding script only when needed, route notes to the right team space, and avoid suggesting Pro features to free users. Returns onboarding.completed (boolean) and onboarding.missing_steps (array of 'connect_mcp' | 'first_note'), which together tell you what, if any, setup is left. May include a `nudge` (key, message, url) — one frequency-capped suggestion; see the NUDGES section of the server instructions for how to handle it. Exposes the user's email address and plan — same data the user sees in account settings, but never billing or token metadata. No parameters required.
    ConnectorOAuth
  • Convert a document inline — pass the content directly as a string (or base64 for binary inputs like .docx). PREFERRED route for documents, and the one to use in sandboxed agent environments (claude.ai, Claude Desktop, Cursor): it runs entirely server-side, so it never needs the S3 upload those sandboxes block. Limit: up to 4 MB of content — already huge (a 500-page book is ~1 MB of text). For anything larger, use convert_from_url with a public URL. Supported inputs: md, html, rst, txt (plain text), docx (base64). Supported outputs: docx (Word), pdf, html, txt, md, rst, xlsx. Returns a job_id — poll get_job_status until 'complete', then get_output_content (inline bytes, sandbox-safe) or get_download_url (S3 link). Flat fee $0.05 per file. TIP: if you have shell access and are NOT sandboxed (e.g. a local coding agent), the `botverse` CLI (`npx botverse convert <file> --to <fmt>`) is faster for local files — it streams from disk instead of re-emitting the content through the model.
    ConnectorNo auth
  • Render a mingrammer/diagrams Python snippet to PNG and return the image. The code must be a complete Python script using `from diagrams import ...` imports and a `with Diagram(...)` context manager block. Use search_nodes to verify node names and get correct import paths before writing code. Read the diagrams://reference/diagram, diagrams://reference/edge, and diagrams://reference/cluster resources for constructor options and usage examples. Args: code: Full Python code using the diagrams library. filename: Output filename without extension. format: Output format — ``"png"`` (default), ``"svg"``, or ``"pdf"``. download_link: If True, return a temporary download URL path (/images/{token}) that expires after 15 minutes; if False, return inline image bytes. Defaults to True (URL) — set ``DIAGRAMS_INLINE_DEFAULT=true`` on the server to flip the default. SVG/PDF and PNGs larger than the inline limit always use a download link.
    ConnectorNo auth
  • Search the RoxyAPI knowledge base and get back ranked documentation snippets, each with a source URL. It covers API endpoints with their request and response fields, SDK usage for TypeScript, Python, PHP, C#, and Go, the WordPress plugin, authentication and API keys, UI components, and step by step integration guides. Call this first whenever you need to integrate RoxyAPI into an app: to find which endpoint or SDK method to use, what parameters a call takes, how to authenticate, or how to wire a feature end to end. Pass the user question verbatim as `query`. If the first results miss, rephrase once and retry.
    ConnectorNo auth
  • Get the current progress and results of one autopilot run. This is how you follow a run started by start_autopilot: call it with the runId, leaving time between polls. Reading status does not pause, stop, or alter the run in any way — it keeps going regardless, and there is no tool here to stop it. Reads only and costs no credits, however often you call it. Requires an API key. A run still in progress is a normal answer, not an error.
    ConnectorNo auth
  • Mint a one-time uploader script for a private Storage blob (any file type). Storage is the org's binary store: bytes go to the Railway bucket, metadata to ``drive_objects``. Objects stay private until a human seat calls ``storage_publish`` (agent seats must ``request_gated_approval(gate=publish)``). Document MIME types (Markdown, HTML, plain text, diagram JSON/YAML) are stored as blobs; versioned edit / ``/s/`` publish still use ``file_upload_request``. Pass ``work_id`` and/or ``project_id`` to attach after ingest (``kind=artifact``; transcripts stay on shared files). Pass ``parent_id`` to place the file in a folder. Batch uploads are multiple grants (one file each) — console multi-select uses sequential ingest, not a multi-file grant. Returns ``upload_url``, ``upload_token``, ``max_bytes``, and a self-deleting Python ``script``. Token is single-use and expires in ~10 min. ``drive_upload_request`` is a deprecated alias of this tool.
    ConnectorNo auth
  • Append a screenshot (with an optional note) to a review created by create_review. The image is stored durably in Cobalt — this is the way to persist screenshots that would otherwise be lost when they only pass through a browser tool. Call once per screen as you go. NO BROWSER? Pass `page_url` and Cobalt renders the page for you (Cloudflare headless Chrome): `viewport` 'desktop' (1280px) or 'mobile' (390px phone, 2x), `full_page` true for the whole scroll. Use it for every screen you would otherwise only describe in text — a review without screenshots is a reduced deliverable, and the mobile viewport is how you test the phone fold without a device. The result includes the rendered image: LOOK AT IT before moving on. Cookie walls and modal veils are stripped automatically, but if what came back is still not the shot (an overlay, a blank, the wrong page), retake it in place with replace_screenshot(item=<that item's number>), adding `hide_selectors` for anything you can name — never leave a useless capture in the review and never append a second copy after it. This tool only ever appends; it never changes an existing item. Otherwise the input is `image_url`: POST the image to https://cobaltcapture.com/api/upload (multipart field `file`, no auth, returns {url, key}) and pass back the url. If a browser-automation script took the screenshot, do that POST inside the same script (Python `requests.post(...)`, or Playwright's request context) rather than shelling out to curl afterwards — same result, one less permission prompt. The `image` base64 parameter exists for small images only: tool-call arguments are model-generated text, so a real screenshot means emitting tens of thousands of base64 tokens perfectly, and an image you received as an image cannot be transcribed at all.
    ConnectorNo auth
  • Run a read-only script against the connected Foundry world. `code` is the body of an async function: call foundry.<domain>.<method>({ ... }) (see docs), use await, console.log, and return the value you want back (JSON, size-limited). Only read methods are bound; writes are not available here — use execute. Every call counts against the per-script limits shown in the docs index (calls, wall time, CPU time, result size); an oversized call result arrives as { __truncated: true, bytes, limit, preview }.
    ConnectorAPI key