Skip to main content
Glama
dumyCq

Jinko Hotel Booking MCP Server

by dumyCq
utils.ts5.2 kB
/** * Utility functions for the hotel MCP server */ import fs from "fs"; import yaml from "js-yaml"; import { API_BASE_URL, FACILITIES_PATH, MAX_QUOTE_POLL_ATTEMPTS, QUOTE_POLL_INTERVAL_MS } from "./config.js"; import { session } from "./state.js"; import { getLogger, getMetrics } from "../telemetry/index.js"; /** * Load facilities data from JSON file * @returns Array of facility objects */ export function loadFacilitiesData(): any[] { try { if (fs.existsSync(FACILITIES_PATH)) { const data = fs.readFileSync(FACILITIES_PATH, "utf-8"); return JSON.parse(data); } else { console.warn("facilities.json not found at:", FACILITIES_PATH); } } catch (error) { console.error("Error loading facilities data:", error); } return []; // Return empty array on error or if file not found } /** * Make API request to the travel BFF API * @param endpoint API endpoint path * @param method HTTP method * @param body Request body (optional) * @returns Response data or null on error */ export async function makeApiRequest<T>( endpoint: string, method: string = "GET", body?: any ): Promise<T | null> { const url = `${API_BASE_URL}${endpoint}`; const logger = getLogger(); const metrics = getMetrics(); const startTime = Date.now(); const headers: Record<string, string> = { "Content-Type": "application/json", Accept: "application/json", }; // Add context information to headers if available in session if (session.conversation_id) { headers["X-Conversation-ID"] = session.conversation_id; } if (session.market) { headers["X-Market"] = session.market; } if (session.language) { headers["X-Language"] = session.language; } if (session.currency) { headers["X-Currency"] = session.currency; } if (session.country_code) { headers["X-Country-Code"] = session.country_code; } await logger.logApiCall(endpoint, method); try { const options: RequestInit = { method, headers, }; if (body) { options.body = JSON.stringify(body); } const response = await fetch(url, options); const duration = (Date.now() - startTime) / 1000; if (!response.ok) { // Record API metrics await metrics.recordApiCall(endpoint, method, duration * 1000, 'error'); // Convert to ms await logger.logApiResult(endpoint, method, duration, response.status, `API call failed: ${response.status}`); throw new Error(`HTTP error! status: ${response.status}`); } const result = (await response.json()) as T; // Record successful API metrics await metrics.recordApiCall(endpoint, method, duration * 1000, 'success'); // Convert to ms await logger.logApiResult(endpoint, method, duration, response.status); return result; } catch (error) { const duration = (Date.now() - startTime) / 1000; // Record error API metrics await metrics.recordApiCall(endpoint, method, duration * 1000, 'error'); // Convert to ms await logger.logApiResult(endpoint, method, duration, 0, `API call error: ${(error as Error).message}`); await logger.logError(error as Error, { endpoint, method }); return null; } } /** * Create a YAML response for MCP tools * @param data Object to convert to YAML * @returns MCP response object with YAML content */ export function createYamlResponse(data: any): { [x: string]: unknown; content: { type: "text"; text: string; }[] } { const yamlString = yaml.dump(data, { indent: 2, lineWidth: -1, // Don't wrap lines noRefs: true, // Don't use references }); return { content: [ { type: "text" as const, text: yamlString, }, ], }; } /** * Create a JSON response for MCP tools * @param data Object to include in JSON * @returns MCP response object with JSON content */ export function createJsonResponse(data: any): { [x: string]: unknown; content: { type: "text"; text: string; }[] } { const jsonString = JSON.stringify(data, null); return { content: [ { type: "text" as const, text: jsonString, }, ], }; } /** * Poll for quote status until it's ready or times out * @param quoteId ID of the quote to poll for * @returns Quote result or null if still processing */ export async function pollForQuoteStatus(quoteId: string): Promise<any | null> { let quoteStatus = "processing"; let quoteResult = null; let attempts = 0; while (quoteStatus === "processing" && attempts < MAX_QUOTE_POLL_ATTEMPTS) { attempts++; // Wait before polling again await new Promise(resolve => setTimeout(resolve, QUOTE_POLL_INTERVAL_MS)); // Poll quote status const pullResponse = await makeApiRequest<any>( `/api/v1/booking/quote/pull/${quoteId}`, "GET" ); if (!pullResponse) { continue; } quoteStatus = pullResponse.status; if (quoteStatus === "success") { quoteResult = pullResponse.quote; break; } else if (quoteStatus === "failed") { throw new Error(`Quote generation failed: ${pullResponse.error || "Unknown error"}`); } } return quoteResult; }

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/dumyCq/jinko-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server