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
JavaScript
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;
}