UNPKG

paper-search-mcp-nodejs

Version:

A Node.js MCP server for searching and downloading academic papers from multiple sources, including arXiv, PubMed, bioRxiv, Web of Science, and more.

545 lines (435 loc) β€’ 18.4 kB
# AIPaper-assisant - Architecture & Design Patterns ## πŸ—οΈ System Architecture Overview ### High-Level Architecture ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Claude Desktop (MCP Client) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ MCP Protocol (JSON-RPC over stdio) β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ MCP Server Core Layer β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ server.ts β”‚ β”‚ β”‚ β”‚ β€’ Tool registration & lifecycle β”‚ β”‚ β”‚ β”‚ β€’ Request routing & validation β”‚ β”‚ β”‚ β”‚ β€’ Error handling & logging β”‚ β”‚ β”‚ β”‚ β€’ MCP protocol compliance β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Business Logic Layer β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Tool Layer β”‚ Service Layer β”‚ Data Layer β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β€’ search_papers β”‚ β€’ RateLimiter β”‚ β€’ Paper (model) β”‚ β”‚ β”‚ β”‚ β€’ download_paperβ”‚ β€’ ErrorHandler β”‚ β€’ PaperFactory β”‚ β”‚ β”‚ β”‚ β€’ get_status β”‚ β€’ Validator β”‚ β€’ SearchOptions β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Platform Abstraction Layer β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ β”‚ PaperSource (Abstract) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β€’ Common interface definition β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β€’ HTTP client configuration β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β€’ Error handling patterns β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β€’ Rate limiting integration β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ArxivSearcher β”‚ β”‚WebOfScienceSearcherβ”‚ β”‚CrossrefSearcher β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚β€’ arXiv API β”‚ β”‚β€’ WoS API β”‚ β”‚β€’ Crossref API β”‚ β”‚ β”‚ β”‚ β”‚β€’ PDF download β”‚ β”‚β€’ Multi-topic β”‚ β”‚β€’ DOI metadata β”‚ β”‚ β”‚ β”‚ β”‚β€’ Categories β”‚ β”‚β€’ Citations β”‚ β”‚β€’ Fallback β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚SciHubSearcher β”‚ β”‚SpringerSearcher β”‚ β”‚ScopusSearcher β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚β€’ Mirror mgmt β”‚ β”‚β€’ Dual API β”‚ β”‚β€’ Elsevier DB β”‚ β”‚ β”‚ β”‚ β”‚β€’ DOI-based β”‚ β”‚β€’ OpenAccess β”‚ β”‚β€’ Citations β”‚ β”‚ β”‚ β”‚ β”‚β€’ Health check β”‚ β”‚β€’ Metadata β”‚ β”‚β€’ Analytics β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ External APIs & Services β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ arXiv β”‚ β”‚ WoS β”‚ β”‚ Crossref β”‚ β”‚ Springer β”‚ β”‚ β”‚ β”‚ API β”‚ β”‚ API β”‚ β”‚ API β”‚ β”‚ API β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ SciHub β”‚ β”‚ Scopus β”‚ β”‚ Wiley β”‚ β”‚ ScienceDirect β”‚ β”‚ β”‚ β”‚ Mirrors β”‚ β”‚ API β”‚ β”‚ TDM API β”‚ β”‚ API β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### Key Architectural Principles #### 1. Separation of Concerns - **MCP Layer**: Pure protocol handling - **Business Logic**: Tool implementations - **Platform Layer**: External API integrations - **Data Layer**: Models and transformations #### 2. Dependency Inversion - Abstract `PaperSource` base class - Platform implementations depend on abstractions - Easy to add new platforms without modifying core #### 3. Interface Segregation - Each platform implements only needed capabilities - Capability system for feature discovery - No forced implementation of unused methods ## 🎯 Design Patterns ### 1. Abstract Factory Pattern **Implementation**: `PaperFactory` in `models/Paper.ts` ```typescript class PaperFactory { static create(data: RawPaperData): Paper { // Validates and transforms raw data into consistent Paper object return { title: this.sanitizeTitle(data.title), authors: this.normalizeAuthors(data.authors), doi: this.validateDoi(data.doi), // ... standardized fields }; } } ``` **Benefits**: - Consistent data format across platforms - Centralized validation logic - Easy to extend with new fields ### 2. Template Method Pattern **Implementation**: `PaperSource` abstract class ```typescript abstract class PaperSource { // Template method defining search algorithm async search(query: string, options?: SearchOptions): Promise<Paper[]> { await this.validateQuery(query); await this.rateLimiter.acquire(); try { const rawResults = await this.performSearch(query, options); return this.transformResults(rawResults); } catch (error) { return this.handleSearchError(error); } } // Abstract methods for subclasses protected abstract performSearch(query: string, options?: SearchOptions): Promise<any>; protected abstract transformResults(data: any): Promise<Paper[]>; } ``` **Benefits**: - Common behavior in base class - Platform-specific logic in subclasses - Consistent error handling ### 3. Strategy Pattern **Implementation**: Platform selection in `server.ts` ```typescript class SearchStrategy { private platforms: Map<string, PaperSource> = new Map(); constructor() { this.platforms.set('arxiv', new ArxivSearcher()); this.platforms.set('crossref', new CrossrefSearcher()); // ... other platforms } async search(platform: string, query: string): Promise<Paper[]> { const searcher = this.platforms.get(platform); if (!searcher) throw new Error('Unknown platform'); return searcher.search(query); } } ``` **Benefits**: - Runtime platform selection - Easy to add new strategies - Clean separation of algorithms ### 4. Decorator Pattern **Implementation**: Capability enhancement in platforms ```typescript // Base capability interface PlatformCapabilities { search: boolean; download: boolean; citations: boolean; } // Enhanced with features class EnhancedPlatform extends BasePlatform { getCapabilities(): PlatformCapabilities { return { ...super.getCapabilities(), advancedFilters: true, batchSearch: true, exportFormats: ['bibtex', 'ris'] }; } } ``` ### 5. Observer Pattern **Implementation**: Event-driven status updates ```typescript class PlatformStatusMonitor { private observers: StatusObserver[] = []; subscribe(observer: StatusObserver) { this.observers.push(observer); } notifyStatusChange(platform: string, status: PlatformStatus) { this.observers.forEach(observer => { observer.onStatusChange(platform, status); }); } } ``` ### 6. Singleton Pattern **Implementation**: Rate limiter instances ```typescript class RateLimiterFactory { private static instances: Map<string, RateLimiter> = new Map(); static getLimiter(platform: string): RateLimiter { if (!this.instances.has(platform)) { this.instances.set(platform, new RateLimiter(platform)); } return this.instances.get(platform)!; } } ``` ## πŸ”§ Advanced Patterns ### 1. Circuit Breaker Pattern **Implementation**: Platform health monitoring ```typescript class CircuitBreaker { private failures = 0; private lastFailureTime = 0; private state: 'CLOSED' | 'OPEN' | 'HALF_OPEN' = 'CLOSED'; async execute<T>(operation: () => Promise<T>): Promise<T> { if (this.state === 'OPEN') { if (Date.now() - this.lastFailureTime > this.timeout) { this.state = 'HALF_OPEN'; } else { throw new Error('Circuit breaker is OPEN'); } } try { const result = await operation(); this.onSuccess(); return result; } catch (error) { this.onFailure(); throw error; } } } ``` ### 2. Retry Pattern **Implementation**: Exponential backoff ```typescript class RetryPolicy { async execute<T>( operation: () => Promise<T>, options: RetryOptions ): Promise<T> { let lastError: Error; for (let attempt = 0; attempt < options.maxAttempts; attempt++) { try { return await operation(); } catch (error) { lastError = error as Error; if (attempt < options.maxAttempts - 1) { const delay = Math.min( options.baseDelay * Math.pow(2, attempt), options.maxDelay ); await this.sleep(delay); } } } throw lastError!; } } ``` ### 3. Polymorphic Serialization **Implementation**: Platform-specific data handling ```typescript abstract class ResultSerializer { abstract serialize(data: any): string; abstract deserialize(data: string): any; } class JsonSerializer extends ResultSerializer { serialize(data: any): string { return JSON.stringify(data); } deserialize(data: string): any { return JSON.parse(data); } } class XmlSerializer extends ResultSerializer { serialize(data: any): string { // XML-specific serialization } } ``` ## πŸ”„ Behavioral Patterns ### 1. Command Pattern **Implementation**: Tool execution in MCP ```typescript interface Command { execute(): Promise<any>; undo(): Promise<void>; } class SearchCommand implements Command { constructor( private searcher: PaperSource, private query: string ) {} async execute(): Promise<Paper[]> { return this.searcher.search(this.query); } async undo(): Promise<void> { // Log search for audit trail } } ``` ### 2. Chain of Responsibility **Implementation**: Fallback mechanism ```typescript abstract class SearchHandler { private nextHandler: SearchHandler | null = null; setNext(handler: SearchHandler): SearchHandler { this.nextHandler = handler; return handler; } async handle(query: string): Promise<Paper[]> { try { return await this.search(query); } catch (error) { if (this.nextHandler) { return this.nextHandler.handle(query); } throw error; } } protected abstract search(query: string): Promise<Paper[]>; } // Usage: Crossref -> arXiv -> Google Scholar ``` ## 🎯 Architectural Decisions ### 1. Platform Abstraction **Decision**: Abstract base class vs Interface **Choice**: Abstract class with Template Method **Reasons**: - Common behavior can be shared - Template method enforces algorithm structure - Protected methods allow customization - Easier to add new platforms ### 2. Error Handling Strategy **Decision**: Typed errors vs Generic errors **Choice**: Platform-specific error types **Reasons**: - Better error handling and recovery - Platform-specific retry logic - Clear error categorization - Enhanced debugging capabilities ### 3. Rate Limiting Approach **Decision**: Centralized vs Distributed **Choice**: Centralized with per-platform configuration **Reasons**: - Consistent rate limiting behavior - Easy to monitor and adjust - Single point of control - Platform-specific optimization ### 4. Data Modeling **Decision**: Single unified model vs Platform-specific models **Choice**: Unified model with factory pattern **Reasons**: - Consistent API for clients - Easier to maintain and extend - Clear data transformation logic - Type safety across platforms ## πŸ” Anti-Patterns Avoided ### 1. God Object - Each class has single responsibility - Platform logic separated from core - Clear boundaries between layers ### 2. Spaghetti Code - Clear module structure - Dependency injection - Interface-based programming ### 3. Magic Numbers - Configuration objects - Named constants - Environment-based settings ### 4. Hard Coding - Platform URLs in config - Rate limits as parameters - Feature flags for capabilities ## πŸš€ Scalability Patterns ### 1. Horizontal Scaling - Stateless design - Platform isolation - No shared state between requests ### 2. Caching Strategy - Platform capability caching - Mirror health status - Configurable TTL ### 3. Load Balancing - Round-robin for mirrors - Health check integration - Automatic failover ### 4. Resource Pooling - HTTP connection reuse - Rate limiter pool - Memory efficient streaming ## πŸ“Š Performance Patterns ### 1. Lazy Loading - Platform initialization on demand - Configuration loading - Resource allocation ### 2. Batch Operations - Bulk search optimization - Parallel downloads - Concurrent API calls ### 3. Streaming - Large result sets - Memory efficiency - Real-time updates ### 4. Indexing - In-memory indexes - Cache keys optimization - Quick lookups ## πŸ” Security Patterns ### 1. Defense in Depth - Input validation - Output sanitization - API key protection ### 2. Principle of Least Privilege - Minimal required permissions - Scope-based access - Platform isolation ### 3. Secure Defaults - Rate limiting enabled - Error sanitization - Timeout configurations ### 4. Audit Trail - Request logging - Error tracking - Performance monitoring ## πŸ§ͺ Testing Patterns ### 1. Test Pyramid - Unit tests (80%) - Integration tests (15%) - E2E tests (5%) ### 2. Mock Strategies - Interface-based mocking - Platform simulators - Network stubbing ### 3. Test Data Management - Fixture factories - Platform-specific data - Edge case coverage ### 4. Continuous Testing - Pre-commit hooks - CI/CD integration - Performance benchmarks --- *This architecture documentation serves as a comprehensive guide to the design patterns and architectural decisions in AIPaper-assisant. It provides a foundation for understanding the system's structure and making informed decisions about future enhancements.*