@tgai96/outlook-mcp 1.0.1 → 1.1.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/README.md CHANGED
@@ -133,13 +133,23 @@ To use this MCP server with an MCP client, you can either use the published npm
133
133
 
134
134
  #### Option 1: Using Published npm Package (Recommended)
135
135
 
136
- If the package is published to npm, you can use it directly:
136
+ **To use the current package as-is**, use `@tgai96/outlook-mcp`:
137
137
 
138
138
  ```json
139
- DDD
139
+ {
140
+ "mcpServers": {
141
+ "outlook": {
142
+ "command": "npx",
143
+ "args": [
144
+ "-y",
145
+ "@tgai96/outlook-mcp"
146
+ ]
147
+ }
148
+ }
149
+ }
140
150
  ```
141
151
 
142
- **Note**: The package name is `@tgai96/outlook-mcp` once published.
152
+ **To create and publish your own version**, replace `@tgai96/outlook-mcp` with your own package name and follow the [Publishing to npm](#publishing-to-npm) guide below.
143
153
 
144
154
  #### Option 2: Using Local Installation
145
155
 
@@ -344,29 +354,36 @@ If you see "Access is denied" errors:
344
354
 
345
355
  ## Publishing to npm
346
356
 
347
- To publish this package to npm:
357
+ To publish this package to npm under your own namespace:
348
358
 
349
- 1. **Update package.json metadata** (optional but recommended):
350
- - `name` field is already set to `@tgai96/outlook-mcp`
351
- - `author` field is set to `tgai96`
359
+ 1. **Update package.json metadata**:
360
+ - Update the `name` field to your desired package name (e.g., `@your-username/outlook-mcp` or `outlook-mcp`)
361
+ - Update the `author` field with your name/username
352
362
  - Optionally add `repository`, `bugs`, and `homepage` fields if you have a GitHub repo
363
+ - Update the `version` field (following semantic versioning)
353
364
 
354
365
  2. **Login to npm**:
355
366
  ```bash
356
367
  npm login
357
368
  ```
369
+
370
+ Enter your npm username, password, and email when prompted.
358
371
 
359
- 3. **Publish to npm**:
372
+ 3. **Verify what will be published** (recommended):
360
373
  ```bash
361
- npm publish
374
+ npm pack --dry-run
362
375
  ```
363
376
 
364
- For scoped packages like `@tgai96/outlook-mcp`, use:
377
+ This shows which files will be included in the package (based on the `files` field in `package.json`).
378
+
379
+ 4. **Publish to npm**:
380
+
381
+ For scoped packages (packages starting with `@username/`), use:
365
382
  ```bash
366
383
  npm publish --access public
367
384
  ```
368
385
 
369
- 4. **After publishing**, users can use it in their MCP client configuration:
386
+ 5. **After publishing**, users can use it in their MCP client configuration:
370
387
  ```json
371
388
  {
372
389
  "mcpServers": {
@@ -374,12 +391,16 @@ To publish this package to npm:
374
391
  "command": "npx",
375
392
  "args": [
376
393
  "-y",
377
- "@tgai96/outlook-mcp"
394
+ "@your-username/outlook-mcp"
378
395
  ]
379
396
  }
380
397
  }
381
398
  }
382
399
  ```
400
+
401
+ Replace `@your-username/outlook-mcp` with your actual published package name.
402
+
403
+ **Note**: Make sure to review the `files` field in `package.json` to ensure only necessary files are published (sensitive files, test files, and development scripts should be excluded).
383
404
 
384
405
  ## License
385
406
 
package/auth/tools.js CHANGED
@@ -3,7 +3,15 @@
3
3
  */
4
4
  const config = require('../config');
5
5
  const tokenManager = require('./token-manager');
6
- const { ensureAuthenticated, tokenStorage } = require('./index');
6
+ // Lazy load to avoid circular dependency with ./index
7
+ let ensureAuthenticated = null;
8
+ function getEnsureAuthenticated() {
9
+ if (!ensureAuthenticated) {
10
+ const authModule = require('./index');
11
+ ensureAuthenticated = authModule.ensureAuthenticated;
12
+ }
13
+ return ensureAuthenticated;
14
+ }
7
15
 
8
16
  /**
9
17
  * About tool handler
@@ -42,7 +50,8 @@ async function handleAuthenticate(args) {
42
50
  // If not forcing, try to get a valid token first (will auto-refresh if needed)
43
51
  if (!force) {
44
52
  try {
45
- const accessToken = await ensureAuthenticated();
53
+ const ensureAuth = getEnsureAuthenticated();
54
+ const accessToken = await ensureAuth();
46
55
  if (accessToken) {
47
56
  console.error('[AUTHENTICATE] Successfully obtained valid access token (may have been refreshed)');
48
57
  return {
package/config.js CHANGED
@@ -51,7 +51,7 @@ const loadedConfig = loadConfig();
51
51
  module.exports = {
52
52
  // Server information
53
53
  SERVER_NAME: "outlook-assistant",
54
- SERVER_VERSION: "1.0.0",
54
+ SERVER_VERSION: "1.1.0",
55
55
 
56
56
  // Test mode setting
57
57
  USE_TEST_MODE: loadedConfig.USE_TEST_MODE,
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Date formatting utilities for email module
3
+ */
4
+
5
+ /**
6
+ * Format date to show both UTC and local time
7
+ * @param {string} dateTimeString - ISO 8601 date string from API
8
+ * @returns {string} - Formatted date string with UTC and local time
9
+ */
10
+ function formatDateTime(dateTimeString) {
11
+ const date = new Date(dateTimeString);
12
+ const utcString = date.toUTCString();
13
+ const localString = date.toLocaleString();
14
+ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
15
+ return `${utcString} (UTC) / ${localString} (${timezone})`;
16
+ }
17
+
18
+ module.exports = {
19
+ formatDateTime
20
+ };
21
+
package/email/list.js CHANGED
@@ -5,11 +5,12 @@ const config = require('../config');
5
5
  const { callGraphAPI, callGraphAPIPaginated } = require('../utils/graph-api');
6
6
  const { ensureAuthenticated } = require('../auth');
7
7
  const { resolveFolderPath } = require('./folder-utils');
8
+ const { formatDateTime } = require('./date-utils');
8
9
 
9
10
  /**
10
11
  * List emails handler
11
12
  * @param {object} args - Tool arguments
12
- * @returns {object} - MCP response
13
+ * @returns {Promise<object>} - MCP response
13
14
  */
14
15
  async function handleListEmails(args) {
15
16
  const folder = args.folder || "inbox";
@@ -44,10 +45,10 @@ async function handleListEmails(args) {
44
45
  // Format results
45
46
  const emailList = response.value.map((email, index) => {
46
47
  const sender = email.from ? email.from.emailAddress : { name: 'Unknown', address: 'unknown' };
47
- const date = new Date(email.receivedDateTime).toLocaleString();
48
+ const date = formatDateTime(email.receivedDateTime);
48
49
  const readStatus = email.isRead ? '' : '[UNREAD] ';
49
50
 
50
- return `${index + 1}. ${readStatus}${date} - From: ${sender.name} (${sender.address})\nSubject: ${email.subject}\nID: ${email.id}\n`;
51
+ return `${index + 1}. ${readStatus}Date: ${date}\nFrom: ${sender.name} (${sender.address})\nSubject: ${email.subject}\nID: ${email.id}\n`;
51
52
  }).join("\n");
52
53
 
53
54
  return {
package/email/read.js CHANGED
@@ -4,11 +4,12 @@
4
4
  const config = require('../config');
5
5
  const { callGraphAPI } = require('../utils/graph-api');
6
6
  const { ensureAuthenticated } = require('../auth');
7
+ const { formatDateTime } = require('./date-utils');
7
8
 
8
9
  /**
9
10
  * Read email handler
10
11
  * @param {object} args - Tool arguments
11
- * @returns {object} - MCP response
12
+ * @returns {Promise<object>} - MCP response
12
13
  */
13
14
  async function handleReadEmail(args) {
14
15
  const emailId = args.id;
@@ -51,7 +52,7 @@ async function handleReadEmail(args) {
51
52
  const to = email.toRecipients ? email.toRecipients.map(r => `${r.emailAddress.name} (${r.emailAddress.address})`).join(", ") : 'None';
52
53
  const cc = email.ccRecipients && email.ccRecipients.length > 0 ? email.ccRecipients.map(r => `${r.emailAddress.name} (${r.emailAddress.address})`).join(", ") : 'None';
53
54
  const bcc = email.bccRecipients && email.bccRecipients.length > 0 ? email.bccRecipients.map(r => `${r.emailAddress.name} (${r.emailAddress.address})`).join(", ") : 'None';
54
- const date = new Date(email.receivedDateTime).toLocaleString();
55
+ const date = formatDateTime(email.receivedDateTime);
55
56
 
56
57
  // Extract body content
57
58
  let body = '';
package/email/search.js CHANGED
@@ -5,11 +5,12 @@ const config = require('../config');
5
5
  const { callGraphAPI, callGraphAPIPaginated } = require('../utils/graph-api');
6
6
  const { ensureAuthenticated } = require('../auth');
7
7
  const { resolveFolderPath } = require('./folder-utils');
8
+ const { formatDateTime } = require('./date-utils');
8
9
 
9
10
  /**
10
11
  * Search emails handler
11
12
  * @param {object} args - Tool arguments
12
- * @returns {object} - MCP response
13
+ * @returns {Promise<object>} - MCP response
13
14
  */
14
15
  async function handleSearchEmails(args) {
15
16
  const folder = args.folder || "inbox";
@@ -262,10 +263,10 @@ function formatSearchResults(response) {
262
263
  // Format results
263
264
  const emailList = response.value.map((email, index) => {
264
265
  const sender = email.from?.emailAddress || { name: 'Unknown', address: 'unknown' };
265
- const date = new Date(email.receivedDateTime).toLocaleString();
266
+ const date = formatDateTime(email.receivedDateTime);
266
267
  const readStatus = email.isRead ? '' : '[UNREAD] ';
267
268
 
268
- return `${index + 1}. ${readStatus}${date} - From: ${sender.name} (${sender.address})\nSubject: ${email.subject}\nID: ${email.id}\n`;
269
+ return `${index + 1}. ${readStatus}Date: ${date}\nFrom: ${sender.name} (${sender.address})\nSubject: ${email.subject}\nID: ${email.id}\n`;
269
270
  }).join("\n");
270
271
 
271
272
  // Add search strategy info if available
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tgai96/outlook-mcp",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "MCP server for Claude to access Outlook data via Microsoft Graph API",
5
5
  "main": "index.js",
6
6
  "bin": {