google-docs-mcp / src /tools /docs /findAndReplace.ts
iFightDucks's picture
Initial HF Space deploy: a-bonus/google-docs-mcp with HF metadata
7dc28be
import type { FastMCP } from 'fastmcp';
import { UserError } from 'fastmcp';
import { z } from 'zod';
import { docs_v1 } from 'googleapis';
import { getDocsClient } from '../../clients.js';
import { DocumentIdParameter } from '../../types.js';
import * as GDocsHelpers from '../../googleDocsApiHelpers.js';
const FindAndReplaceParameters = DocumentIdParameter.extend({
findText: z.string().min(1).describe('The text to search for in the document.'),
replaceText: z
.string()
.describe('The replacement text. Use an empty string to delete all occurrences.'),
matchCase: z
.boolean()
.optional()
.describe('Whether the search should be case-sensitive. Defaults to false.'),
tabId: z
.string()
.optional()
.describe('Scope replacement to a specific tab. If omitted, replaces across all tabs.'),
});
export function register(server: FastMCP) {
server.addTool({
name: 'findAndReplace',
description:
'Replaces all occurrences of a text string throughout the document (or a specific tab). ' +
'Returns the number of replacements made. Use an empty replaceText to delete all matches.',
parameters: FindAndReplaceParameters,
execute: async (args, { log }) => {
const docs = await getDocsClient();
log.info(
`findAndReplace in doc ${args.documentId}: "${args.findText}" → "${args.replaceText}"` +
`${args.matchCase ? ' (case-sensitive)' : ''}` +
`${args.tabId ? ` (tab: ${args.tabId})` : ''}`
);
try {
const request: docs_v1.Schema$Request = {
replaceAllText: {
containsText: {
text: args.findText,
matchCase: args.matchCase ?? false,
},
replaceText: args.replaceText,
...(args.tabId && { tabsCriteria: { tabIds: [args.tabId] } }),
},
};
const response = await GDocsHelpers.executeBatchUpdate(docs, args.documentId, [request]);
const changed = response.replies?.[0]?.replaceAllText?.occurrencesChanged ?? 0;
return `Replaced ${changed} occurrence(s) of "${args.findText}" with "${args.replaceText}".`;
} catch (error: any) {
log.error(`Error in findAndReplace for doc ${args.documentId}: ${error.message || error}`);
if (error instanceof UserError) throw error;
throw new UserError(`Failed to find and replace: ${error.message || 'Unknown error'}`);
}
},
});
}