Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

Bruno MCP Studio

NPM · @OSTICO/BRUNO-MCP · SCANNED AUG 13

Author, edit and run Bruno collections non-destructively: both dialects, groups, gRPC, WebSocket.

Available components

77 Trust /100
Trust breakdown (6 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score →

Supply Chain Security98
  • No malware found by supply-chain analysis.Pass
  • No known CVEs affecting this package version or its production dependencies.Pass
  • No install/post-install scripts declared.Pass
  • 44 of 143 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency97
  • Source repository is publicly reachable at the declared URL. View diagnostics → Pass
  • Cryptographically verified build provenance (signed, bound to Ostico/bruno-mcp-studio). View diagnostics → Pass
  • Clear OSI-approved license (MIT).Pass
  • Actively maintained (last published 0 days ago).Pass
  • Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability57
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 6497 tokens (~360/item across 18 items; 18 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management20
  • Stability observed for 6 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage90
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 69% of tool parameters carry a description.Partial
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Install

Add this component to your MCP client. Where a client-specific snippet is available, pick your client below and copy it straight into your config; otherwise use the connection detail shown.

npm · @ostico/bruno-mcp

# add to Claude Code
claude mcp add ostico-bruno-mcp-studio -- npx -y @ostico/bruno-mcp
# add to Codex CLI
codex mcp add ostico-bruno-mcp-studio -- npx -y @ostico/bruno-mcp
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ostico-bruno-mcp-studio": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "@ostico/bruno-mcp"
      ],
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add ostico-bruno-mcp-studio --command npx --arg -y --arg @ostico/bruno-mcp
# ~/.hermes/config.yaml
mcp_servers:
  ostico-bruno-mcp-studio:
    command: "npx"
    args: ["-y", "@ostico/bruno-mcp"]
// mcp.json
{
  "mcpServers": {
    "ostico-bruno-mcp-studio": {
      "command": "npx",
      "args": [
        "-y",
        "@ostico/bruno-mcp"
      ]
    }
  }
}
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 12 Aug 26 +2
    • Schema quality: 301 → 360 functional
    • Security disclosure: unverified → fail functional
    • Stability: unverified → 0.17 functional
    • Package version: 2.2.1 → 2.3.0 functional
  • 11 Aug 26 +3
    • We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
  • 7 Aug 26 72

    First indexed and scored.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 13 Aug 2026 · Analysed npm/@ostico/bruno-mcp@2.3.0

Provenance Verified

A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.

Result Verified
Ecosystem npm
Reason Verified
Discovered via Registry attestation endpoint
Source repo Ostico/bruno-mcp-studio
Certificate issuer https://token.actions.githubusercontent.com
Certificate SAN https://github.com/Ostico/bruno-mcp-studio/.github/workflows/release.yml@refs/tags/v2.3.0
Rekor log index 2438989943
Predicate type https://slsa.dev/provenance/v1
Subject digest sha512:6c92a4ffe4644698fcc28d6b68020a1fa7c9e9a58dc9800d658f62b486a14497a2faa179848bd0fcbda7cfed8fa0f547df9f3c14ca4dcba95a8fd6c2c
Dependencies 143 packages
Packages resolved 143
Stale 41
No linked repository 4
Tree resolution Complete
MCP tools · 18 exposed · ~6,438 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability.

Tool Tokens
add_test_script ~407

Add pre-request, post-response, or tests scripts to a Bruno request. Canonical scriptType values are pre-request/post-response/tests; the aliases before-request (→ pre-request) and after-response (→ post-response) are also accepted. Appends to any existing script of that type by default — pass scriptMode:"replace" to overwrite it, or use remove_script to clear it. Assertions must be wrapped in test("name", function() { ... }) to be reported. Scripts run as async functions: top-level await works, and bru.sleep(ms), setTimeout and setInterval are available. Time spent waiting counts against the script timeout (settings.timeout, default 5000ms); raise it with modify_request's settings argument.

NameTypeReqDescription
bruFilePathstringyesAbsolute path to the .yml or .bru request file. Get from list_requests or get_collection_stats.
scriptstringyesScript body. For post-response/tests, wrap every assertion in a test() block — test("status is 200", function() { expect(res.getStatus()).to.equal(200); }); — because only test() blocks are recorded…
scriptModestringHow to write the script. "append" (default) concatenates onto any existing script of this type; "replace" overwrites it. Each of the three script types has its own slot in both .bru and .yml, so repl…
scriptTypestringyesScript type. Canonical: pre-request, post-response, tests. Aliases: before-request (→ pre-request), after-response (→ post-response).

No output schema declared.

No examples provided.

create_collection ~72

Create a new Bruno API testing collection with configuration

NameTypeReqDescription
baseUrlstring
descriptionstring
formatstring
ignorearray
namestringyes
outputPathstringyesAbsolute path where the new collection directory will be created.

No output schema declared.

No examples provided.

create_crud_requests ~131

Generate a complete set of CRUD operations for an entity: list, get by id, create, update, delete. All five inherit the collection or folder auth block unless you pass auth.

NameTypeReqDescription
authobjectDefaults to inherit, matching what Bruno itself gives a new request. Passing "none" is an opt-OUT that stops the collection auth block from applying to these five files, not an absence of opinion.
baseUrlstringyes
collectionPathstringyesAbsolute path to existing collection directory.
entityNamestringyes
folderstring

No output schema declared.

No examples provided.

create_environment ~194

Create an environment file for a Bruno collection. Writes the WHOLE file, so it REFUSES a name that already exists rather than overwriting it — the error names the existing variables and says which ones a replace would delete, so you can choose between merging with update_environment, picking another name, and retrying with overwrite: true.

NameTypeReqDescription
collectionPathstringyesAbsolute path to existing collection directory.
namestringyes
overwritebooleanReplace an environment that already exists. Without this an existing name is refused. Keys in the file that this tool does not model are preserved either way.
variablesyesEither a flat name-to-value map, or a list of variable objects when you need flags. Use the list form to declare a secret at create time: a secret variable is stored as a name only (no format persist…

No output schema declared.

No examples provided.

create_request ~889

Generate request files for API testing (supports .bru and .yml formats). Authors HTTP requests by default, WebSocket requests with kind "websocket" (url plus websocket.messages) and gRPC requests with kind "grpc" (url plus grpc.method, grpc.protoPath and grpc.messages); neither takes an HTTP method or a body. Supports multipart/form-data with file uploads and per-part contentType (body.type "form-data" with formData entries of type "file"), and inline scripts (pre-request/post-response/tests) so no separate add_test_script call is needed. Scripts run as async functions: top-level await works, and bru.sleep(ms)/setTimeout/setInterval are available, spending the script timeout (settings.timeout, default 5000ms) — raise it via the settings argument.

NameTypeReqDescription
assertarrayDeclared assertions, evaluated on every run without needing a test() block.
authobject
bodyobject
collectionPathstringyesAbsolute path to existing collection directory.
folderstring
grpcobjectgRPC-only fields. Applies to kind "grpc" and is refused otherwise. Headers given for a gRPC request are written as metadata, which is that transport's only header surface.
headersobject
kindstringTransport. Defaults to "http". "websocket" and "grpc" take no method and no body; their payloads are websocket.messages and grpc.messages.
methodstringRequired for kind "http", refused for "websocket" and "grpc", which have no HTTP method. A gRPC request names its RPC method in grpc.method.
namestringyes
pathParamsobjectValues for :name segments in the URL, e.g. { id: "42" } for /users/:id.
queryobject
scriptsobjectInline scripts to persist with the request. Keys: pre-request, post-response, tests (aliases before-request/after-response accepted). Avoids a separate add_test_script call. IMPORTANT for tests/post-…
sequencenumber
settingsobjectRequest-level settings: transport behaviour (timeouts, redirects, URL encoding), not payload. What reaches the file depends on the dialect, because Bruno's own two writers differ: a .yml request alwa…
urlstringyes
varsobject
websocketobjectWebSocket-only fields. Applies to kind "websocket" and is refused otherwise.

No output schema declared.

No examples provided.

create_test_suite ~54

Generate comprehensive test collections with multiple related requests

NameTypeReqDescription
collectionPathstringyesAbsolute path to existing collection directory.
dependenciesarray
requestsarrayyes
suiteNamestringyes

No output schema declared.

No examples provided.

delete_request ~125

Permanently delete a Bruno request file from a collection. Use this to remove a request created by mistake; the file is unlinked from disk and cannot be recovered through this server. Only .yml/.bru files inside a detected Bruno collection can be deleted. To clear just a script and keep the request, use remove_script instead.

NameTypeReqDescription
confirmbooleanyesMust be true. Explicit acknowledgement that the file is deleted permanently.
filePathstringyesAbsolute path to the .yml or .bru request file to delete. Get from list_requests or get_collection_stats.

No output schema declared.

No examples provided.

get_collection_stats ~106

Get statistics about a Bruno collection — request counts by method, folders, environments, and per-request details including file paths. environmentDetails lists each environment with the NAMES of the variables it declares (values are withheld), so you can see what an environment already defines before merging into it with set_environment_variable. Use filePath values as entries in the requests list of run_collection.

NameTypeReqDescription
collectionPathstringyesAbsolute path to collection directory. Use the path returned by list_collections.

No output schema declared.

No examples provided.

list_collections ~126

List the Bruno collections REGISTERED IN workspace.yml, with their names and paths. This is a registry listing, not a filesystem scan: a collection that exists on disk but is not registered will NOT appear, and registered entries that no longer exist are returned with "exists": false. If you already know a collection's absolute path, pass it directly to the other tools — it does not need to appear here. Use the returned path as collectionPath in other tools (get_collection_stats, list_requests, run_collection).

NameTypeReqDescription
workspacePathstringOptional explicit path to workspace.yml

No output schema declared.

No examples provided.

list_requests ~70

List all request files (.yml/.bru) in a Bruno collection. Returns absolute file paths, each usable as an entry in the requests list of run_collection, or of one of its groups.

NameTypeReqDescription
collectionPathstringyesAbsolute path to collection directory. Use the path returned by list_collections.

No output schema declared.

No examples provided.

modify_request ~854

Update an existing Bruno request file with partial-merge semantics. Only provided fields are updated; all other fields are preserved. Supports multipart/form-data with file uploads and per-part contentType. Inline scripts REPLACE the existing script of the same type by default (idempotent — repeated calls do not accumulate duplicate blocks); pass scriptMode:"append" to concatenate instead. Use remove_script to clear a script entirely.

NameTypeReqDescription
assertarrayReplaces the whole assert block. Omit to leave existing assertions untouched.
authobject
bodyobject
filePathstringyesAbsolute path to the .yml or .bru request file to modify. Get from list_requests or get_collection_stats.
grpcobjectgRPC-only fields. Applies to kind "grpc" and is refused otherwise. Headers given for a gRPC request are written as metadata, which is that transport's only header surface.
headersobject
methodstring
namestring
pathParamsobjectReplaces the declared path parameters; query parameters are left alone.
queryobject
scriptModestringHow to write the scripts field. "replace" (default) overwrites the existing script of each provided type, so calling modify_request repeatedly is idempotent. "append" concatenates onto the existing s…
scriptsobjectInline scripts to persist with the request. Keys: pre-request, post-response, tests (aliases before-request/after-response accepted). Avoids a separate add_test_script call. IMPORTANT for tests/post-…
settingsobjectRequest-level settings: transport behaviour (timeouts, redirects, URL encoding), not payload. What reaches the file depends on the dialect, because Bruno's own two writers differ: a .yml request alwa…
urlstring
varsobject
websocketobjectWebSocket-only fields. Applies to kind "websocket" and is refused otherwise.

No output schema declared.

No examples provided.

read_environment ~104

Read an environment back as structured JSON: every variable with its value, plus its disabled and secret flags. Omit "name" to list the collection's environments instead. Secret variables are returned by name only — Bruno stores no value for a secret in either file format, so there is none to return.

NameTypeReqDescription
collectionPathstringyesAbsolute path to the collection directory.
namestringEnvironment name, without extension. Omit to list the available environment names.

No output schema declared.

No examples provided.

read_request ~152

Read a single request file back as structured JSON: method, url, headers, query and path params, body, auth mode, scripts, assertions, vars, settings and docs. Works on both .bru and .yml and returns the same shape for each, so the on-disk format stays invisible. Use this before modify_request to see current state, and after create_request to confirm what was written. A "notes" array reports anything the file declares that the runner will not act on.

NameTypeReqDescription
filePathstringyesAbsolute path to the .bru or .yml request file. Use the path returned by create_request or list_requests rather than rebuilding it: request filenames are lowercased on write.

No output schema declared.

No examples provided.

remove_environment_variable ~68

Remove a single variable from an existing Bruno environment. MERGES into the environment — all other variables are preserved.

NameTypeReqDescription
collectionPathstringyesAbsolute path to existing collection directory.
environmentstringyesName of the existing environment.
namestringyesVariable key to remove.

No output schema declared.

No examples provided.

remove_script ~170

Delete a pre-request, post-response, or tests script from a Bruno request, leaving the rest of the request intact. Use this to undo or clean up a script written by create_request/modify_request/add_test_script — including duplicate blocks accumulated by appending. Canonical scriptType values are pre-request/post-response/tests; the aliases before-request and after-response are accepted. Removing all scripts also drops the now-empty script container.

NameTypeReqDescription
bruFilePathstringyesAbsolute path to the .yml or .bru request file. Get from list_requests or get_collection_stats.
scriptTypestringyesWhich script to remove. Both .bru and .yml keep the three script types in separate slots, so removal is precise: clearing tests leaves a post-response script in place, and vice versa.

No output schema declared.

No examples provided.

run_collection ~2,609

Execute requests in a Bruno collection and run test scripts. HOW TO RUN A SUBSET: requests takes an ORDERED list of entries, each a .yml/.bru request file or a directory (which expands to every request under it, recursively). Absolute, or relative to collectionPath. Order is yours and duplicates are allowed — naming the same request twice runs it twice. Omit requests to run the whole collection. GROUPS: pass groups instead when one call needs more than one identity or configuration. Each group owns its OWN variable store and cookie jar, so nothing a group sets — a bru.setVar, a session cookie — is visible to any other group. That is what makes running the same five requests as alice and as bob in one call safe. Passing both requests and groups is REJECTED rather than resolved for you. ITERATIONS: data or dataFile runs a group once per row of a table, with the row bound as variables — one call to check the same requests against 50 accounts, or one login against 50 credential pairs. Each row is reported as its own group, with the same name, its own index and an iterationIndex, because each row IS a separate group: it gets that isolation, so two rows differing only in a password authenticate separately instead of one silently reusing the other's token. Rows are independent, so a failing row does not stop the rows after it. Ceiling of 1000 rows per scope. PARALLELISM: parallel on the RUN fans the groups out against each other; parallel on a GROUP fans that group's own requests out. A group is serial unless it says otherwise, whatever the run does. seq no longer constrains execution — it is the default order and the reporting order only, so two requests in one parallel group genuinely run at the same time and may contend on the store they share. RESULTS are group-shaped: groups[] each carry their own summary, results, capturedVariableNames, capturedVariables and warnings, and the top-level summary is the run. There is no top-level results array, in the no-groups case ei…

NameTypeReqDescription
captureVariablesarrayNames of variables set by bru.setVar during the run whose values you want back, e.g. ["token"]. A script that captures a value out of a response — bru.setVar("token", res.body.token) — makes it avail…
collectionPathstringyesAbsolute path to collection root directory. Use the path returned by list_collections.
collectionRootstringThe collection that collectionPath belongs to, when running a subfolder of one: environments and the collection- and folder-level scripts are resolved from here. Must be collectionPath itself or an a…
cookieJarbooleanKeep cookies from each response and send them on later requests in the same run, so a login carries into the requests after it. Scoped to the group — nothing crosses from one group to another, at any…
dataarrayRows every group iterates over, as the group-level data but applied to all of them. A group that gives its own data or dataFile REPLACES this rather than adding to it, the same rule environment follo…
dataFilestringA CSV inside the collection whose rows every group iterates over. Same rules as the group-level dataFile, and likewise replaced by a group that names its own rows. Ceiling of 1000 rows, because every…
environmentstringEnvironment name to use (e.g. "dev", "staging"). Get available names from get_collection_stats.
groupsarrayRun the same collection under more than one identity or configuration in one call. Each group owns its OWN variable store and cookie jar: nothing a group sets is visible to any other group, in either…
includeResponseBodybooleanInclude the response body of each request in the results. Default: true.
maxConcurrencyintegerCeiling on requests in flight across the whole run. Omit to derive one from this machine's cores and memory, held below capacity. 0 lifts it entirely, at your own risk. Applies to THIS run and is giv…
maxResponseBodyBytesnumberMaximum response body size (bytes) to return per request; longer bodies are truncated and response_body_truncated is set. Default: 10240.
parallelbooleanFan out. At the run level this runs the GROUPS concurrently; a group's own requests are serial unless that group sets its own parallel. With no groups given the run is one group, so parallel here run…
reportobjectWrite the run to a file, in addition to returning it here. Name at least one format. Paths are CONFINED TO THE COLLECTION: a path resolving outside it is refused, with the reason as a run warning, be…
requestsarrayThe requests to run, IN THE ORDER GIVEN. Each entry is a .yml or .bru request file, or a directory, which expands to every request under it, recursively. Absolute, or relative to collectionPath. Get…
variablesobjectVariables for this run only, as {name: value}. They override the environment file and work without one. Held in memory and never written to any file — this is the only correct way to supply a secret,…
websocketobjectBounds for websocket requests in this run. Applies to every websocket request in the call; there is no per-request form. Omit and the defaults below apply. A session always ends on one of these bound…

No output schema declared.

No examples provided.

set_environment_variable ~213

Set (add or update) a single variable in an existing Bruno environment. MERGES into the environment — all other variables are preserved.

NameTypeReqDescription
collectionPathstringyesAbsolute path to existing collection directory.
enabledbooleanWhether the variable is enabled. Persisted: enabled=false is written as a disabled variable.
environmentstringyesName of the existing environment.
namestringyesVariable key to set.
secretbooleanWhether the variable is a secret. Persisted. IMPORTANT: marking a variable secret means its VALUE IS NOT SAVED — Bruno stores a secret variable as a name only (.bru lists it under vars:secret, .yml w…
valuestring|number|booleanyesVariable value.

No output schema declared.

No examples provided.

update_environment ~94

Partially update an existing Bruno environment by MERGING the provided variables into the existing ones. Pre-existing variables not listed are preserved (unlike create_environment, which replaces the whole file).

NameTypeReqDescription
collectionPathstringyesAbsolute path to existing collection directory.
namestringyesName of the existing environment to update.
variablesobjectyesVariables to merge into the environment. Existing variables not listed here are kept.

No output schema declared.

No examples provided.