Skip to main content
Glama

get_today_completed_tasks

Retrieve tasks completed today to track daily progress. Set a task limit (default: 20) to view accomplishments and enhance productivity using OmniFocus MCP Enhanced.

Instructions

Get tasks completed today - view today's accomplishments

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNo返回的最大任务数量 (默认: 20)

Implementation Reference

  • The handler function for the 'get_today_completed_tasks' tool. It extracts the 'limit' parameter and calls the primitive getTodayCompletedTasks function, then formats the result as MCP content.
    export async function handler(args: z.infer<typeof schema>) {
      const { limit } = args;
      
      const result = await getTodayCompletedTasks({ 
        limit 
      });
      
      return {
        content: [{ type: "text" as const, text: result }]
      };
    }
  • Zod schema defining the input parameters for the tool, specifically an optional 'limit' for the number of tasks.
    export const schema = z.object({
      limit: z.number().min(1).max(100).default(20).optional().describe('返回的最大任务数量 (默认: 20)')
    });
  • src/server.ts:91-96 (registration)
    Registration of the 'get_today_completed_tasks' tool on the MCP server, providing name, description, schema, and handler.
    server.tool(
      "get_today_completed_tasks",
      "Get tasks completed today - view today's accomplishments",
      getTodayCompletedTasksTool.schema.shape,
      getTodayCompletedTasksTool.handler
    );
  • Core helper function that executes the OmniFocus script, processes the result, formats the completed tasks grouped by project with details, and handles errors.
    export async function getTodayCompletedTasks(options: GetTodayCompletedTasksOptions = {}): Promise<string> {
      try {
        const { limit = 20 } = options;
        
        const result = await executeOmniFocusScript('@todayCompletedTasks.js', { limit });
        
        if (typeof result === 'string') {
          return result;
        }
        
        // 如果结果是对象,格式化它
        if (result && typeof result === 'object') {
          const data = result as any;
          
          if (data.error) {
            throw new Error(data.error);
          }
          
          // 格式化完成任务结果
          let output = `# ✅ 今天完成的任务\\n\\n`;
          
          if (data.tasks && Array.isArray(data.tasks)) {
            if (data.tasks.length === 0) {
              output += "🎯 今天还没有完成任何任务。\\n";
              output += "\\n**加油!** 完成一些任务来让这个列表变得丰富起来!\\n";
            } else {
              const taskCount = data.tasks.length;
              const totalCount = data.filteredCount || taskCount;
              
              output += `🎉 恭喜!今天已完成 **${totalCount}** 个任务`;
              if (taskCount < totalCount) {
                output += `(显示前 ${taskCount} 个)`;
              }
              output += `:\\n\\n`;
              
              // 按项目分组显示任务
              const tasksByProject = groupTasksByProject(data.tasks);
              
              tasksByProject.forEach((tasks, projectName) => {
                if (tasksByProject.size > 1) {
                  output += `## 📁 ${projectName}\\n`;
                }
                
                tasks.forEach((task: any) => {
                  output += formatCompletedTask(task);
                  output += '\\n';
                });
                
                if (tasksByProject.size > 1) {
                  output += '\\n';
                }
              });
              
              // 显示总结
              output += `\\n---\\n📊 **今日完成总结**: ${totalCount} 个任务已完成\\n`;
              output += `📅 **查询时间**: ${new Date().toLocaleString()}\\n`;
            }
          } else {
            output += "无法获取任务数据\\n";
          }
          
          return output;
        }
        
        return "无法解析 OmniFocus 返回结果";
        
      } catch (error) {
        console.error("Error in getTodayCompletedTasks:", error);
        throw new Error(`获取今天完成的任务失败: ${error instanceof Error ? error.message : 'Unknown error'}`);
      }
    }
  • Helper functions to group tasks by project and format individual completed tasks with details like completion time, estimates, notes, and tags.
    function groupTasksByProject(tasks: any[]): Map<string, any[]> {
      const grouped = new Map<string, any[]>();
      
      tasks.forEach(task => {
        const projectName = task.projectName || (task.inInbox ? '📥 收件箱' : '📂 无项目');
        
        if (!grouped.has(projectName)) {
          grouped.set(projectName, []);
        }
        grouped.get(projectName)!.push(task);
      });
      
      return grouped;
    }
    
    // 格式化单个完成任务
    function formatCompletedTask(task: any): string {
      let output = '';
      
      // 任务基本信息
      const flagSymbol = task.flagged ? '🚩 ' : '';
      
      output += `✅ ${flagSymbol}${task.name}`;
      
      // 完成时间
      if (task.completedDate) {
        const completedTime = new Date(task.completedDate).toLocaleTimeString('zh-CN', {
          hour: '2-digit',
          minute: '2-digit'
        });
        output += ` *(${completedTime}完成)*`;
      }
      
      // 其他信息
      const additionalInfo: string[] = [];
      
      if (task.estimatedMinutes) {
        const hours = Math.floor(task.estimatedMinutes / 60);
        const minutes = task.estimatedMinutes % 60;
        if (hours > 0) {
          additionalInfo.push(`⏱ ${hours}h${minutes > 0 ? `${minutes}m` : ''}`);
        } else {
          additionalInfo.push(`⏱ ${minutes}m`);
        }
      }
      
      if (additionalInfo.length > 0) {
        output += ` (${additionalInfo.join(', ')})`;
      }
      
      output += '\\n';
      
      // 任务备注
      if (task.note && task.note.trim()) {
        output += `  📝 ${task.note.trim()}\\n`;
      }
      
      // 标签
      if (task.tags && task.tags.length > 0) {
        const tagNames = task.tags.map((tag: any) => tag.name).join(', ');
        output += `  🏷 ${tagNames}\\n`;
      }
      
      return output;
    }
Behavior2/5

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

With no annotations provided, the description carries full burden for behavioral disclosure. It states this is a read operation ('Get', 'view'), which is helpful, but lacks details on permissions, rate limits, pagination, or what defines 'completed' (e.g., marked done today vs. completed earlier). For a tool with no annotation coverage, this leaves significant gaps in understanding its behavior.

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

Conciseness4/5

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

The description is brief and front-loaded with the core purpose. Both sentences are relevant, though 'view today's accomplishments' is slightly redundant with the first part. It avoids unnecessary fluff and efficiently communicates the tool's intent in two concise phrases.

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 low complexity (1 parameter, 100% schema coverage, no output schema), the description is minimally adequate. It covers the basic purpose but lacks behavioral details that would be helpful without annotations, such as return format or completion criteria. For a simple read tool, it's passable but not comprehensive.

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?

Schema description coverage is 100%, so the schema fully documents the single 'limit' parameter. The description adds no parameter-specific information beyond implying temporal filtering ('today'), which isn't reflected in the schema. This meets the baseline of 3 since the schema does the heavy lifting, but the description doesn't compensate or add meaningful semantic context.

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 tool's purpose: 'Get tasks completed today' specifies the verb (get) and resource (tasks) with a temporal filter (completed today). It distinguishes from siblings like get_flagged_tasks or get_inbox_tasks by focusing on completion status and timeframe. However, it doesn't explicitly differentiate from get_custom_perspective_tasks which might also filter by date.

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites, exclusions, or compare with sibling tools like filter_tasks or get_custom_perspective_tasks that might offer similar functionality. The phrase 'view today's accomplishments' is motivational but doesn't add practical usage context.

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