@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.
Files changed (52) hide show
  1. package/.env.example +22 -0
  2. package/LICENSE +21 -0
  3. package/README.md +422 -0
  4. package/advanced/index.js +652 -0
  5. package/auth/index.js +32 -0
  6. package/auth/oauth-server.js +233 -0
  7. package/auth/token-manager.js +105 -0
  8. package/auth/token-storage.js +359 -0
  9. package/auth/tools.js +159 -0
  10. package/calendar/accept.js +72 -0
  11. package/calendar/cancel.js +72 -0
  12. package/calendar/create.js +115 -0
  13. package/calendar/decline.js +72 -0
  14. package/calendar/delete.js +67 -0
  15. package/calendar/index.js +130 -0
  16. package/calendar/list.js +108 -0
  17. package/categories/index.js +955 -0
  18. package/config.js +95 -0
  19. package/contacts/index.js +754 -0
  20. package/email/attachments.js +365 -0
  21. package/email/conversations.js +666 -0
  22. package/email/delta.js +210 -0
  23. package/email/export.js +572 -0
  24. package/email/folder-utils.js +192 -0
  25. package/email/headers.js +344 -0
  26. package/email/index.js +537 -0
  27. package/email/list.js +136 -0
  28. package/email/mark-as-read.js +114 -0
  29. package/email/mime.js +286 -0
  30. package/email/read.js +161 -0
  31. package/email/search.js +628 -0
  32. package/email/send.js +169 -0
  33. package/folder/create.js +137 -0
  34. package/folder/delete.js +108 -0
  35. package/folder/index.js +112 -0
  36. package/folder/list.js +289 -0
  37. package/folder/move.js +186 -0
  38. package/folder/stats.js +322 -0
  39. package/index.js +162 -0
  40. package/llms.txt +76 -0
  41. package/outlook-auth-server.js +384 -0
  42. package/package.json +97 -0
  43. package/rules/create.js +273 -0
  44. package/rules/index.js +276 -0
  45. package/rules/list.js +216 -0
  46. package/settings/index.js +678 -0
  47. package/utils/field-presets.js +311 -0
  48. package/utils/graph-api.js +268 -0
  49. package/utils/mock-data.js +154 -0
  50. package/utils/odata-helpers.js +33 -0
  51. package/utils/response-formatter.js +457 -0
  52. package/utils/safety.js +123 -0
package/rules/list.js ADDED
@@ -0,0 +1,216 @@
1
+ /**
2
+ * List rules functionality
3
+ */
4
+ const { callGraphAPI } = require('../utils/graph-api');
5
+ const { ensureAuthenticated } = require('../auth');
6
+
7
+ /**
8
+ * List rules handler
9
+ * @param {object} args - Tool arguments
10
+ * @returns {object} - MCP response
11
+ */
12
+ async function handleListRules(args) {
13
+ const includeDetails = args.includeDetails === true;
14
+
15
+ try {
16
+ // Get access token
17
+ const accessToken = await ensureAuthenticated();
18
+
19
+ // Get all inbox rules
20
+ const rules = await getInboxRules(accessToken);
21
+
22
+ // Format the rules based on detail level
23
+ const formattedRules = formatRulesList(rules, includeDetails);
24
+
25
+ return {
26
+ content: [
27
+ {
28
+ type: 'text',
29
+ text: formattedRules,
30
+ },
31
+ ],
32
+ };
33
+ } catch (error) {
34
+ if (error.message === 'Authentication required') {
35
+ return {
36
+ content: [
37
+ {
38
+ type: 'text',
39
+ text: "Authentication required. Please use the 'authenticate' tool first.",
40
+ },
41
+ ],
42
+ };
43
+ }
44
+
45
+ return {
46
+ content: [
47
+ {
48
+ type: 'text',
49
+ text: `Error listing rules: ${error.message}`,
50
+ },
51
+ ],
52
+ };
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Get all inbox rules
58
+ * @param {string} accessToken - Access token
59
+ * @returns {Promise<Array>} - Array of rule objects
60
+ */
61
+ async function getInboxRules(accessToken) {
62
+ try {
63
+ const response = await callGraphAPI(
64
+ accessToken,
65
+ 'GET',
66
+ 'me/mailFolders/inbox/messageRules',
67
+ null
68
+ );
69
+
70
+ return response.value || [];
71
+ } catch (error) {
72
+ console.error(`Error getting inbox rules: ${error.message}`);
73
+ throw error;
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Format rules list for display
79
+ * @param {Array} rules - Array of rule objects
80
+ * @param {boolean} includeDetails - Whether to include detailed conditions and actions
81
+ * @returns {string} - Formatted rules list
82
+ */
83
+ function formatRulesList(rules, includeDetails) {
84
+ if (!rules || rules.length === 0) {
85
+ return "No inbox rules found.\n\nTip: You can create rules using the 'create-rule' tool. Rules are processed in order of their sequence number (lower numbers are processed first).";
86
+ }
87
+
88
+ // Sort rules by sequence to show execution order
89
+ const sortedRules = [...rules].sort((a, b) => {
90
+ return (a.sequence || 9999) - (b.sequence || 9999);
91
+ });
92
+
93
+ // Format rules based on detail level
94
+ if (includeDetails) {
95
+ // Detailed format
96
+ const detailedRules = sortedRules.map((rule) => {
97
+ // Format rule header with sequence
98
+ let ruleText = `[${rule.sequence || 'N/A'}] ${rule.displayName}${rule.isEnabled ? '' : ' (Disabled)'}`;
99
+
100
+ // Format conditions
101
+ const conditions = formatRuleConditions(rule);
102
+ if (conditions) {
103
+ ruleText += `\n Conditions: ${conditions}`;
104
+ }
105
+
106
+ // Format actions
107
+ const actions = formatRuleActions(rule);
108
+ if (actions) {
109
+ ruleText += `\n Actions: ${actions}`;
110
+ }
111
+
112
+ return ruleText;
113
+ });
114
+
115
+ return `Found ${rules.length} inbox rules (sorted by execution order):\n\n${detailedRules.join('\n\n')}\n\nRules are processed in order of their sequence number. You can change rule order using manage-rules with action=reorder.`;
116
+ } else {
117
+ // Simple format
118
+ const simpleRules = sortedRules.map((rule) => {
119
+ return `[${rule.sequence || 'N/A'}] ${rule.displayName}${rule.isEnabled ? '' : ' (Disabled)'}`;
120
+ });
121
+
122
+ return `Found ${rules.length} inbox rules (sorted by execution order):\n\n${simpleRules.join('\n')}\n\nTip: Use 'list-rules with includeDetails=true' to see more information about each rule.`;
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Format rule conditions for display
128
+ * @param {object} rule - Rule object
129
+ * @returns {string} - Formatted conditions
130
+ */
131
+ function formatRuleConditions(rule) {
132
+ const conditions = [];
133
+
134
+ // From addresses
135
+ if (rule.conditions?.fromAddresses?.length > 0) {
136
+ const senders = rule.conditions.fromAddresses
137
+ .map((addr) => addr.emailAddress.address)
138
+ .join(', ');
139
+ conditions.push(`From: ${senders}`);
140
+ }
141
+
142
+ // Subject contains
143
+ if (rule.conditions?.subjectContains?.length > 0) {
144
+ conditions.push(
145
+ `Subject contains: "${rule.conditions.subjectContains.join(', ')}"`
146
+ );
147
+ }
148
+
149
+ // Contains body text
150
+ if (rule.conditions?.bodyContains?.length > 0) {
151
+ conditions.push(
152
+ `Body contains: "${rule.conditions.bodyContains.join(', ')}"`
153
+ );
154
+ }
155
+
156
+ // Has attachment
157
+ if (rule.conditions?.hasAttachment === true) {
158
+ conditions.push('Has attachment');
159
+ }
160
+
161
+ // Importance
162
+ if (rule.conditions?.importance) {
163
+ conditions.push(`Importance: ${rule.conditions.importance}`);
164
+ }
165
+
166
+ return conditions.join('; ');
167
+ }
168
+
169
+ /**
170
+ * Format rule actions for display
171
+ * @param {object} rule - Rule object
172
+ * @returns {string} - Formatted actions
173
+ */
174
+ function formatRuleActions(rule) {
175
+ const actions = [];
176
+
177
+ // Move to folder
178
+ if (rule.actions?.moveToFolder) {
179
+ actions.push(`Move to folder: ${rule.actions.moveToFolder}`);
180
+ }
181
+
182
+ // Copy to folder
183
+ if (rule.actions?.copyToFolder) {
184
+ actions.push(`Copy to folder: ${rule.actions.copyToFolder}`);
185
+ }
186
+
187
+ // Mark as read
188
+ if (rule.actions?.markAsRead === true) {
189
+ actions.push('Mark as read');
190
+ }
191
+
192
+ // Mark importance
193
+ if (rule.actions?.markImportance) {
194
+ actions.push(`Mark importance: ${rule.actions.markImportance}`);
195
+ }
196
+
197
+ // Forward
198
+ if (rule.actions?.forwardTo?.length > 0) {
199
+ const recipients = rule.actions.forwardTo
200
+ .map((r) => r.emailAddress.address)
201
+ .join(', ');
202
+ actions.push(`Forward to: ${recipients}`);
203
+ }
204
+
205
+ // Delete
206
+ if (rule.actions?.delete === true) {
207
+ actions.push('Delete');
208
+ }
209
+
210
+ return actions.join('; ');
211
+ }
212
+
213
+ module.exports = {
214
+ handleListRules,
215
+ getInboxRules,
216
+ };