This is the tool catalog the MaxoPerf MCP server registers. You can call every entry today over POST https://app.maxoperf.com/mcp. Read tools default to response_format: "concise". Pass "detailed" for the full payload. Tools marked write need a session that isn’t read-only. Loadrigo asks for confirmation before a destructive tool, and any agent that calls one should take the same care.
An empty new test. Attach the entrypoint script next with upload_test_file. Each failure_criteria row’s label is an exact sample label or "ANY" (all labels, the default). For a single test, pass capture_error_bodies: false to turn off error body capture (on by default). VarioTests take the setting from each member’s source test.
get_test_overview
{ test_id }
Run-history overview (the console’s Overview tab).
list_test_labels
{ test_id }
{ testId, lastRunId, labels: [{ label, source: 'last-run'|'definition' }] }. These are the sample labels a failure criterion can target. Use "ANY" for all labels; see ANY label.
get_test_data_bindings
{ test_id }
The test’s data bindings, each with slug (the File name), relativePath, containerPath, envVar, columnNames[], scriptVariable, plus executionContext.dataDir/dataDirEnvVar. Same shape as GET /v1/tests/:testId/data-bindings; see Use the data in your script. Read-only. To change a File name, send PUT /v1/tests/:testId/data-bindings through call_platform_api. It replaces every binding, so echo each binding’s write fields (datasetId, datasetRevisionId, entityId, variantId, distribution, position, localOverrides, scope, slug): an omitted one resets (distribution back to split, the revision unpinned, overrides and scope cleared). Leave eofMode out to keep each binding’s current end-of-file mode; sending it when executionContext.eofCapability.supported is false returns 422 dataset_eof_unsupported, even with the unchanged value. Response-only fields (id, relativePath, envVar, effectiveEofMode, …) are rejected with 400.
What you can change on this run right now: { writable, liveRunnerCount, controls: [{ kind, support, requires, requirementMet }] }. support: null means the executor has no such control. requirementMet: false means the script lacks what requires names. Call it before any change.
get_live_control_history
{ run_id, revision?, limit?, cursor? }
Past changes, newest first. With revision, the per-runner acknowledgements for that change.
set_live_virtual_users (write)
{ run_id, total, scope? }
Sets the virtual-user total. MaxoPerf divides it across the runners in scope and returns { revision, runnerCount, matchedRunnerCount, perRunner, dispatchState, delivered }.
set_live_throughput (write)
{ run_id, requests_per_second, scope? }
Sets a requests-per-second cap, divided across runners. 0 removes the cap. On k6 the value is approximate, because MaxoPerf reaches it by changing virtual users.
set_live_properties (write)
{ run_id, properties, scope? }
Sends engine properties to every runner in scope. Keys starting maxoperf_ are reserved.
set_live_config_files (write)
{ run_id, files: [{ name, content }], scope? }
Writes data files your script can read. Send plain text; the tool encodes it.
pause_run / resume_run (write)
{ run_id, scope? }
Stops generating load without ending the run, then resumes where it was. On k6 only with the externally-controlled executor. To end a run, use cancel_run.
scope is optional; without it a change goes to every runner. Use { type: 'locations', locations: [...] } or { type: 'runners', runnerIds: [...] } to target part of the fleet. A location that isn’t a MaxoPerf location returns 400 LIVE_CONTROL_SCOPE_LOCATION_UNKNOWN. A scope that matches no live runner, or names a runner that isn’t live in this run, returns 422 SELECTOR_NO_MATCHING_RUNNERS. Raising load above your plan returns 403 PLAN_LIMIT_EXCEEDED; lowering it always works. A run that isn’t on your account returns 404, on reads as well as writes, and asking for a revision the run never had returns 404 REVISION_NOT_FOUND.
Captured request/response samples with status codes. Filter by signature (from get_run_errors). If that returns nothing, use the error’s label with response_code, then label with category (http_4xx, http_5xx or network, from the error group). Never use label alone: it also returns the bodies of other errors on the same transaction. Body text comes back only with row_id (a snippet by default; the full redacted body with response_format: "detailed").
Managed Selenium-Grid / Playwright-connect() capacity: N browsers behind one endpoint. Your own client drives them directly, so this is not a test run that MaxoPerf orchestrates. See Browser fleets.
Tool
Args
Returns
create_browser_fleet (write, idempotent)
{ browsers: [{ browser: 'chrome'|'firefox'|'edge', count, location }], browsers_per_runner?, ttl_minutes?, idle_timeout_minutes?, name?, step_capture?, workspace_id? }. location is <aws|gcp|azure>:<region> or byoc:<pdcId>. step_capture defaults true — send false to opt sessions out of interaction-step capture. workspace_id defaults to the account’s oldest active workspace when omitted.
{ fleetId, runId, status, endpoints, token, expiresAt, supportedPlaywrightVersions }. The token is shown only in this response. Fetch it again later with get_browser_fleet.
get_browser_fleet
{ fleet_id, include_token? } (default true)
Status, per-location readiness, endpoints, session count, sessionCount (total across every run), stepCapture, the canStart / canStop / terminal flags, and the reconnect token unless you omit it. terminal is not the opposite of canStart: a failed fleet is terminal and restartable.
list_browser_fleets
{ q?, lifecycle?: 'created'|'running'|'stopped'|'failed', page?, page_size?, workspace_id? }. q is a name search (max 100 chars).
{ fleets, total, page, pageSize, summary: { total, running, stopped, activeSessions } }. summary is unaffected by q/lifecycle/page. It covers the whole account, or only that workspace when you pass workspace_id. Never includes tokens.
list_browser_fleet_sessions
{ fleet_id, page?, page_size?, started_from?, started_to? } (default 25, max 100). The two optional bounds are ISO 8601 and keep sessions that started in that window.
{ sessions, total }. Every session across ALL of the fleet’s runs, newest first, each with runId/name and a capture summary (stepCount/harStatus/harFailureReason/consoleStatus/consoleFailureReason). total is the fleet’s overall sessionCount, and is left out when a window is set.
list_browser_fleet_runs
{ fleet_id }
Every run the fleet has ever had, including 0-session runs, newest first: [{ runId, status, startedAt, endedAt, sessionCount }].
scale_browser_fleet (write)
{ fleet_id, browsers: [...] }
Updated fleet detail. Returns 403 when the resulting fleet exceeds your plan’s concurrent VU limit.
release_browser_fleet_browsers (write)
{ fleet_id, browsers: [...] } (counts to remove)
Updated fleet detail. Scales the fleet DOWN — releases whole runner VMs newest-first for the named browser/location slices. Returns 409 when a slice count exceeds the live count.
start_browser_fleet (write)
{ fleet_id }
Updated fleet detail. Mints a fresh run for a created/stopped fleet and provisions it. Returns 409 if already running.
stop_browser_fleet (write)
{ fleet_id, mode?: 'graceful'|'kill' }
Updated fleet detail. Releases the runners but keeps the fleet, its endpoints and its token. Start it again with start_browser_fleet. kill skips the session drain.
Updated fleet detail. A browsers/browsers_per_runner change on a running fleet re-provisions a fresh run; step_capture alone never does — it applies on the fleet’s next Start.
delete_browser_fleet (write, destructive)
{ fleet_id }
{ fleetId, deleted: true }. Tears the runners down, then removes the fleet permanently. After that, get_browser_fleet returns 404 and the endpoints and token stop working. Run history and billing don’t change. Use stop_browser_fleet if you want the fleet back later.
Expose a target that runs locally or isn’t deployed yet at a public https://<name>.maxoperf-tunnel.com URL. See Tunnels.
Tool
Args
Returns
create_tunnel (write)
{ name, auth_mode?: 'none'|'basic'|'bearer', allow_ips?, rate_limit_rpm?, idle_timeout_seconds?, capture_mode?: 'none'|'headers'|'body', workspace_id? }. name is a globally unique DNS label. workspace_id defaults to the account’s oldest active workspace when omitted.
{ id, name, url, status, online, clientToken, runCommand, ... }. This is the only response that shows the clientToken.
list_tunnels
{ page?, page_size?, workspace_id? }
Tunnel list, without client tokens. workspace_id filters to one workspace.
get_tunnel
{ tunnel_id }
One tunnel’s detail.
stop_tunnel (write)
{ tunnel_id }
Disconnects the live client. The URL stays reserved but returns 503s until you restart the tunnel.
Requests, 4xx/5xx, blocked requests, bytes, and p50/p95/p99 latency over a recent window. from/to (ISO-8601) take precedence over window_minutes — use them to line up with a run’s exact time range (span capped at 7 days).
Every virtual service can remember data DURABLY across requests, shared by its replicas — a global
bucket plus one bucket per session (keyed by a header/cookie/query value you choose, so each
virtual user gets its own cart). Transactions gain a state object (conditions, a scenario
step, captures with an optional transform chain, a response sequence), plus top-level cases
(response variants) and then_ops (counters). See
State & scenarios for the full concept walkthrough.
Values whose key name looks like a secret always come back [REDACTED] to every MCP client.
Updated virtual service. state_config ({ session_key, session_idle_ttl_seconds?, variables?, scenario_layout? }) is merged server-side at the top level — send only what changed.
list_vs_transactions
{ virtual_service_id }
{ transactions: [...] } — the VS’s resolved composition, incl. generated CRUD groups. Disabled transactions are not listed.
get_vs_transaction
{ transaction_id }
One transaction, incl. its state, cases, then_ops.
Every secret, virtual service, tunnel and browser-fleet binding a test has, in one place, plus a
read-only summary of its data bindings. Binding one lets you pick it as a live chip in an
interactive HTTP or browser step instead of a literal URL, or injects a runtime env var for a
scripted test. See Test Dependencies.
{ test_id, kind: 'virtual_service'|'tunnel'|'browser_fleet'|'secret', entity_id, env_var_name?, auto_start? }. env_var_name is required for virtual_service/tunnel/browser_fleet (upper-snake, at most 40 characters); optional for secret (inherits the secret’s name when omitted). auto_start only applies to virtual_service.
The created/updated binding. Binding the same test + entity again updates the env var name. For a virtual service it also sets auto_start, which goes back to on if you leave it out.
unbind_test_dependency (write)
{ test_id, kind, entity_id }
Removes the test’s own binding. For a secret, your other manually-bound secrets are kept. A binding the test’s model references inline can’t be removed this way (409 binding_in_use_by_model) — edit the model instead. Bindings a VarioTest member inherits from its master are removed on the master.
get_run_dependencies
{ run_id }
The virtual services, tunnels and browser fleets a run prepared or held, with lease state and timestamps. Secrets aren’t leased and don’t appear here.
One rule set per workspace instead of per test, covering the run-lifecycle triggers plus the
ecosystem ones (dependency pre-flight failure, tunnel disconnected during a run, failure criteria
breached, virtual-service/browser-fleet failure). See Notifications.
{ workspace_id, rule_id?, integration_id, trigger, tag_filter?, enabled? }. Omit rule_id to create a rule; send one to replace its full config (an omitted tag_filter or enabled resets to no filter / enabled).
{ managed: { providers }, byoc: { privateDatacenters } }. byoc.privateDatacenters lists the Shared Sandbox outpost, which MaxoPerf operates and shares, together with any self-hosted outpost your workspace registered. Pass the id as location: "byoc:<id>" (fleets) or placement.privateDatacenterId (virtual services).
inspect_url (write)
{ url }
Starts (or reuses) a real browser, opens url, and returns the DOM, text and outline after JavaScript runs. Use it instead of fetch_url/read_page_dom when the target is a single-page app.
Calls any public endpoint. Admin, internal and key-management paths are always rejected before any upstream call. Read-only sessions can only use GET, HEAD, and OPTIONS.
get_openapi
(none)
The public OpenAPI document. It is large, so try search_endpoints first.
These tools only read, and every one goes through a single SSRF-guarded fetch. If the deployment has no search provider configured, web_search disables itself and leaves the tool catalog.
Tool
Args
Returns
web_search
(query args)
Web search results, when a provider is configured.
fetch_url
{ url, ... }
Static page fetch: HTML only, no JavaScript execution.
read_openapi
{ url, ... }
Fetches and parses a third-party OpenAPI document.
read_page_dom
{ url, ... }
Static DOM extraction, with the same JavaScript limit as fetch_url.
Prompts are multi-step recipes. A client can offer them as one-click flows (prompts/list), so an agent doesn’t have to work out the right sequence of tool calls on its own.
Prompt
Args
What it guides
run-baseline-load-test
{ test_id }
Start a run and report pass/fail, duration, throughput, p95 latency, and error rate once it’s terminal.
diagnose-latency-regression
{ baseline_run_id, candidate_run_id }
Compare p95 latency between two runs of the same test and correlate with errors.
summarize-run
{ run_id }
A short, plain-language summary of one run.
plan-and-build-test
{ goal, target? }
Turn a plain-language goal into the project → test → upload → run sequence.
choose-executor
{ test_kind }
Recommend a test engine/executor and explain why.
scan-endpoints-for-hotspots
{ openapi_or_paste }
Rank likely load-testing hotspots from an OpenAPI spec or pasted endpoint list.
setup-secrets-and-envs
{ test_id }
Set up secrets and per-environment values before the first run.
diagnose-run-failure
{ run_id }
Find the root cause of a failed or slow run from tripped criteria, error bodies, logs, runner health, and anomalies.
explain-run-anomalies
{ run_id }
Run the anomaly scan on a finished run and explain flagged outliers.
Every tool error has the same shape: { isError: true, content: [{ type: "text", text: "<status> <code>: <detail>" }], structuredContent: { status, code, detail } }. Common codes: READ_ONLY_MODE, FORBIDDEN_PATH (call_platform_api deny-listed path), TOO_MANY_QUERIES / TOO_MANY_FILTERS / TOO_MANY_SERIES (query_run_metrics limits), UPLOAD_FAILED, PATH_NOT_ALLOWED (upload_test_file local-path traversal), INVALID_ARGUMENTS.
We use cookies
We use analytics and advertising cookies to understand traffic and measure campaigns. You can
accept all, reject all, or choose per category. See our
privacy notice for details.