msoutlook-mcp 0.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.
Files changed (82) hide show
  1. package/README.md +134 -0
  2. package/dist/api/calendar.d.ts +90 -0
  3. package/dist/api/calendar.d.ts.map +1 -0
  4. package/dist/api/calendar.js +102 -0
  5. package/dist/api/calendar.js.map +1 -0
  6. package/dist/api/client.d.ts +14 -0
  7. package/dist/api/client.d.ts.map +1 -0
  8. package/dist/api/client.js +93 -0
  9. package/dist/api/client.js.map +1 -0
  10. package/dist/api/contacts.d.ts +43 -0
  11. package/dist/api/contacts.d.ts.map +1 -0
  12. package/dist/api/contacts.js +45 -0
  13. package/dist/api/contacts.js.map +1 -0
  14. package/dist/api/mail.d.ts +90 -0
  15. package/dist/api/mail.d.ts.map +1 -0
  16. package/dist/api/mail.js +148 -0
  17. package/dist/api/mail.js.map +1 -0
  18. package/dist/api/people.d.ts +28 -0
  19. package/dist/api/people.d.ts.map +1 -0
  20. package/dist/api/people.js +16 -0
  21. package/dist/api/people.js.map +1 -0
  22. package/dist/auth/browser-login.d.ts +26 -0
  23. package/dist/auth/browser-login.d.ts.map +1 -0
  24. package/dist/auth/browser-login.js +398 -0
  25. package/dist/auth/browser-login.js.map +1 -0
  26. package/dist/auth/index.d.ts +34 -0
  27. package/dist/auth/index.d.ts.map +1 -0
  28. package/dist/auth/index.js +89 -0
  29. package/dist/auth/index.js.map +1 -0
  30. package/dist/auth/session-store.d.ts +38 -0
  31. package/dist/auth/session-store.d.ts.map +1 -0
  32. package/dist/auth/session-store.js +163 -0
  33. package/dist/auth/session-store.js.map +1 -0
  34. package/dist/auth/token-extractor.d.ts +46 -0
  35. package/dist/auth/token-extractor.d.ts.map +1 -0
  36. package/dist/auth/token-extractor.js +126 -0
  37. package/dist/auth/token-extractor.js.map +1 -0
  38. package/dist/auth/token-refresh.d.ts +23 -0
  39. package/dist/auth/token-refresh.d.ts.map +1 -0
  40. package/dist/auth/token-refresh.js +133 -0
  41. package/dist/auth/token-refresh.js.map +1 -0
  42. package/dist/browser/cookie-import.d.ts +30 -0
  43. package/dist/browser/cookie-import.d.ts.map +1 -0
  44. package/dist/browser/cookie-import.js +446 -0
  45. package/dist/browser/cookie-import.js.map +1 -0
  46. package/dist/constants.d.ts +27 -0
  47. package/dist/constants.d.ts.map +1 -0
  48. package/dist/constants.js +39 -0
  49. package/dist/constants.js.map +1 -0
  50. package/dist/index.d.ts +11 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +23 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/server.d.ts +6 -0
  55. package/dist/server.d.ts.map +1 -0
  56. package/dist/server.js +20 -0
  57. package/dist/server.js.map +1 -0
  58. package/dist/tools/auth-tools.d.ts +6 -0
  59. package/dist/tools/auth-tools.d.ts.map +1 -0
  60. package/dist/tools/auth-tools.js +116 -0
  61. package/dist/tools/auth-tools.js.map +1 -0
  62. package/dist/tools/calendar-tools.d.ts +6 -0
  63. package/dist/tools/calendar-tools.d.ts.map +1 -0
  64. package/dist/tools/calendar-tools.js +168 -0
  65. package/dist/tools/calendar-tools.js.map +1 -0
  66. package/dist/tools/contact-tools.d.ts +6 -0
  67. package/dist/tools/contact-tools.d.ts.map +1 -0
  68. package/dist/tools/contact-tools.js +105 -0
  69. package/dist/tools/contact-tools.js.map +1 -0
  70. package/dist/tools/mail-tools.d.ts +6 -0
  71. package/dist/tools/mail-tools.d.ts.map +1 -0
  72. package/dist/tools/mail-tools.js +196 -0
  73. package/dist/tools/mail-tools.js.map +1 -0
  74. package/dist/utils/http.d.ts +15 -0
  75. package/dist/utils/http.d.ts.map +1 -0
  76. package/dist/utils/http.js +48 -0
  77. package/dist/utils/http.js.map +1 -0
  78. package/dist/utils/logger.d.ts +10 -0
  79. package/dist/utils/logger.d.ts.map +1 -0
  80. package/dist/utils/logger.js +21 -0
  81. package/dist/utils/logger.js.map +1 -0
  82. package/package.json +53 -0
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Shared constants used across the codebase.
3
+ */
4
+ /**
5
+ * Microsoft's own Outlook Web App client ID.
6
+ * This is the first-party app ID used by outlook.office.com itself.
7
+ * No app registration required — same pattern as msteams-mcp uses Teams' own client ID.
8
+ */
9
+ export declare const OWA_CLIENT_ID = "9199bf20-a13f-4107-85dc-02114787ef48";
10
+ /** OAuth token endpoint for work/school accounts (used as default when no tenant ID). */
11
+ export declare const TOKEN_ENDPOINT = "https://login.microsoftonline.com/organizations/oauth2/v2.0/token";
12
+ /** Primary resource scope for Outlook Web. */
13
+ export declare const OWA_SCOPE = "https://outlook.office.com/.default";
14
+ /** Microsoft Graph scope. */
15
+ export declare const GRAPH_SCOPE = "https://graph.microsoft.com/.default";
16
+ /** Outlook Web login URL. */
17
+ export declare const OWA_URL = "https://outlook.office.com/mail/";
18
+ export declare const OWA_BASE = "https://outlook.office.com";
19
+ export declare const OWA_REST_V2 = "https://outlook.office.com/api/v2.0";
20
+ export declare const GRAPH_BASE = "https://graph.microsoft.com/v1.0";
21
+ /** Refresh tokens ~55 minutes before expiry (access tokens last 1 hour). */
22
+ export declare const TOKEN_REFRESH_BUFFER_MS: number;
23
+ /** How long to wait for user to complete browser login (ms). */
24
+ export declare const LOGIN_TIMEOUT_MS: number;
25
+ /** User-Agent presented to OWA APIs so requests look like the web client. */
26
+ export declare const OWA_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0";
27
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH;;;;GAIG;AACH,eAAO,MAAM,aAAa,yCAAyC,CAAC;AAEpE,yFAAyF;AACzF,eAAO,MAAM,cAAc,sEAAsE,CAAC;AAElG,8CAA8C;AAC9C,eAAO,MAAM,SAAS,wCAAwC,CAAC;AAE/D,6BAA6B;AAC7B,eAAO,MAAM,WAAW,yCAAyC,CAAC;AAElE,6BAA6B;AAC7B,eAAO,MAAM,OAAO,qCAAqC,CAAC;AAM1D,eAAO,MAAM,QAAQ,+BAA+B,CAAC;AACrD,eAAO,MAAM,WAAW,wCAAyB,CAAC;AAClD,eAAO,MAAM,UAAU,qCAAqC,CAAC;AAM7D,4EAA4E;AAC5E,eAAO,MAAM,uBAAuB,QAAiB,CAAC;AAEtD,gEAAgE;AAChE,eAAO,MAAM,gBAAgB,QAAgB,CAAC;AAM9C,6EAA6E;AAC7E,eAAO,MAAM,cAAc,wIAC4G,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Shared constants used across the codebase.
3
+ */
4
+ // ─────────────────────────────────────────────────────────────────────────────
5
+ // OAuth / Auth
6
+ // ─────────────────────────────────────────────────────────────────────────────
7
+ /**
8
+ * Microsoft's own Outlook Web App client ID.
9
+ * This is the first-party app ID used by outlook.office.com itself.
10
+ * No app registration required — same pattern as msteams-mcp uses Teams' own client ID.
11
+ */
12
+ export const OWA_CLIENT_ID = '9199bf20-a13f-4107-85dc-02114787ef48';
13
+ /** OAuth token endpoint for work/school accounts (used as default when no tenant ID). */
14
+ export const TOKEN_ENDPOINT = 'https://login.microsoftonline.com/organizations/oauth2/v2.0/token';
15
+ /** Primary resource scope for Outlook Web. */
16
+ export const OWA_SCOPE = 'https://outlook.office.com/.default';
17
+ /** Microsoft Graph scope. */
18
+ export const GRAPH_SCOPE = 'https://graph.microsoft.com/.default';
19
+ /** Outlook Web login URL. */
20
+ export const OWA_URL = 'https://outlook.office.com/mail/';
21
+ // ─────────────────────────────────────────────────────────────────────────────
22
+ // API Base URLs
23
+ // ─────────────────────────────────────────────────────────────────────────────
24
+ export const OWA_BASE = 'https://outlook.office.com';
25
+ export const OWA_REST_V2 = `${OWA_BASE}/api/v2.0`;
26
+ export const GRAPH_BASE = 'https://graph.microsoft.com/v1.0';
27
+ // ─────────────────────────────────────────────────────────────────────────────
28
+ // Token / Refresh
29
+ // ─────────────────────────────────────────────────────────────────────────────
30
+ /** Refresh tokens ~55 minutes before expiry (access tokens last 1 hour). */
31
+ export const TOKEN_REFRESH_BUFFER_MS = 55 * 60 * 1000;
32
+ /** How long to wait for user to complete browser login (ms). */
33
+ export const LOGIN_TIMEOUT_MS = 5 * 60 * 1000;
34
+ // ─────────────────────────────────────────────────────────────────────────────
35
+ // HTTP
36
+ // ─────────────────────────────────────────────────────────────────────────────
37
+ /** User-Agent presented to OWA APIs so requests look like the web client. */
38
+ export const OWA_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0';
39
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,gFAAgF;AAChF,eAAe;AACf,gFAAgF;AAEhF;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,sCAAsC,CAAC;AAEpE,yFAAyF;AACzF,MAAM,CAAC,MAAM,cAAc,GAAG,mEAAmE,CAAC;AAElG,8CAA8C;AAC9C,MAAM,CAAC,MAAM,SAAS,GAAG,qCAAqC,CAAC;AAE/D,6BAA6B;AAC7B,MAAM,CAAC,MAAM,WAAW,GAAG,sCAAsC,CAAC;AAElE,6BAA6B;AAC7B,MAAM,CAAC,MAAM,OAAO,GAAG,kCAAkC,CAAC;AAE1D,gFAAgF;AAChF,gBAAgB;AAChB,gFAAgF;AAEhF,MAAM,CAAC,MAAM,QAAQ,GAAG,4BAA4B,CAAC;AACrD,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,QAAQ,WAAW,CAAC;AAClD,MAAM,CAAC,MAAM,UAAU,GAAG,kCAAkC,CAAC;AAE7D,gFAAgF;AAChF,kBAAkB;AAClB,gFAAgF;AAEhF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEtD,gEAAgE;AAChE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAE9C,gFAAgF;AAChF,OAAO;AACP,gFAAgF;AAEhF,6EAA6E;AAC7E,MAAM,CAAC,MAAM,cAAc,GACzB,qIAAqI,CAAC"}
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * msoutlook-mcp — MCP server for Microsoft Outlook Web
4
+ *
5
+ * No app registration required. Uses your existing Outlook Web session,
6
+ * the same way msteams-mcp uses the Microsoft Teams web session.
7
+ *
8
+ * Usage: npx msoutlook-mcp
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG"}
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * msoutlook-mcp — MCP server for Microsoft Outlook Web
4
+ *
5
+ * No app registration required. Uses your existing Outlook Web session,
6
+ * the same way msteams-mcp uses the Microsoft Teams web session.
7
+ *
8
+ * Usage: npx msoutlook-mcp
9
+ */
10
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
11
+ import { createServer } from './server.js';
12
+ import { logger } from './utils/logger.js';
13
+ async function main() {
14
+ const server = createServer();
15
+ const transport = new StdioServerTransport();
16
+ await server.server.connect(transport);
17
+ logger.info('msoutlook-mcp running on stdio');
18
+ }
19
+ main().catch(err => {
20
+ logger.error('Fatal error', err);
21
+ process.exit(1);
22
+ });
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACvC,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;AAChD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;IACjB,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;IACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * MCP server setup — registers all tools and starts the server.
3
+ */
4
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ export declare function createServer(): McpServer;
6
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMpE,wBAAgB,YAAY,IAAI,SAAS,CAYxC"}
package/dist/server.js ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * MCP server setup — registers all tools and starts the server.
3
+ */
4
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import { registerAuthTools } from './tools/auth-tools.js';
6
+ import { registerMailTools } from './tools/mail-tools.js';
7
+ import { registerCalendarTools } from './tools/calendar-tools.js';
8
+ import { registerContactTools } from './tools/contact-tools.js';
9
+ export function createServer() {
10
+ const server = new McpServer({
11
+ name: 'msoutlook-mcp',
12
+ version: '0.1.0',
13
+ });
14
+ registerAuthTools(server);
15
+ registerMailTools(server);
16
+ registerCalendarTools(server);
17
+ registerContactTools(server);
18
+ return server;
19
+ }
20
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAE7B,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Authentication MCP tools.
3
+ */
4
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ export declare function registerAuthTools(server: McpServer): void;
6
+ //# sourceMappingURL=auth-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-tools.d.ts","sourceRoot":"","sources":["../../src/tools/auth-tools.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAOzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyIzD"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Authentication MCP tools.
3
+ */
4
+ import { z } from 'zod';
5
+ import { browserLogin, getAuthStatus, clearSession, getOwaToken, hasSessionState, isSessionLikelyExpired } from '../auth/index.js';
6
+ /** Minimum minutes remaining before we consider the token "still valid" (skip re-login). */
7
+ const TOKEN_VALID_THRESHOLD_MINUTES = 10;
8
+ export function registerAuthTools(server) {
9
+ // ── outlook_login ────────────────────────────────────────────────────────
10
+ server.tool('outlook_login', 'Sign in to Outlook Web. Tries silently first (no browser); opens a browser only when the session has expired. Set force_new: true to force a full re-login.', {
11
+ force_new: z.boolean().optional().describe('Force a full re-login even if a session exists — clears the saved session first. Default: false.'),
12
+ }, async ({ force_new }) => {
13
+ const forceNew = force_new ?? false;
14
+ // Fast path: valid token and not forcing re-login
15
+ if (!forceNew) {
16
+ const existingToken = await getOwaToken();
17
+ if (existingToken) {
18
+ const status = getAuthStatus();
19
+ const mins = status.owaTokenMinutesRemaining ?? 0;
20
+ if (mins >= TOKEN_VALID_THRESHOLD_MINUTES) {
21
+ return {
22
+ content: [{
23
+ type: 'text',
24
+ text: JSON.stringify({
25
+ success: true,
26
+ message: `Already authenticated. Token valid for ${mins} more minutes.`,
27
+ upn: status.upn,
28
+ tokenStatus: {
29
+ expiresAt: status.owaTokenExpiry,
30
+ minutesRemaining: mins,
31
+ },
32
+ }, null, 2),
33
+ }],
34
+ };
35
+ }
36
+ }
37
+ }
38
+ // Need to open a browser — warn the user not to close it
39
+ if (!forceNew) {
40
+ process.stderr.write('[msoutlook-mcp] Opening browser. Do NOT close the window — it closes automatically once signed in.\n');
41
+ }
42
+ const result = await browserLogin(forceNew);
43
+ if (!result) {
44
+ return {
45
+ content: [{
46
+ type: 'text',
47
+ text: JSON.stringify({
48
+ success: false,
49
+ message: 'Login failed. If you closed the browser window manually, run outlook_login again and wait for it to close on its own.',
50
+ }, null, 2),
51
+ }],
52
+ };
53
+ }
54
+ // Return path-specific message (mirrors msteams-mcp)
55
+ const messages = {
56
+ 'token-cache': 'Already authenticated. Token valid.',
57
+ 'headless-sso': 'Login completed silently via SSO. Session has been saved.',
58
+ 'headed-browser': 'Login completed successfully. Session has been saved.',
59
+ };
60
+ return {
61
+ content: [{
62
+ type: 'text',
63
+ text: JSON.stringify({
64
+ success: true,
65
+ message: messages[result.method],
66
+ upn: result.upn,
67
+ }, null, 2),
68
+ }],
69
+ };
70
+ });
71
+ // ── outlook_status ───────────────────────────────────────────────────────
72
+ server.tool('outlook_status', 'Check the current authentication status and token validity.', {}, async () => {
73
+ const token = await getOwaToken();
74
+ if (!token) {
75
+ return {
76
+ content: [{
77
+ type: 'text',
78
+ text: JSON.stringify({ authenticated: false, message: 'Not authenticated. Run outlook_login to sign in.' }, null, 2),
79
+ }],
80
+ };
81
+ }
82
+ const status = getAuthStatus();
83
+ return {
84
+ content: [{
85
+ type: 'text',
86
+ text: JSON.stringify({
87
+ authenticated: true,
88
+ upn: status.upn,
89
+ tenantId: status.tenantId,
90
+ owaToken: {
91
+ expiresAt: status.owaTokenExpiry,
92
+ minutesRemaining: status.owaTokenMinutesRemaining,
93
+ },
94
+ graphToken: status.graphTokenExpiry ? {
95
+ expiresAt: status.graphTokenExpiry,
96
+ } : null,
97
+ session: {
98
+ exists: hasSessionState(),
99
+ likelyExpired: isSessionLikelyExpired(),
100
+ },
101
+ }, null, 2),
102
+ }],
103
+ };
104
+ });
105
+ // ── outlook_logout ───────────────────────────────────────────────────────
106
+ server.tool('outlook_logout', 'Clear the saved Outlook session and tokens. You will need to run outlook_login again.', {}, async () => {
107
+ clearSession();
108
+ return {
109
+ content: [{
110
+ type: 'text',
111
+ text: JSON.stringify({ success: true, message: 'Session cleared. Run outlook_login to sign in again.' }, null, 2),
112
+ }],
113
+ };
114
+ });
115
+ }
116
+ //# sourceMappingURL=auth-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-tools.js","sourceRoot":"","sources":["../../src/tools/auth-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Calendar MCP tools.
3
+ */
4
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ export declare function registerCalendarTools(server: McpServer): void;
6
+ //# sourceMappingURL=calendar-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-tools.d.ts","sourceRoot":"","sources":["../../src/tools/calendar-tools.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAkEzE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAoK7D"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Calendar MCP tools.
3
+ */
4
+ import { z } from 'zod';
5
+ import { listEvents, getEvent, createEvent, updateEvent, deleteEvent, respondToEvent, searchEvents, listCalendars, } from '../api/calendar.js';
6
+ // ─────────────────────────────────────────────────────────────────────────────
7
+ // Formatters
8
+ // ─────────────────────────────────────────────────────────────────────────────
9
+ function formatEvent(e, full = false) {
10
+ const start = e.Start?.DateTime ?? 'Unknown';
11
+ const end = e.End?.DateTime ?? 'Unknown';
12
+ const tz = e.Start?.TimeZone ?? '';
13
+ const location = e.Location?.DisplayName ?? '';
14
+ const organizer = e.Organizer?.EmailAddress?.Address ?? '';
15
+ const attendeeCount = e.Attendees?.length ?? 0;
16
+ const lines = [
17
+ `ID: ${e.Id}`,
18
+ `Subject: ${e.Subject}`,
19
+ `Start: ${start} ${tz}`,
20
+ `End: ${end}`,
21
+ location ? `Location: ${location}` : '',
22
+ organizer ? `Organizer: ${organizer}` : '',
23
+ attendeeCount > 0 ? `Attendees: ${attendeeCount}` : '',
24
+ e.IsOnlineMeeting ? `Online Meeting: ${e.OnlineMeetingUrl ?? 'Yes'}` : '',
25
+ e.ResponseStatus ? `My Response: ${e.ResponseStatus.Response}` : '',
26
+ e.WebLink ? `Web URL: ${e.WebLink}` : '',
27
+ ].filter(Boolean);
28
+ if (full) {
29
+ if (e.Attendees?.length) {
30
+ lines.push('', 'Attendees:');
31
+ lines.push(...e.Attendees.map(a => ` - ${a.EmailAddress.Name ?? a.EmailAddress.Address} (${a.Type ?? 'Required'}) — ${a.Status?.Response ?? 'None'}`));
32
+ }
33
+ if (e.Body) {
34
+ lines.push('', `Body (${e.Body.ContentType}):`, e.Body.Content.slice(0, 3000));
35
+ }
36
+ }
37
+ else if (e.BodyPreview) {
38
+ lines.push(`Preview: ${e.BodyPreview.slice(0, 200)}`);
39
+ }
40
+ return lines.join('\n');
41
+ }
42
+ function formatEventList(events) {
43
+ if (events.length === 0)
44
+ return 'No events found.';
45
+ return events.map((e, i) => `--- Event ${i + 1} ---\n${formatEvent(e)}`).join('\n\n');
46
+ }
47
+ // ─────────────────────────────────────────────────────────────────────────────
48
+ // Tools
49
+ // ─────────────────────────────────────────────────────────────────────────────
50
+ export function registerCalendarTools(server) {
51
+ // ── outlook_list_events ──────────────────────────────────────────────────
52
+ server.tool('outlook_list_events', 'List calendar events within a date range.', {
53
+ start_date: z.string().optional().describe('ISO 8601 start datetime (defaults to now)'),
54
+ end_date: z.string().optional().describe('ISO 8601 end datetime (defaults to 7 days from now)'),
55
+ top: z.number().int().min(1).max(100).optional().describe('Max events to return (default 50)'),
56
+ calendar_id: z.string().optional().describe('Specific calendar ID (defaults to primary calendar)'),
57
+ }, async ({ start_date, end_date, top, calendar_id }) => {
58
+ const events = await listEvents({
59
+ startDateTime: start_date,
60
+ endDateTime: end_date,
61
+ top: top ?? 50,
62
+ calendarId: calendar_id,
63
+ });
64
+ return { content: [{ type: 'text', text: formatEventList(events) }] };
65
+ });
66
+ // ── outlook_get_event ────────────────────────────────────────────────────
67
+ server.tool('outlook_get_event', 'Get full details of a calendar event including attendees and body.', {
68
+ id: z.string().describe('Event ID'),
69
+ }, async ({ id }) => {
70
+ const event = await getEvent(id);
71
+ return { content: [{ type: 'text', text: formatEvent(event, true) }] };
72
+ });
73
+ // ── outlook_create_event ─────────────────────────────────────────────────
74
+ server.tool('outlook_create_event', 'Create a new calendar event or meeting.', {
75
+ subject: z.string().describe('Event title/subject'),
76
+ start: z.string().describe('Start datetime in ISO 8601 format (e.g. 2026-06-10T14:00:00)'),
77
+ end: z.string().describe('End datetime in ISO 8601 format'),
78
+ time_zone: z.string().optional().describe('Timezone name (e.g. Europe/London, UTC). Defaults to UTC'),
79
+ location: z.string().optional().describe('Location or meeting room'),
80
+ body: z.string().optional().describe('Event description/body'),
81
+ attendees: z.array(z.object({
82
+ email: z.string().email(),
83
+ name: z.string().optional(),
84
+ type: z.enum(['Required', 'Optional']).optional(),
85
+ })).optional().describe('List of attendees'),
86
+ is_online_meeting: z.boolean().optional().describe('Add a Teams/online meeting link (default: false)'),
87
+ is_all_day: z.boolean().optional().describe('All-day event (default: false)'),
88
+ importance: z.enum(['Low', 'Normal', 'High']).optional(),
89
+ }, async (params) => {
90
+ const event = await createEvent({
91
+ subject: params.subject,
92
+ start: params.start,
93
+ end: params.end,
94
+ timeZone: params.time_zone,
95
+ location: params.location,
96
+ body: params.body,
97
+ attendees: params.attendees,
98
+ isOnlineMeeting: params.is_online_meeting,
99
+ isAllDay: params.is_all_day,
100
+ importance: params.importance,
101
+ });
102
+ return {
103
+ content: [{
104
+ type: 'text',
105
+ text: `Event created.\nID: ${event.Id}\nSubject: ${event.Subject}\nStart: ${event.Start.DateTime}`,
106
+ }],
107
+ };
108
+ });
109
+ // ── outlook_update_event ─────────────────────────────────────────────────
110
+ server.tool('outlook_update_event', 'Update an existing calendar event.', {
111
+ id: z.string().describe('Event ID to update'),
112
+ subject: z.string().optional().describe('New subject'),
113
+ start: z.string().optional().describe('New start datetime (ISO 8601)'),
114
+ end: z.string().optional().describe('New end datetime (ISO 8601)'),
115
+ time_zone: z.string().optional(),
116
+ location: z.string().optional(),
117
+ body: z.string().optional(),
118
+ }, async ({ id, ...updates }) => {
119
+ const event = await updateEvent(id, {
120
+ subject: updates.subject,
121
+ start: updates.start,
122
+ end: updates.end,
123
+ timeZone: updates.time_zone,
124
+ location: updates.location,
125
+ body: updates.body,
126
+ });
127
+ return {
128
+ content: [{
129
+ type: 'text',
130
+ text: `Event updated.\nID: ${event.Id}\nSubject: ${event.Subject}`,
131
+ }],
132
+ };
133
+ });
134
+ // ── outlook_delete_event ─────────────────────────────────────────────────
135
+ server.tool('outlook_delete_event', 'Delete a calendar event.', {
136
+ id: z.string().describe('Event ID to delete'),
137
+ }, async ({ id }) => {
138
+ await deleteEvent(id);
139
+ return { content: [{ type: 'text', text: 'Event deleted.' }] };
140
+ });
141
+ // ── outlook_respond_to_event ─────────────────────────────────────────────
142
+ server.tool('outlook_respond_to_event', 'Accept, decline, or tentatively accept a meeting invitation.', {
143
+ id: z.string().describe('Event ID'),
144
+ response: z.enum(['accept', 'decline', 'tentativelyAccept']).describe('Your response'),
145
+ comment: z.string().optional().describe('Optional response message'),
146
+ }, async ({ id, response, comment }) => {
147
+ await respondToEvent(id, response, comment);
148
+ return { content: [{ type: 'text', text: `Meeting response sent: ${response}.` }] };
149
+ });
150
+ // ── outlook_search_events ────────────────────────────────────────────────
151
+ server.tool('outlook_search_events', 'Search calendar events by keyword.', {
152
+ query: z.string().describe('Search keyword'),
153
+ from_date: z.string().optional().describe('Search from this date (ISO 8601)'),
154
+ to_date: z.string().optional().describe('Search until this date (ISO 8601)'),
155
+ }, async ({ query, from_date, to_date }) => {
156
+ const events = await searchEvents(query, from_date, to_date);
157
+ return { content: [{ type: 'text', text: formatEventList(events) }] };
158
+ });
159
+ // ── outlook_list_calendars ───────────────────────────────────────────────
160
+ server.tool('outlook_list_calendars', 'List all calendars in the account.', {}, async () => {
161
+ const calendars = await listCalendars();
162
+ const text = calendars
163
+ .map(c => `${c.Name} (ID: ${c.Id})${c.IsDefaultCalendar ? ' [Default]' : ''}${c.CanEdit ? ' [Editable]' : ''}`)
164
+ .join('\n');
165
+ return { content: [{ type: 'text', text: text || 'No calendars found.' }] };
166
+ });
167
+ }
168
+ //# sourceMappingURL=calendar-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-tools.js","sourceRoot":"","sources":["../../src/tools/calendar-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Contacts and people MCP tools.
3
+ */
4
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ export declare function registerContactTools(server: McpServer): void;
6
+ //# sourceMappingURL=contact-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contact-tools.d.ts","sourceRoot":"","sources":["../../src/tools/contact-tools.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAyCzE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4F5D"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Contacts and people MCP tools.
3
+ */
4
+ import { z } from 'zod';
5
+ import { listContacts, getContact, createContact, deleteContact } from '../api/contacts.js';
6
+ import { searchPeople } from '../api/people.js';
7
+ // ─────────────────────────────────────────────────────────────────────────────
8
+ // Formatters
9
+ // ─────────────────────────────────────────────────────────────────────────────
10
+ function formatContact(c) {
11
+ const emails = c.EmailAddresses?.map(e => e.Address).join(', ') ?? '';
12
+ const phones = [...(c.BusinessPhones ?? []), c.MobilePhone].filter(Boolean).join(', ');
13
+ return [
14
+ `ID: ${c.Id}`,
15
+ `Name: ${c.DisplayName}`,
16
+ emails ? `Email: ${emails}` : '',
17
+ phones ? `Phone: ${phones}` : '',
18
+ c.JobTitle ? `Title: ${c.JobTitle}` : '',
19
+ c.CompanyName ? `Company: ${c.CompanyName}` : '',
20
+ c.Department ? `Department: ${c.Department}` : '',
21
+ ].filter(Boolean).join('\n');
22
+ }
23
+ function formatPerson(p) {
24
+ const email = p.ScoredEmailAddresses?.[0]?.Address
25
+ ?? p.EmailAddresses?.[0]?.Address
26
+ ?? '';
27
+ return [
28
+ `Name: ${p.DisplayName}`,
29
+ email ? `Email: ${email}` : '',
30
+ p.UserPrincipalName ? `UPN: ${p.UserPrincipalName}` : '',
31
+ p.JobTitle ? `Title: ${p.JobTitle}` : '',
32
+ p.Department ? `Department: ${p.Department}` : '',
33
+ p.CompanyName ? `Company: ${p.CompanyName}` : '',
34
+ ].filter(Boolean).join('\n');
35
+ }
36
+ // ─────────────────────────────────────────────────────────────────────────────
37
+ // Tools
38
+ // ─────────────────────────────────────────────────────────────────────────────
39
+ export function registerContactTools(server) {
40
+ // ── outlook_list_contacts ────────────────────────────────────────────────
41
+ server.tool('outlook_list_contacts', 'List contacts from the Outlook address book.', {
42
+ search: z.string().optional().describe('Search by name or email'),
43
+ top: z.number().int().min(1).max(100).optional().describe('Max results (default 25)'),
44
+ }, async ({ search, top }) => {
45
+ const contacts = await listContacts(search, top ?? 25);
46
+ if (contacts.length === 0)
47
+ return { content: [{ type: 'text', text: 'No contacts found.' }] };
48
+ const text = contacts.map((c, i) => `--- Contact ${i + 1} ---\n${formatContact(c)}`).join('\n\n');
49
+ return { content: [{ type: 'text', text }] };
50
+ });
51
+ // ── outlook_get_contact ──────────────────────────────────────────────────
52
+ server.tool('outlook_get_contact', 'Get full details of a contact by ID.', {
53
+ id: z.string().describe('Contact ID'),
54
+ }, async ({ id }) => {
55
+ const contact = await getContact(id);
56
+ return { content: [{ type: 'text', text: formatContact(contact) }] };
57
+ });
58
+ // ── outlook_create_contact ───────────────────────────────────────────────
59
+ server.tool('outlook_create_contact', 'Create a new contact in Outlook.', {
60
+ given_name: z.string().optional().describe('First name'),
61
+ surname: z.string().optional().describe('Last name'),
62
+ email: z.string().email().optional().describe('Email address'),
63
+ business_phone: z.string().optional().describe('Business phone number'),
64
+ mobile_phone: z.string().optional().describe('Mobile phone number'),
65
+ job_title: z.string().optional().describe('Job title'),
66
+ company_name: z.string().optional().describe('Company or organisation name'),
67
+ notes: z.string().optional().describe('Personal notes'),
68
+ }, async (params) => {
69
+ const contact = await createContact({
70
+ givenName: params.given_name,
71
+ surname: params.surname,
72
+ email: params.email,
73
+ businessPhone: params.business_phone,
74
+ mobilePhone: params.mobile_phone,
75
+ jobTitle: params.job_title,
76
+ companyName: params.company_name,
77
+ notes: params.notes,
78
+ });
79
+ return {
80
+ content: [{
81
+ type: 'text',
82
+ text: `Contact created.\nID: ${contact.Id}\nName: ${contact.DisplayName}`,
83
+ }],
84
+ };
85
+ });
86
+ // ── outlook_delete_contact ───────────────────────────────────────────────
87
+ server.tool('outlook_delete_contact', 'Delete a contact by ID.', {
88
+ id: z.string().describe('Contact ID to delete'),
89
+ }, async ({ id }) => {
90
+ await deleteContact(id);
91
+ return { content: [{ type: 'text', text: 'Contact deleted.' }] };
92
+ });
93
+ // ── outlook_search_people ────────────────────────────────────────────────
94
+ server.tool('outlook_search_people', 'Search the organisation directory for people by name or email.', {
95
+ query: z.string().describe('Name, email, or job title to search for'),
96
+ top: z.number().int().min(1).max(25).optional().describe('Max results (default 10)'),
97
+ }, async ({ query, top }) => {
98
+ const people = await searchPeople(query, top ?? 10);
99
+ if (people.length === 0)
100
+ return { content: [{ type: 'text', text: 'No people found.' }] };
101
+ const text = people.map((p, i) => `--- Person ${i + 1} ---\n${formatPerson(p)}`).join('\n\n');
102
+ return { content: [{ type: 'text', text }] };
103
+ });
104
+ }
105
+ //# sourceMappingURL=contact-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contact-tools.js","sourceRoot":"","sources":["../../src/tools/contact-tools.ts"],"names":[],"mappings":"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"}