{
  "markdown": "# Backblaze B2 MCP Server\n\n<p align=\"center\">\n  <img src=\".github/social-preview.png\" alt=\"Backblaze B2 MCP Server — safe Model Context Protocol access to Backblaze B2 buckets, files, keys, Object Lock, and S3-compatible storage\" width=\"820\">\n</p>\n\n[![CI](https://github.com/backblaze-labs/b2-mcp/actions/workflows/test.yml/badge.svg)](https://github.com/backblaze-labs/b2-mcp/actions/workflows/test.yml)\n[![CodeQL](https://img.shields.io/badge/CodeQL-enabled-brightgreen?logo=github)](https://github.com/backblaze-labs/b2-mcp/security/code-scanning)\n[![npm](https://img.shields.io/npm/v/@backblaze-labs/b2-mcp?color=cb3837)](https://www.npmjs.com/package/@backblaze-labs/b2-mcp)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![TypeScript](https://img.shields.io/badge/TypeScript-6.x-3178c6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)\n[![Node.js](https://img.shields.io/badge/Node.js-22.22%2B%20%7C%2024%20%7C%2026-339933?logo=nodedotjs&logoColor=white)](https://nodejs.org/)\n[![MCP](https://img.shields.io/badge/MCP-2026--07--28-5b5fc7)](https://modelcontextprotocol.io/specification/2026-07-28)\n[![API docs](https://img.shields.io/badge/API%20docs-TypeDoc-3178c6?logo=readthedocs&logoColor=white)](https://backblaze-labs.github.io/b2-mcp/)\n[![Coverage floors](https://img.shields.io/badge/coverage-S%2094.3%20%7C%20B%2088%20%7C%20F%2097.2%20%7C%20L%2096.6-brightgreen)](docs/TESTING.md)\n[![Runtime dependencies](https://img.shields.io/badge/runtime_dependencies-9-blue)](package-budget.json)\n\n<!-- Directory badges point at deterministic per-server URLs derived from the locked\n     name (io.github.backblaze-labs/b2-mcp) and repo path, so they activate automatically\n     once the package is published to the MCP Registry and ingested by Glama/LobeHub. -->\n[![MCP Registry](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fregistry.modelcontextprotocol.io%2Fv0%2Fservers%3Fsearch%3Dio.github.backblaze-labs%2Fb2-mcp%26version%3Dlatest&query=%24.servers%5B0%5D.server.version&prefix=v&label=MCP%20Registry&color=5b5fc7&logo=modelcontextprotocol&logoColor=white)](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.backblaze-labs/b2-mcp)\n[![Glama](https://glama.ai/mcp/servers/@backblaze-labs/b2-mcp/badges/score.svg)](https://glama.ai/mcp/servers/@backblaze-labs/b2-mcp)\n[![Verified by M8ven](https://m8ven.ai/badge/mcp/backblaze-labs-b2-mcp-92j1t6)](https://m8ven.ai/verified?check=https%3A%2F%2Fgithub.com%2Fbackblaze-labs%2Fb2-mcp)\n[![MCP Badge](https://lobehub.com/badge/mcp/backblaze-labs-b2-mcp?style=plastic)](https://lobehub.com/mcp/backblaze-labs-b2-mcp)\n\nA [Model Context Protocol](https://modelcontextprotocol.io) server for [Backblaze B2 Cloud Storage](https://www.backblaze.com/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.\n\n> **This is the official Backblaze B2 MCP server** — `backblaze-labs/b2-mcp`, published as [`@backblaze-labs/b2-mcp`](https://www.npmjs.com/package/@backblaze-labs/b2-mcp) on npm and listed in the [Official MCP Registry](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.backblaze-labs/b2-mcp) as `io.github.backblaze-labs/b2-mcp`. Community forks and third-party wrappers are not maintained by Backblaze.\n\n**40 tools, assigned by backing category:**\n\n- **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.\n- **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.\n- **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.\n\nDestructive actions are gated, durable B2 secrets stay out of the model's context in the default/file/off modes, and registration is capability-aware so a key only ever sees tools it can use. The server also exposes read-only MCP resources: `b2://server-config` (non-secret, registered even during credential-less discovery), plus capability-gated `b2://capabilities` and `b2://bucket/{bucketName}`.\n\n**Contents**\n\n- [Quick start](#quick-start)\n- [B2 Skills pack](#b2-skills-pack)\n- [Configuration](#configuration)\n- [Tools](#tools)\n- [Package API Surface](#package-api-surface)\n- [CLI Reference](#cli-reference)\n- [Resources](#resources)\n- [Security & self-hosting](#security--self-hosting)\n- [Privacy](#privacy)\n- [Development](#development)\n- [Documentation](#documentation)\n\n---\n\n## Quick start\n\n**Prerequisites:** A supported [Node.js](https://nodejs.org) runtime and a Backblaze B2 [application key](https://www.backblaze.com/docs/cloud-storage-application-keys). 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. One non-master application key covers normal storage work (B2 native, S3, and key management); the Partner/Groups tools additionally need `B2_MASTER_KEY_ID` / `B2_MASTER_KEY`.\n\n### Option A — npx (Claude Desktop config)\n\nEdit `claude_desktop_config.json` (macOS: `~/Library/Application Support/Claude/`, Windows: `%APPDATA%\\Claude\\`, Linux: `~/.config/Claude/`) and add:\n\n```json\n{\n  \"mcpServers\": {\n    \"backblaze-b2\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@backblaze-labs/b2-mcp\"],\n      \"env\": {\n        \"B2_APPLICATION_KEY_ID\": \"your-application-key-id\",\n        \"B2_APPLICATION_KEY\": \"your-application-key-secret\"\n      }\n    }\n  }\n}\n```\n\nRestart Claude Desktop and the B2 tools appear. If you need an explicit fallback region before authorization, add `B2_REGION` to the same `env` block (S3/report tools otherwise derive their region from the authorized B2 account response):\n\n```json\n{\n  \"B2_APPLICATION_KEY_ID\": \"your-application-key-id\",\n  \"B2_APPLICATION_KEY\": \"your-application-key-secret\",\n  \"B2_REGION\": \"us-east-005\"\n}\n```\n\nThe canonical package name is `@backblaze-labs/b2-mcp` and the canonical binary is `b2-mcp` (`b2-mcp-server` is a transition alias); `npx -y @backblaze-labs/b2-mcp` runs it directly. See [Configuration](#configuration) for the full variable list, and [`docs/product-specs/clients.md`](docs/product-specs/clients.md) for a source-checkout setup and copy-paste configs for Cursor, VS Code, Cline, Windsurf, Zed, Continue, Goose, Claude.ai, and hosted (Streamable HTTP).\n\n### Option B — Claude Desktop extension (MCPB)\n\n> Available once a release publishes the `b2-mcp.mcpb` asset (0.2.1 onward); earlier releases carry no bundle, so use Option A until the asset appears on the [releases page](https://github.com/backblaze-labs/b2-mcp/releases).\n\nPrefer no JSON editing? Download **`b2-mcp.mcpb`** from the [latest release](https://github.com/backblaze-labs/b2-mcp/releases/latest), then in Claude Desktop open **Settings → Extensions → Advanced settings → Extension Developer → Install Extension…** and select the downloaded file. Claude Desktop prompts for your **Application Key ID** and **Application Key** (Region and Master keys optional) — no config file to hand-edit. The bundle launches a version-pinned `npx -y @backblaze-labs/b2-mcp@<version>` (npm resolves the server on first run) so it always runs the exact published version. A one-click [Claude Connectors Directory](https://github.com/backblaze-labs/b2-mcp/issues/385) listing is in progress.\n\n**Then just ask:**\n\n> _\"List the buckets this key can access.\"_ · _\"Upload `./data.csv` to `reports/may-2026.csv`.\"_ · _\"Give me a 1-hour download link for `backups/latest.tar.gz`.\"_ · _\"List files under `logs/2026/`.\"_\n\n> **Why your client may show fewer than 40 tools:** registration is capability-aware. With a non-master key and no master key configured, the three Partner/Groups tools that require a master key are not surfaced, so `tools/list` reports 37; add `B2_MASTER_KEY_ID` / `B2_MASTER_KEY` on a Partner-entitled account for the full 40. A read-only key trims the surface further. Credential-free scanners see the full advertised surface, but every `tools/call` returns `missing_credentials` until valid B2 credentials are supplied.\n\n### Docker\n\nThe published image defaults to the HTTP transport and reads configuration only from environment variables (no mutable `latest` tag — pin the release version):\n\n```bash\nB2_MCP_VERSION=VERSION # replace with the release version you want\nB2_MCP_IMAGE=\"ghcr.io/backblaze-labs/b2-mcp:${B2_MCP_VERSION}\"\ndocker run --rm --name b2-mcp \\\n  --stop-timeout 20 \\\n  -p 127.0.0.1:3000:3000 \\\n  -e B2_HTTP_CREDENTIAL_MODE=server \\\n  -e B2_APPLICATION_KEY_ID=your-application-key-id \\\n  -e B2_APPLICATION_KEY=your-application-key-secret \\\n  -e B2_ALLOWED_HOSTS=localhost,127.0.0.1 \\\n  -e B2_DESTRUCTIVE_POLICY=block \\\n  -e B2_REGISTER_ALL_TOOLS=false \\\n  -e B2_SECRET_SINK=off \\\n  -e B2_ALLOW_INLINE_SECRETS=false \\\n  -e B2_ALLOW_LOCAL_FILES=false \\\n  \"$B2_MCP_IMAGE\"\n```\n\nFor stdio clients inside a container, pass the transport explicitly and keep stdin open:\n\n```bash\nB2_MCP_VERSION=VERSION # replace with the release version you want\nB2_MCP_IMAGE=\"ghcr.io/backblaze-labs/b2-mcp:${B2_MCP_VERSION}\"\ndocker run --rm -i \\\n  --no-healthcheck \\\n  -e B2_APPLICATION_KEY_ID=your-application-key-id \\\n  -e B2_APPLICATION_KEY=your-application-key-secret \\\n  \"$B2_MCP_IMAGE\" stdio\n```\n\n**Deploying to hosted HTTP?** See the [deployment matrix](docs/DEPLOY.md) and provider guides (Docker, Vercel, Cloudflare, AWS, GCP, Azure, Render, Railway, Fly.io) linked from [Security & self-hosting](#security--self-hosting), and [`docs/references/deployment/docker.md`](docs/references/deployment/docker.md) for hardened HTTP examples.\n\n## B2 Skills pack\n\nThis repo bundles a client-side Backblaze B2 skills pack under `skills/` (manifest: [`skills/pack.json`](skills/pack.json)) — Markdown playbooks for common workflows (backup/restore, least-privilege keys, Object Lock, lifecycle and cost hygiene, migration, incident response). The MCP server is the action layer; these are the expertise layer. They add no endpoints or permissions — they only sequence existing tools and reinforce the same byte-path and destructive-action guardrails the server enforces.\n\nOptional but recommended for clients that support Markdown skills. Load them by placing each `skills/b2-*/` directory under `~/.claude/skills/` (Claude Code), or upload per-skill ZIPs via **Settings → Capabilities → Skills** (Claude.ai / Claude Desktop). Validate the pack locally:\n\n```bash\npnpm run validate:skills\n```\n\n---\n\n## Configuration\n\n| Variable                                                      | Required              | Default               | Description                                                                                                                |\n| ------------------------------------------------------------- | --------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------- |\n| `B2_APPLICATION_KEY_ID`                                       | stdio / HTTP `server` | —                     | Application key ID (non-master) — the workhorse for native B2 and S3-compatible tools                                      |\n| `B2_APPLICATION_KEY`                                          | stdio / HTTP `server` | —                     | Application key secret                                                                                                     |\n| `B2_MASTER_KEY_ID` / `B2_MASTER_KEY`                          | —                     | falls back to app key | Master credential for SDK-backed Partner/Groups tools; required with Partner API entitlement for those operations          |\n| `B2_REGION`                                                   | —                     | `us-west-004`         | Fallback/default S3-compatible endpoint region; authorized B2 responses override this for S3/report tools                    |\n| `B2_MCP_UA_SUFFIX`                                            | —                     | —                     | Optional operator token appended _after_ the built-in `b2-mcp/<version>` product token on the outbound User-Agent (tag a deployment) |\n| `B2_MCP_OUTPUT_FORMAT`                                        | —                     | `json`                | LLM-facing `TextContent.text` format for structured successes: compact `json` or opt-in `toon`                             |\n| `B2_ENABLE_MCP_PROMPTS`                                       | —                     | `false`               | MCP workflow prompts (`prompts/list`, `prompts/get`) are off by default; set `true` once every replica runs prompt-capable code. Gates registration and advertisement together, so flip it atomically across the fleet (or use sticky routing) |\n| `B2_MCP_TRANSPORT`                                            | —                     | `stdio`               | CLI default transport when no `stdio` / `http` argument or `--transport` flag is passed; Docker images set this to `http`  |\n| `B2_HTTP_HOST`                                                 | HTTP only             | Node listen default   | Standalone Node HTTP listen host; set to `127.0.0.1` when binding behind a same-host reverse proxy                         |\n| `B2_LOG_FILE`                                                 | —                     | stderr                | Optional absolute path for redacted structured JSON logs (POSIX only). When set, the file replaces stderr; stdout is never used for logs. See [`docs/product-specs/clients.md`](docs/product-specs/clients.md) for rename/create + `SIGHUP` rotation guidance |\n| `B2_SECRET_SINK`                                              | —                     | stdio: `file`; HTTP: `off` | Durable-secret output mode: `file`, `inline`, or `off`. File mode supports `b2_create_key` and `b2_create_group_member`; `b2_reserve_trial_create_account` requires explicit inline mode because it has no file-mode recovery path |\n| `B2_SECRET_SINK_FILE`                                         | `file` override       | `~/.b2-mcp/secrets.jsonl` on stdio | Append-only plaintext JSONL credential ledger for file sink mode. HTTP/serverless file mode requires this explicit absolute path and `B2_ALLOW_LOCAL_FILES=true` |\n| `B2_ALLOW_INLINE_SECRETS`                                     | HTTP inline only      | `false`               | Dedicated HTTP/serverless opt-in required before `B2_SECRET_SINK=inline` can return durable secrets in MCP responses       |\n| `B2_HTTP_CREDENTIAL_MODE`                                     | HTTP only             | `headers`             | `headers`, `server`, or `principal`; unset preserves existing header-based clients. Set explicitly for hosted deployments  |\n| `B2_PRINCIPAL_CREDENTIAL_MAP`                                 | HTTP `principal`      | —                     | JSON map from verified MCP principal to a customer-managed credential reference                                            |\n| `B2_CREDENTIAL_<REF>_APPLICATION_KEY_ID` / `_APPLICATION_KEY` | HTTP `principal`      | —                     | Env-backed secret-broker material for the mapped reference                                                                 |\n\n**Security / policy (safe defaults; override as needed):**\n\n| Variable                                                         | Default            | Description                                                                                                               |\n| ---------------------------------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------- |\n| `B2_DESTRUCTIVE_POLICY`                                          | stdio: `confirm`; HTTP: `block` | Gate on destructive tools: `confirm` requires MCP form elicitation approval on compatible 2026 clients, or `confirm: true` when elicitation is unavailable/disabled; `elicit` requires human elicitation approval and refuses when no human can be prompted; `block` refuses before elicitation; `allow` skips both gates |\n| `B2_DESTRUCTIVE_ELICITATION`                                     | `on`               | Set to `off`, `false`, or `0` to disable MCP form elicitation and rely only on `B2_DESTRUCTIVE_POLICY`                    |\n| `B2_MAX_KEY_DURATION_SECONDS`                                    | —                  | Optional maximum for `b2_create_key`; when set, non-expiring keys and longer durations are refused before any B2 create call |\n| `B2_ALLOW_KEY_MGMT_GRANTS` / `B2_ALLOW_UNSCOPED_KEYS`           | `false`            | Explicitly allow `b2_create_key` to mint key-management-capable, or unscoped write/delete, keys                          |\n| `B2_ALLOWED_HOSTS` / `B2_ALLOWED_ORIGINS`                        | _none_             | HTTP transport: Host/Origin allowlists (DNS-rebinding protection) — **set these for any internet-facing HTTP deployment** |\n| `B2_HTTP_REQUEST_TIMEOUT_MS` / `B2_HTTP_HEADERS_TIMEOUT_MS`       | `30000` / `10000`  | Standalone Node HTTP transport request timeout and headers timeout                                                        |\n| `B2_TRUST_PROXY_HEADERS`                                         | `false`            | HTTP transport: trust `X-Forwarded-For` / `X-Real-IP` for unauthenticated admission keys only behind a trusted proxy       |\n| `B2_MCP_RATE_LIMIT_RPS` / `B2_MCP_RATE_LIMIT_BURST`              | `60` / `120`       | HTTP transport: per-credential request throttling                                                                         |\n| `B2_MAX_SESSIONS` / `B2_MAX_SESSIONS_PER_KEY`                    | `1000` / `20`      | HTTP transport: global and per-credential concurrent in-flight request caps                                               |\n| `B2_STDIO_CAPABILITY_TIMEOUT_MS`                                 | `10000`            | Stdio bootstrap capability-discovery deadline; local expiry starts with a fail-closed tool surface                         |\n| `B2_CAPABILITY_CACHE_TTL_MS` / `B2_CAPABILITY_CACHE_MAX_ENTRIES` | `300000` / `10000` | Bounded capability-discovery cache TTL and size; cache identity is secret-bound, log labels are non-secret fingerprints    |\n| `B2_S3_SAVE_TO_PATH_IDLE_TIMEOUT_MS`                             | `60000`            | Idle timeout while streaming `s3_get_object` results to `saveToPath`                                                      |\n\nA ready-to-copy [`.env.example`](.env.example) lists the local variables, and [`deploy/customer-hosted/b2-mcp.env.example`](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`](docs/DEPLOY.md); the capability/cache tuning knobs above are documented inline here.\n\n---\n\n## Tools\n\nThe server exposes **40 tools** (registration is capability-aware, so a given key sees only the subset it can use). **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. Under stdio's default `confirm` policy, fifteen destructive, durable-secret-producing, or protection-weakening tools require confirmation before execution; HTTP defaults to `block`. The per-profile, availability-annotated tool lists (per capability set) live in the generated [`docs/generated/tool-profiles.md`](docs/generated/tool-profiles.md); the destructive-gate policy and durable-secret handling (secret sinks, idempotency keys, POSIX vs. Windows behavior) are documented in [`docs/AUTHENTICATION.md`](docs/AUTHENTICATION.md).\n\n**Native B2 SDK (17):**\n\n- `b2_authorize_account` — Verify credentials and return account info\n- `b2_list_buckets` — List buckets (optional filters)\n- `b2_create_bucket` — Create a persistent bucket with initial policy settings\n- `b2_delete_bucket` — Delete an empty bucket\n- `b2_update_bucket` — Update persistent bucket settings; risky changes are gated\n- `b2_get_bucket_notification_rules` — Read webhook notification rules with secrets redacted\n- `b2_set_bucket_notification_rules` — Replace webhook notification rules; public HTTPS targets only\n- `b2_list_keys` — List application keys\n- `b2_delete_key` — Irreversibly revoke an application key\n- `b2_create_key` — Create a scoped application key through the configured secret sink\n- `b2_update_file_legal_hold` — Set/clear legal hold on an object\n- `b2_update_file_retention` — Set/clear retention on an object\n- `b2_list_groups` — List partner groups (Partner API credential)\n- `b2_eject_group_member` — Remove a member from a partner group (Partner API credential)\n- `b2_list_group_members` — List group members (Partner API credential)\n- `b2_create_group_member` — Create a Partner group member (Partner API credential)\n- `b2_reserve_trial_create_account` — Reserve a trial account (Partner API credential)\n\n**AWS S3 SDK — data plane (19):**\n\n- `s3_put_object` — Inline upload of a small (≤1 MiB) control-plane object\n- `s3_get_object` — Inline download of a small (≤1 MiB) control-plane object\n- `s3_delete_object` — Delete current object or exact version; destructive gate applies\n- `s3_delete_objects` — Bulk-delete objects\n- `s3_head_object` — Object metadata\n- `s3_copy_object` — Server-side copy\n- `s3_list_objects_v2` — List objects\n- `s3_list_object_versions` — List object versions and delete markers (paginated)\n- `s3_create_multipart_upload` — Begin a multipart upload\n- `s3_get_presigned_upload_part_url` — Mint a presigned PUT URL for a part\n- `s3_complete_multipart_upload` — Complete multipart upload from ordered part ETags\n- `s3_abort_multipart_upload` — Abort a multipart upload\n- `s3_list_parts` — List uploaded parts\n- `s3_list_multipart_uploads` — List in-progress multipart uploads (paginated)\n- `s3_upload_part_copy` — Server-side copy of a part\n- `s3_get_presigned_url` — Short-lived presigned PUT/GET bearer URL\n- `s3_head_bucket` — Check a bucket is reachable on the S3 endpoint\n- `s3_get_bucket_location` — Bucket region / location constraint\n- `s3_put_bucket_lifecycle` — Set S3 lifecycle rules\n\n**Custom MCP analytics (4):**\n\n- `b2_report_usage_growth` — Rank accounts by stored-data growth between two dates\n- `b2_rank_egress_leaders` — Top egress by account or bucket over a period\n- `b2_list_largest_files` — A bucket's largest objects via bounded live listing\n- `b2_unfinished_uploads` — Abandoned multipart uploads consuming storage\n\n**MCP workflow prompts (opt-in):** off by default; set `B2_ENABLE_MCP_PROMPTS=true` to advertise five guided workflows through `prompts/list` / `prompts/get`. Prompts are parameterized message templates — they do not execute tools or approve destructive actions — and are filtered against the same tool surface and capability map as tools. Flip the flag atomically across the fleet (it gates registration and advertisement together).\n\n---\n\n## Package API Surface\n\nThe npm package intentionally supports only the root CommonJS entry\n(`require(\"@backblaze-labs/b2-mcp\")`), which exposes\n`startStdio(): Promise<void>`, plus `./package.json` for metadata. TypeScript\nconsumers may compile against that same root CommonJS surface:\n\n```ts\nimport b2Mcp = require(\"@backblaze-labs/b2-mcp\");\n\nconst start: () => Promise<void> = b2Mcp.startStdio;\n```\n\nProgrammatic TypeScript imports beyond that root entry are not a supported\npublic API. ESM named imports are not part of the contract. Deep imports such as\n`@backblaze-labs/b2-mcp/dist/server.js` are private implementation details closed\nby the package `exports` map. Use the CLI/bin entry or the root `startStdio`\nexport instead.\n\n---\n\n## CLI Reference\n\nThe source entry point and installed package binary share the same CLI:\n\n```text\nUsage: b2-mcp [stdio|http] [options]\n\nOptions:\n  --transport <stdio|http>  Transport to serve (default: B2_MCP_TRANSPORT or stdio)\n  --port <port>             HTTP listen port (default: PORT or 3000)\n  --host <host>             HTTP listen host (default: Node listen default)\n  --version                 Print the package version\n  --help                    Show this help\n```\n\nTool results carry the lossless value in `structuredContent`; the LLM-facing\ntext block is selected by `B2_MCP_OUTPUT_FORMAT` (`json` default, or opt-in\n`toon`). See [`docs/design-docs/tool-contract.md#structured-result-text-contract`](docs/design-docs/tool-contract.md#structured-result-text-contract)\nfor the output-format contract.\n\n---\n\n## Resources\n\nRead-only MCP resources expose stable control-plane state without a tool call:\n\n- `b2://server-config` — non-secret server configuration (transport, credential mode, destructive policy, secret-sink mode, public URL, version).\n- `b2://capabilities` — the current credential's B2 capability set and active tool profile.\n- `b2://bucket/{bucketName}` — bucket type/visibility, lifecycle, Object Lock, retention, encryption, CORS, replication, and notification rules when the caller can read them (webhook secrets redacted).\n\n`resources/list` is capped at 100 concrete bucket resources; use the template URI directly for a known authorized bucket. Bucket reads omit a client cache hint because visibility and notification targets are security-relevant after writes.\n\n---\n\n## Security & self-hosting\n\nBuilt-in safeguards (on by default): destructive-action gating (`B2_DESTRUCTIVE_POLICY`), MCP form elicitation for destructive tools on 2026-capable clients, sink-backed durable-secret creation for local stdio with hosted HTTP fail-closed defaults, central recursive response sanitization, explicit credential-provider modes, capability-aware registration that fails closed, rate limiting, and a values-redacted audit log (non-secret credential fingerprints only). The server never phones home.\n\n- **Local use → stdio.** Credentials stay in your client config / environment; the default `confirm` policy asks before destructive actions.\n- **Internet-facing HTTP → `B2_DESTRUCTIVE_POLICY=block`** is the required wall (the HTTP default). Elicitation is relayed by the client, so it is human-in-the-loop friction, not an independent authorization boundary.\n- **Choose a credential mode.** `headers` (default, compatibility), `server` (one B2 credential held in the process / a secret manager), or `principal` (map verified MCP `authInfo` to customer-held credentials). Credential-free discovery (`initialize`, `tools/list`, `resources/list`, `prompts/list`, `server/discover`, `ping`) runs without keys so scanners can enumerate; real `tools/call` still requires credentials.\n- **Use a least-privilege key.** A non-master key is correct for normal storage. `b2_create_key` refuses key-management grants, unscoped write/delete grants, and over-long or non-expiring keys unless the matching override is set.\n- **Presigned URLs are not durable secrets.** `s3_get_presigned_url` / `s3_get_presigned_upload_part_url` return short-lived bearer capabilities (`expiresIn` / `expiresAt`) — sensitive until expiry, but not long-lived B2 keys.\n- **Never commit credentials** — use env vars / a secrets manager. `.env*` is gitignored.\n\nSupported deployments: `deploy/customer-hosted` (portable container, compose, nginx/OAuth edge) and [`deploy/vercel`](deploy/vercel/README.md) (OAuth-secured adapter). Provider guides: [Docker/OCI](docs/references/deployment/docker.md), [Vercel](docs/references/deployment/vercel.md), [Cloudflare Workers](docs/references/deployment/cloudflare-workers.md), [Cloudflare Containers](docs/references/deployment/cloudflare-containers.md), [Google Cloud Run](docs/references/deployment/google-cloud-run.md), [AWS ECS Fargate](docs/references/deployment/aws.md), [Azure Container Apps](docs/references/deployment/azure-container-apps.md), [Render](docs/references/deployment/render.md), [Railway](docs/references/deployment/railway.md), and [Fly.io](docs/references/deployment/fly-io.md) — all sharing the [security & credential contract](docs/references/deployment/security-and-credentials.md).\n\nFull hosted runbook (nginx, Let's Encrypt, hardened systemd, fail2ban, monitoring, and a security baseline checklist): [`deploy/customer-hosted/README.md`](deploy/customer-hosted/README.md) (indexed from the [`docs/DEPLOY.md`](docs/DEPLOY.md) matrix). Authentication, credential custody, and OAuth details are in [`docs/AUTHENTICATION.md`](docs/AUTHENTICATION.md).\n\n---\n\n## Privacy\n\nb2-mcp runs locally over stdio or in a self-hosted HTTP deployment controlled by the user or operator. The publisher does not receive runtime B2 credentials, object data, prompts, logs, or telemetry from normal use. Object-byte workflows should use presigned URLs so bytes move directly between the client or worker and Backblaze B2, and logs are structured with secret redaction.\n\nRead the canonical [`PRIVACY.md`](PRIVACY.md) source or the hosted [privacy policy](https://backblaze-labs.github.io/b2-mcp/privacy/) published by GitHub Pages.\n\n---\n\n## Development\n\nFrom a fresh source checkout, enable the pinned package manager and install\ndependencies first, then run any of the scripts below:\n\n```bash\ncorepack enable pnpm\ncorepack prepare 'pnpm@11.20.0+sha256.34e198cb1e43237517ecedfd31f9ae26a6c0a3e5366ce58a2d05f4b21fb5f19a' --activate\npnpm install --frozen-lockfile\n```\n\n```bash\npnpm run build              # clean + compile to dist/\npnpm run typecheck          # type-check src + tests (no emit)\npnpm test                   # typecheck, then fast unit tests\npnpm run test:contract      # deterministic MCP/package/schema contracts\npnpm run test:protocol      # modern + legacy MCP protocol behavior\npnpm run test:coverage      # deterministic source-covering suites + coverage summary\npnpm run test:package       # packed-package installation test\npnpm run verify             # fast no-credential quality gate\npnpm run test:live:b2       # both protected live B2 suites; requires B2 credentials\npnpm run evals              # deterministic LLM eval harness; live provider cases skip by default\npnpm run docs               # TypeDoc API docs plus hosted privacy page\npnpm start                  # stdio transport\npnpm run start:http --port 3000   # MCP 2026-07-28 HTTP transport\npnpm run smoke:local        # deterministic local MCP smoke; no endpoint or B2 credentials\n```\n\nThe full script list (diagnostics, slow tests, provider-comparison evals, inspector smoke) is in [`docs/TESTING.md`](docs/TESTING.md). Compatible MCP Inspector: `@modelcontextprotocol/inspector@2.5.0` (Node.js 22.19.0+), run via `pnpm run smoke:inspector`.\n\n## Documentation\n\n- [API reference](https://backblaze-labs.github.io/b2-mcp/) — generated TypeDoc for the public `src` surface\n- [Privacy policy](https://backblaze-labs.github.io/b2-mcp/privacy/) / [`PRIVACY.md`](PRIVACY.md) — runtime data-handling policy\n- [`docs/product-specs/clients.md`](docs/product-specs/clients.md) — per-client setup + compatibility matrix\n- [`docs/AUTHENTICATION.md`](docs/AUTHENTICATION.md) — OAuth, credential custody, and auth boundary\n- [`docs/DEPLOY.md`](docs/DEPLOY.md) — deployment matrix and supported-host links\n- [`docs/references/deployment/security-and-credentials.md`](docs/references/deployment/security-and-credentials.md) — shared hosted security contract\n- [`docs/generated/tool-profiles.md`](docs/generated/tool-profiles.md) — generated per-tool availability reference\n- [`docs/design-docs/index.md`](docs/design-docs/index.md) — public contract register with owners and status\n- [`docs/design-docs/tool-contract.md`](docs/design-docs/tool-contract.md) — tool-contract and naming-convention policy\n- [`docs/TESTING.md`](docs/TESTING.md) / [`docs/EVALS.md`](docs/EVALS.md) — test gate and LLM eval runbooks\n- [`docs/references/discoverability.md`](docs/references/discoverability.md) — registry/directory listings runbook\n- [`RELEASE.md`](RELEASE.md) · [`CHANGELOG.md`](CHANGELOG.md) · [`SECURITY.md`](SECURITY.md)\n\n## License\n\nMIT — © 2026 Backblaze, Inc.\n",
  "bytes": 32198,
  "sha": "1f0a963b0f76cbea484e66eed5f60e913fa16e7deb7765c46c1a06e3ce46f878",
  "repo_slug": "backblaze-labs/b2-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_backblaze_labs_b2_mcp_4851f2d6/readme"
}