git:20261031.baad96f to git:20261102.6ac2791

31 added, 1 removed. Audit A to A.

---
name: beacon-api-workbench
description: Drive the Beacon API workbench (github.com/nannndev/beacon) from an agent to discover, create, import, send, chain, load-test, and document API or web endpoints. Supports Beacon/Postman/OpenAPI/Swagger/Insomnia/HAR imports, response assertions/extractors, capturing live responses as documented examples, and authorized rate-limit testing. Prefer the Beacon MCP server; fall back to REST.
---
# Driving Beacon
Beacon defines API endpoints (URL, method, headers, payload with `{{variable}}`
templating) and fires them repeatedly / concurrently to watch `attempts`,
`success`, `rate_limited`, `errors`, and latency. Use it only for **authorized**
testing.
## Prefer the MCP server
If the Beacon MCP server is connected, use its tools directly — they reuse the
engine and the same `tests.json` store:
**Inspect**
- `list_projects`, `list_endpoints`, `get_config` — quick overview. Use
`list_endpoints` only when the project is known to be small.
- `search_endpoints(query?, offset?, limit?)` — preferred discovery for larger
projects. It returns compact results plus `total` and `has_more`; paginate
instead of filling the context window with every endpoint.
- `get_endpoint(name_or_id)` — inspect one editable definition plus preflight:
resolved URL, missing variables, and `ready`. Sensitive literal auth/cookie/
API-key headers are redacted; `{{variable}}` references remain visible.
- `get_tree()` — full folder/endpoint tree with **ids** and nesting. Call this
to discover `folder_id`s for `create_endpoint`/`move_item`.
**Create**
- `create_endpoint(name, url, method, headers, payload, target_type?, folder_id?)`
— add an API request or a `web` HTML document load target.
`url` may be relative to the project `base_url`. Values may use
`{{variable}}` (static config vars or generators like `{{random_email}}`,
- `{{uuid}}`, `{{random_int:1:100}}`).
+ `{{random_name}}`, `{{uuid}}`, `{{iso_date}}`, `{{random_bool}}`,
+ `{{random_int:1:100}}`, `{{random_choice:a|b|c}}`). Always pass a
+ descriptive `name` — see **Naming endpoints**.
- `create_folder(name)` — new top-level folder.
- `add_endpoint_from_curl(curl, name?)` — build an endpoint from a curl string.
- `import_collection(data, into_folder?)` — uses Beacon's production importer
for Beacon exports, Postman v2, OpenAPI 3, Swagger 2, Insomnia, HAR, legacy
config, raw request lists, and single requests. For JSON/YAML text use
`{"content":"...", "filename":"openapi.yaml"}`. `into_folder` must resolve
to an existing folder id/name; omit it to create a source-named folder.
**Edit / organize**
- `update_endpoint(name_or_id, name?, url?, method?, headers?, payload?, payload_type?, extractors?)`
— change only the fields you pass; id and tree position preserved.
- `duplicate_endpoint(name_or_id)` — copy (new id, name +" (copy)").
- `move_item(name_or_id, into_folder?, position?)` — move an endpoint OR folder
into a folder (or root if omitted) and/or **reorder** it (`position` is a
0-based index; reorder in place by passing the same container).
- `rename_folder(name_or_id, new_name)`.
- `delete_endpoint(name_or_id)`; `delete_folder(name_or_id, recursive?)` —
folder delete refuses a non-empty folder unless `recursive=true`.
**Send / inspect & document**
- `send_request(name_or_id, retries?, retry_delay?, max_body_chars?, save_as_example?)` — fire the endpoint **once** and get the full
response: status, reason, time_ms, size_bytes, content_type, headers, body
(capped), parsed json, and `extracted` (names of variables the extractors
refreshed on a 2xx). Pass `save_as_example=True` to immediately save the live
response and payload as the documented example/mock contract.
The MCP body defaults to 20,000 characters to protect agent context
(`max_body_chars` may be 0–100,000). Use it to debug a response or to prime a token (send
"Login" so `{{access_token}}` is fresh) before other calls.
- `capture_endpoint_baseline(name_or_id, generate_assertions?, retries?, retry_delay?)` —
fire the endpoint once, capture the live response as the official documented example/mock baseline,
and optionally auto-generate test assertions (status code, latency SLA, Content-Type, and JSON structure).
- `set_example_response(name_or_id, status?, body?, headers?, enabled?)` — manually document
or mock the expected response contract for an endpoint before the backend is live.
**Run**
- `run_endpoint(name_or_id, concurrency, count, delay, use_min_delay?)` —
**fires real HTTP** and returns final stats (counts, latency p50/p95/p99,
status-code mix, rps, first-rate-limited-at). Confirm the target is authorized
before running with high `count`/`concurrency`.
- `run_scenario(name_or_ids, continue_on_error?, retries?, retry_delay?)` — run
a list of endpoints **in order** as one flow. Variables refreshed by extractors
carry into later steps, so ['Login','Get Profile'] primes `{{access_token}}`
before the profile call. Stops at the first failed step unless
`continue_on_error`. Returns a compact per-step summary.
Notes:
- `send_request`/`run_endpoint` also honor per-endpoint **assertions**
(status/time_ms/body_contains/jsonpath/header → `passed`) and `send_request`
supports `retries`.
- Body types (`payload_type`): `json`, `form` (x-www-form-urlencoded),
`multipart` (file upload), `raw` (text/XML/GraphQL — set Content-Type header).
- Tool failures keep a readable `error` and expose a stable `error_code` such
as `invalid_argument`, `endpoint_not_found`, `folder_not_found`, or
`import_invalid`. Fix the reported field/resource and retry; do not guess.
+
+ ## Naming endpoints
+
+ Every endpoint you create, import, or are asked to tidy gets a short,
+ human-readable name that says **what it does**, not how it is called. The
+ method and URL are already shown next to the name, so never repeat them.
+
+ - Use verb + resource in Title case: `Login`, `List sessions`,
+ `Get session`, `Delete session`, `Delete all sessions`,
+ `Verify two-factor code`, `Resend OTP`, `Update profile`.
+ - Map methods to verbs: GET collection → `List …`, GET one → `Get …`,
+ POST → `Create …` (or the action: `Login`, `Logout`, `Verify …`, `Resend …`),
+ PUT/PATCH → `Update …`, DELETE → `Delete …`.
+ - Path parameters become a qualifier, not braces: `GET branch-qr/{branch}` →
+ `Get branch QR code`; `GET menu-fonts/{font}/{style}` → `Get menu font style`.
+ - Prefer the OpenAPI `summary` when it is meaningful; otherwise derive the name
+ from the path and the folder. Drop prefixes shared by the whole folder
+ (`k-motion/`, `api/v1/`).
+ - Keep names unique inside a folder and under ~40 characters.
+ - Bad: `POST login`, `GET me`, `POST /api/v1/otp/verify`, `New Endpoint`,
+ `Login (copy)`. Good: `Login`, `Get current user`, `Verify OTP`.
+
+ Imports (and `add_endpoint_from_curl` without `name`) fall back to
+ `METHOD path` names. After importing, list the new endpoints and rename the
+ generic ones with `update_endpoint(name_or_id, name=...)`. When the user asks to
+ clean up names in an existing project, page through `search_endpoints`, propose
+ the renames in one table, and apply them after the user agrees. Renaming
+ changes no request behaviour.
## Recommended agent workflow
1. Call `list_projects`; switch explicitly when the intended project is not active.
2. Use `search_endpoints`, then `get_endpoint` on the selected result.
3. If preflight says `ready=false`, resolve the listed variable/base URL problem
before sending traffic.
4. Use `send_request` once to inspect the real response, assertions, and
extractors. For a login flow, send Login first and confirm `extracted`.
Use `capture_endpoint_baseline(name_or_id)` to document the response example
and generate test assertions in a single step.
5. Use `run_scenario` for ordered dependent requests.
6. Use `run_endpoint` only after the single request is correct. Start with
`count=1`, `concurrency=1`; increase gradually and only with authorization.
7. Report the exact target, request count, concurrency, success/error/rate-limit
totals, and latency percentiles. Never report secret variable values.
### Starting the MCP server
```bash
cd backend
python -m app.mcp_server # stdio (local)
BEACON_MCP_TRANSPORT=http python -m app.mcp_server # HTTP/SSE (hostable)
```
### Register the MCP server
Use the **MCP** panel in the Beacon desktop app (best for bundled binary, no Python needed).
Or manually:
```bash
codex mcp add beacon -- python -m app.mcp_server # Codex
claude mcp add beacon -- python -m app.mcp_server # Claude Code
```
For Cursor, Windsurf, Cline, Continue, etc. → use the config snippet from the Beacon **MCP** panel (it gives the correct path to the standalone binary).
## REST fallback (no MCP)
The FastAPI backend (default `http://localhost:8000`) exposes the same surface:
- `GET /projects`, `GET /tests`, `GET /config`
- `POST /tests`, `PUT /tests/{id}`, `DELETE /tests/{id}`, `POST /tests/{id}/duplicate`
- `PUT /projects/{id}` with `{ "items": [...] }` to reorder/move/rename the tree
- `POST /projects/import/preview` then `POST /projects/import` for Beacon,
Postman, OpenAPI/Swagger, Insomnia, HAR, JSON, or YAML import
- `POST /run` `{ test_id, concurrency, max_requests, delay, use_min_delay }` →
`{ run_id }`; poll `GET /status/{run_id}`; stop with `POST /stop/{run_id}`
## Safety
- `run_endpoint` / `POST /run` send real traffic. Get explicit authorization for
the target, and start with small `count`/`concurrency`.
- `tests.json` can contain real tokens — never echo variable *values* back to
the user or into logs.