Skip to main content
Glama

WebDAV MCP Server

by LaubPlusCo
webdav-connection-pool.ts5.79 kB
import { createClient, WebDAVClient, AuthType } from 'webdav'; import { createLogger } from '../utils/logger.js'; const logger = createLogger('WebDAVConnectionPool'); interface WebDAVConnectionOptions { rootUrl: string; username?: string; password?: string; authEnabled?: boolean; } interface PooledConnection { client: WebDAVClient; lastUsed: number; connectionKey: string; } /** * WebDAV Connection Pool for reusing connections */ export class WebDAVConnectionPool { private connections: Map<string, PooledConnection> = new Map(); private cleanupInterval: NodeJS.Timeout; private maxIdleTimeMs: number; private maxConnections: number; /** * Create a new WebDAV connection pool * * @param options Pool configuration options */ constructor(options: { maxIdleTimeMs?: number; // Maximum time in ms a connection can be idle before being removed maxConnections?: number; // Maximum number of connections to keep in the pool cleanupIntervalMs?: number; // How often to check for idle connections } = {}) { this.maxIdleTimeMs = options.maxIdleTimeMs || 5 * 60 * 1000; // Default: 5 minutes this.maxConnections = options.maxConnections || 10; // Default: 10 connections const cleanupIntervalMs = options.cleanupIntervalMs || 60 * 1000; // Default: 1 minute // Start cleanup interval this.cleanupInterval = setInterval(() => { this.cleanupIdleConnections(); }, cleanupIntervalMs); // Ensure cleanup happens even if the process exits process.on('exit', () => { this.destroy(); }); } /** * Generate a unique key for a connection based on its options * * @param options Connection options * @returns Connection key */ private generateConnectionKey(options: WebDAVConnectionOptions): string { const { rootUrl, authEnabled, username } = options; // Include authentication details in key only if auth is enabled return authEnabled ? `${rootUrl}:${authEnabled}:${username}` : `${rootUrl}:${authEnabled}`; } /** * Get a WebDAV client from the pool or create a new one * * @param options Connection options * @returns WebDAV client */ getConnection(options: WebDAVConnectionOptions): WebDAVClient { const connectionKey = this.generateConnectionKey(options); // Check if we have a connection in the pool if (this.connections.has(connectionKey)) { const connection = this.connections.get(connectionKey)!; // Update last used timestamp connection.lastUsed = Date.now(); logger.debug(`Reusing existing WebDAV connection: ${connectionKey}`); return connection.client; } // If we've reached the max connections, remove the oldest one if (this.connections.size >= this.maxConnections) { this.removeOldestConnection(); } // Create new client logger.debug(`Creating new WebDAV connection: ${connectionKey}`); const client = this.createClient(options); // Add to pool this.connections.set(connectionKey, { client, lastUsed: Date.now(), connectionKey }); return client; } /** * Create a new WebDAV client * * @param options Connection options * @returns WebDAV client */ private createClient(options: WebDAVConnectionOptions): WebDAVClient { const { rootUrl, authEnabled, username, password } = options; if (authEnabled && username && password) { // Create authenticated client with plain text password logger.debug(`Creating authenticated WebDAV client for ${rootUrl}`); return createClient(rootUrl, { authType: AuthType.Password, username, password // Password must be in plain text for WebDAV authentication }); } else { // Create unauthenticated client logger.debug(`Creating unauthenticated WebDAV client for ${rootUrl}`); return createClient(rootUrl, { authType: AuthType.None }); } } /** * Remove the oldest connection from the pool */ private removeOldestConnection(): void { if (this.connections.size === 0) return; let oldestKey = ''; let oldestTime = Infinity; // Find the oldest connection for (const [key, connection] of this.connections.entries()) { if (connection.lastUsed < oldestTime) { oldestTime = connection.lastUsed; oldestKey = key; } } if (oldestKey) { logger.debug(`Removing oldest connection: ${oldestKey}`); this.connections.delete(oldestKey); } } /** * Clean up idle connections */ private cleanupIdleConnections(): void { const now = Date.now(); let removedCount = 0; for (const [key, connection] of this.connections.entries()) { const idleTime = now - connection.lastUsed; if (idleTime > this.maxIdleTimeMs) { logger.debug(`Removing idle connection: ${key}, idle for ${idleTime}ms`); this.connections.delete(key); removedCount++; } } if (removedCount > 0) { logger.info(`Cleaned up ${removedCount} idle WebDAV connections, ${this.connections.size} remaining`); } } /** * Get statistics about the connection pool */ getStats() { return { activeConnections: this.connections.size, maxConnections: this.maxConnections, connectionKeys: Array.from(this.connections.keys()) }; } /** * Destroy the connection pool and clean up resources */ destroy(): void { clearInterval(this.cleanupInterval); this.connections.clear(); logger.info('WebDAV connection pool destroyed'); } } // Create and export a singleton instance export const webdavConnectionPool = new WebDAVConnectionPool();

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/LaubPlusCo/mcp-webdav-server'

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