747 lines
16 KiB
Markdown
747 lines
16 KiB
Markdown
# MCP Tool Contracts: Mock GDS MCP Server
|
|
|
|
**Branch**: `001-mock-gds-server` | **Date**: 2026-04-07
|
|
|
|
## Overview
|
|
|
|
This document defines the MCP tool schemas exposed by the Mock GDS MCP server. All tools follow the MCP JSON-RPC 2.0 protocol and include comprehensive JSON Schema validation.
|
|
|
|
## Tool Categories
|
|
|
|
1. **Flight Operations**: searchFlights, bookFlight
|
|
2. **Hotel Operations**: searchHotels, bookHotel
|
|
3. **Car Rental Operations**: searchCars, bookCar
|
|
4. **Booking Management**: retrieveBooking, cancelBooking, listBookings
|
|
|
|
---
|
|
|
|
## Flight Operations
|
|
|
|
### searchFlights
|
|
|
|
Search for available flight options.
|
|
|
|
**Tool Name**: `searchFlights`
|
|
|
|
**Description**: Search for flights between two airports on a specific date. Returns mock flight options with realistic pricing, schedules, and availability.
|
|
|
|
**Input Schema**:
|
|
```json
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"origin": {
|
|
"type": "string",
|
|
"pattern": "^[A-Z]{3}$",
|
|
"description": "Origin airport IATA code (3 letters, e.g., 'JFK')"
|
|
},
|
|
"destination": {
|
|
"type": "string",
|
|
"pattern": "^[A-Z]{3}$",
|
|
"description": "Destination airport IATA code (3 letters, e.g., 'LAX')"
|
|
},
|
|
"departureDate": {
|
|
"type": "string",
|
|
"format": "date",
|
|
"description": "Departure date in ISO 8601 format (YYYY-MM-DD)"
|
|
},
|
|
"passengers": {
|
|
"type": "object",
|
|
"properties": {
|
|
"adults": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"maximum": 9,
|
|
"default": 1
|
|
},
|
|
"children": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"maximum": 9,
|
|
"default": 0
|
|
},
|
|
"infants": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"maximum": 9,
|
|
"default": 0
|
|
}
|
|
},
|
|
"required": ["adults"]
|
|
},
|
|
"cabin": {
|
|
"type": "string",
|
|
"enum": ["economy", "premium_economy", "business", "first"],
|
|
"default": "economy"
|
|
}
|
|
},
|
|
"required": ["origin", "destination", "departureDate"]
|
|
}
|
|
```
|
|
|
|
**Example Request**:
|
|
```json
|
|
{
|
|
"origin": "JFK",
|
|
"destination": "LAX",
|
|
"departureDate": "2026-06-15",
|
|
"passengers": { "adults": 2 },
|
|
"cabin": "economy"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### bookFlight
|
|
|
|
Create a flight booking.
|
|
|
|
**Tool Name**: `bookFlight`
|
|
|
|
**Description**: Book one or more flight segments with passenger details. Creates a PNR (Passenger Name Record) with TEST- prefix.
|
|
|
|
**Input Schema**:
|
|
```json
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"flightIds": {
|
|
"type": "array",
|
|
"items": { "type": "string" },
|
|
"minItems": 1,
|
|
"description": "Array of flight IDs from search results"
|
|
},
|
|
"passengers": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"enum": ["adult", "child", "infant"]
|
|
},
|
|
"firstName": { "type": "string", "minLength": 1, "maxLength": 50 },
|
|
"lastName": { "type": "string", "minLength": 1, "maxLength": 50 },
|
|
"dateOfBirth": { "type": "string", "format": "date" },
|
|
"email": { "type": "string", "format": "email" },
|
|
"phone": { "type": "string" },
|
|
"frequentFlyerNumber": { "type": "string" }
|
|
},
|
|
"required": ["type", "firstName", "lastName"]
|
|
}
|
|
},
|
|
"contactEmail": {
|
|
"type": "string",
|
|
"format": "email",
|
|
"description": "Primary contact email"
|
|
},
|
|
"contactPhone": {
|
|
"type": "string",
|
|
"description": "Primary contact phone"
|
|
}
|
|
},
|
|
"required": ["flightIds", "passengers"],
|
|
"anyOf": [
|
|
{ "required": ["contactEmail"] },
|
|
{ "required": ["contactPhone"] }
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Hotel Operations
|
|
|
|
### searchHotels
|
|
|
|
**Tool Name**: `searchHotels`
|
|
|
|
**Description**: Search for hotel properties in a city with check-in/check-out dates.
|
|
|
|
**Input Schema**:
|
|
```json
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"cityCode": {
|
|
"type": "string",
|
|
"pattern": "^[A-Z]{3}$",
|
|
"description": "City IATA code (3 letters, e.g., 'LAX')"
|
|
},
|
|
"checkInDate": {
|
|
"type": "string",
|
|
"format": "date"
|
|
},
|
|
"checkOutDate": {
|
|
"type": "string",
|
|
"format": "date"
|
|
},
|
|
"guests": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"maximum": 10,
|
|
"default": 1
|
|
},
|
|
"starRating": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"maximum": 5,
|
|
"description": "Minimum star rating filter (optional)"
|
|
}
|
|
},
|
|
"required": ["cityCode", "checkInDate", "checkOutDate"]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### bookHotel
|
|
|
|
**Tool Name**: `bookHotel`
|
|
|
|
**Description**: Book a hotel reservation. Can create a new PNR or add to an existing flight booking.
|
|
|
|
**Input Schema**:
|
|
```json
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"hotelId": { "type": "string" },
|
|
"existingPnr": {
|
|
"type": "string",
|
|
"pattern": "^TEST-[A-Z0-9]{6}$",
|
|
"description": "Optional: Add hotel to existing booking"
|
|
},
|
|
"guests": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"firstName": { "type": "string" },
|
|
"lastName": { "type": "string" },
|
|
"email": { "type": "string", "format": "email" }
|
|
},
|
|
"required": ["firstName", "lastName"]
|
|
}
|
|
},
|
|
"specialRequests": { "type": "string" }
|
|
},
|
|
"required": ["hotelId", "guests"]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Car Rental Operations
|
|
|
|
### searchCars
|
|
|
|
**Tool Name**: `searchCars`
|
|
|
|
**Description**: Search for car rental options at an airport or city location.
|
|
|
|
**Input Schema**:
|
|
```json
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"pickupLocationCode": {
|
|
"type": "string",
|
|
"pattern": "^[A-Z]{3}$"
|
|
},
|
|
"dropoffLocationCode": {
|
|
"type": "string",
|
|
"pattern": "^[A-Z]{3}$",
|
|
"description": "Defaults to pickup location if not specified"
|
|
},
|
|
"pickupDate": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"dropoffDate": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"driverAge": {
|
|
"type": "integer",
|
|
"minimum": 21,
|
|
"maximum": 99,
|
|
"default": 30
|
|
}
|
|
},
|
|
"required": ["pickupLocationCode", "pickupDate", "dropoffDate"]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### bookCar
|
|
|
|
**Tool Name**: `bookCar`
|
|
|
|
**Description**: Book a car rental. Can create a new PNR or add to an existing booking.
|
|
|
|
---
|
|
|
|
## Booking Management Operations
|
|
|
|
### retrieveBooking
|
|
|
|
**Tool Name**: `retrieveBooking`
|
|
|
|
**Description**: Fetch complete booking details including all segments.
|
|
|
|
**Input Schema**:
|
|
```json
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"pnr": {
|
|
"type": "string",
|
|
"pattern": "^TEST-[A-Z0-9]{6}$"
|
|
}
|
|
},
|
|
"required": ["pnr"]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### cancelBooking
|
|
|
|
**Tool Name**: `cancelBooking`
|
|
|
|
**Description**: Cancel a confirmed booking.
|
|
|
|
**Input Schema**:
|
|
```json
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"pnr": {
|
|
"type": "string",
|
|
"pattern": "^TEST-[A-Z0-9]{6}$"
|
|
},
|
|
"reason": { "type": "string" }
|
|
},
|
|
"required": ["pnr"]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### listBookings
|
|
|
|
**Tool Name**: `listBookings`
|
|
|
|
**Description**: Retrieve a list of all PNRs created in the current MCP session.
|
|
|
|
**Input Schema**:
|
|
```json
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"status": {
|
|
"type": "string",
|
|
"enum": ["all", "confirmed", "cancelled"],
|
|
"default": "all"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Error Responses
|
|
|
|
All tools return standard MCP errors:
|
|
|
|
- **-32602**: Invalid params (validation failure)
|
|
- **-32603**: Internal error (server error)
|
|
- **-32001**: Resource not found (invalid PNR, airport code, etc.)
|
|
- **-32002**: Business logic error (cancelled booking, date in past, etc.)
|
|
|
|
**Error Format**:
|
|
```json
|
|
{
|
|
"code": -32602,
|
|
"message": "Invalid airport code 'XYZ': must be a valid 3-letter IATA code",
|
|
"data": {
|
|
"field": "origin",
|
|
"value": "XYZ"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## MCP Resource Endpoints
|
|
|
|
- `gds://session/current` - Current session metadata
|
|
- `gds://session/bookings` - List of all bookings
|
|
- `gds://mock-data/airports` - Mock airport data
|
|
- `gds://mock-data/airlines` - Mock airline data
|
|
|
|
---
|
|
|
|
## Protocol Notes
|
|
|
|
- All tools use JSON-RPC 2.0 over stdio (default) or SSE
|
|
- Tool schemas validated before execution
|
|
- 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`
|
|
|