Skip to main content
Glama
jhirono

Microsoft Todo MCP Service

get-tasks

Retrieve tasks from a Microsoft Todo list with options to filter, sort, and select specific properties for task management.

Instructions

Get tasks from a specific Microsoft Todo list. These are the main todo items that can contain checklist items (subtasks).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
listIdYesID of the task list
filterNoOData $filter query (e.g., 'status eq \'completed\'')
selectNoComma-separated list of properties to include (e.g., 'id,title,status')
orderbyNoProperty to sort by (e.g., 'createdDateTime desc')
topNoMaximum number of tasks to retrieve
skipNoNumber of tasks to skip
countNoWhether to include a count of tasks

Implementation Reference

  • Handler function that authenticates with Microsoft Graph, constructs the API URL with optional OData query parameters (filter, select, orderby, top, skip, count), fetches tasks from /me/todo/lists/{listId}/tasks, formats each task with ID, title, status indicator, due date, importance, categories, and description preview, and returns formatted text response with optional total count.
    async ({ listId, filter, select, orderby, top, skip, count }) => {
      try {
        const token = await getAccessToken();
        if (!token) {
          return {
            content: [
              {
                type: "text",
                text: "Failed to authenticate with Microsoft API",
              },
            ],
          };
        }
    
        // Build the query parameters
        const queryParams = new URLSearchParams();
        
        if (filter) queryParams.append('$filter', filter);
        if (select) queryParams.append('$select', select);
        if (orderby) queryParams.append('$orderby', orderby);
        if (top !== undefined) queryParams.append('$top', top.toString());
        if (skip !== undefined) queryParams.append('$skip', skip.toString());
        if (count !== undefined) queryParams.append('$count', count.toString());
        
        // Construct the URL with query parameters
        const queryString = queryParams.toString();
        const url = `${MS_GRAPH_BASE}/me/todo/lists/${listId}/tasks${queryString ? '?' + queryString : ''}`;
        
        console.error(`Making request to: ${url}`);
    
        const response = await makeGraphRequest<{ value: Task[], '@odata.count'?: number }>(
          url,
          token
        );
        
        if (!response) {
          return {
            content: [
              {
                type: "text",
                text: `Failed to retrieve tasks for list: ${listId}`,
              },
            ],
          };
        }
    
        const tasks = response.value || [];
        if (tasks.length === 0) {
          return {
            content: [
              {
                type: "text",
                text: `No tasks found in list with ID: ${listId}`,
              },
            ],
          };
        }
    
        // Format the tasks based on available properties
        const formattedTasks = tasks.map((task) => {
          // Default format
          let taskInfo = `ID: ${task.id}\nTitle: ${task.title}`;
          
          // Add status if available
          if (task.status) {
            const status = task.status === "completed" ? "✓" : "○";
            taskInfo = `${status} ${taskInfo}`;
          }
          
          // Add due date if available
          if (task.dueDateTime) {
            taskInfo += `\nDue: ${new Date(task.dueDateTime.dateTime).toLocaleDateString()}`;
          }
          
          // Add importance if available
          if (task.importance) {
            taskInfo += `\nImportance: ${task.importance}`;
          }
          
          // Add categories if available
          if (task.categories && task.categories.length > 0) {
            taskInfo += `\nCategories: ${task.categories.join(', ')}`;
          }
          
          // Add body content if available and not empty
          if (task.body && task.body.content && task.body.content.trim() !== '') {
            const previewLength = 50;
            const contentPreview = task.body.content.length > previewLength 
              ? task.body.content.substring(0, previewLength) + '...' 
              : task.body.content;
            taskInfo += `\nDescription: ${contentPreview}`;
          }
          
          return `${taskInfo}\n---`;
        });
    
        // Add count information if requested and available
        let countInfo = '';
        if (count && response['@odata.count'] !== undefined) {
          countInfo = `Total count: ${response['@odata.count']}\n\n`;
        }
    
        return {
          content: [
            {
              type: "text",
              text: `Tasks in list ${listId}:\n\n${countInfo}${formattedTasks.join("\n")}`,
            },
          ],
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `Error fetching tasks: ${error}`,
            },
          ],
        };
      }
    }
  • Zod input schema defining parameters for the get-tasks tool: required listId, optional OData filter, select, orderby, top, skip, and count.
    {
      listId: z.string().describe("ID of the task list"),
      filter: z.string().optional().describe("OData $filter query (e.g., 'status eq \\'completed\\'')"),
      select: z.string().optional().describe("Comma-separated list of properties to include (e.g., 'id,title,status')"),
      orderby: z.string().optional().describe("Property to sort by (e.g., 'createdDateTime desc')"),
      top: z.number().optional().describe("Maximum number of tasks to retrieve"),
      skip: z.number().optional().describe("Number of tasks to skip"),
      count: z.boolean().optional().describe("Whether to include a count of tasks")
    },
  • Registration of the get-tasks tool on the MCP server using server.tool(), specifying name, description, input schema, and inline handler function.
    server.tool(
      "get-tasks",
      "Get tasks from a specific Microsoft Todo list. These are the main todo items that can contain checklist items (subtasks).",
      {
        listId: z.string().describe("ID of the task list"),
        filter: z.string().optional().describe("OData $filter query (e.g., 'status eq \\'completed\\'')"),
        select: z.string().optional().describe("Comma-separated list of properties to include (e.g., 'id,title,status')"),
        orderby: z.string().optional().describe("Property to sort by (e.g., 'createdDateTime desc')"),
        top: z.number().optional().describe("Maximum number of tasks to retrieve"),
        skip: z.number().optional().describe("Number of tasks to skip"),
        count: z.boolean().optional().describe("Whether to include a count of tasks")
      },
      async ({ listId, filter, select, orderby, top, skip, count }) => {
        try {
          const token = await getAccessToken();
          if (!token) {
            return {
              content: [
                {
                  type: "text",
                  text: "Failed to authenticate with Microsoft API",
                },
              ],
            };
          }
    
          // Build the query parameters
          const queryParams = new URLSearchParams();
          
          if (filter) queryParams.append('$filter', filter);
          if (select) queryParams.append('$select', select);
          if (orderby) queryParams.append('$orderby', orderby);
          if (top !== undefined) queryParams.append('$top', top.toString());
          if (skip !== undefined) queryParams.append('$skip', skip.toString());
          if (count !== undefined) queryParams.append('$count', count.toString());
          
          // Construct the URL with query parameters
          const queryString = queryParams.toString();
          const url = `${MS_GRAPH_BASE}/me/todo/lists/${listId}/tasks${queryString ? '?' + queryString : ''}`;
          
          console.error(`Making request to: ${url}`);
    
          const response = await makeGraphRequest<{ value: Task[], '@odata.count'?: number }>(
            url,
            token
          );
          
          if (!response) {
            return {
              content: [
                {
                  type: "text",
                  text: `Failed to retrieve tasks for list: ${listId}`,
                },
              ],
            };
          }
    
          const tasks = response.value || [];
          if (tasks.length === 0) {
            return {
              content: [
                {
                  type: "text",
                  text: `No tasks found in list with ID: ${listId}`,
                },
              ],
            };
          }
    
          // Format the tasks based on available properties
          const formattedTasks = tasks.map((task) => {
            // Default format
            let taskInfo = `ID: ${task.id}\nTitle: ${task.title}`;
            
            // Add status if available
            if (task.status) {
              const status = task.status === "completed" ? "✓" : "○";
              taskInfo = `${status} ${taskInfo}`;
            }
            
            // Add due date if available
            if (task.dueDateTime) {
              taskInfo += `\nDue: ${new Date(task.dueDateTime.dateTime).toLocaleDateString()}`;
            }
            
            // Add importance if available
            if (task.importance) {
              taskInfo += `\nImportance: ${task.importance}`;
            }
            
            // Add categories if available
            if (task.categories && task.categories.length > 0) {
              taskInfo += `\nCategories: ${task.categories.join(', ')}`;
            }
            
            // Add body content if available and not empty
            if (task.body && task.body.content && task.body.content.trim() !== '') {
              const previewLength = 50;
              const contentPreview = task.body.content.length > previewLength 
                ? task.body.content.substring(0, previewLength) + '...' 
                : task.body.content;
              taskInfo += `\nDescription: ${contentPreview}`;
            }
            
            return `${taskInfo}\n---`;
          });
    
          // Add count information if requested and available
          let countInfo = '';
          if (count && response['@odata.count'] !== undefined) {
            countInfo = `Total count: ${response['@odata.count']}\n\n`;
          }
    
          return {
            content: [
              {
                type: "text",
                text: `Tasks in list ${listId}:\n\n${countInfo}${formattedTasks.join("\n")}`,
              },
            ],
          };
        } catch (error) {
          return {
            content: [
              {
                type: "text",
                text: `Error fetching tasks: ${error}`,
              },
            ],
          };
        }
      }
    );

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/jhirono/todoMCP'

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