Skip to main content
Glama
MAG-Cie

MCP for Microsoft To Do

export_tasks_ics

Read-only

Export tasks from Microsoft To Do to iCalendar format for import into Google Calendar, Apple Calendar, Outlook, or Thunderbird. Converts recurrence to RRULE and reminders to VALARM.

Instructions

Export tasks to iCalendar format (text/calendar VTODO) for import into Google Calendar, Apple Calendar, Outlook, Thunderbird, etc. Recurrence converted to RRULE when possible. Reminder converted to VALARM.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
list_idsNo
include_completedNo
top_per_listNo

Implementation Reference

  • Core handler function that exports tasks to iCalendar format. Iterates over task lists, builds VTODO components with UID, summary, description, due date, status, priority, categories, RRULE for recurrence, and VALARM for reminders. Returns the full VCALENDAR string.
    export async function exportTasksIcs(
      opts: {
        listIds?: string[];
        includeCompleted?: boolean;
        topPerList?: number;
      } = {}
    ): Promise<string> {
      const allLists = await listTaskLists();
      const lists = opts.listIds
        ? allLists.filter((l) => opts.listIds!.includes(l.id))
        : allLists;
    
      const filterParts: string[] = [];
      if (!opts.includeCompleted) filterParts.push("status ne 'completed'");
      const filter = filterParts.length > 0 ? filterParts.join(" and ") : undefined;
      const top = opts.topPerList ?? 100;
    
      const lines: string[] = [
        "BEGIN:VCALENDAR",
        "VERSION:2.0",
        "PRODID:-//mag-cie//mcp-microsoft-todo//FR",
        "CALSCALE:GREGORIAN",
      ];
      const now = formatIcsDate(new Date().toISOString());
    
      for (const list of lists) {
        let tasks: TodoTask[] = [];
        try {
          tasks = await listTasks(list.id, { filter, top });
        } catch {
          continue;
        }
        for (const task of tasks) {
          lines.push("BEGIN:VTODO");
          lines.push(`UID:${task.id}@mcp-microsoft-todo`);
          lines.push(`DTSTAMP:${now}`);
          lines.push(
            `SUMMARY:${escapeIcsText(`[${list.displayName}] ${task.title}`)}`
          );
          if (task.body?.content)
            lines.push(`DESCRIPTION:${escapeIcsText(task.body.content)}`);
          if (task.dueDateTime)
            lines.push(`DUE:${formatIcsDate(task.dueDateTime.dateTime)}`);
          if (task.status === "completed") lines.push("STATUS:COMPLETED");
          else if (task.status === "inProgress") lines.push("STATUS:IN-PROCESS");
          else lines.push("STATUS:NEEDS-ACTION");
          if (task.importance === "high") lines.push("PRIORITY:1");
          else if (task.importance === "low") lines.push("PRIORITY:9");
          if (task.categories?.length) {
            lines.push(
              `CATEGORIES:${task.categories.map(escapeIcsText).join(",")}`
            );
          }
          if (task.recurrence) {
            const rrule = recurrenceToRRule(task.recurrence);
            if (rrule) lines.push(`RRULE:${rrule}`);
          }
          if (task.isReminderOn && task.reminderDateTime) {
            lines.push("BEGIN:VALARM");
            lines.push("ACTION:DISPLAY");
            lines.push(
              `TRIGGER;VALUE=DATE-TIME:${formatIcsDate(task.reminderDateTime.dateTime)}`
            );
            lines.push("DESCRIPTION:Reminder");
            lines.push("END:VALARM");
          }
          lines.push("END:VTODO");
        }
      }
      lines.push("END:VCALENDAR");
      return lines.join("\r\n");
    }
  • Zod schema for export_tasks_ics input validation: optional list_ids (array of strings), include_completed (boolean), and top_per_list (positive integer up to 500).
    export_tasks_ics: z.object({
      list_ids: z
        .array(z.string())
        .optional()
        .describe("Restrict to the given list IDs. If omitted: all lists."),
      include_completed: z.boolean().optional(),
      top_per_list: z.number().int().positive().max(500).optional(),
    }),
  • src/index.ts:940-953 (registration)
    MCP tool registration: exports the tool metadata (name, description, inputSchema) alongside other tools. Annotations from ANNOTATIONS object are merged via map().
      {
        name: "export_tasks_ics",
        description:
          "Export tasks to iCalendar format (text/calendar VTODO) for import into Google Calendar, Apple Calendar, Outlook, Thunderbird, etc. Recurrence converted to RRULE when possible. Reminder converted to VALARM.",
        inputSchema: {
          type: "object",
          properties: {
            list_ids: { type: "array", items: { type: "string" } },
            include_completed: { type: "boolean" },
            top_per_list: { type: "number" },
          },
        },
      },
    ]).map((tool) => ({ ...tool, annotations: ANNOTATIONS[tool.name] })),
  • CallTool request handler case for export_tasks_ics: parses args with Zod schema, calls exportTasksIcs from graph.ts, and returns the ICS string as text content.
    case "export_tasks_ics": {
      const a = schemas.export_tasks_ics.strict().parse(args ?? {});
      const ics = await exportTasksIcs({
        listIds: a.list_ids,
        includeCompleted: a.include_completed,
        topPerList: a.top_per_list,
      });
      return text(ics);
    }
  • src/index.ts:491-492 (registration)
    ANNOTATIONS entry for export_tasks_ics tool, inheriting READ annotation.
      export_tasks_ics:       { ...READ,         title: "Export tasks as iCalendar (.ics)" },
    };
Behavior4/5

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

Annotations already indicate readOnlyHint=true, and the description adds behavioral details like conversion of recurrence to RRULE and reminders to VALARM. No contradictions; the description enhances transparency beyond annotations.

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?

Three sentences efficiently cover the tool's core functionality and important details (format, target apps, conversion specifics). No redundant information; well-structured and front-loaded.

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?

Despite clear purpose, the description lacks parameter descriptions and output format details. With no output schema and 3 undocumented parameters, the tool definition is incomplete for an AI agent to use correctly.

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

Parameters2/5

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

Schema coverage is 0%, yet the description provides no explanation of the three parameters (list_ids, include_completed, top_per_list). The AI agent must infer their meaning from names alone, which is insufficient.

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

Purpose5/5

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

The description clearly states the tool exports tasks to iCalendar format, specifying the MIME type and target applications. It includes details about conversion of recurrence and reminders, making its purpose distinct from sibling tools which focus on CRUD operations.

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

Usage Guidelines4/5

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

The description implies usage for exporting tasks to calendar apps but does not explicitly state when to use or avoid this tool. Since there are no sibling export tools, differentiation is not required, but guidance on parameter use is missing.

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/MAG-Cie/mcp-microsoft-todo'

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