@awolve/myoffice 1.6.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 +271 -0
- package/dist/auth/cache-plugin.d.ts +20 -0
- package/dist/auth/cache-plugin.d.ts.map +1 -0
- package/dist/auth/cache-plugin.js +49 -0
- package/dist/auth/cache-plugin.js.map +1 -0
- package/dist/auth/config.d.ts +40 -0
- package/dist/auth/config.d.ts.map +1 -0
- package/dist/auth/config.js +135 -0
- package/dist/auth/config.js.map +1 -0
- package/dist/auth/device-code.d.ts +2 -0
- package/dist/auth/device-code.d.ts.map +1 -0
- package/dist/auth/device-code.js +40 -0
- package/dist/auth/device-code.js.map +1 -0
- package/dist/auth/index.d.ts +4 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +4 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/login.d.ts +7 -0
- package/dist/auth/login.d.ts.map +1 -0
- package/dist/auth/login.js +22 -0
- package/dist/auth/login.js.map +1 -0
- package/dist/auth/token-manager.d.ts +4 -0
- package/dist/auth/token-manager.d.ts.map +1 -0
- package/dist/auth/token-manager.js +85 -0
- package/dist/auth/token-manager.js.map +1 -0
- package/dist/cli/formatter.d.ts +5 -0
- package/dist/cli/formatter.d.ts.map +1 -0
- package/dist/cli/formatter.js +317 -0
- package/dist/cli/formatter.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +973 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/handler.d.ts +8 -0
- package/dist/core/handler.d.ts.map +1 -0
- package/dist/core/handler.js +327 -0
- package/dist/core/handler.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +924 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/calendar.d.ts +124 -0
- package/dist/tools/calendar.d.ts.map +1 -0
- package/dist/tools/calendar.js +129 -0
- package/dist/tools/calendar.js.map +1 -0
- package/dist/tools/chats.d.ts +66 -0
- package/dist/tools/chats.d.ts.map +1 -0
- package/dist/tools/chats.js +102 -0
- package/dist/tools/chats.js.map +1 -0
- package/dist/tools/contacts.d.ts +138 -0
- package/dist/tools/contacts.d.ts.map +1 -0
- package/dist/tools/contacts.js +189 -0
- package/dist/tools/contacts.js.map +1 -0
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +10 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/mail.d.ts +138 -0
- package/dist/tools/mail.d.ts.map +1 -0
- package/dist/tools/mail.js +187 -0
- package/dist/tools/mail.js.map +1 -0
- package/dist/tools/onedrive.d.ts +125 -0
- package/dist/tools/onedrive.d.ts.map +1 -0
- package/dist/tools/onedrive.js +203 -0
- package/dist/tools/onedrive.js.map +1 -0
- package/dist/tools/planner.d.ts +390 -0
- package/dist/tools/planner.d.ts.map +1 -0
- package/dist/tools/planner.js +693 -0
- package/dist/tools/planner.js.map +1 -0
- package/dist/tools/sharepoint.d.ts +138 -0
- package/dist/tools/sharepoint.d.ts.map +1 -0
- package/dist/tools/sharepoint.js +156 -0
- package/dist/tools/sharepoint.js.map +1 -0
- package/dist/tools/tasks.d.ts +107 -0
- package/dist/tools/tasks.d.ts.map +1 -0
- package/dist/tools/tasks.js +131 -0
- package/dist/tools/tasks.js.map +1 -0
- package/dist/tools/teams.d.ts +66 -0
- package/dist/tools/teams.d.ts.map +1 -0
- package/dist/tools/teams.js +69 -0
- package/dist/tools/teams.js.map +1 -0
- package/dist/utils/graph-client.d.ts +15 -0
- package/dist/utils/graph-client.d.ts.map +1 -0
- package/dist/utils/graph-client.js +126 -0
- package/dist/utils/graph-client.js.map +1 -0
- package/dist/utils/signature.d.ts +2 -0
- package/dist/utils/signature.d.ts.map +1 -0
- package/dist/utils/signature.js +17 -0
- package/dist/utils/signature.js.map +1 -0
- package/dist/utils/version.d.ts +2 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +20 -0
- package/dist/utils/version.js.map +1 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# MyOffice MCP
|
|
2
|
+
|
|
3
|
+
A lightweight MCP (Model Context Protocol) server and CLI for personal Microsoft 365 access, designed for AI assistants like Claude Code.
|
|
4
|
+
|
|
5
|
+
Unlike admin-focused M365 tools, this uses **delegated authentication** - users authenticate as themselves and can only access their own data.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Email** - List, read, search, send, reply, delete, mark read/unread
|
|
10
|
+
- **Calendar** - List, create, update, delete events (with Teams meetings)
|
|
11
|
+
- **Tasks** - Manage Microsoft To Do lists and tasks
|
|
12
|
+
- **Planner** - Access plans, buckets, and tasks
|
|
13
|
+
- **OneDrive** - Browse, search, read files
|
|
14
|
+
- **SharePoint** - Access sites and document libraries
|
|
15
|
+
- **Teams** - List teams, channels, read/post messages
|
|
16
|
+
- **Chats** - 1:1 and group chats
|
|
17
|
+
- **Contacts** - List, search, create, update contacts
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
### From npm (recommended)
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install -g awolve-myoffice-cli
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### From source
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
git clone https://github.com/awolve/ops-myoffice.git
|
|
31
|
+
cd ops-myoffice
|
|
32
|
+
npm install
|
|
33
|
+
npm run build
|
|
34
|
+
npm link
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Prerequisites
|
|
38
|
+
|
|
39
|
+
- Node.js 18+
|
|
40
|
+
- An Azure AD app registration with delegated permissions
|
|
41
|
+
- Microsoft 365 account
|
|
42
|
+
|
|
43
|
+
## Configuration
|
|
44
|
+
|
|
45
|
+
Add to your shell profile (`~/.zshrc` or `~/.bashrc`):
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
export M365_CLIENT_ID="your-app-client-id"
|
|
49
|
+
# Optional: export M365_TENANT_ID="your-tenant-id"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Authentication
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
myoffice login
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Opens a browser for device code authentication. Token is cached at `~/.config/myoffice-mcp/msal-cache.json`.
|
|
59
|
+
|
|
60
|
+
## CLI Usage
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Check status
|
|
64
|
+
myoffice status
|
|
65
|
+
|
|
66
|
+
# Email
|
|
67
|
+
myoffice mail list
|
|
68
|
+
myoffice mail list --unread
|
|
69
|
+
myoffice mail read <id>
|
|
70
|
+
myoffice mail send --to user@example.com --subject "Hi" --body "Hello"
|
|
71
|
+
|
|
72
|
+
# Calendar
|
|
73
|
+
myoffice calendar list
|
|
74
|
+
myoffice calendar list --start 2024-01-15 --end 2024-01-20
|
|
75
|
+
|
|
76
|
+
# Tasks (To Do)
|
|
77
|
+
myoffice tasks lists
|
|
78
|
+
myoffice tasks list
|
|
79
|
+
myoffice tasks create "Buy milk"
|
|
80
|
+
|
|
81
|
+
# Files (OneDrive)
|
|
82
|
+
myoffice files list
|
|
83
|
+
myoffice files search "report"
|
|
84
|
+
|
|
85
|
+
# Teams & Chats
|
|
86
|
+
myoffice teams list
|
|
87
|
+
myoffice chats list
|
|
88
|
+
|
|
89
|
+
# Planner
|
|
90
|
+
myoffice planner plans
|
|
91
|
+
myoffice planner tasks <planId>
|
|
92
|
+
|
|
93
|
+
# JSON output (for scripting)
|
|
94
|
+
myoffice mail list --json
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Run `myoffice --help` for all commands.
|
|
98
|
+
|
|
99
|
+
## MCP Server Usage
|
|
100
|
+
|
|
101
|
+
Add to your Claude Code MCP settings:
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"mcpServers": {
|
|
106
|
+
"myoffice": {
|
|
107
|
+
"command": "myoffice-mcp",
|
|
108
|
+
"env": {
|
|
109
|
+
"M365_CLIENT_ID": "your-client-id"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Or with full path if not installed globally:
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"mcpServers": {
|
|
121
|
+
"myoffice": {
|
|
122
|
+
"command": "node",
|
|
123
|
+
"args": ["/path/to/ops-myoffice/dist/index.js"],
|
|
124
|
+
"env": {
|
|
125
|
+
"M365_CLIENT_ID": "your-client-id"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Azure AD App Registration
|
|
133
|
+
|
|
134
|
+
1. Go to [Azure Portal](https://portal.azure.com) > Azure Active Directory > App registrations
|
|
135
|
+
2. Click **New registration**
|
|
136
|
+
- Name: `MyOffice MCP` (or your choice)
|
|
137
|
+
- Supported account types: **Accounts in any organizational directory**
|
|
138
|
+
- Redirect URI: Leave blank (uses device code flow)
|
|
139
|
+
3. Note the **Application (client) ID**
|
|
140
|
+
4. Go to **Authentication** > Enable **Allow public client flows** = Yes
|
|
141
|
+
5. Go to **API permissions** > Add Microsoft Graph delegated permissions:
|
|
142
|
+
- `Mail.ReadWrite`, `Mail.Send`
|
|
143
|
+
- `Calendars.ReadWrite`
|
|
144
|
+
- `Tasks.ReadWrite`
|
|
145
|
+
- `Files.ReadWrite`, `Sites.Read.All`
|
|
146
|
+
- `Contacts.ReadWrite`
|
|
147
|
+
- `Team.ReadBasic.All`, `Channel.ReadBasic.All`
|
|
148
|
+
- `ChannelMessage.Read.All`, `ChannelMessage.Send`
|
|
149
|
+
- `Chat.Create`, `Chat.ReadBasic`, `Chat.Read`, `ChatMessage.Send`
|
|
150
|
+
- `Tasks.Read`, `Tasks.ReadWrite`, `Group.Read.All` (for Planner)
|
|
151
|
+
- `User.Read`, `offline_access`
|
|
152
|
+
|
|
153
|
+
## Development
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
npm install # Install dependencies
|
|
157
|
+
npm run dev # Run with tsx (no build needed)
|
|
158
|
+
npm run build # Compile TypeScript to dist/
|
|
159
|
+
npm run login # Authenticate with Microsoft
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Project Structure
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
src/
|
|
166
|
+
├── index.ts # MCP server entry point
|
|
167
|
+
├── cli.ts # CLI entry point (Commander.js)
|
|
168
|
+
├── core/
|
|
169
|
+
│ └── handler.ts # Shared tool dispatch logic
|
|
170
|
+
├── cli/
|
|
171
|
+
│ └── formatter.ts # Human-readable output formatting
|
|
172
|
+
├── auth/ # Authentication (device code flow, token cache)
|
|
173
|
+
├── tools/ # Microsoft Graph API implementations
|
|
174
|
+
└── utils/ # Graph client, version helper
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Testing Locally
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Test CLI directly (no build needed)
|
|
181
|
+
npx tsx src/cli.ts mail list
|
|
182
|
+
|
|
183
|
+
# Or build first then test
|
|
184
|
+
npm run build
|
|
185
|
+
node dist/cli.js mail list
|
|
186
|
+
|
|
187
|
+
# Test MCP server
|
|
188
|
+
npm run dev
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Deploying to npm
|
|
192
|
+
|
|
193
|
+
The package is published to npm as `awolve-myoffice-cli`.
|
|
194
|
+
|
|
195
|
+
### First-Time Setup
|
|
196
|
+
|
|
197
|
+
1. Create npm account at https://www.npmjs.com/signup
|
|
198
|
+
2. Login from terminal:
|
|
199
|
+
```bash
|
|
200
|
+
npm login
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Publishing a New Version
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# 1. Make sure you're on main branch with clean working directory
|
|
207
|
+
git checkout main
|
|
208
|
+
git pull
|
|
209
|
+
git status # Should be clean
|
|
210
|
+
|
|
211
|
+
# 2. Run tests / verify everything works
|
|
212
|
+
npm run build
|
|
213
|
+
node dist/cli.js --help
|
|
214
|
+
|
|
215
|
+
# 3. Bump version (choose one)
|
|
216
|
+
npm version patch # 1.1.0 -> 1.1.1 (bug fixes)
|
|
217
|
+
npm version minor # 1.1.0 -> 1.2.0 (new features)
|
|
218
|
+
npm version major # 1.1.0 -> 2.0.0 (breaking changes)
|
|
219
|
+
|
|
220
|
+
# 4. Publish to npm (builds automatically via prepublishOnly)
|
|
221
|
+
npm publish --access public
|
|
222
|
+
|
|
223
|
+
# 5. Push version commit and tag to GitHub
|
|
224
|
+
git push && git push --tags
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### What Gets Published
|
|
228
|
+
|
|
229
|
+
The `files` field in package.json controls what's included:
|
|
230
|
+
- `dist/**/*` - Compiled JavaScript
|
|
231
|
+
- `README.md` - Documentation
|
|
232
|
+
|
|
233
|
+
Source code (`src/`), specs, and dev files are NOT published.
|
|
234
|
+
|
|
235
|
+
### Verifying Publication
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
# Check package on npm
|
|
239
|
+
npm view awolve-myoffice-cli
|
|
240
|
+
|
|
241
|
+
# Test fresh install
|
|
242
|
+
npm install -g awolve-myoffice-cli
|
|
243
|
+
myoffice --version
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Important: Version Immutability
|
|
247
|
+
|
|
248
|
+
npm does not allow republishing the same version. Once `1.1.0` is published, that version number is permanently taken. If you need to fix something:
|
|
249
|
+
|
|
250
|
+
1. Bump to a new version (`npm version patch` → `1.1.1`)
|
|
251
|
+
2. Publish the new version
|
|
252
|
+
|
|
253
|
+
There is no way to "update" an existing version.
|
|
254
|
+
|
|
255
|
+
### Troubleshooting
|
|
256
|
+
|
|
257
|
+
- **"You must be logged in"** - Run `npm login`
|
|
258
|
+
- **"Package name already exists"** - Name is taken, choose another
|
|
259
|
+
- **"Cannot publish over existing version"** - Bump version with `npm version patch`
|
|
260
|
+
- **Build fails during publish** - Fix TypeScript errors first
|
|
261
|
+
|
|
262
|
+
## Security
|
|
263
|
+
|
|
264
|
+
- Uses delegated permissions only - users can only access their own data
|
|
265
|
+
- Tokens stored locally with restrictive permissions
|
|
266
|
+
- No client secrets required (public client)
|
|
267
|
+
- Destructive operations require explicit confirmation
|
|
268
|
+
|
|
269
|
+
## License
|
|
270
|
+
|
|
271
|
+
MIT
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ICachePlugin, TokenCacheContext } from '@azure/msal-node';
|
|
2
|
+
/**
|
|
3
|
+
* MSAL Cache Plugin that persists the full token cache (including refresh tokens)
|
|
4
|
+
* to a file. This ensures tokens survive server restarts.
|
|
5
|
+
*/
|
|
6
|
+
export declare class FileCachePlugin implements ICachePlugin {
|
|
7
|
+
private cachePath;
|
|
8
|
+
constructor(cachePath: string);
|
|
9
|
+
/**
|
|
10
|
+
* Called before MSAL accesses the cache.
|
|
11
|
+
* Load the cache from disk into MSAL's memory.
|
|
12
|
+
*/
|
|
13
|
+
beforeCacheAccess(cacheContext: TokenCacheContext): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Called after MSAL accesses the cache.
|
|
16
|
+
* If the cache changed, persist it to disk.
|
|
17
|
+
*/
|
|
18
|
+
afterCacheAccess(cacheContext: TokenCacheContext): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=cache-plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-plugin.d.ts","sourceRoot":"","sources":["../../src/auth/cache-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAInE;;;GAGG;AACH,qBAAa,eAAgB,YAAW,YAAY;IAClD,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,EAAE,MAAM;IAI7B;;;OAGG;IACG,iBAAiB,CAAC,YAAY,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAavE;;;OAGG;IACG,gBAAgB,CAAC,YAAY,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;CAcvE"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
2
|
+
import { dirname } from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* MSAL Cache Plugin that persists the full token cache (including refresh tokens)
|
|
5
|
+
* to a file. This ensures tokens survive server restarts.
|
|
6
|
+
*/
|
|
7
|
+
export class FileCachePlugin {
|
|
8
|
+
cachePath;
|
|
9
|
+
constructor(cachePath) {
|
|
10
|
+
this.cachePath = cachePath;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Called before MSAL accesses the cache.
|
|
14
|
+
* Load the cache from disk into MSAL's memory.
|
|
15
|
+
*/
|
|
16
|
+
async beforeCacheAccess(cacheContext) {
|
|
17
|
+
try {
|
|
18
|
+
if (existsSync(this.cachePath)) {
|
|
19
|
+
const cacheData = readFileSync(this.cachePath, 'utf-8');
|
|
20
|
+
if (cacheData && cacheData.trim()) {
|
|
21
|
+
cacheContext.tokenCache.deserialize(cacheData);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
console.error('[Cache] Failed to load cache:', error instanceof Error ? error.message : error);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Called after MSAL accesses the cache.
|
|
31
|
+
* If the cache changed, persist it to disk.
|
|
32
|
+
*/
|
|
33
|
+
async afterCacheAccess(cacheContext) {
|
|
34
|
+
if (cacheContext.cacheHasChanged) {
|
|
35
|
+
try {
|
|
36
|
+
const dir = dirname(this.cachePath);
|
|
37
|
+
if (!existsSync(dir)) {
|
|
38
|
+
mkdirSync(dir, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
const serialized = cacheContext.tokenCache.serialize();
|
|
41
|
+
writeFileSync(this.cachePath, serialized, { mode: 0o600 });
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
console.error('[Cache] Failed to save cache:', error instanceof Error ? error.message : error);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=cache-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-plugin.js","sourceRoot":"","sources":["../../src/auth/cache-plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B;;;GAGG;AACH,MAAM,OAAO,eAAe;IAClB,SAAS,CAAS;IAE1B,YAAY,SAAiB;QAC3B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,iBAAiB,CAAC,YAA+B;QACrD,IAAI,CAAC;YACH,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC/B,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;gBACxD,IAAI,SAAS,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;oBAClC,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;gBACjD,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACjG,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,gBAAgB,CAAC,YAA+B;QACpD,IAAI,YAAY,CAAC,eAAe,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACpC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBACtC,CAAC;gBACD,MAAM,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;gBACvD,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC7D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACjG,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface TokenCache {
|
|
2
|
+
accessToken: string;
|
|
3
|
+
refreshToken: string;
|
|
4
|
+
expiresAt: number;
|
|
5
|
+
account?: {
|
|
6
|
+
homeAccountId: string;
|
|
7
|
+
environment: string;
|
|
8
|
+
tenantId: string;
|
|
9
|
+
username: string;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export interface AuthConfig {
|
|
13
|
+
clientId: string;
|
|
14
|
+
tenantId: string;
|
|
15
|
+
scopes: string[];
|
|
16
|
+
}
|
|
17
|
+
export interface StoredConfig {
|
|
18
|
+
clientId?: string;
|
|
19
|
+
tenantId?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get stored configuration from config file
|
|
23
|
+
*/
|
|
24
|
+
export declare function getStoredConfig(): StoredConfig;
|
|
25
|
+
/**
|
|
26
|
+
* Save configuration to config file
|
|
27
|
+
*/
|
|
28
|
+
export declare function saveStoredConfig(config: StoredConfig): void;
|
|
29
|
+
/**
|
|
30
|
+
* Get the current auth config (dynamically evaluated)
|
|
31
|
+
* Call this function instead of using DEFAULT_CONFIG directly
|
|
32
|
+
* to ensure env vars and stored config are always checked
|
|
33
|
+
*/
|
|
34
|
+
export declare function getAuthConfig(): AuthConfig;
|
|
35
|
+
export declare const DEFAULT_CONFIG: AuthConfig;
|
|
36
|
+
export declare const MSAL_CACHE_FILE: string;
|
|
37
|
+
export declare function getTokenCache(): TokenCache | null;
|
|
38
|
+
export declare function saveTokenCache(cache: TokenCache): void;
|
|
39
|
+
export declare function clearTokenCache(): void;
|
|
40
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/auth/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE;QACR,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAKD;;GAEG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAU9C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAQ3D;AAuDD;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,UAAU,CAM1C;AAMD,eAAO,MAAM,cAAc,EAAE,UAI5B,CAAC;AAGF,eAAO,MAAM,eAAe,QAAgE,CAAC;AAE7F,wBAAgB,aAAa,IAAI,UAAU,GAAG,IAAI,CAUjD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAMtD;AAED,wBAAgB,eAAe,IAAI,IAAI,CAQtC"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
2
|
+
import { homedir } from 'os';
|
|
3
|
+
import { join, dirname } from 'path';
|
|
4
|
+
const CONFIG_DIR = join(homedir(), '.config', 'myoffice-mcp');
|
|
5
|
+
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
6
|
+
/**
|
|
7
|
+
* Get stored configuration from config file
|
|
8
|
+
*/
|
|
9
|
+
export function getStoredConfig() {
|
|
10
|
+
try {
|
|
11
|
+
if (existsSync(CONFIG_FILE)) {
|
|
12
|
+
const data = readFileSync(CONFIG_FILE, 'utf-8');
|
|
13
|
+
return JSON.parse(data);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// Ignore errors, return empty config
|
|
18
|
+
}
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Save configuration to config file
|
|
23
|
+
*/
|
|
24
|
+
export function saveStoredConfig(config) {
|
|
25
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
26
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
27
|
+
}
|
|
28
|
+
// Merge with existing config
|
|
29
|
+
const existing = getStoredConfig();
|
|
30
|
+
const merged = { ...existing, ...config };
|
|
31
|
+
writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2), { mode: 0o600 });
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get the client ID from env var or stored config
|
|
35
|
+
*/
|
|
36
|
+
function getClientId() {
|
|
37
|
+
// Environment variable takes precedence
|
|
38
|
+
if (process.env.M365_CLIENT_ID) {
|
|
39
|
+
return process.env.M365_CLIENT_ID;
|
|
40
|
+
}
|
|
41
|
+
// Fall back to stored config
|
|
42
|
+
const stored = getStoredConfig();
|
|
43
|
+
return stored.clientId || '';
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get the tenant ID from env var or stored config
|
|
47
|
+
*/
|
|
48
|
+
function getTenantId() {
|
|
49
|
+
// Environment variable takes precedence
|
|
50
|
+
if (process.env.M365_TENANT_ID) {
|
|
51
|
+
return process.env.M365_TENANT_ID;
|
|
52
|
+
}
|
|
53
|
+
// Fall back to stored config, default to 'common'
|
|
54
|
+
const stored = getStoredConfig();
|
|
55
|
+
return stored.tenantId || 'common';
|
|
56
|
+
}
|
|
57
|
+
// Scopes for Graph API access
|
|
58
|
+
const SCOPES = [
|
|
59
|
+
'https://graph.microsoft.com/Mail.ReadWrite',
|
|
60
|
+
'https://graph.microsoft.com/Mail.Send',
|
|
61
|
+
'https://graph.microsoft.com/Calendars.ReadWrite',
|
|
62
|
+
'https://graph.microsoft.com/Tasks.ReadWrite',
|
|
63
|
+
'https://graph.microsoft.com/Files.ReadWrite',
|
|
64
|
+
'https://graph.microsoft.com/Sites.ReadWrite.All',
|
|
65
|
+
'https://graph.microsoft.com/Contacts.ReadWrite',
|
|
66
|
+
'https://graph.microsoft.com/User.Read',
|
|
67
|
+
// Teams
|
|
68
|
+
'https://graph.microsoft.com/Team.ReadBasic.All',
|
|
69
|
+
'https://graph.microsoft.com/Channel.ReadBasic.All',
|
|
70
|
+
'https://graph.microsoft.com/ChannelMessage.Read.All',
|
|
71
|
+
'https://graph.microsoft.com/ChannelMessage.Send',
|
|
72
|
+
// Chats
|
|
73
|
+
'https://graph.microsoft.com/Chat.Create',
|
|
74
|
+
'https://graph.microsoft.com/Chat.ReadBasic',
|
|
75
|
+
'https://graph.microsoft.com/Chat.Read',
|
|
76
|
+
'https://graph.microsoft.com/ChatMessage.Send',
|
|
77
|
+
// Planner
|
|
78
|
+
'https://graph.microsoft.com/Tasks.ReadWrite',
|
|
79
|
+
'https://graph.microsoft.com/Group.Read.All',
|
|
80
|
+
'https://graph.microsoft.com/User.ReadBasic.All',
|
|
81
|
+
'offline_access',
|
|
82
|
+
];
|
|
83
|
+
/**
|
|
84
|
+
* Get the current auth config (dynamically evaluated)
|
|
85
|
+
* Call this function instead of using DEFAULT_CONFIG directly
|
|
86
|
+
* to ensure env vars and stored config are always checked
|
|
87
|
+
*/
|
|
88
|
+
export function getAuthConfig() {
|
|
89
|
+
return {
|
|
90
|
+
clientId: getClientId(),
|
|
91
|
+
tenantId: getTenantId(),
|
|
92
|
+
scopes: SCOPES,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
// Default Azure AD app for personal M365 access
|
|
96
|
+
// Users can override with their own app registration
|
|
97
|
+
// NOTE: This is evaluated once at module load time.
|
|
98
|
+
// For dynamic access, use getAuthConfig() instead.
|
|
99
|
+
export const DEFAULT_CONFIG = {
|
|
100
|
+
clientId: getClientId(),
|
|
101
|
+
tenantId: getTenantId(),
|
|
102
|
+
scopes: SCOPES,
|
|
103
|
+
};
|
|
104
|
+
const TOKEN_FILE = join(homedir(), '.config', 'myoffice-mcp', 'token.json');
|
|
105
|
+
export const MSAL_CACHE_FILE = join(homedir(), '.config', 'myoffice-mcp', 'msal-cache.json');
|
|
106
|
+
export function getTokenCache() {
|
|
107
|
+
try {
|
|
108
|
+
if (existsSync(TOKEN_FILE)) {
|
|
109
|
+
const data = readFileSync(TOKEN_FILE, 'utf-8');
|
|
110
|
+
return JSON.parse(data);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// Ignore errors, return null
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
export function saveTokenCache(cache) {
|
|
119
|
+
const dir = dirname(TOKEN_FILE);
|
|
120
|
+
if (!existsSync(dir)) {
|
|
121
|
+
mkdirSync(dir, { recursive: true });
|
|
122
|
+
}
|
|
123
|
+
writeFileSync(TOKEN_FILE, JSON.stringify(cache, null, 2), { mode: 0o600 });
|
|
124
|
+
}
|
|
125
|
+
export function clearTokenCache() {
|
|
126
|
+
try {
|
|
127
|
+
if (existsSync(TOKEN_FILE)) {
|
|
128
|
+
writeFileSync(TOKEN_FILE, '', { mode: 0o600 });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// Ignore errors
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/auth/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-code.d.ts","sourceRoot":"","sources":["../../src/auth/device-code.ts"],"names":[],"mappings":"AAMA,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,IAAI,CAAC,CA0ChE"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { PublicClientApplication } from '@azure/msal-node';
|
|
2
|
+
import { getAuthConfig, MSAL_CACHE_FILE } from './config.js';
|
|
3
|
+
import { FileCachePlugin } from './cache-plugin.js';
|
|
4
|
+
const cachePlugin = new FileCachePlugin(MSAL_CACHE_FILE);
|
|
5
|
+
export async function authenticateWithDeviceCode() {
|
|
6
|
+
const config = getAuthConfig();
|
|
7
|
+
if (!config.clientId) {
|
|
8
|
+
throw new Error('No client ID configured.\n' +
|
|
9
|
+
'Run: myoffice login --client-id <your-azure-app-client-id>\n' +
|
|
10
|
+
'Or set M365_CLIENT_ID environment variable.');
|
|
11
|
+
}
|
|
12
|
+
const pca = new PublicClientApplication({
|
|
13
|
+
auth: {
|
|
14
|
+
clientId: config.clientId,
|
|
15
|
+
authority: `https://login.microsoftonline.com/${config.tenantId}`,
|
|
16
|
+
},
|
|
17
|
+
cache: {
|
|
18
|
+
cachePlugin,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
const deviceCodeRequest = {
|
|
22
|
+
scopes: config.scopes,
|
|
23
|
+
deviceCodeCallback: (response) => {
|
|
24
|
+
console.log('\n' + '='.repeat(60));
|
|
25
|
+
console.log('AUTHENTICATION REQUIRED');
|
|
26
|
+
console.log('='.repeat(60));
|
|
27
|
+
console.log(`\n${response.message}\n`);
|
|
28
|
+
console.log('='.repeat(60) + '\n');
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
const result = await pca.acquireTokenByDeviceCode(deviceCodeRequest);
|
|
32
|
+
if (!result || !result.accessToken) {
|
|
33
|
+
throw new Error('Failed to acquire access token');
|
|
34
|
+
}
|
|
35
|
+
// The cache plugin automatically persists the tokens via afterCacheAccess
|
|
36
|
+
console.log(`\nAuthenticated as: ${result.account?.username}`);
|
|
37
|
+
console.log('Token cached at:', MSAL_CACHE_FILE);
|
|
38
|
+
console.log('Refresh token is now properly persisted.\n');
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=device-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-code.js","sourceRoot":"","sources":["../../src/auth/device-code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAqB,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,GAAG,IAAI,eAAe,CAAC,eAAe,CAAC,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,0BAA0B;IAC9C,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAE/B,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACb,4BAA4B;YAC5B,8DAA8D;YAC9D,6CAA6C,CAC9C,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,uBAAuB,CAAC;QACtC,IAAI,EAAE;YACJ,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,SAAS,EAAE,qCAAqC,MAAM,CAAC,QAAQ,EAAE;SAClE;QACD,KAAK,EAAE;YACL,WAAW;SACZ;KACF,CAAC,CAAC;IAEH,MAAM,iBAAiB,GAAsB;QAC3C,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,kBAAkB,EAAE,CAAC,QAAQ,EAAE,EAAE;YAC/B,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QACrC,CAAC;KACF,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,wBAAwB,CAAC,iBAAiB,CAAC,CAAC;IAErE,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IAED,0EAA0E;IAC1E,OAAO,CAAC,GAAG,CAAC,uBAAuB,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { getAccessToken, isAuthenticated, getCurrentUser } from './token-manager.js';
|
|
2
|
+
export { authenticateWithDeviceCode } from './device-code.js';
|
|
3
|
+
export { DEFAULT_CONFIG, getAuthConfig, getStoredConfig, saveStoredConfig, clearTokenCache } from './config.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACrF,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,eAAe,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { getAccessToken, isAuthenticated, getCurrentUser } from './token-manager.js';
|
|
2
|
+
export { authenticateWithDeviceCode } from './device-code.js';
|
|
3
|
+
export { DEFAULT_CONFIG, getAuthConfig, getStoredConfig, saveStoredConfig, clearTokenCache } from './config.js';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACrF,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,eAAe,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/auth/login.ts"],"names":[],"mappings":";AACA;;;GAGG"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Standalone login script for initial authentication
|
|
4
|
+
* Run with: npm run login
|
|
5
|
+
*/
|
|
6
|
+
import { authenticateWithDeviceCode } from './device-code.js';
|
|
7
|
+
async function main() {
|
|
8
|
+
console.log('Personal M365 MCP - Authentication');
|
|
9
|
+
console.log('===================================\n');
|
|
10
|
+
try {
|
|
11
|
+
await authenticateWithDeviceCode();
|
|
12
|
+
console.log('Authentication successful!');
|
|
13
|
+
console.log('You can now use the M365 MCP with Claude Code.');
|
|
14
|
+
process.exit(0);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
console.error('Authentication failed:', error);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
main();
|
|
22
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/auth/login.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAE9D,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;IAErD,IAAI,CAAC;QACH,MAAM,0BAA0B,EAAE,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;QAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-manager.d.ts","sourceRoot":"","sources":["../../src/auth/token-manager.ts"],"names":[],"mappings":"AAsCA,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CA0CtD;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAQxD;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQ7D"}
|