update_boop
Creates or updates a boop file to claim a directory for work, signaling in-progress tasks and preventing conflicts with other agents. Requires directory path and agent identifier.
Instructions
Creates or updates a boop file to claim a directory for work. This signals that work is in progress and prevents other agents from working in the same directory.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| agentId | Yes | Agent identifier claiming the work | |
| directory | Yes | Directory path where to create/update the boop file | |
| workDescription | No | Optional description of the work being done |
Implementation Reference
- src/tools.ts:160-296 (handler)The handler function that executes the core logic of the update_boop tool: validates inputs, checks current work status, handles atomic file operations to create/update boop files, sends notifications, and returns formatted responses.export async function handleUpdateBoop(params: UpdateBoopParams): Promise<ToolResponse> { try { const { directory, agentId, workDescription } = params; const config = loadConfig(); // Validate directory access try { validateDirectoryAccess(directory, config); } catch (accessError) { if (accessError instanceof CoordinationError) { return { content: [{ type: "text", text: `❌ ${accessError.message}` }], isError: true }; } throw accessError; } // Validate agent ID with configuration if (!validateAgentIdWithConfig(agentId, config)) { const reasons = []; if (agentId.length > config.maxAgentIdLength) { reasons.push(`exceeds maximum length of ${config.maxAgentIdLength}`); } if (config.requireTeamPrefix && config.teamPrefixes.length > 0) { const hasValidPrefix = config.teamPrefixes.some(prefix => agentId.startsWith(prefix)); if (!hasValidPrefix) { reasons.push(`must start with one of: ${config.teamPrefixes.join(', ')}`); } } if (!/^[a-zA-Z0-9._-]+$/.test(agentId)) { reasons.push('contains invalid characters (only alphanumeric, hyphens, underscores, dots allowed)'); } return { content: [{ type: "text", text: `❌ Invalid agent ID "${agentId}": ${reasons.join(', ')}` }], isError: true }; } // Check current status const status = await getWorkStatus(directory); if (status.status === WorkState.WORK_IN_PROGRESS && status.agentId !== agentId) { return { content: [{ type: "text", text: `⚠️ Cannot claim work: Directory is already being worked on by agent ${status.agentId}. Wait for work to complete or use check_status to monitor progress.` }], isError: true }; } // CRITICAL FIX: Ensure atomic state transition // If transitioning from WORK_ALLOWED to WORK_IN_PROGRESS, remove beep file first if (status.status === WorkState.WORK_ALLOWED && status.beepExists) { try { const { promises: fs } = await import('fs'); const { join } = await import('path'); const beepPath = join(directory, 'beep'); await fs.unlink(beepPath); } catch (error) { // If we can't remove beep file, don't proceed to avoid invalid state return { content: [{ type: "text", text: `❌ Failed to remove existing beep file during state transition: ${error}. Cannot safely claim directory.` }], isError: true }; } } await createBoopFile(directory, agentId, workDescription, config); const actionText = status.status === WorkState.WORK_IN_PROGRESS ? 'updated' : 'created'; // Send notification if enabled if (config.enableNotifications && status.status !== WorkState.WORK_IN_PROGRESS) { try { const notificationManager = createNotificationManager(config); const payload = NotificationManager.createPayload( NotificationType.WORK_STARTED, `Work started by agent ${agentId}`, directory, agentId, workDescription ); // Don't await - send in background to avoid blocking the operation notificationManager.sendNotification(payload).catch(error => { if (config.logLevel === 'debug') { console.error('📤 Notification failed (non-blocking):', error); } }); } catch (error) { // Silently fail notifications - don't block main operation if (config.logLevel === 'debug') { console.error('📤 Notification setup failed:', error); } } } return { content: [{ type: "text", text: `✅ Boop file ${actionText} successfully in ${directory}. Work is now claimed by agent ${agentId}.${workDescription ? ` Work: ${workDescription}` : ''}` }] }; } catch (error) { if (error instanceof CoordinationError) { return { content: [{ type: "text", text: `❌ ${error.message} (${error.code})` }], isError: true }; } return { content: [{ type: "text", text: `❌ Unexpected error updating boop file: ${error}` }], isError: true }; } }
- src/tools.ts:41-48 (schema)Zod schema defining and validating the input parameters for the update_boop tool./** * Schema for update_boop tool parameters */ export const UpdateBoopSchema = z.object({ directory: z.string().describe('Directory path where to create/update the boop file'), agentId: z.string().describe('Agent identifier claiming the work'), workDescription: z.string().optional().describe('Optional description of the work being done') });
- src/index.ts:51-61 (registration)MCP server registration of the update_boop tool, linking the schema and handler function.server.registerTool( 'update_boop', { title: 'Update Boop File', description: 'Creates or updates a boop file to claim a directory for work. This signals that work is in progress and prevents other agents from working in the same directory.', inputSchema: UpdateBoopSchema.shape }, async (params) => { return await handleUpdateBoop(params); } );
- src/types.ts:46-53 (schema)TypeScript interface defining the parameter structure for the update_boop handler.export interface UpdateBoopParams { /** Directory path where to create/update the boop file */ directory: string; /** Agent identifier claiming the work */ agentId: string; /** Optional description of the work being done */ workDescription?: string; }