Skip to main content
Glama
bulc-client.ts3.75 kB
// BULC Client - TCP Socket communication with Java application import * as net from "net"; import type { BulcCommand, BulcResult } from "./types.js"; const DEFAULT_PORT = 19840; const DEFAULT_HOST = "localhost"; const CONNECTION_TIMEOUT = 5000; const RESPONSE_TIMEOUT = 30000; export class BulcClient { private port: number; private host: string; constructor(port: number = DEFAULT_PORT, host: string = DEFAULT_HOST) { this.port = port; this.host = host; } async sendCommand(cmd: BulcCommand): Promise<BulcResult> { return new Promise((resolve, reject) => { const socket = new net.Socket(); let responseData = ""; let resolved = false; // Connection timeout const connectionTimer = setTimeout(() => { if (!resolved) { resolved = true; socket.destroy(); reject(new Error( `BULC 연결 실패: ${this.host}:${this.port}에 연결할 수 없습니다. ` + `BULC 애플리케이션이 실행 중인지 확인하세요.` )); } }, CONNECTION_TIMEOUT); // Response timeout let responseTimer: NodeJS.Timeout | null = null; socket.on("connect", () => { clearTimeout(connectionTimer); // Set response timeout after connection responseTimer = setTimeout(() => { if (!resolved) { resolved = true; socket.destroy(); reject(new Error("BULC 응답 타임아웃: 30초 내에 응답이 없습니다.")); } }, RESPONSE_TIMEOUT); // Send command as JSON line const json = JSON.stringify(cmd) + "\n"; socket.write(json); }); socket.on("data", (data) => { responseData += data.toString(); // Check for complete JSON response (ends with newline) if (responseData.includes("\n")) { if (responseTimer) clearTimeout(responseTimer); if (!resolved) { resolved = true; socket.end(); try { const lines = responseData.trim().split("\n"); const lastLine = lines[lines.length - 1]; const result = JSON.parse(lastLine) as BulcResult; resolve(result); } catch (e) { reject(new Error(`Invalid JSON response: ${responseData}`)); } } } }); socket.on("error", (err) => { clearTimeout(connectionTimer); if (responseTimer) clearTimeout(responseTimer); if (!resolved) { resolved = true; reject(new Error( `BULC 연결 에러: ${err.message}. ` + `BULC 애플리케이션이 실행 중인지 확인하세요.` )); } }); socket.on("close", () => { clearTimeout(connectionTimer); if (responseTimer) clearTimeout(responseTimer); if (!resolved) { resolved = true; reject(new Error("BULC 연결이 닫혔습니다.")); } }); // Connect socket.connect(this.port, this.host); }); } async isConnected(): Promise<boolean> { try { const result = await this.sendCommand({ action: "ping", params: {} }); return result.success === true; } catch { return false; } } } // Singleton instance let clientInstance: BulcClient | null = null; export function getBulcClient(): BulcClient { if (!clientInstance) { const port = process.env.BULC_PORT ? parseInt(process.env.BULC_PORT) : DEFAULT_PORT; clientInstance = new BulcClient(port); } return clientInstance; }

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/using76/BULC_MCP'

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