Skip to main content
Glama
api.ts•7.48 kB
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'; import { EGWAuthManager } from './auth.js'; export interface Language { code: string; name: string; direction: string; } export interface Folder { folder_id: number; name: string; add_class: string; nbooks: number; naudiobooks: number; sort: number; children?: Folder[]; } export interface Book { book_id: number; code: string; lang: string; type: string; subtype: string; title: string; first_para: string; author: string; description: string; npages: number; isbn?: string; publisher: string; pub_year: string; buy_link?: string; folder_id: number; folder_color_group: string; cover: { small: string; large: string; }; files: { mp3?: string; pdf: string; epub: string; mobi: string; }; download: string; last_modified: string; permission_required: string; sort: number; is_audiobook: boolean; cite: string; original_book?: string; translated_into: string[]; nelements: number; } export interface Chapter { id: number; title: string; bookId: number; order: number; paragraphCount: number; } export interface Paragraph { para_id: string; id_prev?: string; id_next?: string; refcode_1: string; refcode_2: string; refcode_3: string; refcode_4: string; refcode_short: string; refcode_long: string; element_type: string; element_subtype: string; content: string; puborder: number; translations: any[]; } export interface SearchHit { index: number; lang: string; para_id: string; pub_code: string; pub_name: string; refcode_long: string; refcode_short: string; pub_year: string; snippet: string; weight: number; group: string; } export interface SearchResult { next: string | null; previous: string | null; total: number; count: number; results: SearchHit[]; } export class EGWApiClient { private client: AxiosInstance; private authManager: EGWAuthManager; private baseUrl: string; constructor(authManager: EGWAuthManager, baseUrl = 'https://a.egwwritings.org') { this.authManager = authManager; this.baseUrl = baseUrl; this.client = axios.create({ baseURL: baseUrl, timeout: 30000, headers: { 'User-Agent': 'EGW-Research-Tool/1.0.0', 'Content-Type': 'application/json' } }); // Add request interceptor to include auth token this.client.interceptors.request.use(async (config) => { try { const token = await this.authManager.getValidToken(); config.headers.Authorization = `Bearer ${token}`; } catch (error) { console.warn('No valid auth token available:', error); } return config; }); // Add response interceptor for error handling this.client.interceptors.response.use( (response) => response, (error) => { if (error.response?.status === 401) { console.error('Authentication failed. Please re-authenticate.'); } return Promise.reject(error); } ); } /** * Add delay between requests to be respectful */ private async delay(ms: number = 1000): Promise<void> { return new Promise(resolve => setTimeout(resolve, ms)); } /** * Get available languages */ async getLanguages(): Promise<Language[]> { const response = await this.client.get('/content/languages'); await this.delay(); return response.data; } /** * Get folders for a language */ async getFolders(languageCode: string): Promise<Folder[]> { const response = await this.client.get(`/content/languages/${languageCode}/folders`); await this.delay(); return response.data; } /** * Get books in a folder */ async getBooksByFolder(folderId: number): Promise<Book[]> { const response = await this.client.get(`/content/books/by_folder/${folderId}`); await this.delay(); return response.data; } /** * Get book information */ async getBook(bookId: number): Promise<Book> { const response = await this.client.get(`/content/books/${bookId}`); await this.delay(); return response.data; } /** * Get book table of contents */ async getBookToc(bookId: number): Promise<Chapter[]> { const response = await this.client.get(`/content/books/${bookId}/toc`); await this.delay(); return response.data; } /** * Get chapter content */ async getChapter(bookId: number, chapterId: number): Promise<Paragraph[]> { const response = await this.client.get(`/content/books/${bookId}/chapter/${chapterId}`); await this.delay(); return response.data; } /** * Get specific paragraph */ async getParagraph(bookId: number, paragraphId: string): Promise<Paragraph> { const response = await this.client.get(`/content/books/${bookId}/content/${paragraphId}`); await this.delay(); return response.data; } /** * Search content (using Android app parameters) */ async search(query: string, options?: { lang?: string[]; folder?: number[]; pubnr?: number[]; limit?: number; offset?: number; highlight?: string; trans?: string; }): Promise<SearchResult> { const params = new URLSearchParams({ query: query, ...(options?.lang && { lang: options.lang.join(',') }), ...(options?.folder && { folder: options.folder.join(',') }), ...(options?.pubnr && { pubnr: options.pubnr.join(',') }), ...(options?.limit && { limit: options.limit.toString() }), ...(options?.offset && { offset: options.offset.toString() }), ...(options?.highlight && { highlight: options.highlight }), ...(options?.trans && { trans: options.trans }) }); const response = await this.client.get(`/search?${params.toString()}`); await this.delay(); return response.data; } /** * Get search suggestions (using Android app parameters) */ async getSearchSuggestions(query: string): Promise<string[]> { const response = await this.client.get(`/search/suggestions?query=${encodeURIComponent(query)}`); await this.delay(); return response.data; } /** * Download book as ZIP */ async downloadBook(bookId: number): Promise<Buffer> { const response = await this.client.get(`/content/books/${bookId}/download`, { responseType: 'arraybuffer' }); await this.delay(2000); // Longer delay for downloads return Buffer.from(response.data); } /** * Get user information */ async getUserInfo(): Promise<any> { const response = await this.client.get('/user/info/'); await this.delay(); return response.data; } /** * Test API connectivity and authentication */ async testConnection(): Promise<boolean> { try { await this.getUserInfo(); return true; } catch (error) { console.error('API connection test failed:', error); return false; } } /** * Get API status and basic info */ async getApiStatus(): Promise<any> { try { // Try a simple endpoint that might not require auth const response = await this.client.get('/content/mirrors'); return { status: 'connected', data: response.data }; } catch (error) { return { status: 'error', error: error }; } } } // Create default API client export const createApiClient = (authManager: EGWAuthManager): EGWApiClient => { return new EGWApiClient(authManager); };

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/pythondev-pro/egw_writings_mcp_server'

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