fixing jsonSchema validation by using zod
This commit is contained in:
@@ -393,3 +393,354 @@ All tools return standard MCP errors:
|
||||
- Timestamps use ISO 8601 format
|
||||
- Prices in USD cents (integer)
|
||||
- All PNRs prefixed with "TEST-" for safety
|
||||
|
||||
---
|
||||
|
||||
## Remote Access Endpoints (Added 2026-04-07)
|
||||
|
||||
The following endpoints are available when running in HTTP/2 remote transport mode.
|
||||
|
||||
### Health Check Endpoint
|
||||
|
||||
**Endpoint**: `GET /health`
|
||||
|
||||
**Description**: Returns server operational status for monitoring and health checks. This endpoint is unauthenticated and exempt from rate limiting.
|
||||
|
||||
**Use Cases**:
|
||||
- Load balancer health checks
|
||||
- Monitoring system integration (Prometheus, Datadog, etc.)
|
||||
- Deployment validation
|
||||
- Debugging connection and memory issues
|
||||
|
||||
**HTTP Method**: GET
|
||||
|
||||
**Authentication**: None (publicly accessible)
|
||||
|
||||
**Rate Limiting**: Exempt (not subject to rate limits)
|
||||
|
||||
**Request**: No body required
|
||||
|
||||
**Response Schema**:
|
||||
```json
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": ["healthy", "degraded", "unhealthy"],
|
||||
"description": "Overall server health status"
|
||||
},
|
||||
"uptime": {
|
||||
"type": "integer",
|
||||
"description": "Server uptime in seconds since start"
|
||||
},
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "Server version (from package.json)"
|
||||
},
|
||||
"connections": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"stdio": {
|
||||
"type": "integer",
|
||||
"description": "Active stdio connections (0 or 1)"
|
||||
},
|
||||
"http": {
|
||||
"type": "integer",
|
||||
"description": "Active HTTP/2 connections"
|
||||
},
|
||||
"total": {
|
||||
"type": "integer",
|
||||
"description": "Total active connections"
|
||||
}
|
||||
},
|
||||
"required": ["stdio", "http", "total"]
|
||||
},
|
||||
"sessions": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"active": {
|
||||
"type": "integer",
|
||||
"description": "Sessions with recent activity (within 5 minutes)"
|
||||
},
|
||||
"total": {
|
||||
"type": "integer",
|
||||
"description": "Total sessions in storage"
|
||||
}
|
||||
},
|
||||
"required": ["active", "total"]
|
||||
},
|
||||
"storage": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"connected": {
|
||||
"type": "boolean",
|
||||
"description": "Valkey connection status"
|
||||
},
|
||||
"responseTime": {
|
||||
"type": "number",
|
||||
"description": "Valkey ping response time in milliseconds"
|
||||
}
|
||||
},
|
||||
"required": ["connected", "responseTime"]
|
||||
},
|
||||
"memory": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"used": {
|
||||
"type": "number",
|
||||
"description": "Process memory used in MB"
|
||||
},
|
||||
"total": {
|
||||
"type": "number",
|
||||
"description": "Total system memory in MB"
|
||||
},
|
||||
"percentage": {
|
||||
"type": "number",
|
||||
"description": "Memory usage percentage (0-1)"
|
||||
}
|
||||
},
|
||||
"required": ["used", "total", "percentage"]
|
||||
},
|
||||
"timestamp": {
|
||||
"type": "integer",
|
||||
"description": "Health check timestamp (Unix milliseconds)"
|
||||
}
|
||||
},
|
||||
"required": ["status", "uptime", "version", "connections", "sessions", "storage", "memory", "timestamp"]
|
||||
}
|
||||
```
|
||||
|
||||
**Status Determination**:
|
||||
- **healthy** (200 OK): All systems operational
|
||||
- Storage connected
|
||||
- Memory usage < 80%
|
||||
- Valkey response time < 100ms
|
||||
- **degraded** (200 OK): Some issues but still serving requests
|
||||
- Storage slow (ping 100-500ms)
|
||||
- Memory usage 80-90%
|
||||
- **unhealthy** (503 Service Unavailable): Critical issues
|
||||
- Storage disconnected
|
||||
- Memory usage > 90%
|
||||
- Unable to serve requests
|
||||
|
||||
**Example Response (Healthy)**:
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"uptime": 3600,
|
||||
"version": "0.1.0",
|
||||
"connections": {
|
||||
"stdio": 0,
|
||||
"http": 12,
|
||||
"total": 12
|
||||
},
|
||||
"sessions": {
|
||||
"active": 8,
|
||||
"total": 15
|
||||
},
|
||||
"storage": {
|
||||
"connected": true,
|
||||
"responseTime": 2.5
|
||||
},
|
||||
"memory": {
|
||||
"used": 45.2,
|
||||
"total": 8192,
|
||||
"percentage": 0.0055
|
||||
},
|
||||
"timestamp": 1712486460000
|
||||
}
|
||||
```
|
||||
|
||||
**Example Response (Degraded)**:
|
||||
```json
|
||||
{
|
||||
"status": "degraded",
|
||||
"uptime": 7200,
|
||||
"version": "0.1.0",
|
||||
"connections": {
|
||||
"stdio": 0,
|
||||
"http": 45,
|
||||
"total": 45
|
||||
},
|
||||
"sessions": {
|
||||
"active": 42,
|
||||
"total": 50
|
||||
},
|
||||
"storage": {
|
||||
"connected": true,
|
||||
"responseTime": 150
|
||||
},
|
||||
"memory": {
|
||||
"used": 6553.6,
|
||||
"total": 8192,
|
||||
"percentage": 0.8
|
||||
},
|
||||
"timestamp": 1712490060000
|
||||
}
|
||||
```
|
||||
|
||||
**Example Response (Unhealthy)**:
|
||||
```json
|
||||
{
|
||||
"status": "unhealthy",
|
||||
"uptime": 10800,
|
||||
"version": "0.1.0",
|
||||
"connections": {
|
||||
"stdio": 0,
|
||||
"http": 0,
|
||||
"total": 0
|
||||
},
|
||||
"sessions": {
|
||||
"active": 0,
|
||||
"total": 0
|
||||
},
|
||||
"storage": {
|
||||
"connected": false,
|
||||
"responseTime": null
|
||||
},
|
||||
"memory": {
|
||||
"used": 120,
|
||||
"total": 8192,
|
||||
"percentage": 0.015
|
||||
},
|
||||
"timestamp": 1712493660000
|
||||
}
|
||||
```
|
||||
|
||||
**cURL Example**:
|
||||
```bash
|
||||
curl -i http://localhost:8080/health
|
||||
```
|
||||
|
||||
**Load Balancer Integration** (Nginx):
|
||||
```nginx
|
||||
upstream mcp_backend {
|
||||
server mcp-server:3000;
|
||||
health_check interval=10s uri=/health;
|
||||
}
|
||||
```
|
||||
|
||||
**Prometheus Monitoring**:
|
||||
```yaml
|
||||
scrape_configs:
|
||||
- job_name: 'mcp-server'
|
||||
static_configs:
|
||||
- targets: ['localhost:8080']
|
||||
metrics_path: '/health'
|
||||
scrape_interval: 30s
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rate Limiting (HTTP Mode Only)
|
||||
|
||||
When running in HTTP/2 remote mode, all MCP tool endpoints are subject to rate limiting.
|
||||
|
||||
**Algorithm**: Sliding Window Counter (Hybrid)
|
||||
|
||||
**Default Limits**:
|
||||
- 100 requests per minute per client IP address
|
||||
- Window size: 60 seconds
|
||||
- Burst tolerance: ~150 requests in worst-case window overlap
|
||||
|
||||
**Rate Limit Headers** (included in all HTTP responses):
|
||||
```
|
||||
X-RateLimit-Limit: 100
|
||||
X-RateLimit-Remaining: 45
|
||||
X-RateLimit-Reset: 1712486520
|
||||
```
|
||||
|
||||
**Rate Limit Exceeded Response** (429 Too Many Requests):
|
||||
```json
|
||||
{
|
||||
"error": "Rate limit exceeded",
|
||||
"code": "RATE_LIMIT_EXCEEDED",
|
||||
"limit": 100,
|
||||
"current": 105,
|
||||
"resetAt": "2026-04-07T10:02:00.000Z",
|
||||
"retryAfter": 15
|
||||
}
|
||||
```
|
||||
|
||||
**HTTP Headers on 429**:
|
||||
```
|
||||
HTTP/1.1 429 Too Many Requests
|
||||
X-RateLimit-Limit: 100
|
||||
X-RateLimit-Remaining: 0
|
||||
X-RateLimit-Reset: 1712486520
|
||||
Retry-After: 15
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**Exemptions**:
|
||||
- Health check endpoint (`/health`) is exempt from rate limiting
|
||||
- CORS preflight requests (OPTIONS) are exempt
|
||||
|
||||
**Configuration**:
|
||||
```bash
|
||||
RATE_LIMIT_ENABLED=true
|
||||
RATE_LIMIT_PER_MINUTE=100
|
||||
RATE_LIMIT_WINDOW_SECONDS=60
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CORS Headers (HTTP Mode Only)
|
||||
|
||||
When running in HTTP/2 remote mode, all endpoints support cross-origin requests.
|
||||
|
||||
**CORS Policy**: Permissive wildcard (`Access-Control-Allow-Origin: *`)
|
||||
|
||||
**Preflight Request** (OPTIONS):
|
||||
```
|
||||
OPTIONS /mcp HTTP/1.1
|
||||
Origin: https://web-client.example.com
|
||||
Access-Control-Request-Method: POST
|
||||
Access-Control-Request-Headers: Content-Type, MCP-Session-ID
|
||||
```
|
||||
|
||||
**Preflight Response**:
|
||||
```
|
||||
HTTP/1.1 204 No Content
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Methods: GET, POST, OPTIONS
|
||||
Access-Control-Allow-Headers: Content-Type, MCP-Session-ID, X-Requested-With
|
||||
Access-Control-Max-Age: 86400
|
||||
```
|
||||
|
||||
**Actual Request Headers** (added to all responses):
|
||||
```
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Credentials: false
|
||||
Access-Control-Expose-Headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
|
||||
```
|
||||
|
||||
**Security Note**: Wildcard CORS is appropriate for development/testing with mock data only. Deploy within private networks (VPN, firewalls) for security.
|
||||
|
||||
---
|
||||
|
||||
## Transport Mode Configuration
|
||||
|
||||
**Environment Variables**:
|
||||
```bash
|
||||
# Transport selection
|
||||
TRANSPORT_MODE=stdio|http|both # Default: stdio
|
||||
|
||||
# HTTP/2 configuration (when http or both)
|
||||
HTTP_PORT=3000 # Internal port (default: 3000)
|
||||
HTTP_HOST=127.0.0.1 # Bind address (default: 127.0.0.1 for proxy)
|
||||
|
||||
# External access via reverse proxy
|
||||
# Nginx listens on :8080 (HTTP/2 + TLS)
|
||||
# Proxies to mcp-server:3000 (HTTP/1.1)
|
||||
```
|
||||
|
||||
**Protocol Notes (Updated)**:
|
||||
- stdio mode: JSON-RPC 2.0 over stdin/stdout (local only)
|
||||
- http mode: JSON-RPC 2.0 over SSE via StreamableHTTPServerTransport
|
||||
- HTTP/2: Provided by nginx reverse proxy (terminates HTTP/2, proxies HTTP/1.1)
|
||||
- CORS: Enabled in http mode, wildcard policy
|
||||
- Rate limiting: Enabled in http mode, IP-based tracking
|
||||
- Health checks: Available in http mode at `/health`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user