Skip to main content
Glama

RS.ge Waybill MCP Server

xml-parser.tsโ€ข5.08 kB
/** * XML Parsing Utilities * * Uses fast-xml-parser for reliable XML parsing * * ๐ŸŽ“ TEACHING: Why fast-xml-parser? * - โœ… Correctly handles XML arrays (no phantom elements!) * - โœ… Preserves XML structure accurately * - โœ… Fast and memory-efficient * - โœ… Configurable parsing options * * โš ๏ธ CRITICAL: Unlike Jackson XmlMapper, this parser: * - Returns correct array sizes * - Doesn't create phantom entries * - Handles nested structures properly */ import { XMLParser, XMLBuilder } from 'fast-xml-parser'; /** * XML Parser configuration */ const parserOptions = { ignoreAttributes: false, // Keep XML attributes attributeNamePrefix: '@_', // Prefix for attributes textNodeName: '#text', // Name for text content ignoreDeclaration: true, // Ignore <?xml?> declaration removeNSPrefix: false, // Keep namespace prefixes parseAttributeValue: true, // Parse attribute values parseTagValue: true, // Parse tag values trimValues: true, // Trim whitespace cdataPropName: '__cdata', // CDATA property name numberParseOptions: { leadingZeros: false, hex: false, eNotation: false, }, }; /** * XML Builder configuration */ const builderOptions = { ignoreAttributes: false, attributeNamePrefix: '@_', textNodeName: '#text', format: false, // Don't format output (compact) suppressEmptyNode: false, // Keep empty nodes }; /** * Create XML parser instance */ export const xmlParser = new XMLParser(parserOptions); /** * Create XML builder instance */ export const xmlBuilder = new XMLBuilder(builderOptions); /** * Parse SOAP XML response * * Extracts the SOAP Body content and returns parsed object * * @param xmlString Raw SOAP XML response * @returns Parsed response object */ export function parseSoapResponse<T = any>(xmlString: string): T { const parsed = xmlParser.parse(xmlString); // Navigate SOAP structure: Envelope > Body > [Method]Response const envelope = parsed['soap:Envelope'] || parsed['soapenv:Envelope'] || parsed.Envelope; if (!envelope) { throw new Error('Invalid SOAP response: Missing Envelope'); } const body = envelope['soap:Body'] || envelope['soapenv:Body'] || envelope.Body; if (!body) { throw new Error('Invalid SOAP response: Missing Body'); } // Check for SOAP Fault const fault = body['soap:Fault'] || body['soapenv:Fault'] || body.Fault; if (fault) { const faultString = fault.faultstring || fault.message || 'Unknown SOAP fault'; throw new Error(`SOAP Fault: ${faultString}`); } // Return the response content (first non-fault element in Body) const keys = Object.keys(body).filter(k => !k.includes('Fault')); if (keys.length === 0) { throw new Error('Invalid SOAP response: Empty body'); } // Get the method response (e.g., get_waybillsResponse) const methodResponse = body[keys[0]]; // Some responses have a nested result element // e.g., get_waybillsResponse > get_waybillsResult if (methodResponse && typeof methodResponse === 'object') { // Filter out XML attributes (keys starting with @_) const resultKeys = Object.keys(methodResponse).filter(k => !k.startsWith('@_')); // Check if there's a Result element const resultKey = resultKeys.find(k => k.endsWith('Result')); if (resultKey) { const result = methodResponse[resultKey]; // Check for RS.ge API error format: <RESULT><STATUS>-1072</STATUS></RESULT> if (result && typeof result === 'object' && 'RESULT' in result) { const rsResult = (result as any).RESULT; if (rsResult && rsResult.STATUS && Number(rsResult.STATUS) < 0) { const errorCode = rsResult.STATUS; throw new Error( `RS.ge API Error ${errorCode}. ` + `Please check error code documentation or use a valid date range (max 3 days).` ); } } return result as T; } } return methodResponse as T; } /** * Build SOAP XML request * * @param method SOAP method name (e.g., 'get_waybills') * @param params Method parameters * @param namespace SOAP namespace URI * @returns SOAP XML string */ export function buildSoapRequest( method: string, params: Record<string, any>, namespace: string = 'http://tempuri.org/' ): string { const soapEnvelope = { 'soap:Envelope': { '@_xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', '@_xmlns:xsd': 'http://www.w3.org/2001/XMLSchema', '@_xmlns:soap': 'http://schemas.xmlsoap.org/soap/envelope/', 'soap:Body': { [method]: { '@_xmlns': namespace, ...params, }, }, }, }; const xml = xmlBuilder.build(soapEnvelope); // Add XML declaration return `<?xml version="1.0" encoding="utf-8"?>${xml}`; } /** * Build nested XML structure for save_waybill * * Special handling for complex nested structures */ export function buildWaybillXml(waybill: any): string { return xmlBuilder.build({ WAYBILL: waybill }); }

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/BorisSolomonia/MCPWaybill'

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