@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 +11 -0
- package/LICENSE +21 -0
- package/README.md +257 -0
- package/SKILL.md +59 -0
- package/dist/auth-cli.d.ts +13 -0
- package/dist/auth-cli.js +127 -0
- package/dist/auth-cli.js.map +1 -0
- package/dist/auth.d.ts +44 -0
- package/dist/auth.js +288 -0
- package/dist/auth.js.map +1 -0
- package/dist/graph.d.ts +32 -0
- package/dist/graph.js +189 -0
- package/dist/graph.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +152 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/calendar.d.ts +236 -0
- package/dist/tools/calendar.js +255 -0
- package/dist/tools/calendar.js.map +1 -0
- package/dist/tools/contacts.d.ts +207 -0
- package/dist/tools/contacts.js +169 -0
- package/dist/tools/contacts.js.map +1 -0
- package/dist/tools/files.d.ts +135 -0
- package/dist/tools/files.js +127 -0
- package/dist/tools/files.js.map +1 -0
- package/dist/tools/mail.d.ts +300 -0
- package/dist/tools/mail.js +233 -0
- package/dist/tools/mail.js.map +1 -0
- package/dist/tools/tasks.d.ts +171 -0
- package/dist/tools/tasks.js +129 -0
- package/dist/tools/tasks.js.map +1 -0
- package/dist/tools/teams.d.ts +71 -0
- package/dist/tools/teams.js +75 -0
- package/dist/tools/teams.js.map +1 -0
- package/dist/tools/users.d.ts +55 -0
- package/dist/tools/users.js +64 -0
- package/dist/tools/users.js.map +1 -0
- package/dist/types.d.ts +197 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +48 -0
- package/tsconfig.json +19 -0
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 {};
|
package/dist/auth-cli.js
ADDED
|
@@ -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
|
+
}>;
|