File size: 3,108 Bytes
7dc28be
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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'}`);
      }
    },
  });
}