Skip to main content
Glama
timer-discard.ts4 kB
/** * Timer Discard Tool * * Discards a running timer without logging the time by deleting the TimeEntry. * This is useful when you started a timer by mistake or want to abandon tracked time. */ import { z } from "zod"; import { TimerDiscardInputSchema, TimerDiscardOutputSchema } from "./schemas.js"; import { ErrorHandler } from "../../errors/error-handler.js"; import { ToolContext } from "../../errors/types.js"; import { FreshBooksClientWrapper } from "../../client/freshbooks-client.js"; /** * Tool definition for timer_discard */ export const timerDiscardTool = { name: "timer_discard", description: `Discard a running timer without logging the time in FreshBooks. WHEN TO USE: - User says "discard timer", "delete timer", "cancel tracking" - Timer was started by mistake - Work was not actually performed - Want to abandon tracked time without saving IMPORTANT DIFFERENCE: Discard vs Stop - timer_stop: Logs the time, saves the time entry with calculated duration - timer_discard: DELETES the time entry, no record is kept USE WITH CAUTION: - This permanently deletes the time entry - The tracked time CANNOT be recovered after discarding - Use timer_stop if you want to keep the time entry HOW IT WORKS: Deletes the time entry completely: - Time entry is removed from FreshBooks - No duration is logged - No record remains (except in audit logs) REQUIRED: - accountId: FreshBooks account ID - timeEntryId: ID of the timer to discard (from timer_start or timer_current) FINDING THE TIMER ID: If you don't know the timer ID: 1. Use timer_current to get all active timers 2. The response includes the timeEntryId for each active timer WHAT IF TIMER DOESN'T EXIST: - If timeEntryId is not found: Returns error - If timer already stopped/logged: Can still delete it (removes logged time) - If timer already discarded: Returns error (not found) CONFIRMATION: Always confirm with the user before discarding: - "Are you sure you want to discard this timer?" - "This will delete the tracked time. Continue?" EXAMPLE USAGE: - "Discard my current timer" (requires getting current timer first) - "Delete timer 12345" - "Cancel time tracking - I didn't actually work on it" RETURNS: Confirmation object with: - success: true if deletion succeeded - timeEntryId: The ID that was deleted - message: Confirmation message ALTERNATIVE: If user wants to keep the time but stop tracking: - Use timer_stop instead - This saves the time entry with calculated duration`, inputSchema: TimerDiscardInputSchema, outputSchema: TimerDiscardOutputSchema, async execute( input: z.infer<typeof TimerDiscardInputSchema>, client: FreshBooksClientWrapper ): Promise<z.infer<typeof TimerDiscardOutputSchema>> { const handler = ErrorHandler.wrapHandler( 'timer_discard', async (input: z.infer<typeof TimerDiscardInputSchema>, _context: ToolContext) => { const { accountId, timeEntryId } = input; // Use the FreshBooks client to delete the time entry await client.executeWithRetry( "timer_discard", async (fbClient) => { const response = await fbClient.timeEntries.delete(parseInt(accountId), timeEntryId); if (!response.ok) { throw response.error; } return response.data; } ); // Return success confirmation return { success: true, timeEntryId, message: `Timer ${timeEntryId} has been discarded successfully. The time entry was deleted and no time was logged.`, }; } ); return handler(input, { accountId: input.accountId }); }, }; /** * Wrapped handler for backward compatibility with tests */ export async function timerDiscardHandler( input: z.infer<typeof TimerDiscardInputSchema>, context: ToolContext & { client: FreshBooksClientWrapper } ): Promise<z.infer<typeof TimerDiscardOutputSchema>> { return timerDiscardTool.execute(input, context.client); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Good-Samaritan-Software-LLC/freshbooks-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server