UNPKG

dbx-mcp-server

Version:

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

129 lines 4.87 kB
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'; import { ResourceHandler } from '../resource/resource-handler.js'; export class ResourcePromptHandler { constructor() { this.resourceHandler = new ResourceHandler(); } replaceArguments(text, args) { return text.replace(/\{(\w+)\}/g, (match, key) => { if (args[key] === undefined) { throw new McpError(ErrorCode.InvalidParams, `Missing argument: ${key}`); } return String(args[key]); }); } async resolveResourceUris(resources, args) { const resolveUris = (refs) => { if (!refs || !Array.isArray(refs)) return; for (const ref of refs) { ref.uri = this.replaceArguments(ref.uri, args); } }; if (resources.inline) resolveUris(resources.inline); if (resources.attachments) resolveUris(resources.attachments); if (resources.collections) resolveUris(resources.collections); } async processPrompt(prompt, args) { try { // Validate required arguments if (prompt.arguments) { for (const arg of prompt.arguments) { if (arg.required && args[arg.name] === undefined) { throw new McpError(ErrorCode.InvalidParams, `Missing required argument: ${arg.name}`); } } } // Clone the prompt to avoid modifying the original const processedPrompt = JSON.parse(JSON.stringify(prompt)); // Replace argument placeholders in messages if (Array.isArray(processedPrompt.messages)) { processedPrompt.messages = processedPrompt.messages.map(msg => ({ ...msg, content: { ...msg.content, text: typeof msg.content === 'object' && msg.content && 'text' in msg.content ? this.replaceArguments(msg.content.text, args) : '' } })); } // Process resources if present if (processedPrompt.resources) { // Replace argument placeholders in resource URIs await this.resolveResourceUris(processedPrompt.resources, args); // Process and load resources await this.resourceHandler.processPromptResources(processedPrompt.resources); } return processedPrompt; } catch (error) { throw new McpError(ErrorCode.InternalError, `Failed to process prompt: ${error.message}`); } } // Helper method to process a folder review prompt async processFolderReview(path, fileTypes) { const args = { path, fileTypes: fileTypes || '*' }; // If specific file types are provided, update the collection options if (fileTypes) { const extensions = fileTypes.split(',').map(ext => ext.trim()); args.fileTypes = extensions.join(', '); } return this.processPrompt({ name: 'folder_review', description: 'Review contents of a folder', messages: [ { role: 'assistant', content: { type: 'text', text: 'Analyzing folder: {path}\nFile types: {fileTypes}\n\n', resources: [] } } ], resources: { collections: [{ type: 'collection', uri: 'dbx://{path}' }] } }, args); } // Helper method to process a file comparison prompt async processFileComparison(file1, file2) { return this.processPrompt({ name: 'file_comparison', description: 'Compare two files', messages: [ { role: 'assistant', content: { type: 'text', text: 'Comparing files:\n1. {file1}\n2. {file2}\n\n', resources: [] } } ], resources: { inline: [ { type: 'inline', uri: 'dbx://{file1}' }, { type: 'inline', uri: 'dbx://{file2}' } ] } }, { file1, file2 }); } } //# sourceMappingURL=resource-prompt-handler.js.map