Skip to main content
Glama
client.ts6.2 kB
/** * Luminork API Client * * A client for interacting with the Luminork API service. * Provides methods for authentication and interacting with various endpoints. */ // Default configuration values const DEFAULT_CONFIG = { baseUrl: 'http://localhost:5380', timeout: 30000, }; // Types for request/response handling export interface ApiClientConfig { baseUrl: string; timeout: number; authToken?: string; } export interface RequestOptions { method: string; headers?: Record<string, string>; body?: unknown; timeout?: number; } export interface ApiResponse<T> { status: number; statusText: string; data: T; headers: Headers; } export class ApiError extends Error { status: number; statusText: string; data: unknown; constructor( message: string, status: number, statusText: string, data: unknown, ) { super(message); this.name = 'ApiError'; this.status = status; this.statusText = statusText; this.data = data; } } export class ConfigError extends Error { constructor(message: string) { super(message); this.name = 'ConfigError'; } } /** * LuminorkClient provides a simple client for interacting with the Luminork API */ export class LuminorkClient { private config: ApiClientConfig; constructor(config: Partial<ApiClientConfig> = {}) { this.config = { ...DEFAULT_CONFIG, ...config }; } /** * Set the authentication token for API requests */ setAuthToken(token: string): void { this.config.authToken = token; } /** * Update client configuration */ updateConfig(config: Partial<ApiClientConfig>): void { this.config = { ...this.config, ...config }; } /** * Get the base URL */ getBaseUrl(): string { return this.config.baseUrl; } /** * Perform a request to the API */ async request<T = unknown>( path: string, options: RequestOptions, ): Promise<ApiResponse<T>> { const url = new URL(path, this.config.baseUrl); const headers: Record<string, string> = { 'Content-Type': 'application/json', Accept: 'application/json', ...options.headers, }; // Add auth token if available if (this.config.authToken) { headers['Authorization'] = `Bearer ${this.config.authToken}`; } // Prepare request options const requestInit: RequestInit = { method: options.method, headers, }; // Add body for non-GET requests if (options.method !== 'GET' && options.body) { requestInit.body = JSON.stringify(options.body); } // Handle timeout const timeout = options.timeout || this.config.timeout; try { // Create abort controller for timeout handling const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeout); requestInit.signal = controller.signal; const response = await fetch(url.toString(), requestInit); clearTimeout(timeoutId); // Parse response let data: T; const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { data = (await response.json()) as T; } else { data = (await response.text()) as unknown as T; } if (!response.ok) { throw new ApiError( `API request failed: ${response.status} ${response.statusText}`, response.status, response.statusText, data, ); } return { status: response.status, statusText: response.statusText, data, headers: response.headers, }; } catch (error) { if (error instanceof ApiError) { throw error; } if (error instanceof DOMException && error.name === 'AbortError') { throw new ApiError( `Request timeout after ${timeout}ms`, 408, 'Request Timeout', { error: 'timeout' }, ); } throw new ApiError( `API request failed: ${error instanceof Error ? error.message : String(error)}`, 500, 'Internal Error', { error: String(error) }, ); } } /** * GET request helper */ async get<T = unknown>( path: string, options: Omit<RequestOptions, 'method' | 'body'> = {}, ): Promise<ApiResponse<T>> { return this.request<T>(path, { ...options, method: 'GET' }); } /** * POST request helper */ async post<T = unknown>( path: string, body: unknown = undefined, options: Omit<RequestOptions, 'method' | 'body'> = {}, ): Promise<ApiResponse<T>> { return this.request<T>(path, { ...options, method: 'POST', body }); } /** * PUT request helper */ async put<T = unknown>( path: string, body: unknown = undefined, options: Omit<RequestOptions, 'method' | 'body'> = {}, ): Promise<ApiResponse<T>> { return this.request<T>(path, { ...options, method: 'PUT', body }); } /** * DELETE request helper */ async delete<T = unknown>( path: string, options: Omit<RequestOptions, 'method' | 'body'> = {}, ): Promise<ApiResponse<T>> { return this.request<T>(path, { ...options, method: 'DELETE' }); } /** * Check system status */ async getSystemStatus(): Promise< ApiResponse<{ 'What is this?': string; 'API Documentation': string }> > { return this.get<{ 'What is this?': string; 'API Documentation': string }>('/'); } /** * Get current user information */ async whoami(): Promise< ApiResponse<{ userId: string; userEmail: string; workspaceId: string; token: { iat: number; exp: number; sub: string; jti: string; version: string; userId: string; workspaceId: string; role: string; }; }> > { return this.get<{ userId: string; userEmail: string; workspaceId: string; token: { iat: number; exp: number; sub: string; jti: string; version: string; userId: string; workspaceId: string; role: string; }; }>('/whoami'); } }

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/systeminit/si'

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