Skip to content

Conversation

@mkczarkowski
Copy link
Collaborator

This PR implements three critical production features for the 10x Rules MCP Server:

  1. Health Check Endpoint - Lightweight monitoring without DO creation
  2. Accept Header Validation - Proper HTTP content negotiation (406 responses)
  3. Global IP-Based Rate Limiting - Protection against abuse using Cloudflare KV

These changes make the MCP server production-ready, prevent abuse, reduce costs, and follow industry best practices.

Problem Statement

The MCP server was missing essential production features:

1. No Health Check Endpoint

  • Load balancers and monitoring tools need lightweight health checks
  • Every health check request was creating expensive Durable Objects
  • No way to verify service health without side effects
  • Cost Impact: Unnecessary DO creations costing ~$X/month

2. No Request Validation

  • SSE endpoints were accepting requests with any Accept header
  • Browsers and incorrect clients could connect unintentionally
  • Missing proper HTTP 406 (Not Acceptable) responses
  • Impact: Resource waste, incorrect client behavior

3. No Rate Limiting

  • Zero protection against abuse or DoS attacks
  • Malicious users could create unlimited Durable Objects
  • No cost controls on DO creation
  • Risk: Potential for unlimited cost escalation

4. Discovery: Per-Session Rate Limiting Issue

During initial implementation, we discovered that DO-level rate limiting:

  • Interfered with WebSocket upgrades (500 errors)
  • Only worked within single DO instances
  • Could be bypassed by creating multiple sessions
  • Didn't prevent DO creation abuse

Solution

Architecture: Worker-Level Rate Limiting

We implemented a two-phase approach, ultimately landing on global IP-based rate limiting at the Worker level:

Client Request → Worker fetch()
                     ↓
        Health Check? → Return 200 (no rate limit, no DO)
                     ↓
                 Extract IP
                     ↓
            Check KV Rate Limit (Global)
                     ↓
         Over Limit? → Return 429 (before DO creation)
                     ↓
          Validate Accept Header → 406 if invalid
                     ↓
            Route to Durable Object
                     ↓
              Return Response

Key Decision: Rate limiting BEFORE DO routing prevents abuse and cost overruns.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +110 to +118
try {
// Get current count
const value = await kv.get(key);
const currentCount = value ? parseInt(value, 10) : 0;
const newCount = currentCount + 1;

// Store with TTL and metadata
await kv.put(
key,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use atomic counter for KV-based rate limiter

The new rate limiting logic increments the request count by performing a kv.get followed by a kv.put with the incremented value. Cloudflare KV does not guarantee atomicity for this read–modify–write pattern, so when multiple requests from the same IP arrive concurrently they can all read the same count and overwrite each other’s updates. In practice the counter can remain at 1 even after dozens of parallel requests, allowing attackers to bypass the limit and continue creating Durable Objects. Consider using kv.atomic() or moving the counter into a Durable Object to ensure increments are serialized.

Useful? React with 👍 / 👎.

@github-actions
Copy link

✅ All checks have passed successfully!

  • Lint: ✅
  • Unit Tests: ✅
  • E2E Tests: ✅

Coverage reports have been uploaded as artifacts.

@mkczarkowski mkczarkowski merged commit 4f84c64 into master Oct 22, 2025
5 checks passed
@mkczarkowski mkczarkowski deleted the cloudflare-kv branch October 22, 2025 13:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants