UNPKG

dbx-mcp-server

Version:

A Model Context Protocol server for Dropbox integration with AI-powered PDF analysis, multi-directory indexing, and parallel processing

223 lines 8.76 kB
import { getDropboxClient, getDropboxClientForPath, formatDropboxPath } from './client-factory.js'; import { handleDropboxError } from './error-handler.js'; import { getCachedTeamConfig, shouldUseTeamSpace } from './team-config.js'; // File manipulation operations export async function copyItem(fromPath, toPath) { try { // Use team space if either path suggests it const teamConfig = await getCachedTeamConfig(); const useTeamSpace = shouldUseTeamSpace(fromPath, teamConfig) || shouldUseTeamSpace(toPath, teamConfig); const client = await getDropboxClient({ useTeamSpace }); await client.filesCopyV2({ from_path: formatDropboxPath(fromPath), to_path: formatDropboxPath(toPath), allow_shared_folder: true, autorename: false, allow_ownership_transfer: false, }); return { content: [{ type: 'text', text: `Copied from ${fromPath} to ${toPath}`, }], }; } catch (error) { handleDropboxError(error); } } export async function moveItem(fromPath, toPath) { try { // Use team space if either path suggests it const teamConfig = await getCachedTeamConfig(); const useTeamSpace = shouldUseTeamSpace(fromPath, teamConfig) || shouldUseTeamSpace(toPath, teamConfig); const client = await getDropboxClient({ useTeamSpace }); await client.filesMoveV2({ from_path: formatDropboxPath(fromPath), to_path: formatDropboxPath(toPath), allow_shared_folder: true, autorename: false, allow_ownership_transfer: false, }); return { content: [{ type: 'text', text: `Moved from ${fromPath} to ${toPath}`, }], }; } catch (error) { handleDropboxError(error); } } export async function getSharingLink(path) { try { const client = await getDropboxClientForPath(path); try { const response = await client.sharingCreateSharedLinkWithSettings({ path: formatDropboxPath(path), settings: { requested_visibility: { '.tag': 'public' }, audience: { '.tag': 'public' }, access: { '.tag': 'viewer' }, }, }); return { content: [{ type: 'text', text: JSON.stringify({ url: response.result.url, path: response.result.path_lower, visibility: response.result.link_permissions?.resolved_visibility?.['.tag'] || 'unknown', }, null, 2), }], }; } catch (error) { // If sharing failed, try to get existing links if (error?.error?.error_summary?.includes('shared_link_already_exists')) { const linksResponse = await client.sharingListSharedLinks({ path: formatDropboxPath(path), }); const existingLink = linksResponse.result.links?.[0]; if (existingLink) { return { content: [{ type: 'text', text: JSON.stringify({ url: existingLink.url, path: existingLink.path_lower, visibility: existingLink.link_permissions?.resolved_visibility?.['.tag'] || 'unknown', note: 'Using existing shared link' }, null, 2), }], }; } } throw error; } } catch (error) { handleDropboxError(error); } } // Helper function to categorize files function categorizeFile(metadata) { const name = metadata.name?.toLowerCase() || ''; if (metadata['.tag'] === 'folder') { return 'folder'; } const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.svg', '.webp']; const documentExtensions = ['.doc', '.docx', '.txt', '.rtf', '.odt']; const pdfExtensions = ['.pdf']; const spreadsheetExtensions = ['.xls', '.xlsx', '.csv', '.ods']; const presentationExtensions = ['.ppt', '.pptx', '.odp']; const audioExtensions = ['.mp3', '.wav', '.flac', '.aac', '.ogg']; const videoExtensions = ['.mp4', '.avi', '.mov', '.wmv', '.flv', '.mkv']; if (imageExtensions.some(ext => name.endsWith(ext))) { return 'image'; } if (documentExtensions.some(ext => name.endsWith(ext))) { return 'document'; } if (pdfExtensions.some(ext => name.endsWith(ext))) { return 'pdf'; } if (spreadsheetExtensions.some(ext => name.endsWith(ext))) { return 'spreadsheet'; } if (presentationExtensions.some(ext => name.endsWith(ext))) { return 'presentation'; } if (audioExtensions.some(ext => name.endsWith(ext))) { return 'audio'; } if (videoExtensions.some(ext => name.endsWith(ext))) { return 'video'; } return 'other'; } export async function searchFiles(options) { try { const client = await getDropboxClientForPath(options.path || ''); const response = await client.filesSearchV2({ query: options.query, options: { path: formatDropboxPath(options.path || ''), max_results: Math.min(Math.max(1, options.maxResults || 20), 1000), file_status: { '.tag': 'active' }, filename_only: !options.includeContentMatch, }, match_field_options: { include_highlights: true, }, }); let matches = response.result.matches .map(match => ({ metadata: match.metadata.metadata, match_type: match.match_type, highlights: match.highlight_spans, })) .filter(match => { // Apply filters const metadata = match.metadata; // File extension filter if (options.fileExtensions && options.fileExtensions.length > 0) { const fileName = metadata.name?.toLowerCase() || ''; const hasMatchingExt = options.fileExtensions.some(ext => fileName.endsWith(ext.toLowerCase())); if (!hasMatchingExt) return false; } // File category filter if (options.fileCategories && options.fileCategories.length > 0) { const category = categorizeFile(metadata); if (!options.fileCategories.includes(category)) return false; } // Date range filter if (options.dateRange && metadata.server_modified) { const modifiedDate = new Date(metadata.server_modified); const startDate = new Date(options.dateRange.start); const endDate = new Date(options.dateRange.end); if (modifiedDate < startDate || modifiedDate > endDate) { return false; } } return true; }); // Sort results if (options.sortBy) { matches.sort((a, b) => { let aValue, bValue; switch (options.sortBy) { case 'last_modified_time': aValue = new Date(a.metadata.server_modified || 0).getTime(); bValue = new Date(b.metadata.server_modified || 0).getTime(); break; case 'file_size': aValue = a.metadata.size || 0; bValue = b.metadata.size || 0; break; default: // relevance return 0; // Keep original order for relevance } return options.order === 'asc' ? aValue - bValue : bValue - aValue; }); } const results = { query: options.query, total_matches: matches.length, matches: matches, }; return { content: [{ type: 'text', text: JSON.stringify(results, null, 2), }], }; } catch (error) { handleDropboxError(error); } } //# sourceMappingURL=advanced-operations.js.map