@sam2kb/m365-mcp 1.0.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 ADDED
@@ -0,0 +1,11 @@
1
+ # Account name configured with: npm run auth -- add <name> <tenant-id> <client-id>
2
+ M365_ACCOUNT=work
3
+
4
+ # IANA timezone used for Microsoft Graph calendar operations
5
+ M365_TIMEZONE=America/New_York
6
+
7
+ # Optional auth storage override (default: ~/.m365-mcp/auth)
8
+ # Use an absolute path; variable expansion is not supported by every .env loader.
9
+ # M365_MCP_AUTH_DIR=/absolute/path/to/m365-mcp-auth
10
+
11
+ # This project does not load .env files automatically; source it or pass these variables through your MCP client.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Alex Kay
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,257 @@
1
+ # m365-mcp
2
+
3
+ **Production-grade Microsoft 365 MCP server** — Email, Calendar, Contacts, OneDrive, Teams, Tasks, and Users via delegated OAuth.
4
+
5
+ Built from the best of both `office365-connector` (delegated OAuth, multi-account) and `mcp-microsoft365` (MCP protocol, full scope), with all the gaps fixed: pagination, rate limiting, retry logic, proper timezone handling, and TypeScript throughout.
6
+
7
+ ## Why this exists
8
+
9
+ | Feature | mcp-microsoft365 | office365-connector | **m365-mcp** |
10
+ |---|---|---|---|
11
+ | Auth model | Client credentials (tenant-wide) | Delegated (device code) | **Delegated (device code)** ✅ |
12
+ | MCP server | ✅ | ❌ (CLI scripts) | ✅ |
13
+ | Multi-account | ❌ | ✅ | ✅ |
14
+ | Pagination | ❌ | ❌ | ✅ |
15
+ | Rate limit handling | ❌ | Partial | ✅ |
16
+ | Email | ✅ | ✅ | ✅ |
17
+ | Calendar | ✅ | ✅ | ✅ |
18
+ | Contacts | ❌ | ✅ | ✅ |
19
+ | OneDrive | ✅ | ❌ | ✅ |
20
+ | Teams | ✅ | ❌ | ✅ |
21
+ | Tasks | ✅ | ❌ | ✅ |
22
+ | Users | ✅ | ❌ | ✅ |
23
+ | TypeScript | ✅ | ❌ (JS) | ✅ |
24
+ | **Total tools** | 19 | ~12 (CLI) | **38** |
25
+
26
+ ## Scope
27
+
28
+ **Delegated permissions** — the app acts AS YOU, not as the tenant. It can only access YOUR data:
29
+
30
+ - `Mail.Read` / `Mail.ReadWrite` / `Mail.Send`
31
+ - `Calendars.Read` / `Calendars.ReadWrite`
32
+ - `Contacts.Read` / `Contacts.ReadWrite`
33
+ - `Files.Read.All` (your OneDrive)
34
+ - `Tasks.ReadWrite` (To Do)
35
+ - `Chat.Read` / `Chat.ReadWrite` (Teams)
36
+ - `User.Read` + `offline_access`
37
+
38
+ No tenant-wide `Mail.Read.All` or `Files.Read.All` needed.
39
+
40
+ ## Setup
41
+
42
+ ### 1. Create Azure Entra ID App Registration
43
+
44
+ 1. Go to [Azure Portal → App registrations](https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade)
45
+ 2. **New registration**
46
+ - Name: `m365-mcp`
47
+ - Supported account types: **Single tenant** (or multi-tenant if you manage your own tenant)
48
+ - Redirect URI: `http://localhost` (not used for device code, but required)
49
+ 3. Click **Register**
50
+ 4. Go to **Authentication** → **Advanced settings** → set **"Allow public client flows"** to **Yes** → **Save**
51
+ > This is required for device-code OAuth to work without a client secret.
52
+
53
+ ### 2. Add API Permissions
54
+
55
+ Under **API Permissions** → **Add a permission** → **Microsoft Graph** → **Delegated permissions**:
56
+
57
+ ```
58
+ offline_access
59
+ User.Read
60
+ Mail.Read
61
+ Mail.ReadWrite
62
+ Mail.Send
63
+ Calendars.Read
64
+ Calendars.ReadWrite
65
+ Contacts.Read
66
+ Contacts.ReadWrite
67
+ Files.Read.All
68
+ Tasks.ReadWrite
69
+ Chat.Read
70
+ Chat.ReadWrite
71
+ ```
72
+
73
+ Click **Grant admin consent** (or each user will consent individually during login).
74
+
75
+ > Organization-wide user listing and lookup additionally requires delegated `User.Read.All` with admin consent. This broader scope is not requested by default.
76
+
77
+ ### 3. Install
78
+
79
+ Install the published command-line tools:
80
+
81
+ ```bash
82
+ npm install --global @sam2kb/m365-mcp
83
+ ```
84
+
85
+ Or build from source:
86
+
87
+ ```bash
88
+ # Clone
89
+ git clone https://github.com/sam2kb/m365-mcp.git
90
+ cd m365-mcp
91
+
92
+ # Install dependencies
93
+ npm install
94
+
95
+ # Build
96
+ npm run build
97
+ ```
98
+
99
+ ### 4. Add Your Account & Authenticate
100
+
101
+ ```bash
102
+ m365-mcp-auth add work <tenant-id> <client-id> you@company.com "Work account"
103
+ m365-mcp-auth login --account=work
104
+ ```
105
+
106
+ When running from a source checkout, use `node dist/auth-cli.js` instead of
107
+ `m365-mcp-auth`.
108
+
109
+ Follow the on-screen URL + code to sign in. Tokens are stored securely in `~/.m365-mcp/auth/` by default. Set `M365_MCP_AUTH_DIR` to use another location.
110
+
111
+ ### 5. Configure an MCP Client
112
+
113
+ The server uses standard MCP over stdio and works with any MCP client (Claude Desktop, Cursor, Continue, etc.).
114
+
115
+ #### OpenClaw
116
+
117
+ For the global npm installation, add this to your mcporter config at `~/.openclaw/mcporter.json`:
118
+
119
+ ```json
120
+ {
121
+ "mcpServers": {
122
+ "m365": {
123
+ "command": "m365-mcp",
124
+ "args": [],
125
+ "env": {
126
+ "M365_ACCOUNT": "work",
127
+ "M365_TIMEZONE": "America/Chicago"
128
+ }
129
+ }
130
+ }
131
+ }
132
+ ```
133
+
134
+ Or via mcporter CLI:
135
+
136
+ ```bash
137
+ mcporter config add m365 --stdio "m365-mcp" \
138
+ --env M365_ACCOUNT=work \
139
+ --env M365_TIMEZONE=America/Chicago
140
+ ```
141
+
142
+ For a source checkout, use `"command": "node"` with
143
+ `"args": ["/absolute/path/to/m365-mcp/dist/index.js"]`.
144
+
145
+ Then restart OpenClaw for the server to load.
146
+
147
+ #### Other MCP Clients
148
+
149
+ Use the same JSON config in your client's MCP server configuration — `m365-mcp` is a standard stdio MCP server with no client-specific requirements.
150
+
151
+ ## Multi-Account
152
+
153
+ ```bash
154
+ # Add more accounts
155
+ node dist/auth-cli.js add personal <tenant2> <client2> you@outlook.com "Personal"
156
+ node dist/auth-cli.js add client <tenant3> <client3> you@client.com "Consulting"
157
+
158
+ # Authenticate each
159
+ node dist/auth-cli.js login --account=personal
160
+ node dist/auth-cli.js login --account=client
161
+
162
+ # Set default
163
+ node dist/auth-cli.js default work
164
+
165
+ # List
166
+ node dist/auth-cli.js list
167
+ ```
168
+
169
+ Each account needs its own App Registration in its respective tenant. Tokens are isolated per account.
170
+
171
+ ## Available Tools (38)
172
+
173
+ ### 📧 Mail (9 tools)
174
+ | Tool | Description |
175
+ |---|---|
176
+ | `m365_mail_list` | List emails (folder, filter, search, paginated) |
177
+ | `m365_mail_read` | Read full email by ID |
178
+ | `m365_mail_send` | Send email (to/cc/bcc, HTML or plain) |
179
+ | `m365_mail_reply` | Reply / reply-all to an email |
180
+ | `m365_mail_search` | Search emails across folders |
181
+ | `m365_mail_move` | Move email to another folder |
182
+ | `m365_mail_delete` | Delete email |
183
+ | `m365_mail_mark_read` | Mark as read/unread |
184
+ | `m365_mail_folders` | List all mail folders with counts |
185
+
186
+ ### 📅 Calendar (7 tools)
187
+ | Tool | Description |
188
+ |---|---|
189
+ | `m365_calendar_list` | Events in a date range (paginated) |
190
+ | `m365_calendar_today` | Today's events, nicely formatted |
191
+ | `m365_calendar_week` | Week view grouped by day |
192
+ | `m365_calendar_create` | Create event (optional Teams meeting) |
193
+ | `m365_calendar_update` | Update event |
194
+ | `m365_calendar_delete` | Cancel event with message |
195
+ | `m365_calendar_availability` | Free/busy lookup |
196
+
197
+ ### 👤 Contacts (6 tools)
198
+ | Tool | Description |
199
+ |---|---|
200
+ | `m365_contacts_list` | List contacts |
201
+ | `m365_contacts_search` | Search by name/email/company |
202
+ | `m365_contacts_read` | Full contact details |
203
+ | `m365_contacts_create` | Create contact |
204
+ | `m365_contacts_update` | Update contact |
205
+ | `m365_contacts_delete` | Delete contact |
206
+
207
+ ### 📁 OneDrive (5 tools)
208
+ | Tool | Description |
209
+ |---|---|
210
+ | `m365_files_list` | List files/folders (paginated) |
211
+ | `m365_files_search` | Search files |
212
+ | `m365_files_read` | Read text file content |
213
+ | `m365_files_info` | File/folder metadata |
214
+ | `m365_files_create_folder` | Create folder |
215
+
216
+ ### 💬 Teams (3 tools)
217
+ | Tool | Description |
218
+ |---|---|
219
+ | `m365_teams_chats` | List your chats |
220
+ | `m365_teams_messages` | Get chat messages |
221
+ | `m365_teams_send` | Send chat message |
222
+
223
+ ### ✅ Tasks (5 tools)
224
+ | Tool | Description |
225
+ |---|---|
226
+ | `m365_tasks_lists` | List To Do lists |
227
+ | `m365_tasks_list` | List tasks in a list |
228
+ | `m365_tasks_create` | Create task |
229
+ | `m365_tasks_update` | Update task |
230
+ | `m365_tasks_delete` | Delete task |
231
+
232
+ ### 👥 Users (3 tools)
233
+ | Tool | Description |
234
+ |---|---|
235
+ | `m365_users_list` | List org users |
236
+ | `m365_users_profile` | Get user profile |
237
+ | `m365_users_manager` | Get user's manager |
238
+
239
+ ## Development
240
+
241
+ ```bash
242
+ npm install
243
+ npm run dev # tsx watch mode
244
+ npm run build # compile TypeScript
245
+ ```
246
+
247
+ ## Security
248
+
249
+ - **Delegated OAuth** — app acts as the authenticated user. No tenant-wide access.
250
+ - **Device code flow** — you never type your password into anything but Microsoft's login page.
251
+ - **Tokens stored with 0600 permissions** in `~/.m365-mcp/auth/` by default, configurable with `M365_MCP_AUTH_DIR`.
252
+ - **Auto-refresh** — tokens refreshed before expiry, expired refresh tokens trigger re-auth.
253
+ - **No telemetry, no analytics, no third-party calls** besides `login.microsoftonline.com` and `graph.microsoft.com`.
254
+
255
+ ## License
256
+
257
+ MIT
package/SKILL.md ADDED
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: m365-mcp
3
+ description: Production-grade Microsoft 365 MCP server with delegated OAuth, multi-account support, pagination, rate limiting, and 38 tools covering email, calendar, contacts, OneDrive, Teams, tasks, and users.
4
+ ---
5
+
6
+ # m365-mcp
7
+
8
+ Production-grade Microsoft 365 MCP server combining the best of office365-connector (delegated OAuth, multi-account) and mcp-microsoft365 (MCP protocol, full scope), with production-ready features: pagination, rate limiting, retry logic, and full TypeScript.
9
+
10
+ ## Requirements
11
+
12
+ - Node.js 18+
13
+ - Azure Entra ID App Registration with delegated Microsoft Graph permissions
14
+ - Device code OAuth (no client-credentials, no tenant-wide access)
15
+
16
+ ## Capabilities
17
+
18
+ ### Email (9 tools)
19
+ - List, read, send, reply, search, move, delete, mark read/unread, list folders
20
+
21
+ ### Calendar (7 tools)
22
+ - List events, today view, week view, create (with Teams meeting), update, delete, free/busy
23
+
24
+ ### Contacts (6 tools)
25
+ - List, search, read, create, update, delete
26
+
27
+ ### OneDrive (5 tools)
28
+ - List files, search, read content, metadata, create folders
29
+
30
+ ### Teams (3 tools)
31
+ - List chats, read messages, send messages
32
+
33
+ ### Tasks (5 tools)
34
+ - List lists, list tasks, create, update, delete
35
+
36
+ ### Users (3 tools)
37
+ - List org users, profile lookup, manager lookup
38
+
39
+ ## Setup
40
+
41
+ ```bash
42
+ cd m365-mcp
43
+ npm install
44
+ npm run build
45
+
46
+ # Add account
47
+ node dist/auth-cli.js add work <tenantId> <clientId> you@company.com
48
+
49
+ # Authenticate
50
+ node dist/auth-cli.js login --account=work
51
+ ```
52
+
53
+ Then configure as an MCP server in your mcporter config.
54
+
55
+ See [README.md](README.md) for full Azure setup guide.
56
+
57
+ ## License
58
+
59
+ MIT
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * m365-mcp-auth CLI — manage accounts and authenticate outside the MCP server
4
+ *
5
+ * Usage:
6
+ * npx tsx src/auth-cli.ts add <name> <tenantId> <clientId> [email] [desc]
7
+ * npx tsx src/auth-cli.ts remove <name>
8
+ * npx tsx src/auth-cli.ts default <name>
9
+ * npx tsx src/auth-cli.ts list
10
+ * npx tsx src/auth-cli.ts login [--account=name]
11
+ * npx tsx src/auth-cli.ts status [--account=name]
12
+ */
13
+ export {};
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * m365-mcp-auth CLI — manage accounts and authenticate outside the MCP server
4
+ *
5
+ * Usage:
6
+ * npx tsx src/auth-cli.ts add <name> <tenantId> <clientId> [email] [desc]
7
+ * npx tsx src/auth-cli.ts remove <name>
8
+ * npx tsx src/auth-cli.ts default <name>
9
+ * npx tsx src/auth-cli.ts list
10
+ * npx tsx src/auth-cli.ts login [--account=name]
11
+ * npx tsx src/auth-cli.ts status [--account=name]
12
+ */
13
+ import { addAccount, removeAccount, setDefaultAccount, listAccounts, authenticate, getTokenStatus, } from "./auth.js";
14
+ async function main() {
15
+ const args = process.argv.slice(2);
16
+ const cmd = args[0];
17
+ const rest = args.slice(1);
18
+ const accountArg = rest.find((a) => a.startsWith("--account="));
19
+ const accountName = accountArg ? accountArg.split("=")[1] : undefined;
20
+ const positional = rest.filter((a) => !a.startsWith("--"));
21
+ try {
22
+ switch (cmd) {
23
+ case "add": {
24
+ if (positional.length < 3) {
25
+ console.log("Usage: m365-mcp-auth add <name> <tenantId> <clientId> [email] [description]");
26
+ process.exit(1);
27
+ }
28
+ const [name, tenantId, clientId, email, desc] = positional;
29
+ addAccount(name, tenantId, clientId, email, desc);
30
+ console.log(`✅ Account "${name}" added.`);
31
+ break;
32
+ }
33
+ case "remove": {
34
+ if (positional.length < 1) {
35
+ console.log("Usage: m365-mcp-auth remove <name>");
36
+ process.exit(1);
37
+ }
38
+ removeAccount(positional[0]);
39
+ console.log(`✅ Account "${positional[0]}" removed.`);
40
+ break;
41
+ }
42
+ case "default": {
43
+ if (positional.length < 1) {
44
+ console.log("Usage: m365-mcp-auth default <name>");
45
+ process.exit(1);
46
+ }
47
+ setDefaultAccount(positional[0]);
48
+ console.log(`✅ Default account set to "${positional[0]}".`);
49
+ break;
50
+ }
51
+ case "list": {
52
+ const { default: def, accounts } = listAccounts();
53
+ if (accounts.length === 0) {
54
+ console.log("No accounts configured.\n");
55
+ console.log("Add one: m365-mcp-auth add <name> <tenantId> <clientId>");
56
+ break;
57
+ }
58
+ console.log("📧 M365 Accounts:\n");
59
+ for (const acc of accounts) {
60
+ const marker = acc.isDefault ? " [DEFAULT]" : "";
61
+ console.log(` ${acc.name}${marker}`);
62
+ if (acc.email)
63
+ console.log(` Email: ${acc.email}`);
64
+ if (acc.description)
65
+ console.log(` Desc: ${acc.description}`);
66
+ console.log(` Tenant: ${acc.tenantId}`);
67
+ console.log();
68
+ }
69
+ break;
70
+ }
71
+ case "login": {
72
+ await authenticate(accountName, (url, code) => {
73
+ console.log("\n" + "=".repeat(60));
74
+ console.log("🔐 Sign in to Microsoft");
75
+ console.log("=".repeat(60));
76
+ console.log(`\n1. Open: ${url}`);
77
+ console.log(`2. Enter code: ${code}`);
78
+ console.log(`3. Sign in and approve permissions\n`);
79
+ });
80
+ console.log("✅ Authenticated successfully.");
81
+ break;
82
+ }
83
+ case "status": {
84
+ const status = await getTokenStatus(accountName);
85
+ if (status.valid) {
86
+ console.log(`✅ ${status.account}: Authenticated (expires ${status.expires})`);
87
+ }
88
+ else {
89
+ console.log(`❌ ${status.account}: Not authenticated`);
90
+ process.exit(1);
91
+ }
92
+ break;
93
+ }
94
+ case "env": {
95
+ // Dump environment variables for MCP client setup instructions
96
+ const { accounts } = listAccounts();
97
+ if (accounts.length === 0) {
98
+ console.log("# No accounts configured.");
99
+ break;
100
+ }
101
+ const acc = accounts.find((a) => a.isDefault) || accounts[0];
102
+ console.log(`M365_ACCOUNT=${acc.name}`);
103
+ console.log(`# M365_TIMEZONE=UTC (optional, default: UTC)`);
104
+ console.log(`# Run 'm365-mcp-auth login --account=${acc.name}' to authenticate`);
105
+ break;
106
+ }
107
+ default:
108
+ console.log("m365-mcp-auth — Account Management CLI\n");
109
+ console.log("Commands:");
110
+ console.log(" add <name> <tenantId> <clientId> [email] [desc]");
111
+ console.log(" remove <name>");
112
+ console.log(" default <name>");
113
+ console.log(" list");
114
+ console.log(" login [--account=name]");
115
+ console.log(" status [--account=name]");
116
+ console.log(" env");
117
+ console.log("\nSetup guide: https://github.com/sam2kb/m365-mcp#readme");
118
+ process.exit(1);
119
+ }
120
+ }
121
+ catch (err) {
122
+ console.error(`❌ ${err.message}`);
123
+ process.exit(1);
124
+ }
125
+ }
126
+ main();
127
+ //# sourceMappingURL=auth-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-cli.js","sourceRoot":"","sources":["../src/auth-cli.ts"],"names":[],"mappings":"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"}
package/dist/auth.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ /**
2
+ * OAuth 2.0 Device Code Flow + Multi-Account Token Management
3
+ *
4
+ * Uses delegated permissions — the app acts AS YOU, not as the tenant.
5
+ * Tokens stored in ~/.m365-mcp/auth/ by default with 0600 permissions.
6
+ */
7
+ import type { AccountConfig, AccountsStore, TokenData } from "./types.js";
8
+ export declare function resolveAuthDir(env?: NodeJS.ProcessEnv, homeDir?: string): string;
9
+ export declare function ensureDirs(): void;
10
+ export declare function getTokenPath(accountName: string): string;
11
+ export declare function loadAccounts(): AccountsStore;
12
+ export declare function addAccount(name: string, tenantId: string, clientId: string, email?: string, description?: string): void;
13
+ export declare function removeAccount(name: string): void;
14
+ export declare function setDefaultAccount(name: string): void;
15
+ export declare function resolveAccount(accountName?: string): AccountConfig;
16
+ export declare function listAccounts(): {
17
+ default: string | null;
18
+ accounts: (AccountConfig & {
19
+ isDefault: boolean;
20
+ })[];
21
+ };
22
+ export declare function loadTokens(config: AccountConfig): TokenData | null;
23
+ export declare function requestDeviceCode(config: AccountConfig): Promise<{
24
+ device_code: string;
25
+ user_code: string;
26
+ verification_uri: string;
27
+ expires_in: number;
28
+ interval: number;
29
+ }>;
30
+ /**
31
+ * Get a valid access token (auto-refresh if expired or within 5 min of expiry).
32
+ * Uses a mutex to avoid concurrent refresh races.
33
+ */
34
+ export declare function getAccessToken(accountName?: string): Promise<string>;
35
+ /**
36
+ * Full device-code authentication flow.
37
+ * Calls onPrompt(verificationUrl, userCode) so the caller can display instructions.
38
+ */
39
+ export declare function authenticate(accountName: string | undefined, onPrompt: (verificationUrl: string, userCode: string) => void): Promise<TokenData>;
40
+ export declare function getTokenStatus(accountName?: string): Promise<{
41
+ account: string;
42
+ valid: boolean;
43
+ expires: string | null;
44
+ }>;