TRANSFER_API_FIX.md•8.82 kB
# Transfer API Location Format Fix
## Problem Summary
The Amadeus Transfer API was failing with error "MISSING DROP OFF LOCATION INFORMATION" when users provided free-text addresses like "Times Square" or "New York, NY".
### Root Cause
The API requires complete, structured location data including:
- Address line
- City name
- Country code
- Geographic coordinates (latitude, longitude)
- Location name
Free-text addresses lack this structured information, causing the API to reject the request.
### Why This Failed for AI Agents
AI agents would naturally try addresses like "Times Square" or "hotel address", which would:
1. Get accepted by the tool (no validation)
2. Fail at the API level with cryptic error
3. Force retry with different format
4. Waste tokens on trial-and-error
## Solution Implemented
### Philosophy: Fail Fast with Clear Guidance (Best for AI Agents)
Instead of accepting any input and letting the API fail, we now **validate inputs before making API calls** and provide clear, actionable error messages. This is optimal for AI agents because:
1. **Clear requirements** in tool definition → agent knows exactly what format to use
2. **Validation before API call** → no wasted API quota on invalid requests
3. **No trial-and-error** → agent gets it right on first try
4. **Helpful errors** → if agent makes mistake, error explains exactly how to fix it
### 1. Airport Location Database (Unchanged)
Created `AIRPORT_LOCATIONS` dictionary with complete information for 20+ major airports:
```python
AIRPORT_LOCATIONS = {
"CDG": {
"name": "Paris Charles de Gaulle Airport",
"cityName": "Paris",
"countryCode": "FR",
"geoCode": "49.0097,2.5479",
"addressLine": "95700 Roissy-en-France"
},
"ORY": {
"name": "Paris Orly Airport",
"cityName": "Paris",
"countryCode": "FR",
"geoCode": "48.7233,2.3794",
"addressLine": "94390 Orly"
},
# ... 18 more major airports
}
```
**Airports included:**
- Paris: CDG, ORY
- New York: JFK, LGA, EWR
- London: LHR, LGW, STN
- Los Angeles: LAX
- Tokyo: NRT, HND
- San Francisco: SFO
- Miami: MIA
- Dubai: DXB
- Frankfurt: FRA
- Amsterdam: AMS
- Madrid: MAD
- Barcelona: BCN
- Singapore: SIN
- Hong Kong: HKG
- Seoul: ICN
### 2. Enhanced Location Validation Function
Updated `format_location_for_transfer()` to return `(result, error)` tuple:
**Now validates and rejects invalid formats:**
1. ✅ **Airport codes** in database → enriched with full location data
2. ✅ **Coordinates** in "lat,long" format → validated and passed through
3. ❌ **Free-text addresses** → rejected with helpful error explaining why
4. ❌ **Invalid airport codes** → suggests available airports
5. ❌ **Invalid coordinates** → explains correct format and valid ranges
**Key changes:**
```python
# OLD - accepted anything, caused API failures
def format_location_for_transfer(location: str) -> Dict[str, Any]:
# ...silently accepts free-text addresses...
return {"endAddressLine": location} # ❌ Missing required fields
# NEW - validates input, fails fast with clear errors
def format_location_for_transfer(location: str) -> tuple[Dict[str, Any], Optional[str]]:
# ...validates format...
if is_unsupported_format:
return {}, "Clear error message explaining requirements" # ✅
return formatted_data, None
```
### 3. Updated search_transfers Tool
**New features:**
- ✅ **Input validation before API call** - catches errors immediately
- ✅ **Clear tool documentation** - AI agents know exactly what format to use
- ✅ **Helpful error messages** - if validation fails, explains how to fix it
- ✅ Automatic location enrichment for airport codes
- ✅ Support for all transfer types: PRIVATE, TAXI, HOURLY, SHUTTLE, SHARED
- ✅ Duration parameter for HOURLY transfers
- ✅ **Strict input requirements** - only airports or coordinates, no free-text
**Updated signature:**
```python
async def search_transfers(
start_location: str,
end_location: str,
transfer_type: str,
start_date_time: str,
passengers: int = 1,
duration: Optional[str] = None # NEW: for HOURLY transfers
) -> str
```
## API Payload Format
### Before (Incorrect)
```json
{
"startLocationCode": "CDG",
"endAddressLine": "ORY",
"transferType": "PRIVATE",
"startDateTime": "2024-11-20T10:30:00",
"passengers": 1
}
```
### After (Correct)
```json
{
"startLocationCode": "CDG",
"endLocationCode": "ORY",
"endAddressLine": "94390 Orly",
"endCityName": "Paris",
"endCountryCode": "FR",
"endGeoCode": "48.7233,2.3794",
"endName": "Paris Orly Airport",
"transferType": "PRIVATE",
"startDateTime": "2024-11-20T10:30:00",
"passengers": 1
}
```
## Usage Examples
### ✅ Airport to Airport (VALID)
```python
search_transfers(
start_location="CDG",
end_location="ORY",
transfer_type="PRIVATE",
start_date_time="2024-11-20T10:30:00",
passengers=2
)
# ✅ Both airport codes in database - works perfectly
```
### ✅ Airport to Coordinates (VALID)
```python
search_transfers(
start_location="JFK",
end_location="40.7580,-73.9855", # Times Square coordinates
transfer_type="TAXI",
start_date_time="2024-11-20T14:00:00",
passengers=1
)
# ✅ JFK in database, coordinates valid - works perfectly
```
### ✅ Coordinates to Coordinates (VALID)
```python
search_transfers(
start_location="51.4700,-0.4543", # LHR coordinates
end_location="51.5074,-0.1278", # London city center
transfer_type="PRIVATE",
start_date_time="2024-11-20T09:00:00",
passengers=3
)
# ✅ Both coordinates valid - works perfectly
```
### ❌ Free-Text Address (INVALID - Rejected)
```python
search_transfers(
start_location="JFK",
end_location="Times Square, New York, NY", # ❌ Free-text not supported
transfer_type="TAXI",
start_date_time="2024-11-20T14:00:00",
passengers=1
)
# ❌ Returns validation error explaining to use coordinates
# Error: "Free-text addresses are NOT supported. Use coordinates: '40.7580,-73.9855'"
```
### How AI Agents Should Use This Tool
1. **If destination is a known airport** → use airport code
2. **If destination is a custom location** → look up coordinates first, then call tool
3. **Tool will validate immediately** → no wasted API calls on bad format
### Hourly Rental
```python
search_transfers(
start_location="LAX",
end_location="Santa Monica Pier",
transfer_type="HOURLY",
start_date_time="2024-11-20T10:00:00",
passengers=4,
duration="PT4H30M" # 4 hours 30 minutes
)
```
## Benefits of This Approach
### For AI Agents:
- ✅ **Tool definition is self-documenting** - agent reads docstring, knows exact format needed
- ✅ **No trial-and-error** - validation happens before API call, saves tokens
- ✅ **Clear error messages** - if format is wrong, error explains exactly how to fix it
- ✅ **Efficient** - agent can look up coordinates first, then call tool with confidence
### For API Reliability:
- ✅ **PRIVATE**: Full location data prevents country code errors
- ✅ **TAXI**: Proper formatting increases provider success rate
- ✅ **HOURLY**: Duration parameter supported and validated
- ✅ **SHUTTLE**: Complete location data prevents service type errors
- ✅ **SHARED**: Country code and full location info provided
### For Development:
- ✅ **Fail fast** - errors caught before wasting API quota
- ✅ **Clear requirements** - documentation makes expectations explicit
- ✅ **Easy debugging** - validation errors pinpoint exact problem
## Files Modified
1. `src/mcp_server_amadeus/server.py`:
- Added `AIRPORT_LOCATIONS` dictionary (lines 1001-1155)
- Added `format_location_for_transfer()` function (lines 1158-1207)
- Updated `search_transfers()` tool (lines 1210-1272)
2. `AMADEUS_README.md`:
- Updated transfer types documentation
- Added transfer usage examples
## Testing Recommendations
Re-test with the same CDG → ORY scenario:
```bash
# Test PRIVATE
search_transfers("CDG", "ORY", "PRIVATE", "2024-11-25T10:00:00", 1)
# Test TAXI
search_transfers("CDG", "ORY", "TAXI", "2024-11-25T10:00:00", 1)
# Test HOURLY (with duration)
search_transfers("CDG", "ORY", "HOURLY", "2024-11-25T10:00:00", 1, "PT3H")
# Test SHUTTLE
search_transfers("CDG", "ORY", "SHUTTLE", "2024-11-25T10:00:00", 1)
# Test SHARED
search_transfers("CDG", "ORY", "SHARED", "2024-11-25T10:00:00", 1)
```
## Future Enhancements
1. **Expand airport database**: Add more airports as needed
2. **Geocoding integration**: Auto-lookup coordinates for addresses
3. **Address validation**: Verify address format for different countries
4. **Provider filtering**: Allow filtering by specific providers
5. **Cache location data**: Avoid repeated lookups