Skip to main content
Glama
ffumero2003

b2-mcp-server

by ffumero2003

b2-mcp-server

An MCP server that exposes Backblaze B2 Cloud Storage as tools any MCP-compatible AI client can call. Manage B2 by talking to an assistant -- "which buckets are over 80% of their budget?", "upload this file", "delete that version" -- instead of writing SDK code or clicking through the web console.

Nine tools over stdio: list buckets, list files, upload, download, hide, unhide, delete a version, report bucket usage against a budget, and list application keys.

Built on @backblaze-labs/b2-sdk and the MCP TypeScript SDK.

Why it is shaped this way

The interesting part of an MCP server is not the API calls. It is what happens when a language model is the one calling them.

  • Local filesystem access denies by default. Upload reads only from B2_UPLOAD_ROOT, download writes only to B2_DOWNLOAD_ROOT, and both are refused outright when the root is unset. Read and write roots are separate so they can be granted independently. Paths are resolved with realpath before the containment check, so a symlink inside the root cannot point outside it, and containment is target === root || target.startsWith(root + sep) -- a bare startsWith would admit the sibling directory /data/uploads-evil for the root /data/uploads. Rejection messages name the offending path and never the root.

  • The one tool that destroys data cannot be aimed loosely. b2_delete_file_version takes an exact fileId and refuses to resolve one from a file name, so "delete hello.txt" cannot be satisfied in a single step: the id has to come out of a listing a human can see. A confirm flag would not help, since the same model that calls the tool would set it. Deletion is also refused unless B2_AUDIT_LOG is configured, and writes an INTENT record before acting and an OUTCOME record after -- on failure too, because a log that can miss events is not a log. With B2_ARCHIVE_ROOT set, the bytes are copied locally first.

  • The credentials boundary enumerates its fields. b2_list_keys names all nine fields it emits rather than spreading the SDK's key object, so a future SDK version that adds a secret-bearing field to a list response cannot leak it by accident. Key creation is deliberately not implemented for the same reason: B2 returns the live secret only from createKey, and that value would land in a model's context window.

  • Partial results announce themselves. Anything that can return less than the whole truth says so in the payload -- truncated/nextFileName on file listings, truncated/anyTruncated/unfinishedLargeFiles on usage, truncated on key listings, and scopedToBucketId when the application key's own restriction narrowed a whole-account listing to a single bucket. A partial answer presented as a complete one is worse than a refusal, because the caller cannot tell.

  • Least-privilege keys are the tested path, not an afterthought. B2 rejects an unfiltered b2_list_buckets from a bucket-restricted key with a 401, and the listAllBucketNames capability does not exempt it -- so a server that only ever ran on a master key would ship broken for the credential its own docs mandate. That is exactly what happened here, and it was caught by rotating the key rather than by any test: a fake listBuckets() agrees with whatever the caller does, so no fixture can catch an authorization rule.

  • Downloads are written atomically. Bytes go to <target>.<pid>.partial, are counted and length-checked, and are renamed onto the target only on a match. The SDK documents that a checksum failure errors the stream after bytes have flowed, so writing straight to the final path would leave a truncated file behind.

  • Errors are returned, never thrown, across the MCP boundary. A throw tears down the stdio session; an error result lets the client read the reason and explain it.

On bucket usage

B2's API exposes no quota or usage endpoint -- caps and alerts live only in the web console. b2_bucket_usage therefore sums file versions, including old ones, because B2 bills for those too. Hide markers, folder markers, and start records are excluded. Parts of unfinished large uploads are billed but not summable, so they are reported separately as unfinishedLargeFiles and bytesUsed is an honest floor rather than a total. The budget it is measured against is project policy defined in code (10 GiB default, the B2 free tier), not a B2 concept.

Related MCP server: duplicati-mcp

Requirements

Node >= 22.3.0. This is a hard floor, not a preference -- the B2 SDK declares it in engines. Pinned by .nvmrc, so run nvm use first if your shell default is older; every command below fails on Node 20 and the failure does not mention the version.

Setup

npm install
cp .env.example .env   # then fill in .env; it is gitignored
npm test               # 131 passing
npm run build

Create an application key in the Backblaze console under Account > Application Keys. Use a regular scoped key, not the master key: the master key carries every capability, cannot be scoped, and cannot be deleted, only regenerated.

Environment

.env.example is committed documentation holding names only. Values go in .env.

Variable

Required

Purpose

B2_APPLICATION_KEY_ID

yes

Application key id.

B2_APPLICATION_KEY

yes

Application key secret.

B2_UPLOAD_ROOT

for uploads

The only directory b2_upload_file may read from. Unset means every upload is refused.

B2_DOWNLOAD_ROOT

for downloads

The only directory b2_download_file may write to. Unset means every download is refused.

B2_AUDIT_LOG

for deletion

Append-only JSON Lines file, one object per mutation. Deletion is refused when unset.

B2_ARCHIVE_ROOT

optional

Where a copy of each deleted version is kept before it is destroyed. A manifest proves what existed; this keeps the bytes.

Capabilities needed per tool: listBuckets/listFiles for the read tools, writeFiles for upload, readFiles for download, deleteFiles for deletion, listKeys for b2_list_keys. A Read Only key fails at the B2 API on any write, by design.

Running

npm start     # node dist/server.js  (built)
npm run dev   # tsx src/server.ts    (from source)

The server speaks MCP over stdio. Nothing is ever written to stdout except the protocol stream; diagnostics go to stderr.

Wiring it into a client

Add to your MCP client config (Claude Desktop, Claude Code, or any other MCP host):

{
  "mcpServers": {
    "b2": {
      "command": "node",
      "args": ["/absolute/path/to/b2-mcp-server/dist/server.js"]
    }
  }
}

Credentials come from the .env file next to the package, so none appear in client config.

Calling tools by hand

npx @modelcontextprotocol/inspector --cli npm run dev --method tools/list

npx @modelcontextprotocol/inspector --cli npm run dev \
  --method tools/call --tool-name b2_bucket_usage

Each argument needs its own --tool-arg, for example --tool-arg bucketName=my-bucket.

Gotcha worth knowing: a relative localPath resolves against the configured root, not your shell's working directory. With B2_UPLOAD_ROOT=".../uploads", pass localPath=hello.txt, not localPath=uploads/hello.txt -- the latter looks for uploads/uploads/hello.txt. The error message shows the candidate as you gave it and deliberately not the resolved path, because that would print the root.

Tools

Tool

Read/write

What it does

b2_list_buckets

read

The buckets the key can see, with id, name, and type, plus scopedToBucketId when the key is restricted to one.

b2_list_files

read

One page of current files in a bucket, optional prefix and limit, with truncated/nextFileName.

b2_upload_file

write

Uploads from B2_UPLOAD_ROOT into a bucket. Adds a version rather than replacing.

b2_download_file

write (local)

Downloads to B2_DOWNLOAD_ROOT, atomically. Returns the path and SHA-1, never the content. Will not replace an existing file unless overwrite is true.

b2_hide_file

write

Hides a file from listings. Reversible; the data stays in version history.

b2_unhide_file

write

Removes the latest hide marker. Reports restored: false rather than failing when nothing was hidden.

b2_delete_file_version

destructive

Permanently destroys one version. Needs the exact fileId, requires B2_AUDIT_LOG, honours B2_ARCHIVE_ROOT.

b2_bucket_usage

read

Bytes stored per bucket against a budget, flagging buckets over the threshold. Omit bucketName to scan every bucket.

b2_list_keys

read

Application keys with capabilities, bucket restrictions resolved to names, and derived expiry. No secrets.

Every tool carries a zod input schema with per-field descriptions and MCP annotations (readOnlyHint, destructiveHint, idempotentHint) set honestly, so a client can decide what needs confirmation.

Testing

npm test

131 tests across 12 files, no network and no credentials required -- modules take the narrow structural type they actually use (BucketLister, not B2Client), so a fake satisfies them while tsc still proves the real client fits.

Several test files are regression coverage for bugs that a green suite would not otherwise catch, and their fixtures are shaped from observed dependency behavior rather than from what the API ought to do:

  • The B2 SDK throws errors with an empty .message; the diagnosis lives on name/code/status. Reading .message alone returned a blank string to the user for every B2-side failure.

  • Node's process.loadEnvFile() reports an unreadable file as ENOENT, not EACCES, which downgrades "your .env has wrong permissions" to "you have no .env".

Where an invariant can be checked against real data instead of a fixture, it was: usage was validated against a live account by the property that b2_bucket_usage can never report fewer bytes than b2_list_files sums (it exceeded it by exactly one 28-byte old version), and the delete path by a four-way SHA-1 match across the original, the download, the archive copy, and B2's own checksum. A fixture agrees with whatever the code does; a real corpus does not.

Project layout

src/
  server.ts        MCP server, tool registration
  config.ts        credentials from the environment
  env-file.ts      .env loading (Node built-in, zero dependencies)
  path-fence.ts    read and write containment, both directions
  atomic-write.ts  temp file plus rename
  audit-log.ts     append-only JSON Lines mutation record
  b2/              client, buckets, files, upload, download, delete, usage, keys
tests/             vitest, one file per module
claude-plans/      numbered design docs, written before the code

Roadmap

The full parked list lives in claude-plans/ROADMAP.md. The largest known gap: b2_list_file_versions. Usage counts every version the account is billed for while b2_list_files shows only current ones, so the server can report "you are paying for 91 versions across 90 files" and offer no way to see the difference. Deleting a current version promotes the next-oldest, which makes discovery destructive-only today.

License

MIT.

Available Tools

9 tools
b2_bucket_usageReport bucket storage used against a budgetA
Read-only

Reports bytes stored per bucket and how that compares to a budget, flagging buckets over the threshold. B2 exposes no usage endpoint, so this is computed by summing every file version, INCLUDING old versions, which B2 also bills for. The figure EXCLUDES parts of unfinished large uploads, which B2 does bill for; those uploads are counted separately as unfinishedLargeFiles, so treat bytesUsed as a floor rather than a total. Omitting bucketName scans every bucket, which costs one transaction per 1000 versions per bucket and is the most expensive call this server makes. A scan is capped at 20 pages per bucket and sets truncated when the cap stops it.

ParametersJSON Schema
NameRequiredDescriptionDefault
bucketNameNoBucket to measure. Omit to scan every bucket.
budgetBytesNoBudget to measure against. Defaults to 10 GiB, B2 free tier.
thresholdPercentNoPercent of budget at which a bucket is flagged. Defaults to 80.

TDQS

A4.7/5.0
Behavior5/5

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

While annotations already indicate readOnlyHint=true, the description goes far beyond that by explaining critical behavioral nuances: the calculation sums all file versions including old ones, excludes unfinished large upload parts, treats bytesUsed as a floor, and caps scans at 20 pages per bucket. These details are not available in annotations or schema, significantly enhancing the agent's understanding of side effects and limitations.

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 four sentences long, with no fluff. It front-loads the primary purpose, then adds caveats and cost implications. Each sentence provides essential information for correct usage and expectation-setting, making it appropriately sized for the tool's complexity.

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 absence of an output schema, the description compensates by explaining key output concepts (bytesUsed, unfinishedLargeFiles, truncated) and the operational context (scan cap, cost). It covers all critical aspects an agent needs to correctly invoke and interpret results, making it complete for this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already provides descriptions for all three parameters (100% coverage), establishing a baseline of 3. The description adds meaningful context beyond the schema, particularly for bucketName: omitting it scans every bucket and incurs the highest cost. It also clarifies the semantics of budgetBytes and thresholdPercent defaults, which are present in the schema but reinforced contextually.

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 clearly states the tool reports bytes stored per bucket against a budget and flags over-threshold buckets. This distinguishes it from sibling tools, which focus on file/bucket listing, upload/download, or deletion. The verb 'Reports' plus specific resource and outcome make the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use the tool, such as noting that omitting bucketName triggers a full scan that is 'the most expensive call this server makes.' It does not explicitly name alternative tools, but the unique purpose among siblings makes the usage context clear. It lacks explicit when-not-to-use guidance, but the cost warning serves as a caution.

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

b2_delete_file_versionPermanently delete one version of a B2 fileA
DestructiveIdempotent

PERMANENTLY destroys ONE version of a file. B2 cannot undo this, and older versions of the same name are left in place. Requires the exact fileId, which you must get from b2_list_files first: this tool will not look one up from a file name. Refused unless B2_AUDIT_LOG is configured, since every deletion is recorded. When B2_ARCHIVE_ROOT is set, a copy of the version is saved locally before it is destroyed. To remove a file from view reversibly, use b2_hide_file instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileIdYesExact version id to destroy. Get it from b2_list_files.
fileNameYesName of the file version to delete.
bucketNameYesBucket containing the file.

TDQS

A4.9/5.0
Behavior5/5

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

Beyond annotations (destructive, read-only false, idempotent), description discloses permanence ('B2 cannot undo this'), scope ('older versions... left in place'), environmental prerequisite (B2_AUDIT_LOG required), and conditional archiving (B2_ARCHIVE_ROOT copies locally). These are genuinely valuable behavioral details not present in annotations.

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?

Every sentence contributes new information: permanence, scope, prerequisite, audit requirement, archival behavior, and alternative. Dense but not bloated, front-loaded with the core function.

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?

For a destructive, environment-sensitive tool, the description covers what, why, when, prerequisites, side effects, and reversible alternatives. With no output schema, it appropriately focuses on operational requirements and consequences.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema already provides 100% coverage, so baseline is 3. Description adds meaningful nuance: the fileId is not interchangeable with fileName, and the fileId must come from b2_list_files. This clarifies parameter relationships beyond the schema's individual field descriptions.

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?

Description states 'PERMANENTLY destroys ONE version of a file' — a specific verb, resource, and scope. It clearly distinguishes from the reversible 'b2_hide_file' alternative, making the tool's purpose unmistakable.

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?

Explicitly instructs to obtain exact fileId from b2_list_files first and guards against misuse by noting it will not look up by file name. Also names the reversible alternative (b2_hide_file) for different use cases.

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

b2_download_fileDownload a B2 file to local diskA
DestructiveIdempotent

Downloads a file from a bucket to the local filesystem and returns where it landed, its size, type, and SHA-1. The destination must sit inside the directory named by B2_DOWNLOAD_ROOT. An existing file is not replaced unless overwrite is true. File content is never returned, only the path it was written to.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileNameYesName of the file in the bucket.
localPathNoDestination inside B2_DOWNLOAD_ROOT. Defaults to the file base name.
overwriteNoReplace an existing destination file. Defaults to false.
bucketNameYesName of the bucket to read from.

TDQS

A4.5/5.0
Behavior5/5

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

The description goes beyond annotations by disclosing the B2_DOWNLOAD_ROOT constraint, overwrite behavior, return payload (path, size, type, SHA-1), and explicitly stating file content is never returned. This is rich behavioral context that aligns with annotations.

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?

Four sentences, front-loaded with the core action, then essential constraints and edge cases. Every sentence adds value with no fluff or repetition.

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?

With no output schema, the description explains return values (path, size, type, SHA-1) and key constraints (root directory, overwrite semantics). It is complete for a download tool with good annotations, leaving no major operational gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema already documents defaults and constraints for localPath and overwrite. The description adds no new parameter meaning beyond the schema, so baseline 3 applies.

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 uses a specific verb and resource: 'Downloads a file from a bucket to the local filesystem' and clarifies it returns metadata. This clearly distinguishes it from siblings like b2_upload_file or b2_list_files.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The context is clear: this is the tool for retrieving file content to local disk. It doesn't explicitly name when-not-to-use or alternative tools, but the operation is self-evident among the sibling list with no ambiguity.

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

b2_hide_fileHide a B2 fileA
Idempotent

Hides a file so it stops appearing in b2_list_files. Reversible: the data stays in version history and b2_unhide_file restores it. Prefer this over deleting when the goal is to remove something from view.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileNameYesName of the file to hide.
bucketNameYesBucket containing the file.

TDQS

A4.7/5.0
Behavior5/5

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

The description goes beyond the annotations by disclosing that the file data remains in version history, that the action is reversible via b2_unhide_file, and that hidden files no longer appear in list operations. This adds significant behavioral context beyond the readOnly, idempotent, and destructive hints. No contradiction with annotations.

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 three concise sentences, front-loaded with the primary action and effect, followed by reversibility and usage guidance. Every sentence earns its place with no redundant text.

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?

For a simple two-parameter tool with annotations and no output schema, the description is complete: it explains the action, its behavioral consequence, reversibility, and how it relates to sibling tools (delete and unhide). No critical gaps are apparent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already provides complete descriptions for both required parameters (bucketName and fileName) with 100% coverage. The tool description does not add additional parameter-level meaning, so it meets the baseline but does not exceed it.

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 uses a specific verb ('hides') and names the resource ('file') with a concrete effect: 'stops appearing in b2_list_files'. It clearly distinguishes from siblings like delete and unhide by stating reversibility and preference over deletion.

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?

It explicitly states when to prefer this tool: 'Prefer this over deleting when the goal is to remove something from view.' It also names the alternative for restoration (b2_unhide_file), providing clear context for when to use this tool versus alternatives.

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

b2_list_bucketsList B2 bucketsA
Read-only

Lists every bucket in the configured Backblaze B2 account, as JSON objects with bucketId, bucketName, and bucketType.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.1/5.0
Behavior3/5

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

Annotations already indicate readOnlyHint=true, so the description carries a lower burden. It adds the return format (JSON objects with specific fields) and the 'every bucket' scoping, but does not disclose other behaviors like pagination or authentication. This provides some value beyond the annotation.

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 a single, well-formed sentence that is front-loaded with the action and provides necessary details without any waste.

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?

For a simple list tool with no parameters and an annotation for read-only safety, the description is complete. It specifies the output shape, making it sufficient even without an output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the baseline is 4. The description correctly implies no inputs are needed by listing buckets without any filters or options, and the empty schema confirms this.

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 clearly states the verb 'Lists' and the resource 'every bucket in the configured Backblaze B2 account', and it specifies the output format as JSON objects with bucketId, bucketName, and bucketType. This distinguishes it from sibling tools like b2_list_files which list files, not buckets.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The context is clear from the name and description—this tool is for listing buckets—but there is no explicit 'when to use' vs alternatives. With no parameters and a straightforward purpose, the usage is implied rather than directly stated.

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

b2_list_filesList files in a B2 bucketA
Read-only

Lists one page of current files in a bucket, as JSON objects with fileName, fileId, contentLength, contentType, and uploadedAt. Optionally filtered by name prefix. The result reports truncated and nextFileName when more files exist beyond the page.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum files to return. Defaults to 100.
prefixNoOnly list files whose name starts with this prefix.
bucketNameYesName of the bucket to list.

TDQS

A4.2/5.0
Behavior4/5

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

With readOnlyHint=true, the annotation already signals a safe read. The description adds valuable context: it returns a page, mentions the fields, and explicitly reveals pagination via 'truncated and nextFileName'. This goes beyond the annotation. However, it doesn't clarify whether 'current files' excludes hidden files, which is relevant given sibling hide/unhide tools, so a minor gap prevents a 5.

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 three concise sentences, front-loaded with the main purpose, then output details, then pagination behavior. Every sentence contributes new information with no waste. It is appropriately sized for a tool with three parameters and a simple output structure.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the tool's core function, return format, filtering, and pagination, which is particularly important given no output schema exists. It doesn't mention error cases or auth, but readOnlyHint covers safety. The only notable omission is clarification of 'current files' regarding hidden files, but overall the description is adequate for a listing tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents limit, prefix, and bucketName. The description adds minimal parameter meaning: it mentions prefix filtering and one page (which relates to limit), but these are already in the schema. Since the description doesn't clarify syntax or format beyond the schema, baseline 3 is appropriate.

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 clearly states the action ('Lists'), the resource ('files in a bucket'), and the scope ('one page', 'current files'). It also distinguishes from siblings like b2_list_buckets and b2_upload_file by specifying the exact JSON fields returned. This is a specific verb+resource+scope, providing high purpose clarity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context: it lists files in a bucket with optional prefix filtering and pagination. It doesn't explicitly name alternatives or exclusions, but the sibling tools are distinct (e.g., b2_hide_file, b2_upload_file), so the intended use is fairly obvious. A full 5 would require explicit 'use this instead of X' guidance, but the context is sufficient.

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

b2_list_keysList B2 application keysA
Read-only

Lists the application keys on the account with their capabilities, bucket restrictions, name prefix, and expiry. Contains NO key secrets: B2 returns a secret only when a key is created, and this server never creates keys. It does reveal what each key is permitted to do. Requires a key carrying the listKeys capability; a key scoped only to file operations will be told so.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior5/5

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

Beyond the readOnlyHint annotation, the description adds critical behavioral context: it never returns key secrets, only reveals capabilities, and requires a specific capability. This is valuable transparency for a security-sensitive tool.

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 three sentences, all dense with relevant information. It front-loads the core purpose, then appends security and permission details without wasted words.

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?

For a no-parameter, read-only listing tool, the description covers what the tool returns, what it doesn't reveal, and the required permissions. No output schema exists, so the description satisfies the need for return value context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the schema trivially covers everything. The description adds no parameter info because none exists, and the baseline for 0 params is 4, which is appropriate.

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 clearly states the tool lists application keys with specific attributes (capabilities, bucket restrictions, name prefix, expiry). It explicitly distinguishes from sibling tools by focusing on application keys and not files/buckets.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a clear prerequisite (requires listKeys capability) and warns about insufficient permissions. While it doesn't explicitly compare to alternatives, the sibling context and the tool's specific scope make when-to-use clear.

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

b2_unhide_fileUnhide a B2 fileA
Idempotent

Removes the latest hide marker, making a hidden file visible again. If the file was not hidden, this reports restored false rather than failing.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileNameYesName of the file to restore.
bucketNameYesBucket containing the file.

TDQS

A4.2/5.0
Behavior4/5

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

Beyond the annotations (readOnlyHint=false, idempotentHint=true, destructiveHint=false), the description adds that only the latest hide marker is removed and that the response includes a 'restored false' field when the file wasn't hidden. This provides additional behavioral nuance not present in the annotations.

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 two sentences with no wasted words. It front-loads the action ('Removes the latest hide marker') and includes a concise edge-case note, making it both efficient and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter tool with annotations and no output schema, the description sufficiently covers the purpose and the edge case of non-hidden files. It hints at the response shape via 'restored false' but doesn't fully specify return values, which is acceptable given the tool's simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already provides descriptions for both parameters (bucketName and fileName) with 100% coverage, so the description doesn't need to repeat them. It adds no extra parameter-level meaning, so the baseline score of 3 is appropriate.

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 uses a specific verb ('Removes') and clearly identifies the resource ('B2 file') and action (unhiding). It distinguishes from the sibling b2_hide_file by stating it removes the hide marker, making the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool (to reverse a hide operation) and adds that if the file was not hidden, it reports restored false rather than failing, which is useful context for safe invocation. It does not explicitly name alternatives, but the context is clear given sibling tool names.

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

b2_upload_fileUpload a local file to a B2 bucketA

Uploads a file from the local filesystem into a bucket and returns the stored file id, name, size, and type. The local path must sit inside the directory named by B2_UPLOAD_ROOT; uploads are refused otherwise. Uploading an existing name adds a new version rather than replacing the old one.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileNameNoName to store in the bucket. Defaults to the local file name.
localPathYesPath to the local file. Must be inside B2_UPLOAD_ROOT.
bucketNameYesName of the destination bucket.
contentTypeNoMIME type. Omit to let B2 detect it.

TDQS

A4.5/5.0
Behavior5/5

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

The description adds substantial behavior beyond annotations: it says the tool returns the stored file id, name, size, and type, and explains versioning behavior (adds a new version instead of replacing). It also discloses the root-directory constraint. Annotations only indicate it is not read-only, not idempotent, and not destructive, so the description's extra detail is valuable.

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 three tight sentences: first states the core action and return value, second gives a critical path constraint, third explains versioning. No filler or redundancy; 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?

For a 4-parameter upload tool with no output schema, the description covers the essential return values, path constraint, and versioning behavior. It gives the agent enough context to invoke the tool correctly and understand consequences, especially since sibling tools are all unrelated to uploading.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all four parameters. The description repeats the localPath root restriction that appears in the schema and adds the versioning behavior relevant to fileName, but does not significantly extend parameter understanding beyond the structured definitions.

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 clearly states the action ('Uploads a file from the local filesystem into a bucket') and the resource ('B2 bucket'), which distinguishes it from sibling tools like b2_list_files, b2_download_file, and b2_delete_file_version. The title and first sentence align, providing a specific verb+resource with no ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use the tool: uploading a local file to a bucket, with an explicit prerequisite (path must be inside B2_UPLOAD_ROOT). It does not explicitly mention alternatives or exclusions, but among the sibling tools there is no other upload tool, so the purpose itself guides selection.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 9 tool updatesv0.1.0
    • First observedb2_bucket_usage
    • First observedb2_delete_file_version
    • First observedb2_download_file
    • First observedb2_hide_file
    • First observedb2_list_buckets
    • First observedb2_list_files
    • First observedb2_list_keys
    • First observedb2_unhide_file
    • First observedb2_upload_file

TDQS

A4.3/5.0
Disambiguation5/5

Each tool targets a distinct resource and action: files (list/upload/download/hide/unhide/delete), buckets (list usage), and keys (list). The hide/delete pair is explicitly contrasted, preventing confusion. No two tools overlap in purpose.

Naming Consistency4/5

Almost all tools follow a consistent b2_verb_noun pattern (e.g., b2_list_files, b2_upload_file, b2_hide_file). The sole exception is b2_bucket_usage, which uses a noun phrase rather than a verb, but it remains clear and does not disrupt overall readability.

Tool Count5/5

Nine tools is well-scoped for a Backblaze B2 server. Each tool serves a distinct, necessary function, and there is no redundancy or bloat. The count feels appropriate for the domain.

Completeness3/5

The tool set covers file operations (list, upload, download, hide, delete) and includes bucket/key listing and usage, but misses bucket lifecycle (create/delete) and key management (create/delete). Hiding and unhiding work well, but no direct file metadata retrieval or bucket configuration exists. Core workflows are present, yet notable gaps remain.

Maintenance

ActivityMaintained
ResponsivenessUnresponsive

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    F
    maintenance
    Enables seamless integration with Backblaze B2 cloud storage for managing buckets, uploading/downloading files, handling large multipart uploads, and managing application keys through natural language interactions.
    27
    1
    MIT
  • A
    license
    A
    quality
    F
    maintenance
    MCP server for the Rclone RC API. Gives AI assistants the ability to manage cloud storage remotes, copy/sync files, list directories, and more — all through natural language.
    56
    55
    10
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    A Model Context Protocol (MCP) server that provides a bridge between MCP-compatible clients and MinIO object storage. It exposes MinIO operations as MCP tools for seamless bucket management and object operations.
    4
    -

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ffumero2003/b2-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server