import type { FastMCP } from 'fastmcp'; import { UserError } from 'fastmcp'; import { getDocsClient } from '../../../clients.js'; import { ApplyTextStyleToolParameters, ApplyTextStyleToolArgs, NotImplementedError, } from '../../../types.js'; import * as GDocsHelpers from '../../../googleDocsApiHelpers.js'; export function register(server: FastMCP) { server.addTool({ name: 'applyTextStyle', description: 'Applies character-level formatting (bold, italic, color, font, etc.) to text identified by a character range or by searching for a text string. This is the primary tool for styling text in a document.', parameters: ApplyTextStyleToolParameters, execute: async (args: ApplyTextStyleToolArgs, { log }) => { const docs = await getDocsClient(); let { startIndex, endIndex } = args.target as any; // Will be updated if target is text log.info( `Applying text style in doc ${args.documentId}${args.tabId ? ` (tab: ${args.tabId})` : ''}. Target: ${JSON.stringify(args.target)}, Style: ${JSON.stringify(args.style)}` ); try { // Determine target range if ('textToFind' in args.target) { const range = await GDocsHelpers.findTextRange( docs, args.documentId, args.target.textToFind, args.target.matchInstance, args.tabId ); if (!range) { throw new UserError( `Could not find instance ${args.target.matchInstance} of text "${args.target.textToFind}"${args.tabId ? ` in tab ${args.tabId}` : ''}.` ); } startIndex = range.startIndex; endIndex = range.endIndex; log.info( `Found text "${args.target.textToFind}" (instance ${args.target.matchInstance}) at range ${startIndex}-${endIndex}` ); } if (startIndex === undefined || endIndex === undefined) { throw new UserError('Target range could not be determined.'); } if (endIndex <= startIndex) { throw new UserError('End index must be greater than start index for styling.'); } // Build the request const requestInfo = GDocsHelpers.buildUpdateTextStyleRequest( startIndex, endIndex, args.style, args.tabId ); if (!requestInfo) { return 'No valid text styling options were provided.'; } await GDocsHelpers.executeBatchUpdate(docs, args.documentId, [requestInfo.request]); return `Successfully applied text style (${requestInfo.fields.join(', ')}) to range ${startIndex}-${endIndex}${args.tabId ? ` in tab ${args.tabId}` : ''}.`; } catch (error: any) { log.error(`Error applying text style in doc ${args.documentId}: ${error.message || error}`); if (error instanceof UserError) throw error; if (error instanceof NotImplementedError) throw error; // Should not happen here throw new UserError(`Failed to apply text style: ${error.message || 'Unknown error'}`); } }, }); }