Skip to main content
Glama

RS.ge Waybill MCP Server

index.tsโ€ข6.49 kB
#!/usr/bin/env node /** * RS.ge Waybill MCP Server * * Main entry point for the MCP server that connects Claude Desktop to RS.ge Waybill API * * ๐ŸŽ“ TEACHING: MCP Server Architecture * ==================================== * * This server: * 1. Loads configuration from config.json * 2. Initializes logging and error handling * 3. Creates SOAP client for RS.ge API * 4. Registers MCP tools that Claude can invoke * 5. Listens for tool calls from Claude Desktop via stdio * * Communication Flow: * Claude Desktop โ†” stdio โ†” This MCP Server โ†” SOAP โ†” RS.ge API */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { loadConfig, getCredentials, getLoggingConfig, getFeaturesConfig } from './config/config.js'; import { initLogger } from './utils/logger.js'; import { formatErrorForUser } from './utils/error-handler.js'; import { RsWaybillSoapClient } from './services/soap-client.js'; // Import tools import { getWaybillsTool, executeGetWaybills } from './tools/get-waybills.js'; import { lookupTinTool, executeLookupTin } from './tools/lookup-tin.js'; import { getWaybillTypesTool, executeGetWaybillTypes, getErrorCodesTool, executeGetErrorCodes, getAkcizCodesTool, executeGetAkcizCodes, } from './tools/get-dictionaries.js'; /** * Main function - Initialize and start MCP server */ async function main() { let logger: any; try { // Load configuration const config = loadConfig(); // Initialize logger const loggingConfig = getLoggingConfig(config); logger = initLogger(loggingConfig as any); logger.info('RS.ge Waybill MCP Server starting', { version: config.server.version, name: config.server.name, }); // Get credentials const credentials = getCredentials(config); logger.info('Credentials loaded', { user: credentials.user.substring(0, 10) + '...', }); // Get feature flags const features = getFeaturesConfig(config) || { getWaybills: true, saveWaybill: true, sendWaybill: true, closeWaybill: true, confirmWaybill: true, rejectWaybill: true, getErrorCodes: true, getAkcizCodes: true, getNameFromTin: true, }; // Create SOAP client const soapClient = new RsWaybillSoapClient(config.api, credentials); logger.info('SOAP client initialized'); // Verify credentials logger.info('Verifying credentials with RS.ge...'); const authResult = await soapClient.checkServiceUser(); if (!authResult) { throw new Error('Authentication failed. Please check your RS.ge credentials.'); } logger.info('โœ… Authentication successful'); // Create MCP server const server = new Server( { name: config.server.name, version: config.server.version, }, { capabilities: { tools: {}, }, } ); /** * Handle: List available tools */ server.setRequestHandler(ListToolsRequestSchema, async () => { const tools = []; // Add tools based on feature flags if (features.getWaybills) { tools.push(getWaybillsTool); } if (features.getNameFromTin) { tools.push(lookupTinTool); } if (features.getErrorCodes) { tools.push(getWaybillTypesTool); tools.push(getErrorCodesTool); } if (features.getAkcizCodes) { tools.push(getAkcizCodesTool); } logger.debug('Listed tools', { count: tools.length }); return { tools }; }); /** * Handle: Execute tool */ server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; logger.info('Tool called', { name, args }); try { let result: string; switch (name) { case 'get_waybills': if (!features.getWaybills) { throw new Error('get_waybills tool is disabled'); } result = await executeGetWaybills(soapClient, args); break; case 'lookup_tin': if (!features.getNameFromTin) { throw new Error('lookup_tin tool is disabled'); } result = await executeLookupTin(soapClient, args); break; case 'get_waybill_types': if (!features.getErrorCodes) { throw new Error('get_waybill_types tool is disabled'); } result = await executeGetWaybillTypes(soapClient); break; case 'get_error_codes': if (!features.getErrorCodes) { throw new Error('get_error_codes tool is disabled'); } result = await executeGetErrorCodes(soapClient); break; case 'get_akciz_codes': if (!features.getAkcizCodes) { throw new Error('get_akciz_codes tool is disabled'); } result = await executeGetAkcizCodes(soapClient, args); break; default: throw new Error(`Unknown tool: ${name}`); } logger.info('Tool executed successfully', { name }); return { content: [ { type: 'text', text: result, }, ], }; } catch (error) { logger.error('Tool execution failed', { name, error }); return { content: [ { type: 'text', text: formatErrorForUser(error), }, ], isError: true, }; } }); // Connect to stdio transport const transport = new StdioServerTransport(); await server.connect(transport); logger.info('โœ… MCP server started successfully on stdio'); const enabledTools = Object.entries(features) .filter(([_, v]) => v) .map(([k]) => k) .join(', '); logger.info(`Enabled tools: ${enabledTools}`); } catch (error) { if (logger) { logger.error('Fatal error during startup', { error }); } else { console.error('Fatal error during startup:', error); } process.exit(1); } } // Start the server main().catch((error) => { console.error('Unhandled error:', error); process.exit(1); });

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