Skip to main content
Glama

batch_add_items

Add multiple tasks or projects to OmniFocus in one operation, specifying details like due dates, flags, tags, and project associations.

Instructions

Add multiple tasks or projects to OmniFocus in a single operation

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
itemsYesArray of items (tasks or projects) to add

Implementation Reference

  • The handler function for the batch_add_items tool. It calls the primitive batchAddItems function and formats the response with success/failure details.
    export async function handler(args: z.infer<typeof schema>, extra: RequestHandlerExtra) {
      try {
        // Call the batchAddItems function
        const result = await batchAddItems(args.items as BatchAddItemsParams[]);
        
        if (result.success) {
          const successCount = result.results.filter(r => r.success).length;
          const failureCount = result.results.filter(r => !r.success).length;
          
          let message = `✅ Successfully added ${successCount} items.`;
          
          if (failureCount > 0) {
            message += ` ⚠️ Failed to add ${failureCount} items.`;
          }
          
          // Include details about added items
          const details = result.results.map((item, index) => {
            if (item.success) {
              const itemType = args.items[index].type;
              const itemName = args.items[index].name;
              return `- ✅ ${itemType}: "${itemName}"`;
            } else {
              const itemType = args.items[index].type;
              const itemName = args.items[index].name;
              return `- ❌ ${itemType}: "${itemName}" - Error: ${item.error}`;
            }
          }).join('\n');
          
          return {
            content: [{
              type: "text" as const,
              text: `${message}\n\n${details}`
            }]
          };
        } else {
          // Batch operation failed completely
          return {
            content: [{
              type: "text" as const,
              text: `Failed to process batch operation: ${result.error}`
            }],
            isError: true
          };
        }
      } catch (err: unknown) {
        const error = err as Error;
        console.error(`Tool execution error: ${error.message}`);
        return {
          content: [{
            type: "text" as const,
            text: `Error processing batch operation: ${error.message}`
          }],
          isError: true
        };
      }
    } 
  • Zod schema defining the input parameters for the batch_add_items tool, matching the BatchAddItemsParams type.
    export const schema = z.object({
      items: z.array(z.object({
        type: z.enum(['task', 'project']).describe("Type of item to add ('task' or 'project')"),
        name: z.string().describe("The name of the item"),
        note: z.string().optional().describe("Additional notes for the item"),
        dueDate: z.string().optional().describe("The due date in ISO format (YYYY-MM-DD or full ISO date)"),
        deferDate: z.string().optional().describe("The defer date in ISO format (YYYY-MM-DD or full ISO date)"),
        flagged: z.boolean().optional().describe("Whether the item is flagged or not"),
        estimatedMinutes: z.number().optional().describe("Estimated time to complete the item, in minutes"),
        tags: z.array(z.string()).optional().describe("Tags to assign to the item"),
        
        // Task-specific properties
        projectName: z.string().optional().describe("For tasks: The name of the project to add the task to"),
        parentTaskId: z.string().optional().describe("For tasks: The ID of the parent task to create this task as a subtask"),
        parentTaskName: z.string().optional().describe("For tasks: The name of the parent task to create this task as a subtask"),
        
        // Project-specific properties
        folderName: z.string().optional().describe("For projects: The name of the folder to add the project to"),
        sequential: z.boolean().optional().describe("For projects: Whether tasks in the project should be sequential")
      })).describe("Array of items (tasks or projects) to add")
    });
  • src/server.ts:69-74 (registration)
    Registration of the batch_add_items tool on the MCP server using schema and handler from batchAddItemsTool.
    server.tool(
      "batch_add_items",
      "Add multiple tasks or projects to OmniFocus in a single operation",
      batchAddItemsTool.schema.shape,
      batchAddItemsTool.handler
    );
  • Core helper function that implements the batch addition logic by iterating over items and calling individual addOmniFocusTask or addProject functions.
    export async function batchAddItems(items: BatchAddItemsParams[]): Promise<BatchResult> {
      try {
        // Results array to track individual operation outcomes
        const results: ItemResult[] = [];
        
        // Process each item in sequence
        for (const item of items) {
          try {
            if (item.type === 'task') {
              // Extract task-specific params
              const taskParams: AddOmniFocusTaskParams = {
                name: item.name,
                note: item.note,
                dueDate: item.dueDate,
                deferDate: item.deferDate,
                flagged: item.flagged,
                estimatedMinutes: item.estimatedMinutes,
                tags: item.tags,
                projectName: item.projectName,
                parentTaskId: item.parentTaskId,
                parentTaskName: item.parentTaskName
              };
              
              // Add task
              const taskResult = await addOmniFocusTask(taskParams);
              results.push({
                success: taskResult.success,
                id: taskResult.taskId,
                error: taskResult.error
              });
            } else if (item.type === 'project') {
              // Extract project-specific params
              const projectParams: AddProjectParams = {
                name: item.name,
                note: item.note,
                dueDate: item.dueDate,
                deferDate: item.deferDate,
                flagged: item.flagged,
                estimatedMinutes: item.estimatedMinutes,
                tags: item.tags,
                folderName: item.folderName,
                sequential: item.sequential
              };
              
              // Add project
              const projectResult = await addProject(projectParams);
              results.push({
                success: projectResult.success,
                id: projectResult.projectId,
                error: projectResult.error
              });
            } else {
              // Invalid type
              results.push({
                success: false,
                error: `Invalid item type: ${(item as any).type}`
              });
            }
          } catch (itemError: any) {
            // Handle individual item errors
            results.push({
              success: false,
              error: itemError.message || "Unknown error processing item"
            });
          }
        }
        
        // Determine overall success (true if at least one item was added successfully)
        const overallSuccess = results.some(result => result.success);
        
        return {
          success: overallSuccess,
          results: results
        };
      } catch (error: any) {
        console.error("Error in batchAddItems:", error);
        return {
          success: false,
          results: [],
          error: error.message || "Unknown error in batchAddItems"
        };
      }
    } 
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden but only states it's an add operation without disclosing behavioral traits like whether it's idempotent, requires specific permissions, returns confirmation details, or handles errors for partial failures in batch processing. It mentions the batch nature but lacks depth on how it behaves.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that front-loads the key action and benefit with zero wasted words. It's appropriately sized for the tool's complexity and gets straight to the point without unnecessary elaboration.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (batch mutation with nested objects) and no annotations or output schema, the description is adequate but incomplete. It covers the basic purpose but lacks details on behavioral aspects, error handling, or return values, which are important for a mutation tool with multiple items.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description mentions 'tasks or projects' and 'multiple items', which aligns with the 'items' array parameter in the schema. With 100% schema description coverage, the schema fully documents the parameter details, so the description adds minimal value beyond confirming the parameter's purpose without providing additional semantics or usage examples.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Add multiple tasks or projects') and target system ('to OmniFocus'), with the specific benefit of 'in a single operation' distinguishing it from single-item tools. However, it doesn't explicitly differentiate from sibling tools like 'add_omnifocus_task' or 'add_project' beyond the batch aspect.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage when adding multiple items is needed, but provides no explicit guidance on when to use this versus alternatives like 'add_omnifocus_task' or 'add_project' for single items, or prerequisites for batch operations. The context is clear but lacks comparative or exclusionary details.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

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/jqlts1/omnifocus-mcp-enhanced'

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