outlook-mcp
Version:
Comprehensive MCP server for Claude to access Microsoft Outlook and Teams via Microsoft Graph API - including Email, Calendar, Contacts, Tasks, Teams, Chats, and Online Meetings
133 lines (114 loc) • 3.94 kB
JavaScript
/**
* List tasks functionality
*/
const { callGraphAPI } = require('../utils/graph-api');
const { ensureAuthenticated } = require('../auth');
const config = require('../config');
/**
* List tasks handler
* @param {object} args - Tool arguments
* @returns {object} - MCP response
*/
async function handleListTasks(args) {
try {
const {
listId,
status = 'all', // all, notStarted, inProgress, completed
count = config.DEFAULT_PAGE_SIZE,
orderBy = 'createdDateTime desc'
} = args;
// Ensure user is authenticated
const accessToken = await ensureAuthenticated();
// Validate count parameter
const validCount = Math.min(Math.max(1, count), config.MAX_RESULT_COUNT);
// Build the API path
let apiPath = 'me/todo/lists';
// If no specific list ID is provided, get tasks from all lists
if (listId) {
apiPath = `me/todo/lists/${listId}/tasks`;
} else {
// Get default task list
const listsResponse = await callGraphAPI(accessToken, 'GET', apiPath, null, { '$select': 'id,displayName,isOwner' });
const defaultList = listsResponse.value.find(list => list.displayName === 'Tasks') || listsResponse.value[0];
if (!defaultList) {
return {
error: {
code: -32603,
message: "No task lists found"
}
};
}
apiPath = `me/todo/lists/${defaultList.id}/tasks`;
}
// Build query parameters
const queryParams = {
'$select': config.TASKS_SELECT_FIELDS,
'$top': validCount,
'$orderby': orderBy
};
// Add status filter if specified
if (status !== 'all') {
queryParams['$filter'] = `status eq '${status}'`;
}
console.error(`Fetching ${validCount} tasks with status: ${status}`);
// Make API call
const response = await callGraphAPI(accessToken, 'GET', apiPath, null, queryParams);
const tasks = response.value || [];
// Format the response
const formatDate = (dateStr) => {
if (!dateStr) return 'Not set';
return new Date(dateStr).toLocaleDateString();
};
const formatDateTime = (dateStr) => {
if (!dateStr) return 'Not set';
return new Date(dateStr).toLocaleString();
};
const getStatusIcon = (status) => {
switch (status) {
case 'completed': return '✅';
case 'inProgress': return '🔄';
case 'notStarted': return '📋';
default: return '❓';
}
};
const getImportanceIcon = (importance) => {
switch (importance) {
case 'high': return '🔴';
case 'normal': return '🟡';
case 'low': return '🟢';
default: return '⚪';
}
};
return {
content: [
{
type: "text",
text: `Found ${tasks.length} tasks:\n\n${tasks.map(task => {
const title = task.title || 'No title';
const statusIcon = getStatusIcon(task.status);
const importanceIcon = getImportanceIcon(task.importance);
const dueDate = formatDate(task.dueDateTime?.dateTime);
const reminderDate = formatDateTime(task.reminderDateTime?.dateTime);
const hasReminder = task.isReminderOn ? '🔔' : '';
return `${statusIcon} ${importanceIcon} ${title} ${hasReminder}
ID: ${task.id}
Status: ${task.status || 'Not set'}
Due: ${dueDate}
Reminder: ${reminderDate}
Created: ${formatDateTime(task.createdDateTime)}
${task.body?.content ? `Notes: ${task.body.content.substring(0, 100)}...` : ''}`;
}).join('\n\n')}`
}
]
};
} catch (error) {
console.error('Error in handleListTasks:', error);
return {
error: {
code: -32603,
message: `Failed to list tasks: ${error.message}`
}
};
}
}
module.exports = handleListTasks;