import { Tool } from '@modelcontextprotocol/sdk/types.js';
import { SFExpressClient } from '../sf-express-client.js';
import {
ServiceInquiryRequestSchema,
ServiceInquiryRequest,
SFExpressError
} from '../types.js';
export const serviceInquiryTool: Tool = {
name: 'sf_express_service_inquiry',
description: 'Inquire about SF Express service availability, restrictions, and capabilities between locations.',
inputSchema: {
type: 'object',
properties: {
originCode: {
type: 'string',
description: 'Origin area code (e.g., "010" for Beijing, "021" for Shanghai)'
},
destCode: {
type: 'string',
description: 'Destination area code (e.g., "010" for Beijing, "021" for Shanghai)'
},
serviceType: {
type: 'string',
description: 'Specific service type to query (optional). Leave empty to query all available services.'
}
},
required: ['originCode', 'destCode']
}
};
export async function handleServiceInquiry(
args: any,
client: SFExpressClient
): Promise<any> {
try {
// Validate input using Zod schema
const validatedRequest = ServiceInquiryRequestSchema.parse(args);
// Call SF Express API
const result = await client.serviceInquiry(validatedRequest);
// Format the response with enhanced service information
const formattedServices = result.services.map(service => ({
serviceCode: service.serviceCode,
serviceName: service.serviceName,
serviceType: service.serviceType,
availability: {
available: service.available,
status: service.available ? 'Available' : 'Not Available'
},
transitInfo: {
estimatedTransitTime: service.transitTime || 'Not specified',
businessDays: parseTransitTime(service.transitTime)
},
restrictions: service.restrictions || [],
hasRestrictions: (service.restrictions?.length || 0) > 0
}));
// Separate available and unavailable services
const availableServices = formattedServices.filter(s => s.availability.available);
const unavailableServices = formattedServices.filter(s => !s.availability.available);
return {
success: true,
data: {
route: {
from: result.originCode,
to: result.destCode,
serviceType: validatedRequest.serviceType || 'All services'
},
summary: {
totalServices: formattedServices.length,
availableServices: availableServices.length,
unavailableServices: unavailableServices.length
},
services: {
available: availableServices,
unavailable: unavailableServices
},
message: `Found ${availableServices.length} available service(s) and ${unavailableServices.length} unavailable service(s)`
}
};
} catch (error) {
if (error instanceof SFExpressError) {
return {
success: false,
error: {
code: error.errorCode || 'SERVICE_INQUIRY_ERROR',
message: error.message,
details: error.details
}
};
}
// Handle Zod validation errors
if (error.name === 'ZodError') {
return {
success: false,
error: {
code: 'VALIDATION_ERROR',
message: 'Invalid input parameters',
details: error.errors
}
};
}
return {
success: false,
error: {
code: 'UNKNOWN_ERROR',
message: 'An unexpected error occurred during service inquiry',
details: error instanceof Error ? error.message : 'Unknown error'
}
};
}
}
/**
* Parse transit time string and extract business days if possible
*/
function parseTransitTime(transitTime?: string): number | null {
if (!transitTime) return null;
// Try to extract number of days from transit time string
const dayMatch = transitTime.match(/(\d+).*天|(\d+).*day/i);
if (dayMatch) {
return parseInt(dayMatch[1] || dayMatch[2]);
}
// Try to extract hours and convert to days
const hourMatch = transitTime.match(/(\d+).*小时|(\d+).*hour/i);
if (hourMatch) {
const hours = parseInt(hourMatch[1] || hourMatch[2]);
return Math.ceil(hours / 24);
}
return null;
}