File size: 2,334 Bytes
85d69fd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import time
from typing import Dict
from fastapi import Request, Response, HTTPException
from fastapi.responses import JSONResponse
from mcp_config import mcp_settings

# Simple in-memory rate limiting (use Redis in production)
request_counts: Dict[str, Dict[str, int]] = {}

async def rate_limit_middleware(request: Request, call_next):
    """Rate limiting middleware"""
    client_ip = request.client.host if request.client else "unknown"
    current_time = int(time.time())
    window_start = current_time // mcp_settings.RATE_LIMIT_PERIOD * mcp_settings.RATE_LIMIT_PERIOD
    
    # Initialize client data if not exists
    if client_ip not in request_counts:
        request_counts[client_ip] = {}
    
    # Clean old windows
    for window in list(request_counts[client_ip].keys()):
        if window < window_start:
            del request_counts[client_ip][window]
    
    # Check current window
    if window_start not in request_counts[client_ip]:
        request_counts[client_ip][window_start] = 0
    
    # Check rate limit
    if request_counts[client_ip][window_start] >= mcp_settings.RATE_LIMIT_REQUESTS:
        return JSONResponse(
            status_code=429,
            content={
                "code": "RATE_LIMIT_EXCEEDED",
                "message": f"Rate limit exceeded. Max {mcp_settings.RATE_LIMIT_REQUESTS} requests per {mcp_settings.RATE_LIMIT_PERIOD} seconds.",
                "details": {
                    "retry_after": mcp_settings.RATE_LIMIT_PERIOD - (current_time % mcp_settings.RATE_LIMIT_PERIOD)
                }
            }
        )
    
    # Increment counter
    request_counts[client_ip][window_start] += 1
    
    response = await call_next(request)
    return response

async def validate_mcp_request(request: Request, call_next):
    """Validate MCP request format"""
    try:
        response = await call_next(request)
        return response
    except Exception as e:
        if mcp_settings.DEBUG:
            print(f"Request validation error: {str(e)}")
        return JSONResponse(
            status_code=500,
            content={
                "code": "INTERNAL_ERROR",
                "message": "Internal server error",
                "details": {"timestamp": time.time()}
            }
        )