Skip to main content
Glama
joelmnz

Article Manager MCP Server

by joelmnz
apiClient.ts5.54 kB
/** * Runtime configuration interface */ interface RuntimeConfig { baseUrl: string; apiBaseUrl: string; mcpBaseUrl: string; } /** * API client configuration */ interface ApiClientConfig { baseUrl: string; defaultHeaders?: Record<string, string>; } /** * API client with runtime base path support * * This client: * 1. Dynamically constructs URLs using runtime configuration * 2. Supports reconfiguration when runtime config changes * 3. Automatically prepends base path to all endpoints * 4. Provides a centralized interface for all API calls * * MIGRATION GUIDE: * * Before (direct fetch): * ```typescript * const response = await fetch('/api/articles', { * headers: { 'Authorization': `Bearer ${token}` } * }); * ``` * * After (using API client): * ```typescript * import { getConfiguredApiClient } from '../utils/apiClient'; * const apiClient = getConfiguredApiClient(); * const response = await apiClient.get('/api/articles', token); * ``` * * Or using the singleton: * ```typescript * import { apiClient } from '../utils/apiClient'; * const response = await apiClient.get('/api/articles', token); * ``` */ class ApiClient { private config: ApiClientConfig; constructor(config?: ApiClientConfig) { this.config = config || this.getDefaultConfig(); } /** * Get default configuration from runtime environment */ private getDefaultConfig(): ApiClientConfig { const runtimeConfig = (window as any).__APP_CONFIG__ as RuntimeConfig; return { baseUrl: runtimeConfig?.apiBaseUrl || '', defaultHeaders: { 'Content-Type': 'application/json' } }; } /** * Configure the API client with new settings */ configure(config: ApiClientConfig): void { this.config = { ...this.config, ...config }; } /** * Build a full URL for an API endpoint */ private buildUrl(endpoint: string): string { // Normalize endpoint to ensure it starts with / const normalizedEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`; // If base URL is empty (root deployment), return endpoint as-is if (!this.config.baseUrl) { return normalizedEndpoint; } // Combine base URL with endpoint, avoiding double slashes return `${this.config.baseUrl}${normalizedEndpoint}`; } /** * Prepare headers for a request */ private prepareHeaders(token?: string, additionalHeaders?: Record<string, string>): Record<string, string> { const headers = { ...this.config.defaultHeaders }; if (token) { headers['Authorization'] = `Bearer ${token}`; } if (additionalHeaders) { Object.assign(headers, additionalHeaders); } return headers; } /** * Make a GET request */ async get(endpoint: string, token?: string, additionalHeaders?: Record<string, string>): Promise<Response> { const url = this.buildUrl(endpoint); const headers = this.prepareHeaders(token, additionalHeaders); return fetch(url, { method: 'GET', headers }); } /** * Make a POST request */ async post(endpoint: string, data?: any, token?: string, additionalHeaders?: Record<string, string>): Promise<Response> { const url = this.buildUrl(endpoint); const headers = this.prepareHeaders(token, additionalHeaders); return fetch(url, { method: 'POST', headers, body: data ? JSON.stringify(data) : undefined }); } /** * Make a PUT request */ async put(endpoint: string, data?: any, token?: string, additionalHeaders?: Record<string, string>): Promise<Response> { const url = this.buildUrl(endpoint); const headers = this.prepareHeaders(token, additionalHeaders); return fetch(url, { method: 'PUT', headers, body: data ? JSON.stringify(data) : undefined }); } /** * Make a DELETE request */ async delete(endpoint: string, token?: string, additionalHeaders?: Record<string, string>): Promise<Response> { const url = this.buildUrl(endpoint); const headers = this.prepareHeaders(token, additionalHeaders); return fetch(url, { method: 'DELETE', headers }); } /** * Make a request with custom method and options */ async request(endpoint: string, options: RequestInit & { token?: string }): Promise<Response> { const url = this.buildUrl(endpoint); const { token, ...fetchOptions } = options; // Merge headers const headers = this.prepareHeaders(token, fetchOptions.headers as Record<string, string>); return fetch(url, { ...fetchOptions, headers }); } /** * Get the current base URL configuration */ getBaseUrl(): string { return this.config.baseUrl; } } // Create and export a singleton instance export const apiClient = new ApiClient(); // Export the class for custom instances if needed export { ApiClient }; /** * Utility function to reconfigure the API client with runtime config */ export function configureApiClient(runtimeConfig: RuntimeConfig): void { apiClient.configure({ baseUrl: runtimeConfig.apiBaseUrl, defaultHeaders: { 'Content-Type': 'application/json' } }); } /** * Utility function to get API client configured for current runtime */ export function getConfiguredApiClient(): ApiClient { const runtimeConfig = (window as any).__APP_CONFIG__ as RuntimeConfig; if (runtimeConfig) { configureApiClient(runtimeConfig); } return apiClient; }

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/joelmnz/mcp-markdown-manager'

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