Skip to main content
Glama
jhirono

Microsoft Todo MCP Service

create-task

Add new tasks to Microsoft Todo lists with titles, descriptions, due dates, priorities, and reminders to organize work and personal projects.

Instructions

Create a new task in a specific Microsoft Todo list. A task is the main todo item that can have a title, description, due date, and other properties.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
listIdYesID of the task list
titleYesTitle of the task
bodyNoDescription or body content of the task
dueDateTimeNoDue date in ISO format (e.g., 2023-12-31T23:59:59Z)
startDateTimeNoStart date in ISO format (e.g., 2023-12-31T23:59:59Z)
importanceNoTask importance
isReminderOnNoWhether to enable reminder for this task
reminderDateTimeNoReminder date and time in ISO format
statusNoStatus of the task
categoriesNoCategories associated with the task

Implementation Reference

  • Registration of the 'create-task' MCP tool using server.tool(). Includes inline schema definition and handler implementation. The tool creates a new task in Microsoft To Do via Graph API.
    server.tool(
      "create-task",
      "Create a new task in a specific Microsoft Todo list. A task is the main todo item that can have a title, description, due date, and other properties.",
      {
        listId: z.string().describe("ID of the task list"),
        title: z.string().describe("Title of the task"),
        body: z.string().optional().describe("Description or body content of the task"),
        dueDateTime: z.string().optional().describe("Due date in ISO format (e.g., 2023-12-31T23:59:59Z)"),
        startDateTime: z.string().optional().describe("Start date in ISO format (e.g., 2023-12-31T23:59:59Z)"),
        importance: z.enum(["low", "normal", "high"]).optional().describe("Task importance"),
        isReminderOn: z.boolean().optional().describe("Whether to enable reminder for this task"),
        reminderDateTime: z.string().optional().describe("Reminder date and time in ISO format"),
        status: z.enum(["notStarted", "inProgress", "completed", "waitingOnOthers", "deferred"]).optional().describe("Status of the task"),
        categories: z.array(z.string()).optional().describe("Categories associated with the task")
      },
      async ({ listId, title, body, dueDateTime, startDateTime, importance, isReminderOn, reminderDateTime, status, categories }) => {
        try {
          const token = await getAccessToken();
          if (!token) {
            return {
              content: [
                {
                  type: "text",
                  text: "Failed to authenticate with Microsoft API",
                },
              ],
            };
          }
    
          // Construct the task body with all supported properties
          const taskBody: any = { title };
          
          // Add optional properties if provided
          if (body) {
            taskBody.body = {
              content: body,
              contentType: "text"
            };
          }
          
          if (dueDateTime) {
            taskBody.dueDateTime = {
              dateTime: dueDateTime,
              timeZone: "UTC",
            };
          }
          
          if (startDateTime) {
            taskBody.startDateTime = {
              dateTime: startDateTime,
              timeZone: "UTC",
            };
          }
          
          if (importance) {
            taskBody.importance = importance;
          }
          
          if (isReminderOn !== undefined) {
            taskBody.isReminderOn = isReminderOn;
          }
          
          if (reminderDateTime) {
            taskBody.reminderDateTime = {
              dateTime: reminderDateTime,
              timeZone: "UTC",
            };
          }
          
          if (status) {
            taskBody.status = status;
          }
          
          if (categories && categories.length > 0) {
            taskBody.categories = categories;
          }
    
          const response = await makeGraphRequest<Task>(
            `${MS_GRAPH_BASE}/me/todo/lists/${listId}/tasks`,
            token,
            "POST",
            taskBody
          );
          
          if (!response) {
            return {
              content: [
                {
                  type: "text",
                  text: `Failed to create task in list: ${listId}`,
                },
              ],
            };
          }
    
          return {
            content: [
              {
                type: "text",
                text: `Task created successfully!\nID: ${response.id}\nTitle: ${response.title}`,
              },
            ],
          };
        } catch (error) {
          return {
            content: [
              {
                type: "text",
                text: `Error creating task: ${error}`,
              },
            ],
          };
        }
      }
    );
  • The core handler logic for executing the 'create-task' tool. Handles authentication, builds the task payload from inputs, calls makeGraphRequest to POST to Graph API, and returns success/error messages.
    async ({ listId, title, body, dueDateTime, startDateTime, importance, isReminderOn, reminderDateTime, status, categories }) => {
      try {
        const token = await getAccessToken();
        if (!token) {
          return {
            content: [
              {
                type: "text",
                text: "Failed to authenticate with Microsoft API",
              },
            ],
          };
        }
    
        // Construct the task body with all supported properties
        const taskBody: any = { title };
        
        // Add optional properties if provided
        if (body) {
          taskBody.body = {
            content: body,
            contentType: "text"
          };
        }
        
        if (dueDateTime) {
          taskBody.dueDateTime = {
            dateTime: dueDateTime,
            timeZone: "UTC",
          };
        }
        
        if (startDateTime) {
          taskBody.startDateTime = {
            dateTime: startDateTime,
            timeZone: "UTC",
          };
        }
        
        if (importance) {
          taskBody.importance = importance;
        }
        
        if (isReminderOn !== undefined) {
          taskBody.isReminderOn = isReminderOn;
        }
        
        if (reminderDateTime) {
          taskBody.reminderDateTime = {
            dateTime: reminderDateTime,
            timeZone: "UTC",
          };
        }
        
        if (status) {
          taskBody.status = status;
        }
        
        if (categories && categories.length > 0) {
          taskBody.categories = categories;
        }
    
        const response = await makeGraphRequest<Task>(
          `${MS_GRAPH_BASE}/me/todo/lists/${listId}/tasks`,
          token,
          "POST",
          taskBody
        );
        
        if (!response) {
          return {
            content: [
              {
                type: "text",
                text: `Failed to create task in list: ${listId}`,
              },
            ],
          };
        }
    
        return {
          content: [
            {
              type: "text",
              text: `Task created successfully!\nID: ${response.id}\nTitle: ${response.title}`,
            },
          ],
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `Error creating task: ${error}`,
            },
          ],
        };
      }
    }
  • Input validation schema for the 'create-task' tool using Zod. Defines required listId and title, and optional fields for body, dates, importance, status, etc.
      listId: z.string().describe("ID of the task list"),
      title: z.string().describe("Title of the task"),
      body: z.string().optional().describe("Description or body content of the task"),
      dueDateTime: z.string().optional().describe("Due date in ISO format (e.g., 2023-12-31T23:59:59Z)"),
      startDateTime: z.string().optional().describe("Start date in ISO format (e.g., 2023-12-31T23:59:59Z)"),
      importance: z.enum(["low", "normal", "high"]).optional().describe("Task importance"),
      isReminderOn: z.boolean().optional().describe("Whether to enable reminder for this task"),
      reminderDateTime: z.string().optional().describe("Reminder date and time in ISO format"),
      status: z.enum(["notStarted", "inProgress", "completed", "waitingOnOthers", "deferred"]).optional().describe("Status of the task"),
      categories: z.array(z.string()).optional().describe("Categories associated with the task")
    },
  • Supporting helper function 'makeGraphRequest' used by the create-task handler to perform authenticated HTTP requests to the Microsoft Graph API, handling errors like personal account limitations.
    async function makeGraphRequest<T>(url: string, token: string, method = "GET", body?: any): Promise<T | null> {
      const headers = {
        "User-Agent": USER_AGENT,
        "Accept": "application/json",
        "Authorization": `Bearer ${token}`,
        "Content-Type": "application/json"
      };
    
      try {
        const options: RequestInit = { 
          method, 
          headers 
        };
    
        if (body && (method === "POST" || method === "PATCH")) {
          options.body = JSON.stringify(body);
        }
    
        console.error(`Making request to: ${url}`);
        console.error(`Request options: ${JSON.stringify({
          method,
          headers: {
            ...headers,
            Authorization: 'Bearer [REDACTED]'
          }
        })}`);
    
        const response = await fetch(url, options);
        
        if (!response.ok) {
          const errorText = await response.text();
          console.error(`HTTP error! status: ${response.status}, body: ${errorText}`);
          
          // Check for the specific MailboxNotEnabledForRESTAPI error
          if (errorText.includes('MailboxNotEnabledForRESTAPI')) {
            console.error(`
    =================================================================
    ERROR: MailboxNotEnabledForRESTAPI
    
    The Microsoft To Do API is not available for personal Microsoft accounts 
    (outlook.com, hotmail.com, live.com, etc.) through the Graph API.
    
    This is a limitation of the Microsoft Graph API, not an authentication issue.
    Microsoft only allows To Do API access for Microsoft 365 business accounts.
    
    You can still use Microsoft To Do through the web interface or mobile apps,
    but API access is restricted for personal accounts.
    =================================================================
            `);
            
            throw new Error("Microsoft To Do API is not available for personal Microsoft accounts. See console for details.");
          }
          
          throw new Error(`HTTP error! status: ${response.status}, body: ${errorText}`);
        }
        
        const data = await response.json();
        console.error(`Response received: ${JSON.stringify(data).substring(0, 200)}...`);
        return data as T;
      } catch (error) {
        console.error("Error making Graph API request:", error);
        return null;
      }
    }
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 creation operation but doesn't mention permissions required, whether it's idempotent, error conditions, or what happens on success (e.g., returns task ID). The description only covers basic functionality without behavioral traits.

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 appropriately concise with two sentences that directly address the tool's purpose. It's front-loaded with the core action and avoids unnecessary elaboration. However, the second sentence could be slightly more focused on tool usage rather than general task definition.

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

Completeness2/5

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

For a creation tool with 10 parameters, no annotations, and no output schema, the description is incomplete. It doesn't address behavioral aspects like authentication needs, error handling, or return values. While the schema covers parameters well, the description lacks context about the tool's operation in the broader system.

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 already documents all 10 parameters thoroughly. The description mentions some properties ('title, description, due date, and other properties') but adds minimal semantic value beyond what's in the schema. Baseline 3 is appropriate when schema does heavy lifting.

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 ('Create a new task') and resource ('in a specific Microsoft Todo list'), with additional context about what a task is. However, it doesn't explicitly differentiate from sibling tools like 'create-checklist-item' or 'create-task-list', which would be needed for a score of 5.

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 like 'create-checklist-item' or 'update-task'. It mentions the context ('in a specific Microsoft Todo list') but doesn't specify prerequisites, exclusions, or comparison with sibling tools.

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

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