UNPKG

@siva-sub/mcp-public-transport

Version:

A Model Context Protocol server for Singapore transport data with real-time information and routing

154 lines (153 loc) 6.69 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TaxiAvailabilityTool = void 0; const zod_1 = require("zod"); const base_js_1 = require("../base.js"); const validation_js_1 = require("../../utils/validation.js"); const logger_js_1 = require("../../utils/logger.js"); const haversine_distance_1 = __importDefault(require("haversine-distance")); const TaxiAvailabilityInputSchema = zod_1.z.intersection(validation_js_1.LocationSchema, zod_1.z.object({ radius: zod_1.z.number().min(100).max(5000).default(1000), })); class TaxiAvailabilityTool extends base_js_1.BaseTool { constructor(ltaService, oneMapService) { super(); this.ltaService = ltaService; this.oneMapService = oneMapService; } getDefinitions() { return [ { name: 'get_nearby_taxis', description: 'Find available taxis near a specified location', inputSchema: this.createSchema({ location: { type: 'string', description: 'Location name (e.g., "Marina Bay", "Orchard Road")', }, lat: { type: 'number', description: 'Latitude coordinate', }, lng: { type: 'number', description: 'Longitude coordinate', }, radius: { type: 'number', minimum: 100, maximum: 5000, default: 1000, description: 'Search radius in meters', }, }), }, ]; } canHandle(toolName) { return toolName === 'get_nearby_taxis'; } async execute(toolName, args) { try { const { location, lat, lng, radius } = (0, validation_js_1.validateInput)(TaxiAvailabilityInputSchema, args); let searchLat = lat; let searchLng = lng; // Geocode location if coordinates not provided if (!searchLat || !searchLng) { if (!location) { throw new Error('Either location name or coordinates must be provided'); } logger_js_1.logger.info(`Geocoding location for taxi search: ${location}`); const geocoded = await this.oneMapService.geocode(location); if (!geocoded) { return { error: `Could not find coordinates for location: ${location}`, timestamp: new Date().toISOString(), }; } searchLat = geocoded.latitude; searchLng = geocoded.longitude; } logger_js_1.logger.info(`Finding taxis near ${searchLat}, ${searchLng}`, { radius }); // Get taxi availability data const taxis = await this.ltaService.getTaxiAvailability(); // Filter taxis within radius const nearbyTaxis = taxis .map(taxi => ({ ...taxi, distance: (0, haversine_distance_1.default)({ latitude: searchLat, longitude: searchLng }, { latitude: taxi.coordinates[0], longitude: taxi.coordinates[1] }), })) .filter(taxi => taxi.distance <= (radius || 1000)) .sort((a, b) => a.distance - b.distance); const closestTaxi = nearbyTaxis[0]; return { searchLocation: { latitude: searchLat, longitude: searchLng, name: location, }, radius, availableTaxis: nearbyTaxis.length, closestTaxi: closestTaxi ? { distanceMeters: Math.round(closestTaxi.distance), estimatedWalkTime: `${Math.ceil(closestTaxi.distance / 80)} minutes`, coordinates: closestTaxi.coordinates, } : null, taxiDensity: this.calculateTaxiDensity(nearbyTaxis.length, radius || 1000), recommendations: this.generateTaxiRecommendations(nearbyTaxis.length, location), timestamp: new Date().toISOString(), }; } catch (error) { logger_js_1.logger.error(`Taxi availability tool failed: ${toolName}`, error); return this.formatError(error, toolName); } } calculateTaxiDensity(count, radius) { const area = Math.PI * Math.pow(radius / 1000, 2); // km² const density = count / area; if (density > 10) return 'very_high'; if (density > 5) return 'high'; if (density > 2) return 'moderate'; if (density > 0.5) return 'low'; return 'very_low'; } generateTaxiRecommendations(taxiCount, location) { const recommendations = []; if (taxiCount === 0) { recommendations.push('No taxis available in this area'); recommendations.push('Consider using ride-hailing apps like Grab or ComfortDelGro'); recommendations.push('Check nearby MRT stations or bus stops for public transport'); } else if (taxiCount < 3) { recommendations.push('Limited taxi availability - consider booking in advance'); recommendations.push('Alternative: Use ride-hailing apps for better availability'); } else if (taxiCount >= 10) { recommendations.push('High taxi availability in this area'); recommendations.push('Good area for finding taxis quickly'); } else { recommendations.push('Moderate taxi availability'); } // Location-specific recommendations if (location) { const locationLower = location.toLowerCase(); if (locationLower.includes('airport') || locationLower.includes('changi')) { recommendations.push('Airport taxi queue available for departing passengers'); } else if (locationLower.includes('orchard') || locationLower.includes('cbd')) { recommendations.push('Peak hours may have longer wait times in this busy area'); } } return recommendations; } } exports.TaxiAvailabilityTool = TaxiAvailabilityTool;