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
Markdown
# 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.*