b2-mcp-server
This server provides an MCP-compatible interface for managing Backblaze B2 Cloud Storage, enabling AI clients to interact with buckets, files, and application keys through a set of nine controlled tools.
b2_list_buckets: List all accessible buckets with ID, name, and type.
b2_list_files: List current files in a bucket with optional prefix filtering and pagination (up to 1,000 files), with truncation indicators.
b2_upload_file: Upload a local file from a configured safe directory (B2_UPLOAD_ROOT) to a bucket; creates a new version if the file name exists.
b2_download_file: Download a B2 file to a configured safe local directory (B2_DOWNLOAD_ROOT) atomically; returns the local path and SHA-1 checksum without exposing file content.
b2_hide_file: Hide a file from listings without deleting its data (reversible).
b2_unhide_file: Restore a previously hidden file by removing its latest hide marker.
b2_delete_file_version: Permanently delete a specific file version using its exact file ID (not inferred from filename); requires audit logging and can archive the file locally first.
b2_bucket_usage: Calculate storage used per bucket (including old versions) against a configurable budget, flagging buckets that exceed a threshold.
b2_list_keys: List application keys, their capabilities, and restrictions without exposing secrets.
All tools enforce strict path containment for local operations (B2_UPLOAD_ROOT and B2_DOWNLOAD_ROOT), guarding against symlink traversal and arbitrary filesystem access. The server handles errors gracefully by returning structured results, supports least-privilege credentials (B2 application keys with restricted capabilities), and indicates when listings or usage reports are partial. Deletion is deliberate and traceable thanks to audit logging and optional local archiving.
Provides tools for interacting with Backblaze B2 Cloud Storage, enabling AI agents to manage buckets, upload and download files, hide/unhide files, delete file versions, report bucket usage against a budget, and list application keys.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@b2-mcp-serverCheck which buckets are over 80% of their budget?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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 toB2_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 withrealpathbefore the containment check, so a symlink inside the root cannot point outside it, and containment istarget === root || target.startsWith(root + sep)-- a barestartsWithwould admit the sibling directory/data/uploads-evilfor 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_versiontakes an exactfileIdand 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 unlessB2_AUDIT_LOGis 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. WithB2_ARCHIVE_ROOTset, the bytes are copied locally first.The credentials boundary enumerates its fields.
b2_list_keysnames 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 fromcreateKey, 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/nextFileNameon file listings,truncated/anyTruncated/unfinishedLargeFileson usage,truncatedon key listings, andscopedToBucketIdwhen 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_bucketsfrom a bucket-restricted key with a 401, and thelistAllBucketNamescapability 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 fakelistBuckets()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 buildCreate 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 |
| yes | Application key id. |
| yes | Application key secret. |
| for uploads | The only directory |
| for downloads | The only directory |
| for deletion | Append-only JSON Lines file, one object per mutation. Deletion is refused when unset. |
| 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_usageEach 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 |
| read | The buckets the key can see, with id, name, and type, plus |
| read | One page of current files in a bucket, optional |
| write | Uploads from |
| write (local) | Downloads to |
| write | Hides a file from listings. Reversible; the data stays in version history. |
| write | Removes the latest hide marker. Reports |
| destructive | Permanently destroys one version. Needs the exact |
| read | Bytes stored per bucket against a budget, flagging buckets over the threshold. Omit |
| 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 test131 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 onname/code/status. Reading.messagealone returned a blank string to the user for every B2-side failure.Node's
process.loadEnvFile()reports an unreadable file asENOENT, notEACCES, 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 codeRoadmap
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 toolsb2_bucket_usageReport bucket storage used against a budgetARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| bucketName | No | Bucket to measure. Omit to scan every bucket. | |
| budgetBytes | No | Budget to measure against. Defaults to 10 GiB, B2 free tier. | |
| thresholdPercent | No | Percent of budget at which a bucket is flagged. Defaults to 80. |
TDQS
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.
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.
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.
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.
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.
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 fileADestructiveIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| fileId | Yes | Exact version id to destroy. Get it from b2_list_files. | |
| fileName | Yes | Name of the file version to delete. | |
| bucketName | Yes | Bucket containing the file. |
TDQS
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.
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.
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.
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.
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.
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 diskADestructiveIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| fileName | Yes | Name of the file in the bucket. | |
| localPath | No | Destination inside B2_DOWNLOAD_ROOT. Defaults to the file base name. | |
| overwrite | No | Replace an existing destination file. Defaults to false. | |
| bucketName | Yes | Name of the bucket to read from. |
TDQS
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.
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.
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.
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.
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.
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 fileAIdempotent
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.
| Name | Required | Description | Default |
|---|---|---|---|
| fileName | Yes | Name of the file to hide. | |
| bucketName | Yes | Bucket containing the file. |
TDQS
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.
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.
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.
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.
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.
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 bucketsARead-only
Lists every bucket in the configured Backblaze B2 account, as JSON objects with bucketId, bucketName, and bucketType.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
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.
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.
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.
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.
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.
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 bucketARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum files to return. Defaults to 100. | |
| prefix | No | Only list files whose name starts with this prefix. | |
| bucketName | Yes | Name of the bucket to list. |
TDQS
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.
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.
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.
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.
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.
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 keysARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
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.
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.
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.
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.
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.
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 fileAIdempotent
Removes the latest hide marker, making a hidden file visible again. If the file was not hidden, this reports restored false rather than failing.
| Name | Required | Description | Default |
|---|---|---|---|
| fileName | Yes | Name of the file to restore. | |
| bucketName | Yes | Bucket containing the file. |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| fileName | No | Name to store in the bucket. Defaults to the local file name. | |
| localPath | Yes | Path to the local file. Must be inside B2_UPLOAD_ROOT. | |
| bucketName | Yes | Name of the destination bucket. | |
| contentType | No | MIME type. Omit to let B2 detect it. |
TDQS
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.
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.
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.
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.
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.
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.
9 tool updates
v0.1.0- First observed
b2_bucket_usage - First observed
b2_delete_file_version - First observed
b2_download_file - First observed
b2_hide_file - First observed
b2_list_buckets - First observed
b2_list_files - First observed
b2_list_keys - First observed
b2_unhide_file - First observed
b2_upload_file
TDQS
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.
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.
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.
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
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
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
MCP server exposing the Backtest360 engine API as tools for AI agents.
An MCP server that provides an API to LLMs to manage their JumpCloud resources.
- UnifAPIOAuthcom.unifapi
Hosted MCP server for live public-data APIs and Skills for AI agents.
Related MCP Servers
- AlicenseNot gradedqualityFmaintenanceEnables 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.271MIT
- AlicenseAqualityDmaintenanceMCP server for managing Duplicati backups from an LLM.17MIT
- AlicenseAqualityFmaintenanceMCP 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.565510MIT
- FlicenseNot gradedqualityDmaintenanceA 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
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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