feat: optional Bearer token auth, screenshot download, and SSE keepalive for CLI/TUI clients#55
Open
ebrainte wants to merge 3 commits into
Open
Conversation
…oyment - Bump compatibility_date to 2025-09-23 for fs.mkdir support in Workers - Pin @cloudflare/playwright to 1.1.2 with patch replacing fs.mkdtemp (not implemented in Workers nodejs_compat) with fs.mkdir + random suffix - Upgrade agents to ^0.4.0 to fix MCP Server 'Already connected to a transport' error on Durable Object hibernation wake-up (CVE-2026-25536) - Fix vite.config.ts fs alias: use node:fs instead of @cloudflare/playwright/fs
3effeeb to
de1d929
Compare
zod-to-json-schema 3.25.x produces empty schemas (strips type, properties, etc.), causing MCP clients to reject all tool definitions with schema validation errors. Pin to tilde range ~3.24.6 so only patch updates within 3.24.x are allowed.
- Optional Bearer token authentication via MCP_AUTH_TOKEN secret - SSE stream interception: extracts base64 image data from browser_take_screenshot responses, stores in memory with 5-min TTL, replaces with /download/<hash> URL for local retrieval - /download/<hash> endpoint: auth-protected, one-time use, returns the original image data - SSE keepalive: injects SSE comment (: keepalive) every 15s to prevent Cloudflare proxy from dropping idle connections (~60-90s timeout). Uses ctx.waitUntil() to keep Worker execution context alive.
de1d929 to
df722c9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds three features to the Cloudflare example worker that improve security, usability, and connection reliability for non-browser MCP clients (CLI tools, terminal UIs like OpenCode, etc.).
Feature 1: Optional Bearer Token Authentication
Protects all routes with Bearer token auth when the
MCP_AUTH_TOKENsecret is configured.crypto.subtle.timingSafeEqualfor constant-time comparisonWWW-Authenticate: Bearerheader on failureMCP_AUTH_TOKENis not set, all routes remain publicly accessibleFeature 2: Screenshot Download via SSE Stream Interception
Problem: CLI and TUI MCP clients (terminal-based tools) cannot display inline base64 images returned by
browser_take_screenshot. The image data is returned as{ type: 'image', data: '<base64>', mimeType: 'image/...' }in the JSON-RPC response, but terminal clients have no way to render it.Solution: A ReadableStream wraps the SSE response stream and:
type: 'image'content/download/<hash>for one-time authenticated file downloadThe download endpoint:
Feature 3: SSE Keepalive
Problem: The legacy SSE transport (
/sse) creates a long-lived HTTP connection. Cloudflare's proxy layer drops idle connections after ~60-90 seconds. When the MCP client sends a tool call after idle time, the POST succeeds (202 Accepted) but the SSE read stream is dead, so the response never arrives — resulting in a timeout.Solution: Injects SSE comment frames (
: keepalive\n\n) every 15 seconds into the SSE stream. SSE comments are ignored by all compliant clients per the spec.setIntervalfor the keepalive timerctx.waitUntil(done)to keep the Worker execution context alive for the SSE session lifetime/ssestream (not POST/sse/message)Changes
cloudflare/example/src/index.ts/download/<hash>endpointcloudflare/example/worker-configuration.d.tsMCP_AUTH_TOKENto Env typeTesting
Deployed and tested on two Cloudflare accounts. Verified:
/download/<hash>serves valid JPEG/PNG files (verified dimensions/format)