@littlebearapps/outlook-assistant 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +22 -0
- package/LICENSE +21 -0
- package/README.md +422 -0
- package/advanced/index.js +652 -0
- package/auth/index.js +32 -0
- package/auth/oauth-server.js +233 -0
- package/auth/token-manager.js +105 -0
- package/auth/token-storage.js +359 -0
- package/auth/tools.js +159 -0
- package/calendar/accept.js +72 -0
- package/calendar/cancel.js +72 -0
- package/calendar/create.js +115 -0
- package/calendar/decline.js +72 -0
- package/calendar/delete.js +67 -0
- package/calendar/index.js +130 -0
- package/calendar/list.js +108 -0
- package/categories/index.js +955 -0
- package/config.js +95 -0
- package/contacts/index.js +754 -0
- package/email/attachments.js +365 -0
- package/email/conversations.js +666 -0
- package/email/delta.js +210 -0
- package/email/export.js +572 -0
- package/email/folder-utils.js +192 -0
- package/email/headers.js +344 -0
- package/email/index.js +537 -0
- package/email/list.js +136 -0
- package/email/mark-as-read.js +114 -0
- package/email/mime.js +286 -0
- package/email/read.js +161 -0
- package/email/search.js +628 -0
- package/email/send.js +169 -0
- package/folder/create.js +137 -0
- package/folder/delete.js +108 -0
- package/folder/index.js +112 -0
- package/folder/list.js +289 -0
- package/folder/move.js +186 -0
- package/folder/stats.js +322 -0
- package/index.js +162 -0
- package/llms.txt +76 -0
- package/outlook-auth-server.js +384 -0
- package/package.json +97 -0
- package/rules/create.js +273 -0
- package/rules/index.js +276 -0
- package/rules/list.js +216 -0
- package/settings/index.js +678 -0
- package/utils/field-presets.js +311 -0
- package/utils/graph-api.js +268 -0
- package/utils/mock-data.js +154 -0
- package/utils/odata-helpers.js +33 -0
- package/utils/response-formatter.js +457 -0
- package/utils/safety.js +123 -0
package/auth/tools.js
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication-related tools for the Outlook Assistant server
|
|
3
|
+
*/
|
|
4
|
+
const config = require('../config');
|
|
5
|
+
const tokenManager = require('./token-manager');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* About tool handler
|
|
9
|
+
* @returns {object} - MCP response
|
|
10
|
+
*/
|
|
11
|
+
async function handleAbout() {
|
|
12
|
+
const scopes = config.AUTH_CONFIG.scopes.filter(
|
|
13
|
+
(s) => s !== 'offline_access'
|
|
14
|
+
);
|
|
15
|
+
const testMode = config.USE_TEST_MODE ? 'Enabled' : 'Disabled';
|
|
16
|
+
const rateLimit =
|
|
17
|
+
process.env.OUTLOOK_MAX_EMAILS_PER_SESSION || 'Unlimited (no limit set)';
|
|
18
|
+
const allowlist =
|
|
19
|
+
process.env.OUTLOOK_ALLOWED_RECIPIENTS || 'None (all recipients allowed)';
|
|
20
|
+
|
|
21
|
+
const lines = [
|
|
22
|
+
`# Outlook Assistant Server v${config.SERVER_VERSION}\n`,
|
|
23
|
+
`Provides access to Microsoft Outlook email, calendar, and contacts through Microsoft Graph API.\n`,
|
|
24
|
+
`## Diagnostics\n`,
|
|
25
|
+
`| Setting | Value |`,
|
|
26
|
+
`|---------|-------|`,
|
|
27
|
+
`| Tools | 20 across 9 modules |`,
|
|
28
|
+
`| Modules | auth, email, calendar, folder, rules, contacts, categories, settings, advanced |`,
|
|
29
|
+
`| Timezone | ${config.DEFAULT_TIMEZONE} |`,
|
|
30
|
+
`| Test Mode | ${testMode} |`,
|
|
31
|
+
`| Rate Limit | ${rateLimit} |`,
|
|
32
|
+
`| Recipient Allowlist | ${allowlist} |`,
|
|
33
|
+
`| Scopes | ${scopes.length} configured |`,
|
|
34
|
+
``,
|
|
35
|
+
`**Scopes**: ${scopes.join(', ')}`,
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
content: [
|
|
40
|
+
{
|
|
41
|
+
type: 'text',
|
|
42
|
+
text: lines.join('\n'),
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Authentication tool handler
|
|
50
|
+
* @param {object} args - Tool arguments
|
|
51
|
+
* @returns {object} - MCP response
|
|
52
|
+
*/
|
|
53
|
+
async function handleAuthenticate(args) {
|
|
54
|
+
const _force = args && args.force === true;
|
|
55
|
+
|
|
56
|
+
// For test mode, create a test token
|
|
57
|
+
if (config.USE_TEST_MODE) {
|
|
58
|
+
// Create a test token with a 1-hour expiry
|
|
59
|
+
tokenManager.createTestTokens();
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
content: [
|
|
63
|
+
{
|
|
64
|
+
type: 'text',
|
|
65
|
+
text: 'Successfully authenticated with Microsoft Graph API (test mode)',
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// For real authentication, generate an auth URL and instruct the user to visit it
|
|
72
|
+
const authUrl = `${config.AUTH_CONFIG.authServerUrl}/auth?client_id=${config.AUTH_CONFIG.clientId}`;
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
content: [
|
|
76
|
+
{
|
|
77
|
+
type: 'text',
|
|
78
|
+
text: `Authentication required. Please visit the following URL to authenticate with Microsoft: ${authUrl}\n\nAfter authentication, you will be redirected back to this application.`,
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Check authentication status tool handler
|
|
86
|
+
* @returns {object} - MCP response
|
|
87
|
+
*/
|
|
88
|
+
async function handleCheckAuthStatus() {
|
|
89
|
+
console.error('[CHECK-AUTH-STATUS] Starting authentication status check');
|
|
90
|
+
|
|
91
|
+
const tokens = tokenManager.loadTokenCache();
|
|
92
|
+
|
|
93
|
+
console.error(`[CHECK-AUTH-STATUS] Tokens loaded: ${tokens ? 'YES' : 'NO'}`);
|
|
94
|
+
|
|
95
|
+
if (!tokens || !tokens.access_token) {
|
|
96
|
+
console.error('[CHECK-AUTH-STATUS] No valid access token found');
|
|
97
|
+
return {
|
|
98
|
+
content: [{ type: 'text', text: 'Not authenticated' }],
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.error('[CHECK-AUTH-STATUS] Access token present');
|
|
103
|
+
console.error(`[CHECK-AUTH-STATUS] Token expires at: ${tokens.expires_at}`);
|
|
104
|
+
console.error(`[CHECK-AUTH-STATUS] Current time: ${Date.now()}`);
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
content: [{ type: 'text', text: 'Authenticated and ready' }],
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Tool definitions
|
|
112
|
+
const authTools = [
|
|
113
|
+
{
|
|
114
|
+
name: 'auth',
|
|
115
|
+
description:
|
|
116
|
+
'Manage authentication with Microsoft Graph API. action=status (default) checks auth state, action=authenticate starts OAuth flow, action=about shows server info.',
|
|
117
|
+
annotations: {
|
|
118
|
+
title: 'Authentication',
|
|
119
|
+
readOnlyHint: false,
|
|
120
|
+
destructiveHint: false,
|
|
121
|
+
openWorldHint: false,
|
|
122
|
+
},
|
|
123
|
+
inputSchema: {
|
|
124
|
+
type: 'object',
|
|
125
|
+
properties: {
|
|
126
|
+
action: {
|
|
127
|
+
type: 'string',
|
|
128
|
+
enum: ['status', 'authenticate', 'about'],
|
|
129
|
+
description: 'Action to perform (default: status)',
|
|
130
|
+
},
|
|
131
|
+
force: {
|
|
132
|
+
type: 'boolean',
|
|
133
|
+
description:
|
|
134
|
+
'Force re-authentication even if already authenticated (action=authenticate only)',
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
required: [],
|
|
138
|
+
},
|
|
139
|
+
handler: async (args) => {
|
|
140
|
+
const action = args.action || 'status';
|
|
141
|
+
switch (action) {
|
|
142
|
+
case 'authenticate':
|
|
143
|
+
return handleAuthenticate(args);
|
|
144
|
+
case 'about':
|
|
145
|
+
return handleAbout();
|
|
146
|
+
case 'status':
|
|
147
|
+
default:
|
|
148
|
+
return handleCheckAuthStatus();
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
];
|
|
153
|
+
|
|
154
|
+
module.exports = {
|
|
155
|
+
authTools,
|
|
156
|
+
handleAbout,
|
|
157
|
+
handleAuthenticate,
|
|
158
|
+
handleCheckAuthStatus,
|
|
159
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accept event functionality
|
|
3
|
+
*/
|
|
4
|
+
const { callGraphAPI } = require('../utils/graph-api');
|
|
5
|
+
const { ensureAuthenticated } = require('../auth');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Accept event handler
|
|
9
|
+
* @param {object} args - Tool arguments
|
|
10
|
+
* @returns {object} - MCP response
|
|
11
|
+
*/
|
|
12
|
+
async function handleAcceptEvent(args) {
|
|
13
|
+
const { eventId, comment } = args;
|
|
14
|
+
|
|
15
|
+
if (!eventId) {
|
|
16
|
+
return {
|
|
17
|
+
content: [
|
|
18
|
+
{
|
|
19
|
+
type: 'text',
|
|
20
|
+
text: 'Event ID is required to accept an event.',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
// Get access token
|
|
28
|
+
const accessToken = await ensureAuthenticated();
|
|
29
|
+
|
|
30
|
+
// Build API endpoint
|
|
31
|
+
const endpoint = `me/events/${eventId}/accept`;
|
|
32
|
+
|
|
33
|
+
// Request body
|
|
34
|
+
const body = {
|
|
35
|
+
comment: comment || 'Accepted via API',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Make API call
|
|
39
|
+
await callGraphAPI(accessToken, 'POST', endpoint, body);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
content: [
|
|
43
|
+
{
|
|
44
|
+
type: 'text',
|
|
45
|
+
text: `Event with ID ${eventId} has been successfully accepted.`,
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
};
|
|
49
|
+
} catch (error) {
|
|
50
|
+
if (error.message === 'Authentication required') {
|
|
51
|
+
return {
|
|
52
|
+
content: [
|
|
53
|
+
{
|
|
54
|
+
type: 'text',
|
|
55
|
+
text: "Authentication required. Please use the 'authenticate' tool first.",
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
content: [
|
|
63
|
+
{
|
|
64
|
+
type: 'text',
|
|
65
|
+
text: `Error accepting event: ${error.message}`,
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = handleAcceptEvent;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cancel event functionality
|
|
3
|
+
*/
|
|
4
|
+
const { callGraphAPI } = require('../utils/graph-api');
|
|
5
|
+
const { ensureAuthenticated } = require('../auth');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Cancel event handler
|
|
9
|
+
* @param {object} args - Tool arguments
|
|
10
|
+
* @returns {object} - MCP response
|
|
11
|
+
*/
|
|
12
|
+
async function handleCancelEvent(args) {
|
|
13
|
+
const { eventId, comment } = args;
|
|
14
|
+
|
|
15
|
+
if (!eventId) {
|
|
16
|
+
return {
|
|
17
|
+
content: [
|
|
18
|
+
{
|
|
19
|
+
type: 'text',
|
|
20
|
+
text: 'Event ID is required to cancel an event.',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
// Get access token
|
|
28
|
+
const accessToken = await ensureAuthenticated();
|
|
29
|
+
|
|
30
|
+
// Build API endpoint
|
|
31
|
+
const endpoint = `me/events/${eventId}/cancel`;
|
|
32
|
+
|
|
33
|
+
// Request body
|
|
34
|
+
const body = {
|
|
35
|
+
comment: comment || 'Cancelled via API',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Make API call
|
|
39
|
+
await callGraphAPI(accessToken, 'POST', endpoint, body);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
content: [
|
|
43
|
+
{
|
|
44
|
+
type: 'text',
|
|
45
|
+
text: `Event with ID ${eventId} has been successfully cancelled.`,
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
};
|
|
49
|
+
} catch (error) {
|
|
50
|
+
if (error.message === 'Authentication required') {
|
|
51
|
+
return {
|
|
52
|
+
content: [
|
|
53
|
+
{
|
|
54
|
+
type: 'text',
|
|
55
|
+
text: "Authentication required. Please use the 'authenticate' tool first.",
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
content: [
|
|
63
|
+
{
|
|
64
|
+
type: 'text',
|
|
65
|
+
text: `Error cancelling event: ${error.message}`,
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = handleCancelEvent;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create event functionality
|
|
3
|
+
*/
|
|
4
|
+
const { callGraphAPI } = require('../utils/graph-api');
|
|
5
|
+
const { ensureAuthenticated } = require('../auth');
|
|
6
|
+
const { DEFAULT_TIMEZONE } = require('../config');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Create event handler
|
|
10
|
+
* @param {object} args - Tool arguments
|
|
11
|
+
* @returns {object} - MCP response
|
|
12
|
+
*/
|
|
13
|
+
async function handleCreateEvent(args) {
|
|
14
|
+
const { subject, start, end, attendees, body } = args;
|
|
15
|
+
|
|
16
|
+
if (!subject || !start || !end) {
|
|
17
|
+
return {
|
|
18
|
+
content: [
|
|
19
|
+
{
|
|
20
|
+
type: 'text',
|
|
21
|
+
text: 'Subject, start, and end times are required to create an event.',
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
// Get access token
|
|
29
|
+
const accessToken = await ensureAuthenticated();
|
|
30
|
+
|
|
31
|
+
// Build API endpoint
|
|
32
|
+
const endpoint = `me/events`;
|
|
33
|
+
|
|
34
|
+
// Request body
|
|
35
|
+
const bodyContent = {
|
|
36
|
+
subject,
|
|
37
|
+
start: {
|
|
38
|
+
dateTime: start.dateTime || start,
|
|
39
|
+
timeZone: start.timeZone || DEFAULT_TIMEZONE,
|
|
40
|
+
},
|
|
41
|
+
end: {
|
|
42
|
+
dateTime: end.dateTime || end,
|
|
43
|
+
timeZone: end.timeZone || DEFAULT_TIMEZONE,
|
|
44
|
+
},
|
|
45
|
+
attendees: attendees?.map((email) => ({
|
|
46
|
+
emailAddress: { address: email },
|
|
47
|
+
type: 'required',
|
|
48
|
+
})),
|
|
49
|
+
body: { contentType: 'HTML', content: body || '' },
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Make API call
|
|
53
|
+
const response = await callGraphAPI(
|
|
54
|
+
accessToken,
|
|
55
|
+
'POST',
|
|
56
|
+
endpoint,
|
|
57
|
+
bodyContent
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const output = [`Event '${subject}' has been successfully created.`];
|
|
61
|
+
if (response.id) {
|
|
62
|
+
output.push(`**ID**: \`${response.id}\``);
|
|
63
|
+
}
|
|
64
|
+
if (response.start) {
|
|
65
|
+
output.push(
|
|
66
|
+
`**Start**: ${response.start.dateTime} (${response.start.timeZone})`
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
if (response.end) {
|
|
70
|
+
output.push(
|
|
71
|
+
`**End**: ${response.end.dateTime} (${response.end.timeZone})`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if (response.webLink) {
|
|
75
|
+
output.push(`**Link**: ${response.webLink}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
content: [
|
|
80
|
+
{
|
|
81
|
+
type: 'text',
|
|
82
|
+
text: output.join('\n'),
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
_meta: {
|
|
86
|
+
eventId: response.id,
|
|
87
|
+
subject: response.subject,
|
|
88
|
+
start: response.start,
|
|
89
|
+
end: response.end,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
} catch (error) {
|
|
93
|
+
if (error.message === 'Authentication required') {
|
|
94
|
+
return {
|
|
95
|
+
content: [
|
|
96
|
+
{
|
|
97
|
+
type: 'text',
|
|
98
|
+
text: "Authentication required. Please use the 'authenticate' tool first.",
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
content: [
|
|
106
|
+
{
|
|
107
|
+
type: 'text',
|
|
108
|
+
text: `Error creating event: ${error.message}`,
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
module.exports = handleCreateEvent;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decline event functionality
|
|
3
|
+
*/
|
|
4
|
+
const { callGraphAPI } = require('../utils/graph-api');
|
|
5
|
+
const { ensureAuthenticated } = require('../auth');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Decline event handler
|
|
9
|
+
* @param {object} args - Tool arguments
|
|
10
|
+
* @returns {object} - MCP response
|
|
11
|
+
*/
|
|
12
|
+
async function handleDeclineEvent(args) {
|
|
13
|
+
const { eventId, comment } = args;
|
|
14
|
+
|
|
15
|
+
if (!eventId) {
|
|
16
|
+
return {
|
|
17
|
+
content: [
|
|
18
|
+
{
|
|
19
|
+
type: 'text',
|
|
20
|
+
text: 'Event ID is required to decline an event.',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
// Get access token
|
|
28
|
+
const accessToken = await ensureAuthenticated();
|
|
29
|
+
|
|
30
|
+
// Build API endpoint
|
|
31
|
+
const endpoint = `me/events/${eventId}/decline`;
|
|
32
|
+
|
|
33
|
+
// Request body
|
|
34
|
+
const body = {
|
|
35
|
+
comment: comment || 'Declined via API',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Make API call
|
|
39
|
+
await callGraphAPI(accessToken, 'POST', endpoint, body);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
content: [
|
|
43
|
+
{
|
|
44
|
+
type: 'text',
|
|
45
|
+
text: `Event with ID ${eventId} has been successfully declined.`,
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
};
|
|
49
|
+
} catch (error) {
|
|
50
|
+
if (error.message === 'Authentication required') {
|
|
51
|
+
return {
|
|
52
|
+
content: [
|
|
53
|
+
{
|
|
54
|
+
type: 'text',
|
|
55
|
+
text: "Authentication required. Please use the 'authenticate' tool first.",
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
content: [
|
|
63
|
+
{
|
|
64
|
+
type: 'text',
|
|
65
|
+
text: `Error declining event: ${error.message}`,
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = handleDeclineEvent;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delete event functionality
|
|
3
|
+
*/
|
|
4
|
+
const { callGraphAPI } = require('../utils/graph-api');
|
|
5
|
+
const { ensureAuthenticated } = require('../auth');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Delete event handler
|
|
9
|
+
* @param {object} args - Tool arguments
|
|
10
|
+
* @returns {object} - MCP response
|
|
11
|
+
*/
|
|
12
|
+
async function handleDeleteEvent(args) {
|
|
13
|
+
const { eventId } = args;
|
|
14
|
+
|
|
15
|
+
if (!eventId) {
|
|
16
|
+
return {
|
|
17
|
+
content: [
|
|
18
|
+
{
|
|
19
|
+
type: 'text',
|
|
20
|
+
text: 'Event ID is required to delete an event.',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
// Get access token
|
|
28
|
+
const accessToken = await ensureAuthenticated();
|
|
29
|
+
|
|
30
|
+
// Build API endpoint
|
|
31
|
+
const endpoint = `me/events/${eventId}`;
|
|
32
|
+
|
|
33
|
+
// Make API call
|
|
34
|
+
await callGraphAPI(accessToken, 'DELETE', endpoint);
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
content: [
|
|
38
|
+
{
|
|
39
|
+
type: 'text',
|
|
40
|
+
text: `Event with ID ${eventId} has been successfully deleted.`,
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
} catch (error) {
|
|
45
|
+
if (error.message === 'Authentication required') {
|
|
46
|
+
return {
|
|
47
|
+
content: [
|
|
48
|
+
{
|
|
49
|
+
type: 'text',
|
|
50
|
+
text: "Authentication required. Please use the 'authenticate' tool first.",
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
content: [
|
|
58
|
+
{
|
|
59
|
+
type: 'text',
|
|
60
|
+
text: `Error deleting event: ${error.message}`,
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = handleDeleteEvent;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calendar module for Outlook Assistant server
|
|
3
|
+
*/
|
|
4
|
+
const handleListEvents = require('./list');
|
|
5
|
+
const handleDeclineEvent = require('./decline');
|
|
6
|
+
const handleCreateEvent = require('./create');
|
|
7
|
+
const handleCancelEvent = require('./cancel');
|
|
8
|
+
const handleDeleteEvent = require('./delete');
|
|
9
|
+
|
|
10
|
+
// Calendar tool definitions (consolidated: 5 → 3)
|
|
11
|
+
const calendarTools = [
|
|
12
|
+
{
|
|
13
|
+
name: 'list-events',
|
|
14
|
+
description: 'Lists upcoming events from your calendar',
|
|
15
|
+
annotations: {
|
|
16
|
+
title: 'List Calendar Events',
|
|
17
|
+
readOnlyHint: true,
|
|
18
|
+
openWorldHint: false,
|
|
19
|
+
},
|
|
20
|
+
inputSchema: {
|
|
21
|
+
type: 'object',
|
|
22
|
+
properties: {
|
|
23
|
+
count: {
|
|
24
|
+
type: 'number',
|
|
25
|
+
description: 'Number of events to retrieve (default: 10, max: 50)',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
required: [],
|
|
29
|
+
},
|
|
30
|
+
handler: handleListEvents,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'create-event',
|
|
34
|
+
description: 'Creates a new calendar event',
|
|
35
|
+
annotations: {
|
|
36
|
+
title: 'Create Calendar Event',
|
|
37
|
+
readOnlyHint: false,
|
|
38
|
+
destructiveHint: false,
|
|
39
|
+
openWorldHint: false,
|
|
40
|
+
},
|
|
41
|
+
inputSchema: {
|
|
42
|
+
type: 'object',
|
|
43
|
+
properties: {
|
|
44
|
+
subject: {
|
|
45
|
+
type: 'string',
|
|
46
|
+
description: 'The subject of the event',
|
|
47
|
+
},
|
|
48
|
+
start: {
|
|
49
|
+
type: 'string',
|
|
50
|
+
description: 'The start time of the event in ISO 8601 format',
|
|
51
|
+
},
|
|
52
|
+
end: {
|
|
53
|
+
type: 'string',
|
|
54
|
+
description: 'The end time of the event in ISO 8601 format',
|
|
55
|
+
},
|
|
56
|
+
attendees: {
|
|
57
|
+
type: 'array',
|
|
58
|
+
items: {
|
|
59
|
+
type: 'string',
|
|
60
|
+
},
|
|
61
|
+
description: 'List of attendee email addresses',
|
|
62
|
+
},
|
|
63
|
+
body: {
|
|
64
|
+
type: 'string',
|
|
65
|
+
description: 'Optional body content for the event',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
required: ['subject', 'start', 'end'],
|
|
69
|
+
},
|
|
70
|
+
handler: handleCreateEvent,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'manage-event',
|
|
74
|
+
description:
|
|
75
|
+
'Manage an existing calendar event. action=decline declines an invitation. action=cancel cancels an event you organised. action=delete permanently removes an event.',
|
|
76
|
+
annotations: {
|
|
77
|
+
title: 'Manage Calendar Event',
|
|
78
|
+
readOnlyHint: false,
|
|
79
|
+
destructiveHint: true,
|
|
80
|
+
openWorldHint: false,
|
|
81
|
+
},
|
|
82
|
+
inputSchema: {
|
|
83
|
+
type: 'object',
|
|
84
|
+
properties: {
|
|
85
|
+
action: {
|
|
86
|
+
type: 'string',
|
|
87
|
+
enum: ['decline', 'cancel', 'delete'],
|
|
88
|
+
description: 'Action to perform (required)',
|
|
89
|
+
},
|
|
90
|
+
eventId: {
|
|
91
|
+
type: 'string',
|
|
92
|
+
description: 'The ID of the event',
|
|
93
|
+
},
|
|
94
|
+
comment: {
|
|
95
|
+
type: 'string',
|
|
96
|
+
description: 'Optional comment for declining or cancelling the event',
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
required: ['action', 'eventId'],
|
|
100
|
+
},
|
|
101
|
+
handler: async (args) => {
|
|
102
|
+
switch (args.action) {
|
|
103
|
+
case 'decline':
|
|
104
|
+
return handleDeclineEvent(args);
|
|
105
|
+
case 'cancel':
|
|
106
|
+
return handleCancelEvent(args);
|
|
107
|
+
case 'delete':
|
|
108
|
+
return handleDeleteEvent(args);
|
|
109
|
+
default:
|
|
110
|
+
return {
|
|
111
|
+
content: [
|
|
112
|
+
{
|
|
113
|
+
type: 'text',
|
|
114
|
+
text: "Invalid action. Use 'decline', 'cancel', or 'delete'.",
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
module.exports = {
|
|
124
|
+
calendarTools,
|
|
125
|
+
handleListEvents,
|
|
126
|
+
handleDeclineEvent,
|
|
127
|
+
handleCreateEvent,
|
|
128
|
+
handleCancelEvent,
|
|
129
|
+
handleDeleteEvent,
|
|
130
|
+
};
|