b2-mcp
OfficialProvides tools for interacting with Backblaze B2 Cloud Storage, enabling management of buckets, files, application keys, Object Lock, event notifications, lifecycle, and S3-compatible storage operations.
Backblaze B2 MCP Server
A Model Context Protocol server for Backblaze B2 Cloud Storage. It lets any MCP-compatible AI client (Claude, and others) operate B2 through a focused, safe set of tools, currently incubating in Backblaze-Labs.
40 tools, assigned by backing category:
Native B2 SDK (
@backblaze-labs/b2-sdk) (17) — B2 control-plane operations the S3 API has no equivalent for: buckets, application keys, Object Lock, event notifications, and Partner/Groups operations.AWS S3 SDK (
@aws-sdk/client-s3) (19) — the S3-compatible data plane: object upload/download/copy/list/delete, multipart, bucket reachability, lifecycle, and presigned URL paths.Neither SDK (custom MCP code) (4) — repository-owned analytics over B2 reports and bounded live listings: storage growth, egress leaders, largest files, and abandoned uploads.
Availability is a per-tool annotation, separate from those backing categories: durable-secret-producing tools are sink-backed for local stdio runs and remain non-secret unavailable stubs on HTTP/serverless unless an explicit sink is configured.
Destructive actions are gated, durable B2 secrets stay out of the model's context in the default/file/off modes, and the unsafe B2_SECRET_SINK=inline escape hatch is explicit. The tool surface is deliberately lean (registration is capability-aware, so a key only ever sees tools it can use).
Quick start
Prerequisites: A supported Node.js runtime (22.22.2+, or 24 / 26) and a Backblaze B2 application key. A non-master key is all you need. The package engine range is ^22.22.2 || ^24 || ^26; CI runs on Node.js 22.23.1, 24, and 26.
The canonical package name is @backblaze-labs/b2-mcp and the canonical binary is b2-mcp (b2-mcp-server is a transition alias). The fastest setup runs it with npx, no clone or build.
S3-compatible and report tools derive their endpoint region from the authorized B2 account response. B2_REGION is only a fallback/default for paths that need a region before authorization, or when authorization is temporarily unavailable.
Connect Claude Desktop by editing its config file — claude_desktop_config.json, located per OS:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.jsonLinux:
~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"backblaze-b2": {
"command": "npx",
"args": ["-y", "@backblaze-labs/b2-mcp"],
"env": {
"B2_APPLICATION_KEY_ID": "your-application-key-id",
"B2_APPLICATION_KEY": "your-application-key-secret"
}
}
}
}If you need an explicit fallback region before authorization, include B2_REGION in the same env block before restarting Claude Desktop:
{
"B2_APPLICATION_KEY_ID": "your-application-key-id",
"B2_APPLICATION_KEY": "your-application-key-secret",
"B2_REGION": "us-east-005"
}Restart Claude Desktop and the B2 tools appear. To persist local stdio logs from clients that do not expose child-process stderr, add "B2_LOG_FILE" to the same env block, set to an OS-appropriate absolute path (for example /var/log/b2-mcp.log on macOS/Linux or C:\\logs\\b2-mcp.log on Windows).
One non-master application key covers normal storage work: B2 native, S3, and key management. SDK-backed Partner/Groups tools require
B2_MASTER_KEY_ID/B2_MASTER_KEYon an account authorized for the Partner API. B2's S3 endpoint rejects master keys, which is why the application key remains the primary credential. See Configuration for the full list.Why your client may show fewer than 40 tools: registration is capability-aware, so a client only sees the tools its key can actually use. With a non-master key and no master key configured, the three Partner/Groups tools that require a master key (
b2_list_groups,b2_list_group_members,b2_eject_group_member) are not surfaced, sotools/listreports 37. AddB2_MASTER_KEY_ID/B2_MASTER_KEYon a Partner-entitled account to get the full 40. A read-only key trims the surface further, and durable-secret tools appear as non-secret "unavailable" stubs unless a secret sink is configured. This is expected, not a missing-install problem.
Other clients:
docs/CLIENTS.mdhas copy-paste setup for Cursor, VS Code, Cline, Windsurf, Zed, Continue, Goose, Claude.ai, and hosted (Streamable HTTP), plus a compatibility matrix.
git clone https://github.com/backblaze-labs/b2-mcp.git b2-mcp
cd b2-mcp
corepack enable pnpm
corepack prepare 'pnpm@11.20.0+sha256.34e198cb1e43237517ecedfd31f9ae26a6c0a3e5366ce58a2d05f4b21fb5f19a' --activate
pnpm install --frozen-lockfile
pnpm run build # produces dist/, required before first runThen set "command": "node" and "args": ["/ABSOLUTE/PATH/TO/b2-mcp/dist/index.js"] (or use the installed b2-mcp binary) in the config above.
Then just ask:
"List the buckets this key can access." · "Upload
./data.csvtoreports/may-2026.csv." · "Give me a 1-hour download link forbackups/latest.tar.gz." · "List files underlogs/2026/."
Local stdio runs can create application keys through the sink-backed tools; the
new key secret is written to ~/.b2-mcp/secrets.jsonl by default and is not
shown in the MCP response on POSIX platforms. Windows currently rejects file
sink paths because this implementation does not enforce owner-only ACLs there,
so use B2_SECRET_SINK=off or explicit local inline mode on Windows. For
hosted HTTP deployments, create and rotate keys outside the MCP flow unless you
have deliberately configured a reviewed secret sink.
Related MCP server: MinIO MCP Server
B2 Skills pack
This repo bundles a client-side Backblaze B2 skills pack under skills/ (manifest: skills/pack.json).
The MCP server is the action layer; these Markdown playbooks are the expertise
layer for common workflows: backup/restore, least-privilege keys, Object Lock,
lifecycle and cost hygiene, migration, and incident response.
The pack is optional but recommended for clients that support Markdown skills.
Each skill keeps bulk object bytes off the model and MCP server, uses
presigned/direct transfer paths for data movement, and pauses before destructive
or irreversible steps that are also gated by B2_DESTRUCTIVE_POLICY.
Validate the pack locally. The Node validator is a structural guard for the
declared pack, tool references, byte-path rules, and per-tool destructive gates;
it is not a content-safety proof, so skills/** changes require CODEOWNERS
review before publish. Each skill repeats the byte-path guardrails intentionally
so standalone client imports keep the no-model/no-server object-byte rule.
pnpm run validate:skillsLoad the pack in supported clients:
Claude Code: put each
skills/b2-*/directory under~/.claude/skills/or the client-supported project skills directory, then restart the session.Claude.ai / Claude Desktop with Skills: create ZIP archives for the desired
skills/b2-*/directories, with eachSKILL.mdat the ZIP root, then open Settings -> Capabilities -> Skills and upload those ZIP files.Other MCP clients with Markdown skills: register each
skills/b2-*/SKILL.mdfile or containing directory according to that client's skills documentation.
The skills do not add server endpoints or new permissions. They only sequence the existing B2 MCP tools and reinforce the same byte-path and destructive-action guardrails enforced by the server.
Docker quick start
The published image defaults to the HTTP transport, reads configuration only
from environment variables, and does not publish a mutable latest tag. Choose
the version tag that matches the package release. Cosign signatures are published
to a sibling GHCR repository so the package page's default pull command stays on
a runnable image tag:
B2_MCP_VERSION=VERSION # replace with the release version you want
B2_MCP_IMAGE="ghcr.io/backblaze-labs/b2-mcp:${B2_MCP_VERSION}"
docker run --rm --name b2-mcp \
--stop-timeout 20 \
-p 127.0.0.1:3000:3000 \
-e B2_HTTP_CREDENTIAL_MODE=server \
-e B2_APPLICATION_KEY_ID=your-application-key-id \
-e B2_APPLICATION_KEY=your-application-key-secret \
-e B2_ALLOWED_HOSTS=localhost,127.0.0.1 \
-e B2_DESTRUCTIVE_POLICY=block \
-e B2_REGISTER_ALL_TOOLS=false \
-e B2_SECRET_SINK=off \
-e B2_ALLOW_INLINE_SECRETS=false \
-e B2_ALLOW_LOCAL_FILES=false \
"$B2_MCP_IMAGE"For stdio clients inside a container, pass the transport explicitly and keep stdin open:
B2_MCP_VERSION=VERSION # replace with the release version you want
B2_MCP_IMAGE="ghcr.io/backblaze-labs/b2-mcp:${B2_MCP_VERSION}"
docker run --rm -i \
--no-healthcheck \
-e B2_APPLICATION_KEY_ID=your-application-key-id \
-e B2_APPLICATION_KEY=your-application-key-secret \
"$B2_MCP_IMAGE" stdioSee deploy/customer-hosted/README.md for
hardened HTTP examples with signature verification, B2_ALLOWED_ORIGINS, rate
limits, and in-flight request caps. The deployment index is
docs/DEPLOY.md, and the OAuth-secured Vercel adapter
runbook is deploy/vercel. Direct deployment guides
are available for
Vercel,
Cloudflare Workers,
Cloudflare Containers,
Docker/OCI,
Google Cloud Run,
AWS ECS Fargate,
Azure Container Apps,
Render,
Railway, and
Fly.io. All hosted paths share the
security and credential contract.
The image healthcheck applies to HTTP mode. For stdio containers, pass
--no-healthcheck. For HTTP containers, set the listen port through PORT so
the healthcheck probes the same port the server binds.
Configuration
Variable | Required | Default | Description |
| stdio / HTTP | — | Application key ID (non-master) — the workhorse for native B2 and S3-compatible tools |
| stdio / HTTP | — | Application key secret |
| — | falls back to app key | Master credential for SDK-backed Partner/Groups tools; required with Partner API entitlement for those operations |
| — |
| Fallback/default S3-compatible endpoint region; authorized B2 responses override this for S3/report tools |
| — | — | Optional operator token appended after the built-in |
| — |
| LLM-facing |
| — |
| CLI default transport when no |
| HTTP only | Node listen default | Standalone Node HTTP listen host; set to |
| — | stderr | Optional path for redacted structured JSON logs. When set, the file replaces stderr; stdout is never used for logs |
| — | stdio: | Durable-secret output mode: |
|
|
| Append-only plaintext JSONL credential ledger for file sink mode. HTTP/serverless file mode requires this explicit absolute path and |
| HTTP inline only |
| Dedicated HTTP/serverless opt-in required before |
| — | deprecated | Legacy alias retained for compatibility; S3 tools use the authorized |
| HTTP only |
|
|
| HTTP | — | JSON map from verified MCP principal to a customer-managed credential reference |
| HTTP | — | Env-backed secret-broker material for the mapped reference |
Every outbound B2 API call (native B2 SDK and the S3-compatible data plane) carries
a b2-mcp product token on its User-Agent so the traffic is attributable to this
server. A published release emits b2-mcp/<version> (for example b2-mcp/0.1.2);
a source checkout, CI, or a dev/prerelease build emits b2-mcp/dev. B2_MCP_UA_SUFFIX
appends an optional operator token after that built-in product token and does not
replace it.
S3-compatible and report tools use the s3ApiUrl returned by b2_authorize_account when a tool call authorizes; setting B2_REGION does not override that authorized region. On a cold authorization cache, the first S3/report call attempts B2 authorization to learn the authoritative region. That wait is bounded, and if authorization is temporarily unavailable, S3 tools fall back to the B2_REGION endpoint for that operation so the S3 data plane can still be attempted with the configured default. Once authorization succeeds, the derived S3 endpoint is cached for the server process lifetime; restart the process to pick up a later account-region migration. Authorized S3 endpoints remain restricted to HTTPS s3.<region>.backblazeb2.com hosts with no credentials, custom port, path, query, or fragment.
Security / policy (safe defaults; override as needed):
Variable | Default | Description |
| stdio: | Gate on destructive tools: |
|
| Set to |
| — | Optional maximum for |
|
| Explicitly allow |
|
| Explicitly allow |
| none | HTTP transport: Host/Origin allowlists (DNS-rebinding protection) — set these for any internet-facing HTTP deployment |
|
| Standalone Node HTTP transport request timeout and headers timeout |
|
| HTTP transport: trust |
|
| HTTP transport: per-credential request throttling |
|
| HTTP transport: global and per-credential concurrent in-flight request caps |
|
| Stdio bootstrap capability-discovery deadline; local expiry starts with a fail-closed tool surface |
|
| Bounded capability-discovery cache TTL and size. Cache identity is secret-bound; log labels are non-secret fingerprints |
|
| Idle timeout while streaming |
A ready-to-copy .env.example lists the local environment
variables, and deploy/customer-hosted/b2-mcp.env.example
lists the hosted container baseline. HTTP-only file-access vars
(B2_ALLOW_LOCAL_FILES, B2_FILE_ROOT) are covered in docs/DEPLOY.md.
Logging
b2-mcp emits one structured JSON log object per line. Logs default to stderr so the stdio transport's stdout channel stays reserved for MCP protocol frames.
Set B2_LOG_FILE=/absolute/path/to/b2-mcp.log to append those same redacted JSON
lines to a file instead of stderr. The path must be absolute. The file is created
with owner-only permissions when it does not exist; its parent directory must
already exist and be writable. Existing log files must be regular files, must
not be symlinks or hard links, and must be owned by the current user. Owned
pre-existing files are tightened to owner-only permissions at startup. A bad
path fails at startup with a clear B2_LOG_FILE error. Runtime write failures
are reported to stderr, and subsequent structured log lines fall back to stderr.
B2_LOG_FILE is currently supported only on POSIX platforms; Windows startup
fails clearly because this implementation does not enforce owner-only ACLs.
File logging does not mirror to stderr by default. Because B2_LOG_FILE is an
append-only file sink with no built-in rotation or retention, use
operator-managed rotation before enabling it for a long-running process. Do not
enable it on an internet-facing HTTP transport unless the host has a size and
retention policy and a log shipper tails the file directly. For external
logrotate, use rename/create rotation and send SIGHUP to the b2-mcp process
after rotation so the file destination is reopened. Copytruncate is not
recommended.
Package API Surface
The npm package intentionally supports only the root CommonJS entry
(require("@backblaze-labs/b2-mcp")), which exposes
startStdio(): Promise<void>, plus ./package.json for metadata. TypeScript
consumers may compile against that same root CommonJS surface:
import b2Mcp = require("@backblaze-labs/b2-mcp");
const start: () => Promise<void> = b2Mcp.startStdio;Programmatic TypeScript imports beyond that root entry are not a supported
public API. The supported form is the CommonJS import = require interop shown
above; ESM named imports such as import { startStdio } from "@backblaze-labs/b2-mcp" are not part of the contract. Deep imports such as
@backblaze-labs/b2-mcp/dist/server.js are private implementation details and
are closed by the package exports map. Use the CLI/bin entry or the root
startStdio export instead.
CLI Reference
The source entry point and installed package binary share the same CLI:
Usage: b2-mcp [stdio|http] [options]
Options:
--transport <stdio|http> Transport to serve (default: B2_MCP_TRANSPORT or stdio)
--port <port> HTTP listen port (default: PORT or 3000)
--host <host> HTTP listen host (default: Node listen default)
--version Print the package version
--help Show this helpExamples:
b2-mcp --transport stdio # or: npx -y @backblaze-labs/b2-mcp --transport stdio
b2-mcp http --host 127.0.0.1 --port 3000
node dist/index.js http --host 127.0.0.1 --port 3000 # equivalent from a source checkoutTool result text format
MCP transport messages always remain JSON-RPC JSON. Structured successful tool
results carry the lossless sanitized value in structuredContent, and the
single LLM-facing text block in content[0].text is selected by
B2_MCP_OUTPUT_FORMAT.
json(default): compact JSON text for clients that parse text content.toon: opt-in TOON text using the repo-owned encoder for TOON spec4.1.
Errors, validation failures, and concise one-line status messages stay plain
text. TextContent has no media-type field, so the server advertises the
selected text format in instructions instead of per-result prefixes or protocol
extensions.
Example b2_list_buckets text in default compact JSON mode:
{"accountId":"account-123","buckets":[{"bucketId":"bucket-a","bucketName":"logs-2026","bucketType":"allPrivate"},{"bucketId":"bucket-b","bucketName":"public-assets","bucketType":"allPublic"}],"bucket_count":2,"total_bucket_count":2}The same structured result with B2_MCP_OUTPUT_FORMAT=toon:
accountId: account-123
buckets[2]{bucketId,bucketName,bucketType}:
bucket-a,logs-2026,allPrivate
bucket-b,public-assets,allPublic
bucket_count: 2
total_bucket_count: 2The canonical structuredContent value is identical in both modes.
Rollout note: TextContent has no media-type field. Keep the default json
for rolling deployments and text-parsing clients. Opt into TOON only after
clients prefer structuredContent or explicitly support TOON; otherwise a fleet
with mixed B2_MCP_OUTPUT_FORMAT values can return either text shape.
Available tools
40 total — 17 Native B2 SDK + 19 AWS S3 SDK + 4 Neither SDK/custom MCP tools. Prefix counts remain 21 native b2_* names + 19 data-plane s3_* names. Availability is orthogonal to backing: b2_create_key and b2_create_group_member are available when B2_SECRET_SINK=file or inline; b2_reserve_trial_create_account is available only with explicit inline mode because Reserve Trial has no provider-side recovery path after a file sink write failure. These names are non-secret compatibility stubs when unavailable. The inherited s3_* aliases use the AWS S3 SDK against B2's S3-compatible endpoint, with configuration derived from the official B2 SDK /s3 helper. Under stdio's default confirm policy, fifteen destructive, durable-secret-producing, or protection-weakening tool names require confirm: true or MCP form elicitation before execution: the explicit deletes (s3_delete_object, s3_delete_objects, s3_abort_multipart_upload, b2_delete_bucket, b2_delete_key), durable key creation (b2_create_key), PutObject presigning (s3_get_presigned_url with operation: "PutObject"), Partner group membership changes (b2_eject_group_member, b2_create_group_member), trial-account reservation (b2_reserve_trial_create_account), persistent outbound webhook replacement (b2_set_bucket_notification_rules), and the protection-removal or copy/delete policy paths (b2_update_file_retention when clearing/bypassing, b2_update_file_legal_hold when set off, b2_update_bucket when it makes a bucket public or weakens Object Lock/lifecycle/replication, and s3_put_bucket_lifecycle when a rule schedules deletion). HTTP defaults to block, so the same calls are refused unless the operator explicitly selects confirm or allow.
Tool | Availability | Description |
| Available | Verify credentials and return account info |
| Available | List buckets (optional filters) |
| Available | Create a bucket |
| Available | Delete an empty bucket |
| Available | Update type, CORS, lifecycle, encryption, replication, Object Lock |
| Available | Get webhook notification rules |
| Available | Set webhook notification rules |
| Available | List application keys |
| Available | Delete an application key |
| Sink-backed; HTTP default stub | Create an application key; file mode writes the one-time secret out of band |
| Available | Set/clear legal hold on an object |
| Available | Set/clear retention on an object |
| Available with Partner API credential | List partner groups through the official B2 SDK |
| Available with Partner API credential | Remove a member from a partner group through the official B2 SDK |
| Available with Partner API credential | List group members through the official B2 SDK |
| Sink-backed with Partner credential | Create a Partner group member; file mode writes the one-time secret out of band |
| Inline only with Partner credential | Reserve a trial account; file mode is unavailable because no provider-side recovery exists |
Durable-secret-producing operations split their result: the one-time
applicationKey is written to the configured sink, while MCP output returns
redacted metadata plus a secretSink pointer. Each request must include an
idempotencyKey; retrying the same key with identical input returns the
original sink pointer without creating a second credential or account. On POSIX
platforms, stdio defaults to file at ~/.b2-mcp/secrets.jsonl. Windows
rejects file sink paths because owner-only ACLs are not enforced by this
implementation; configure B2_SECRET_SINK=off or explicit local inline mode
there. HTTP/serverless defaults to off; enabling file there requires both
B2_ALLOW_LOCAL_FILES=true and an explicit B2_SECRET_SINK_FILE.
B2_SECRET_SINK=inline is an unsafe explicit opt-in that returns the secret
into MCP output with a warning; HTTP/serverless also requires
B2_ALLOW_INLINE_SECRETS=true. File sink records use stable JSONL
metadata fields (ts, tool, recordId) plus idempotency metadata and a
result payload. File mode also writes non-secret sidecar idempotency markers,
plus <B2_SECRET_SINK_FILE>.idempotency.jsonl as an audit trail, so retry
history survives when the plaintext ledger is rotated or vaulted. The ledger has
no built-in rotation or pruning, so operators must rotate, prune, vault, or
delete it under the same credential-retention policy used for live B2 keys while
retaining the sidecars for the deployment's retry window. The SDK-backed
Partner/Groups tools remain available only when a distinct master key is
configured and the account is authorized for the Partner API.
Tool | Availability | Description |
| Available | Inline upload / download of small (<=1 MiB) control-plane objects; bulk data uses a presigned URL |
| Available | Delete one / bulk-delete objects |
| Available | Object metadata |
| Available | Server-side copy; |
| Available | List objects / versions |
| Available | Multipart upload flow (large files); parts use short-lived presigned bearer URLs |
| Available | Manage multipart uploads |
| Available | Server-side copy of a part |
| Available | Short-lived presigned PUT/GET bearer URL (browser/CORS handoff) |
| Available | Check bucket exists/reachable on the S3 endpoint |
| Available | Bucket region / location constraint |
| Available | Lifecycle rules incl. |
Tool | Availability | Description |
| Available | Rank accounts by stored-data growth between two dates (daily usage reports; requires Usage Reports) |
| Available | Top egress by account or bucket over a period (daily usage reports; requires Usage Reports) |
| Available | A bucket's largest objects via live listing (bounded scan) |
| Available | Abandoned multipart uploads silently consuming storage (bounded live listing) |
Scope follows the caller's key — a partner key sees its sub-accounts; a customer key sees only itself. The usage-report tools feature-detect the b2-reports-<accountId> bucket and return a clear "not enabled" message when Usage Reports aren't enabled on the account.
Security & self-hosting
Built-in safeguards (on by default): destructive-action gating (B2_DESTRUCTIVE_POLICY), MCP form elicitation for destructive tools on clients that advertise it for the 2026 protocol, sink-backed durable-secret creation for local stdio with hosted HTTP fail-closed defaults, central recursive response sanitization, explicit credential-provider modes, capability-aware tool registration that fails closed, rate limiting, and a values-redacted audit log (non-secret credential fingerprints only — never secrets, values, or file contents). The server never phones home.
Destructive actions have two layers. B2_DESTRUCTIVE_POLICY=block is the hard refusal and remains the required wall for internet-facing or untrusted-client HTTP deployments. Under confirm, capable 2026 MCP clients are asked for form elicitation first; clients without compatible elicitation, or servers with B2_DESTRUCTIVE_ELICITATION=off, fall back to the existing confirm: true retry. elicit is the stricter middle ground between confirm and block: it requires an accepted MCP form-elicitation response from a form-capable client and refuses (rather than falling back to a model confirm: true) whenever no such response can be obtained, for deployments that want human-in-the-loop friction on every destructive action without giving up the operation entirely. Because the response is relayed by the client, this is friction, not an independent authorization boundary. Under allow, both the confirm gate and elicitation are skipped for trusted single-user sessions. Elicitation responses are relayed by the MCP client, so they are useful human-in-the-loop friction but not an independent security boundary against a malicious or compromised internet-facing client.
Rollout note: elicitation changes compatible 2026 confirm clients from a one-request confirm: true flow to a two-request flow carrying server-minted requestState. Deploy all HTTP replicas with the same credentials and config. During an expand/contract rollout, an elicitation follow-up routed to a pre-elicitation pod fails safe with the old confirmation refusal; it does not execute an unapproved destructive operation.
Running it safely:
Use a supported deployment for hosted HTTP —
deploy/customer-hostedcontains the portable container, compose, and nginx/OAuth edge example.deploy/vercelcontains the OAuth-secured Vercel runtime adapter. The deployment index links the current provider guides:Vercel,Cloudflare Workers,Cloudflare Containers,Docker/OCI,Google Cloud Run,AWS ECS Fargate,Azure Container Apps,Render,Railway,Fly.io, andshared security.Use a least-privilege key — a non-master key is correct for normal storage operations. Local stdio can create scoped keys through the file sink; hosted HTTP deployments should create and rotate keys outside the MCP tool flow unless the file sink has been explicitly configured and reviewed.
b2_create_keyrefuses key-management grants, unscoped write/delete grants, and over-long or non-expiring keys unless the corresponding policy override is set.Presigned URLs are different from durable secrets —
s3_get_presigned_urlands3_presign_upload_partreturn short-lived bearer capabilities withexpiresIn/expiresAt. Treat the URL as sensitive until expiry, but it is not a long-lived B2 application key.Local use → stdio (the Quick Start above). Credentials stay in your client config / environment.
Exposing HTTP → choose a credential mode. Unset mode remains
headersfor one-release compatibility with existing header clients; B2 credential headers must be present on every MCP request. SetB2_HTTP_CREDENTIAL_MODE=serverto keep one B2 credential in the server process/customer secret manager, orprincipalto map verified MCPauthInfoto customer-held credentials.Caller auth stays at your edge. For
principalmode, terminate TLS and validate OAuth before the SDK handler receivesauthInfo; strip any trusted identity headers at the edge and only re-add them inside an allowlisted proxy boundary.MCP SDK v2 packages are pinned. HTTP and stdio use the official
@modelcontextprotocol/serverv2 package fromgithub.com/modelcontextprotocol/typescript-sdk; opt-in TOON output uses a reviewed repo-owned encoder for spec4.1, with@toon-format/toon@4.1.1retained only as a dev/test decoder oracle.Never commit credentials — use env vars / a secrets manager.
.env*is gitignored.
Full hosted runbook (nginx, Let's Encrypt, hardened systemd, fail2ban, monitoring, and a security baseline checklist): docs/DEPLOY.md.
Authentication, credential custody, OAuth metadata, and B2 credential-mode
details are documented in docs/AUTHENTICATION.md.
Development
pnpm run build # clean + compile to dist/
pnpm run typecheck # type-check src + tests (no emit)
pnpm test # typecheck, then fast unit tests
pnpm run test:contract # deterministic MCP/package/schema contracts
pnpm run test:protocol # modern + legacy MCP protocol behavior
pnpm run test:coverage # deterministic source-covering suites + coverage summary
pnpm run test:diagnostics # MaxListeners/open-handle warning diagnostics
pnpm run test:slow # deterministic high-cost tests, isolated from unit
pnpm run test:package # packed-package installation test
pnpm run verify # fast no-credential quality gate
pnpm run test:live:b2-integration # live B2 tests; requires B2_APPLICATION_KEY_ID / B2_APPLICATION_KEY
pnpm run test:live:b2-contract # live B2 request-shape checks; requires B2 credentials
pnpm run test:live:b2 # both protected live B2 suites
pnpm run evals # deterministic LLM eval harness; live provider cases skip by default
pnpm run evals:provider-comparison # opt-in Claude vs OpenAI comparison; requires provider keys and current dist/
pnpm start # stdio transport
pnpm run start:http --port 3000 # MCP 2026-07-28 HTTP transport
b2-mcp --help # installed package CLI help after publish/install
b2-mcp --transport http --port 3000 # installed package HTTP command after publish/install
pnpm run smoke:local # deterministic local MCP smoke; no endpoint or B2 credentials
pnpm run smoke:client # advisory SDK client smoke; requires existing dist/, no B2 calls
pnpm run smoke:inspector # advisory locked Inspector CLI smoke; requires existing dist/Compatible MCP Inspector release for isolated manual inspection:
@modelcontextprotocol/inspector@2.4.0, which requires Node.js 22.19.0 or
newer. Run it through pnpm run smoke:inspector so the command uses the
committed lockfile and a sanitized temporary environment.
Documentation
API reference — generated TypeDoc for the public
srcsurface, published to GitHub Pages frommaindocs/CLIENTS.md— per-client setup + compatibility matrixdocs/AUTHENTICATION.md— OAuth, credential custody, and auth boundarydocs/DEPLOY.md— deployment matrix and supported-host linksdocs/deployment/security-and-credentials.md— shared hosted security contractdocs/deployment/vercel.md,docs/deployment/cloudflare-workers.md,docs/deployment/cloudflare-containers.md,docs/deployment/docker.md,docs/deployment/google-cloud-run.md,docs/deployment/aws.md,docs/deployment/azure-container-apps.md,docs/deployment/render.md,docs/deployment/railway.md,docs/deployment/fly-io.md— provider deployment guidesdocs/PUBLIC_CONTRACTS.md— public document ownership and contract statusdocs/TOOL_CONTRACT.md— Phase 1 tool-contract policydocs/TOOL_PROFILES.md— generated tool-profile referencedocs/TESTING.md— deterministic and live-test gate skeletondocs/EVALS.md— LLM eval local and CI runbookdocs/SECURITY_REVIEW.md— pre-public security and provenance review checklistRELEASE.md— release process and[Unreleased]disciplineCHANGELOG.md— release notesSECURITY.md— reporting vulnerabilities
License
MIT — © 2026 Backblaze, Inc.
This server cannot be installed
Maintenance
Related MCP Connectors
MCP server for InsForge BaaS — database, storage, edge functions, and deployments
Cloud-hosted MCP server for durable AI memory
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
MCP Hub: AI service discovery, per-user OAuth, and multi-service workflow orchestration
Related MCP Servers
- AlicenseBqualityCmaintenanceMCP server enabling AI models to list S3 buckets, objects, and download files securely.24MIT
- 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
- AlicenseNot gradedqualityAmaintenanceLightweight object storage with S3, HTTP, and MCP interfaces, enabling AI agents to store and retrieve files via structured tool definitions.4Do What The F*ck You Want To Public
- AlicenseNot gradedqualityDmaintenanceMCP server for AWS S3 and compatible object stores, enabling LLM clients to browse buckets and fetch objects.MIT No Attribution
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/backblaze-labs/b2-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server