The Worker exposes R2 object storage capabilities to authenticated MCP clients over the internet. Every enabled tool — reads, writes, deletes, listings, and presigned URL generation — is callable by any client that holds a valid session token. The security model is layered: GitHub OAuth determines who can obtain a token,Documentation Index
Fetch the complete documentation index at: https://mintlify.com/XxYouDeaDPunKxX/cloudflare-r2-remote-mcp-worker/llms.txt
Use this file to discover all available pages before exploring further.
R2_ROOT_PREFIX limits which keys tools can touch, runtime guards protect destructive operations, and payload limits bound the size of inline transfers. This page covers each layer and what happens when any of them is weakened or misconfigured.
Auth mode risk
TheAUTH_MODE variable is the outermost access control boundary.
| Mode | Risk |
|---|---|
github | Access is limited to GitHub logins explicitly listed in ALLOWED_GITHUB_LOGINS. An empty allowlist denies all logins. |
none | Any client that can reach /mcp can invoke all enabled tools. The R2 bucket binding is effectively public through MCP. |
Root prefix scoping
SettingR2_ROOT_PREFIX in wrangler.jsonc restricts all object tools to a logical subtree of the bucket. Tool calls that specify a key are resolved relative to the prefix, and the Worker prepends the prefix before any R2 API call.
readme.md resolves to projects/example/readme.md in R2. Attempts to escape the subtree are rejected by the path normalization layer.
The server rejects the following path patterns at the normalization step:
| Pattern | Example | Rejection reason |
|---|---|---|
| Absolute paths | /etc/passwd | Leading / not allowed |
| Drive-letter paths | C:\data\file.txt | Windows-style roots not allowed |
. segments | a/./b | Current-directory reference not allowed |
.. segments | a/../b | Parent-directory traversal not allowed |
| Null bytes | file\0.txt | Null bytes in path not allowed |
R2_ROOT_PREFIX is not set, tools operate on the full bucket namespace. Set a prefix on any deployment where MCP clients should not be able to read or write every key in the bucket.
Destructive operation guards
Delete, delete-many, move, and rename operations are irreversible. The Worker enforces two runtime guards to reduce accidental or malicious data loss. Confirmation required. Every destructive tool requires the caller to passconfirm: true explicitly. A call that omits or sets confirm: false is rejected before any R2 API call is made.
Dry run available. Batch operations — delete-many, move, and rename — support dryRun: true. A dry-run call validates inputs and reports what would be changed without modifying any objects. Use dry run to preview the scope of a bulk operation before committing.
Account administration tools are read-only by design. Bucket creation and deletion, CORS mutation, lifecycle mutation, custom domain mutation, and notification mutation are not implemented. Account tools cannot make changes to bucket configuration.
Presigned URL risks
Presigned URLs grant temporary, direct HTTP access to a single object operation — no Worker authentication is required to use them. Treat every presigned URL as a bearer credential. Recommended handling:- Short expirations. Set the shortest expiry that is practical for the intended use. A URL that expires in minutes limits the window of exposure if it leaks.
- No shared logs. Do not log presigned URLs to shared systems. Any log entry containing a URL grants access to whoever can read the log until expiry.
- No untrusted chat transcripts. Do not paste presigned URLs into chat sessions that are not trusted end-to-end. The URL is the credential — sharing it is sharing access.
- Prefer presigned for large payloads. Worker-mediated transfers are bounded by
MAX_TRANSFER_BYTES. For objects larger than that limit, generate a presigned URL instead of reading or writing through the Worker.
ENABLE_PRESIGN_TOOLS=false). Enable them only when direct upload or download URLs are genuinely needed.
Cloudflare API token
Read-only account administration tools requireCLOUDFLARE_API_TOKEN. Use the narrowest R2 read scope the deployment needs — do not use a global API token. A global token can read, write, and delete across all services in your Cloudflare account.
Set the token as a Wrangler secret:
ENABLE_ACCOUNT_TOOLS=false). Enable them only when read-only account-level visibility is required.
Payload limits
Inline MCP transfers are bounded by two configuration values:| Variable | Default | Applies to |
|---|---|---|
MAX_INLINE_TEXT_BYTES | 262 144 (256 KiB) | Text object reads returned inline in the MCP response |
MAX_TRANSFER_BYTES | 1 048 576 (1 MiB) | Base64 binary reads and Worker-mediated object copies |
wrangler.jsonc vars, but increasing them raises the maximum memory and bandwidth a single tool call can consume in a Worker invocation.
Secrets that must never be committed
The following values must not appear in any file committed to version control:.dev.vars— local development environment file containing secretswrangler.jsonc— may contain API tokens or S3 keys if edited carelesslyCLOUDFLARE_API_TOKEN— Cloudflare account API tokenGITHUB_CLIENT_IDandGITHUB_CLIENT_SECRET— GitHub OAuth App credentialsCOOKIE_ENCRYPTION_KEY— HMAC key used to sign session cookiesR2_ACCESS_KEY_IDandR2_SECRET_ACCESS_KEY— R2 S3-compatible credentials for presigned URLs- Any presigned URLs themselves — treat as short-lived bearer tokens
Public deployment checklist
Before exposing/mcp to the internet, verify every item:
-
AUTH_MODE=githubis set inwrangler.jsoncvars -
ALLOWED_GITHUB_LOGINSis non-empty and contains only intended users -
OAUTH_KVnamespace is created and the binding is present inwrangler.jsonc - The GitHub OAuth App callback URL matches the deployed Worker URL exactly (
https://<worker-url>/callback) -
GITHUB_CLIENT_IDis set as a Wrangler secret -
GITHUB_CLIENT_SECRETis set as a Wrangler secret -
COOKIE_ENCRYPTION_KEYis set as a Wrangler secret (generated withopenssl rand -base64 32) -
wrangler.jsoncis listed in.gitignoreand not committed to version control -
.dev.varsis listed in.gitignoreand not committed to version control - Account tools remain disabled (
ENABLE_ACCOUNT_TOOLSunset orfalse) unless read-only account visibility is required - Presign tools remain disabled (
ENABLE_PRESIGN_TOOLSunset orfalse) unless direct upload/download URLs are required
See also
Authentication Overview
OAuth flow, auth modes, and allowlist semantics.
GitHub OAuth Setup
Step-by-step OAuth App creation, KV namespace provisioning, and secrets.