EdgeContext
Click on "Deploy 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., "@EdgeContextsave a project note: edge relay deployed to staging"
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.
EdgeContext
A Cloudflare Workers MCP context relay. It sits between MCP clients and upstream MCP servers as a transparent Streamable HTTP proxy, and adds persistent project-scoped context, multi-tenant isolation, per-tenant rate limiting, edge caching, and durable request logging at the edge.
Entirely Cloudflare-native — Workers, Durable Objects, KV, and R2. No Node server, no external database.
Architecture
MCP Client
│ JSON-RPC / SSE + Bearer API key
▼
┌──────────────────────────────────────────────┐
│ EdgeContext Worker │
│ │
│ Auth ──────► KV (tenant config) │
│ Rate limit ► RateLimiterDO (per tenant) │
│ Routing ───► tenant upstream allow-list │
│ │
│ ┌────────── MCP dispatch ────────────────┐ │
│ │ edgecontext_* ──► SessionDO │ │
│ │ cacheable tool ──► KV cache │ │
│ │ everything else ──► upstream MCP │ │
│ └────────────────────────────────────────┘ │
│ │
│ SessionDO ──► project context + log buffer │
│ Alarm ──────► R2 (JSONL logs) │
└──────────────────────┬───────────────────────┘
▼
Upstream MCP serversUnrecognized methods and tools pass through untouched, so any MCP client and server pair keeps working; the edge features are additive.
Related MCP server: Remote MCP Server on Cloudflare
Core Design
Context & project isolation
One SessionDO per project ID, addressed by name, so state survives Worker restarts and client reconnects. Each session holds project notes plus a rolling history of the last 50 tool calls and 30 resource reads.
Projects are isolated at the Durable Object level — separate namespaces, no shared storage — so one project cannot read another's session state. The cache, by contrast, is tenant-scoped, so a tenant reuses cached tool results across its projects.
Authentication & routing
Clients send two headers:
Authorization: Bearer <api-key>
X-EdgeContext-Project: <project-id>The key is SHA-256 hashed and used to look up tenant:<hash> in KV; the raw key is never stored and is unrecoverable after creation. Each tenant record carries its own upstream allow-list and rate limit. A request to /mcp/:serverName is rejected before any upstream contact unless that server is both configured and present in the tenant's allow-list.
Rate limiting
One Durable Object per tenant maintains a sliding window. Durable Objects are used rather than KV because admission control needs a serialized read-increment-check: KV is eventually consistent and offers no atomic increment, so concurrent requests would over-admit.
Each JSON-RPC request consumes one slot, and a batch consumes one slot per sub-request — batching cannot be used to bypass the limit. Throttled requests are rejected at the edge:
HTTP/1.1 429 Too Many Requests
Retry-After: 58
X-EdgeContext-RateLimit-Limit: 60
X-EdgeContext-RateLimit-Remaining: 0Caching
Caching is opt-in per tool through CACHEABLE_TOOLS; nothing is cached unless explicitly configured. Keys are tenant-scoped:
cache:<tenantHash>:<toolName>:<sha256(stableStringify(arguments))>stableStringify sorts object keys recursively, so semantically equivalent argument objects hash identically while array order stays significant.
Responses carry X-EdgeContext-Cache: HIT | MISS. Upstream errors are never cached, and a cache read or write failure degrades to a normal upstream request rather than failing the MCP call.
Streaming & batching
EdgeContext implements MCP Streamable HTTP: POST for JSON-RPC, GET for event streams, DELETE for session termination, with Mcp-Session-Id, MCP-Protocol-Version, and Last-Event-ID handled across the hop. SSE responses are forwarded as they arrive rather than buffered.
A streamed call can still be cached, but only once its final result is observed — a client-abandoned stream is never cached. A cached result from a previously streamed call is served as final JSON, not as a reconstructed event sequence.
JSON-RPC arrays are accepted up to 100 sub-requests, executed sequentially so session history stays ordered, later sub-requests can observe earlier ones, and a single client cannot fan out dozens of concurrent upstream calls. Failures are scoped accordingly: a per-request error stays attached to its request ID, while a transport-level failure rejects the batch with one error and a null ID. Notifications produce no response, and a notification-only request returns 202 Accepted.
Logging
Tool calls are buffered in the project's SessionDO and flushed to R2 by a 60-second alarm:
logs/<YYYY-MM-DD>/<projectId>/<timestamp>-<random>.jsonlEach flush writes a new object instead of appending to a shared daily file, which avoids read-modify-write races between concurrently flushing projects. A failed R2 write is re-buffered for the next flush.
MCP Context Tools
Three tools are served locally from the SessionDO and never reach the upstream:
Tool | Purpose |
| Store project notes |
| Return recent activity and notes |
| Return the project context as Markdown |
Quick Start
Requires Node.js 20+ and pnpm 10+.
pnpm install
pnpm test
pnpm typecheckFor local development, copy .dev.vars.example to .dev.vars:
UPSTREAM_MCP_SERVERS={"default":"http://127.0.0.1:8902/mcp"}
CACHEABLE_TOOLS=search_codebase:600
DEFAULT_RATE_LIMIT=60
CACHE_TTL_SECONDS=300Seed a tenant with the SHA-256 hash of a test key, then start the Worker:
node -e "console.log(require('crypto').createHash('sha256').update('demo-key-123').digest('hex'))"
pnpm exec wrangler kv key put --local --preview --binding TENANTS \
"tenant:<hash>" '{"name":"demo","allowedServers":["default"],"rateLimitRpm":60}'
pnpm devcurl -X POST http://127.0.0.1:8787/mcp/default \
-H 'Authorization: Bearer demo-key-123' \
-H 'X-EdgeContext-Project: my-project' \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}'Deployment
# Storage
pnpm exec wrangler kv namespace create TENANTS
pnpm exec wrangler kv namespace create TENANTS --preview
pnpm exec wrangler kv namespace create CACHE
pnpm exec wrangler kv namespace create CACHE --preview
pnpm exec wrangler r2 bucket create edgecontext-logs
pnpm exec wrangler r2 bucket create edgecontext-logs-preview
# Upstreams, then deploy
pnpm exec wrangler secret put UPSTREAM_MCP_SERVERS
pnpm exec wrangler deployDurable Object migrations are declared in wrangler.toml; no manual Durable Object setup is required.
Provision a tenant by storing only the hash of its key:
KEY=$(openssl rand -hex 32)
HASH=$(node -e "console.log(require('crypto').createHash('sha256').update('$KEY').digest('hex'))")
pnpm exec wrangler kv key put --remote --binding TENANTS \
"tenant:$HASH" '{"name":"my-team","allowedServers":["docs"],"rateLimitRpm":120}'
echo "API key: $KEY"Point an MCP client at https://<worker>/mcp/<serverName> with the Authorization and X-EdgeContext-Project headers; the project ID selects the persistent context namespace.
Configuration
Binding | Type | Purpose |
| KV | API-key hashes and tenant configuration |
| KV | Cached MCP tool results |
| R2 | Durable request logs |
| Durable Object | Project context and log buffering |
| Durable Object | Per-tenant rate limiting |
Variable | Default | Purpose |
|
| Named upstream MCP servers |
|
| Requests/minute when a tenant sets none |
|
| Default cache TTL |
|
| Cacheable tools, with optional per-tool TTL — |
JSON-RPC errors use implementation-specific codes in the -32000 range, alongside standard HTTP statuses (401, 405, 429):
Code | Meaning |
| Missing or invalid API key |
| Rate limit exceeded |
| Tenant not authorized for upstream |
| Upstream unavailable |
| Unknown upstream |
| Local EdgeContext tool failure |
Testing
pnpm test
pnpm typecheck
pnpm exec wrangler deploy --dry-run147 tests run inside the real Workers runtime via @cloudflare/vitest-pool-workers, against real KV namespaces, Durable Objects, and R2 rather than in-memory fakes. Only the upstream MCP server is mocked, through Miniflare's outboundService, so no test makes a real network request.
Coverage spans authentication and tenant isolation, upstream routing, cache behavior, Durable Object persistence and project isolation, sliding-window rate limiting under concurrent requests, SSE streaming, GET/DELETE transport handling, JSON-RPC batching, notifications, and R2 log flushing.
Known Limitations
No dashboard: logs land in R2 with no UI for browsing them.
Sequential batches: batches trade throughput for ordering and upstream fan-out control by design.
Whole-batch admission: a batch exceeding the remaining rate-limit budget is rejected in full rather than partially.
Stream cache replay: cached streamed calls replay as final JSON, not as the original SSE event sequence.
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Remote streamable-HTTP MCP server running on a single Cloudflare Worker. Your assistant gets live Airbnb, Amazon, Booking.com, Google Flights, Maps and Reddit data, social search on X, Instagram and TikTok, the Meta Ad Library, and image/video generation without any keys. Connect your own accounts to let it send WhatsApp or Telegram messages, work an IMAP inbox, manage Meta Ads campaigns and publish to X and LinkedIn. OAuth 2.1 with PKCE; stored credentials are AES-256-GCM encrypted.
Share one project context across ChatGPT, Claude, Telegram and any MCP client.
- QuallaaOAuthcom.quallaa
Talk to your public-facing AI from any MCP client — Claude, ChatGPT, Cursor, Cline, Windsurf.
MCP-native notes and memory for ChatGPT, Claude, and other AI tools.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceA Cloudflare Workers-based implementation of the Model Context Protocol server with OAuth login, allowing Claude and other MCP clients to connect to remote tools.1-
- FlicenseNot gradedqualityCmaintenanceA Model Context Protocol server implementation designed to run on Cloudflare Workers with integrated OAuth authentication. It enables hosting and securely accessing MCP tools remotely via SSE transport from clients like Claude Desktop.-
- AlicenseNot gradedqualityBmaintenanceUnifies local MCP servers into a single secure Cloudflare Tunnel endpoint, making them accessible to MCP clients like Notion and Claude. Supports HTTP/SSE/stdio servers, built-in file system tools, bearer authentication, and one-click Windows setup.MIT
- FlicenseNot gradedqualityBmaintenanceDeploys a stateless remote MCP server on Cloudflare Workers without authentication, enabling MCP tool calls from clients like Claude Desktop and Cloudflare AI Playground.-