UNPKG

mcp-gdrive-enhanced-markov

Version:

MCP server for Google Drive and Sheets with write capabilities, AI-powered PDF analysis, SQLite document indexing, and advanced directory exploration tools

158 lines (157 loc) 7.83 kB
import { google } from 'googleapis'; import { getValidCredentials } from '../auth.js'; export const schema = { name: "gdrive_find_documents", description: "Find documents in Google Drive with intelligent search and present options for user selection (does not automatically analyze content)", inputSchema: { type: "object", properties: { query: { type: "string", description: "Search query - can be document type (e.g., 'business plan', 'financial', 'proposal') or specific keywords", }, maxResults: { type: "number", description: "Maximum number of documents to return (default: 10)", optional: true, }, fileType: { type: "string", description: "Filter by file type: 'pdf', 'document', 'spreadsheet', 'presentation'", optional: true, }, modifiedAfter: { type: "string", description: "Only return files modified after this date (ISO format: YYYY-MM-DD)", optional: true, }, includeDetails: { type: "boolean", description: "Include raw JSON data in the response (default: false)", optional: true, }, }, required: ["query"], }, }; export async function gdrive_find_documents(args) { try { const authClient = await getValidCredentials(); const drive = google.drive({ version: 'v3', auth: authClient }); const maxResults = args.maxResults || 10; // Build search query with intelligent keywords let searchQuery = ''; const queryLower = args.query.toLowerCase(); // Add intelligent search terms based on query if (queryLower.includes('business plan')) { searchQuery = `(name contains 'business plan' or name contains 'business' or name contains 'plan' or fullText contains 'business plan' or fullText contains 'executive summary')`; } else if (queryLower.includes('financial') || queryLower.includes('budget')) { searchQuery = `(name contains 'financial' or name contains 'budget' or name contains 'finance' or fullText contains 'financial' or fullText contains 'budget')`; } else if (queryLower.includes('proposal')) { searchQuery = `(name contains 'proposal' or fullText contains 'proposal')`; } else if (queryLower.includes('contract')) { searchQuery = `(name contains 'contract' or fullText contains 'contract' or fullText contains 'agreement')`; } else { // Generic search - search in name and content const searchTerms = args.query.split(' ').filter(term => term.length > 2); const nameQueries = searchTerms.map(term => `name contains '${term}'`).join(' or '); const contentQueries = searchTerms.map(term => `fullText contains '${term}'`).join(' or '); searchQuery = `(${nameQueries}) or (${contentQueries})`; } // Add file type filter if specified if (args.fileType) { const mimeTypeMap = { 'pdf': "mimeType='application/pdf'", 'document': "mimeType='application/vnd.google-apps.document' or mimeType='application/vnd.openxmlformats-officedocument.wordprocessingml.document'", 'spreadsheet': "mimeType='application/vnd.google-apps.spreadsheet' or mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'", 'presentation': "mimeType='application/vnd.google-apps.presentation' or mimeType='application/vnd.openxmlformats-officedocument.presentationml.presentation'" }; if (mimeTypeMap[args.fileType]) { searchQuery = `(${searchQuery}) and (${mimeTypeMap[args.fileType]})`; } } // Add date filter if specified if (args.modifiedAfter) { searchQuery = `(${searchQuery}) and modifiedTime > '${args.modifiedAfter}'`; } // Exclude trashed files searchQuery = `(${searchQuery}) and trashed=false`; const response = await drive.files.list({ q: searchQuery, pageSize: maxResults, fields: 'files(id,name,mimeType,size,modifiedTime,webViewLink,parents,description)', orderBy: 'modifiedTime desc' }); const files = response.data.files || []; if (files.length === 0) { return { content: [{ type: "text", text: `No documents found matching "${args.query}". Try different search terms or check if the files exist in your Google Drive.` }], isError: false }; } // Format results for user selection const documents = files.map(file => ({ id: file.id, name: file.name, mimeType: file.mimeType, size: file.size ? `${Math.round(parseInt(file.size) / 1024)} KB` : undefined, modifiedTime: file.modifiedTime, webViewLink: file.webViewLink, parents: file.parents || undefined, description: file.description || undefined })); // Create user-friendly display let content = `Found ${documents.length} document${documents.length > 1 ? 's' : ''} matching "${args.query}":\n\n`; documents.forEach((doc, index) => { const fileType = getFileTypeDisplay(doc.mimeType); const modifiedDate = new Date(doc.modifiedTime).toLocaleDateString(); const sizeInfo = doc.size ? ` (${doc.size})` : ''; content += `**${index + 1}. ${doc.name}**\n`; content += ` • Type: ${fileType}${sizeInfo}\n`; content += ` • Modified: ${modifiedDate}\n`; content += ` • ID: \`${doc.id}\`\n`; content += ` • Link: ${doc.webViewLink}\n`; if (doc.description) { content += ` • Description: ${doc.description}\n`; } content += '\n'; }); content += `\n**Next Steps:**\n`; content += `• To read a document: Use \`gdrive_read_file\` with the file ID\n`; content += `• To analyze a PDF: Use \`gdrive_analyze_pdf\` with the file ID and your analysis prompt\n`; content += `• To read Excel/Sheets: Use \`gdrive_read_excel\` with the file ID\n`; if (args.includeDetails) { content += `\n**Raw Data:**\n\`\`\`json\n${JSON.stringify(documents, null, 2)}\n\`\`\``; } return { content: [{ type: "text", text: content }], isError: false }; } catch (error) { console.error('Error in gdrive_find_documents:', error); return { content: [{ type: "text", text: `Error finding documents: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } function getFileTypeDisplay(mimeType) { const typeMap = { 'application/pdf': 'PDF', 'application/vnd.google-apps.document': 'Google Doc', 'application/vnd.google-apps.spreadsheet': 'Google Sheet', 'application/vnd.google-apps.presentation': 'Google Slides', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'Word Document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'Excel Spreadsheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'PowerPoint', 'text/plain': 'Text File', 'image/jpeg': 'JPEG Image', 'image/png': 'PNG Image' }; return typeMap[mimeType] || mimeType; }