UNPKG

@utaba/ucm-mcp-server

Version:

Universal Context Manager MCP Server - AI Productivity Platform

145 lines 6.86 kB
/** * SharePointReadFileTool * Read and convert SharePoint files to text */ import { BaseToolController } from '../base/BaseToolController.js'; import { McpError, McpErrorCode } from '../../utils/McpErrorHandler.js'; import { SharePointErrorHandler } from '../../utils/SharePointErrorHandler.js'; export class SharePointReadFileTool extends BaseToolController { constructor(ucmClient, logger, publishingAuthorId) { super(ucmClient, logger, publishingAuthorId); } get name() { return 'ucm_sharepoint_read_file'; } get description() { return 'Read a file from SharePoint and convert it to text. Supports Office documents (Word, Excel, PowerPoint), PDFs, and text files. Maximum file size is 20MB. Provide either a full SharePoint URL or relative path. Supports pagination with offset/limit for TEXT CONTENT ONLY. Pagination parameters are ignored for binary files (images, PDFs with embedded images).'; } get inputSchema() { return { type: 'object', properties: { connectionId: { type: 'string', description: 'SharePoint connection ID to use for reading file (get this from list_connections)', minLength: 36, maxLength: 36 }, webUrl: { type: 'string', description: 'SharePoint file URL (e.g., "https://contoso.sharepoint.com/sites/Sales/Shared Documents/report.docx") OR relative path ("/Shared Documents/report.docx")', minLength: 1, maxLength: 2000 }, extractMetadata: { type: 'boolean', description: 'Include file metadata in response (default: true)' }, offset: { type: 'number', description: 'Number of characters to skip from the start of the content (default: 0). Pagination for text content only - ignored for binary/image files.', minimum: 0 }, limit: { type: 'number', description: 'Maximum number of characters to return (default: unlimited). Pagination for text content only - ignored for binary/image files.', minimum: 1 } }, required: ['connectionId', 'webUrl'], additionalProperties: false }; } validateParams(params) { super.validateParams(params); // Validate connectionId is UUID format const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; if (!uuidPattern.test(params.connectionId)) { throw new McpError(McpErrorCode.InvalidParams, 'Connection ID must be a valid UUID'); } // Validate that webUrl is provided if (!params.webUrl || typeof params.webUrl !== 'string' || params.webUrl.trim() === '') { throw new McpError(McpErrorCode.InvalidParams, 'File URL is required and must be a non-empty string'); } // Set boolean defaults if (params.extractMetadata === undefined) { params.extractMetadata = true; } // Validate and set offset/limit defaults if (params.offset !== undefined) { if (typeof params.offset !== 'number' || params.offset < 0) { throw new McpError(McpErrorCode.InvalidParams, 'Offset must be a non-negative number'); } } else { params.offset = 0; } if (params.limit !== undefined) { if (typeof params.limit !== 'number' || params.limit < 1) { throw new McpError(McpErrorCode.InvalidParams, 'Limit must be a positive number'); } } } async handleExecute(params) { this.logger.info('SharePointReadFileTool', `Reading file: ${params.webUrl} (offset: ${params.offset || 0}, limit: ${params.limit || 'unlimited'})`); try { // Call the API to read and convert SharePoint file // organizationId is auto-detected from auth token in V1 API const readParams = { fileUrl: params.webUrl, // Map webUrl parameter to fileUrl for internal command extractMetadata: params.extractMetadata }; // Add pagination parameters if provided if (params.offset !== undefined) { readParams.offset = params.offset; } if (params.limit !== undefined) { readParams.limit = params.limit; } // Make API call via UCM client (V1 API) const result = await this.ucmClient.sharePointReadFile(params.connectionId, readParams); this.logger.info('SharePointReadFileTool', `File read successfully: ${result.fileName}`); // Format response const response = { success: true, fileName: result.fileName, fileType: result.fileType, contentLength: result.contentLength, returnedLength: result.returnedLength, offset: result.offset, hasMore: result.hasMore, content: result.content, conversionNotes: result.conversionNotes, convertedAt: result.convertedAt }; // Add nextOffset if there's more content if (result.hasMore && result.nextOffset !== undefined) { response.nextOffset = result.nextOffset; } // Include metadata if requested if (params.extractMetadata && result.metadata) { response.metadata = result.metadata; } return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } catch (error) { // Handle ReadFile-specific errors first if (error?.response?.status === 400 && error?.response?.data?.error === 'TENANT_MISMATCH') { throw new McpError(McpErrorCode.InvalidParams, 'File URL does not match the connection tenant'); } if (error?.response?.status === 413 || error?.message?.includes('size')) { throw new McpError(McpErrorCode.InvalidParams, 'File exceeds maximum size limit of 20MB'); } // Delegate to common SharePoint error handler for generic errors return SharePointErrorHandler.handle(error, this.logger, 'SharePointReadFileTool'); } } } //# sourceMappingURL=SharePointReadFileTool.js.map