@softeria/ms-365-mcp-server 0.24.1 → 0.24.3

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/Dockerfile ADDED
@@ -0,0 +1,13 @@
1
+ FROM node:20-alpine
2
+
3
+ WORKDIR /app
4
+
5
+ COPY package*.json ./
6
+ RUN npm ci --ignore-scripts
7
+
8
+ COPY . .
9
+ RUN npm run build
10
+ RUN npm prune --production
11
+
12
+ ENTRYPOINT ["node", "dist/index.js"]
13
+ CMD ["--http"]
package/README.md CHANGED
@@ -287,19 +287,30 @@ registration:
287
287
  - Navigate to Azure Active Directory → App registrations → New registration
288
288
  - Set name: "MS365 MCP Server"
289
289
 
290
- 1. **Configure Redirect URIs**:
291
- Add these redirect URIs for testing with MCP Inspector (`npm run inspector`):
290
+ 2. **Configure Redirect URIs**:
292
291
 
293
- - `http://localhost:6274/oauth/callback`
294
- - `http://localhost:6274/oauth/callback/debug`
295
- - `http://localhost:3000/callback` (optional, for server callback)
292
+ - **Configure the OAuth callback URI**: Go to your app registration and on the left side, go to Authentication.
293
+ - Under Platform configurations:
294
+ - Click Add a platform (if you don’t already see one for "Mobile and desktop applications" / "Public client").
295
+ - Choose Mobile and desktop applications or Public client/native (mobile & desktop) (label depends on portal version).
296
296
 
297
- 1. **Get Credentials**:
297
+ 3. **Testing with MCP Inspector (`npm run inspector`)**:
298
+
299
+ - Go to your app registration and on the left side, go to Authentication.
300
+ - Under Platform configurations:
301
+ - Click Add a platform (if you don’t already see one for "Web").
302
+ - Choose Web.
303
+ - Configure the following redirect URIs
304
+ - `http://localhost:6274/oauth/callback`
305
+ - `http://localhost:6274/oauth/callback/debug`
306
+ - `http://localhost:3000/callback` (optional, for server callback)
307
+
308
+ 4. **Get Credentials**:
298
309
 
299
310
  - Copy the **Application (client) ID** from Overview page
300
311
  - Go to Certificates & secrets → New client secret → Copy the secret value
301
312
 
302
- 1. **Configure Environment Variables**:
313
+ 5. **Configure Environment Variables**:
303
314
  Create a `.env` file in your project root:
304
315
  ```env
305
316
  MS365_MCP_CLIENT_ID=your-azure-ad-app-client-id-here
package/dist/auth.js CHANGED
@@ -1,9 +1,25 @@
1
1
  import { PublicClientApplication } from "@azure/msal-node";
2
- import keytar from "keytar";
3
2
  import logger from "./logger.js";
4
3
  import fs, { existsSync, readFileSync } from "fs";
5
4
  import { fileURLToPath } from "url";
6
5
  import path from "path";
6
+ let keytar = null;
7
+ async function getKeytar() {
8
+ if (keytar === void 0) {
9
+ return null;
10
+ }
11
+ if (keytar === null) {
12
+ try {
13
+ keytar = await import("keytar");
14
+ return keytar;
15
+ } catch (error) {
16
+ logger.info("keytar not available, using file-based credential storage");
17
+ keytar = void 0;
18
+ return null;
19
+ }
20
+ }
21
+ return keytar;
22
+ }
7
23
  const __filename = fileURLToPath(import.meta.url);
8
24
  const __dirname = path.dirname(__filename);
9
25
  const endpointsData = JSON.parse(
@@ -87,9 +103,12 @@ class AuthManager {
87
103
  try {
88
104
  let cacheData;
89
105
  try {
90
- const cachedData = await keytar.getPassword(SERVICE_NAME, TOKEN_CACHE_ACCOUNT);
91
- if (cachedData) {
92
- cacheData = cachedData;
106
+ const kt = await getKeytar();
107
+ if (kt) {
108
+ const cachedData = await kt.getPassword(SERVICE_NAME, TOKEN_CACHE_ACCOUNT);
109
+ if (cachedData) {
110
+ cacheData = cachedData;
111
+ }
93
112
  }
94
113
  } catch (keytarError) {
95
114
  logger.warn(
@@ -111,9 +130,12 @@ class AuthManager {
111
130
  try {
112
131
  let selectedAccountData;
113
132
  try {
114
- const cachedData = await keytar.getPassword(SERVICE_NAME, SELECTED_ACCOUNT_KEY);
115
- if (cachedData) {
116
- selectedAccountData = cachedData;
133
+ const kt = await getKeytar();
134
+ if (kt) {
135
+ const cachedData = await kt.getPassword(SERVICE_NAME, SELECTED_ACCOUNT_KEY);
136
+ if (cachedData) {
137
+ selectedAccountData = cachedData;
138
+ }
117
139
  }
118
140
  } catch (keytarError) {
119
141
  logger.warn(
@@ -136,7 +158,12 @@ class AuthManager {
136
158
  try {
137
159
  const cacheData = this.msalApp.getTokenCache().serialize();
138
160
  try {
139
- await keytar.setPassword(SERVICE_NAME, TOKEN_CACHE_ACCOUNT, cacheData);
161
+ const kt = await getKeytar();
162
+ if (kt) {
163
+ await kt.setPassword(SERVICE_NAME, TOKEN_CACHE_ACCOUNT, cacheData);
164
+ } else {
165
+ fs.writeFileSync(FALLBACK_PATH, cacheData);
166
+ }
140
167
  } catch (keytarError) {
141
168
  logger.warn(
142
169
  `Keychain save failed, falling back to file storage: ${keytarError.message}`
@@ -151,7 +178,12 @@ class AuthManager {
151
178
  try {
152
179
  const selectedAccountData = JSON.stringify({ accountId: this.selectedAccountId });
153
180
  try {
154
- await keytar.setPassword(SERVICE_NAME, SELECTED_ACCOUNT_KEY, selectedAccountData);
181
+ const kt = await getKeytar();
182
+ if (kt) {
183
+ await kt.setPassword(SERVICE_NAME, SELECTED_ACCOUNT_KEY, selectedAccountData);
184
+ } else {
185
+ fs.writeFileSync(SELECTED_ACCOUNT_PATH, selectedAccountData);
186
+ }
155
187
  } catch (keytarError) {
156
188
  logger.warn(
157
189
  `Keychain save failed for selected account, falling back to file storage: ${keytarError.message}`
@@ -304,8 +336,11 @@ class AuthManager {
304
336
  this.tokenExpiry = null;
305
337
  this.selectedAccountId = null;
306
338
  try {
307
- await keytar.deletePassword(SERVICE_NAME, TOKEN_CACHE_ACCOUNT);
308
- await keytar.deletePassword(SERVICE_NAME, SELECTED_ACCOUNT_KEY);
339
+ const kt = await getKeytar();
340
+ if (kt) {
341
+ await kt.deletePassword(SERVICE_NAME, TOKEN_CACHE_ACCOUNT);
342
+ await kt.deletePassword(SERVICE_NAME, SELECTED_ACCOUNT_KEY);
343
+ }
309
344
  } catch (keytarError) {
310
345
  logger.warn(`Keychain deletion failed: ${keytarError.message}`);
311
346
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softeria/ms-365-mcp-server",
3
- "version": "0.24.1",
3
+ "version": "0.24.3",
4
4
  "description": " A Model Context Protocol (MCP) server for interacting with Microsoft 365 and Office services through the Graph API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -40,12 +40,14 @@
40
40
  "dotenv": "^17.0.1",
41
41
  "express": "^5.1.0",
42
42
  "js-yaml": "^4.1.0",
43
- "keytar": "^7.9.0",
44
43
  "winston": "^3.17.0",
45
44
  "zod": "^3.24.2"
46
45
  },
46
+ "optionalDependencies": {
47
+ "keytar": "^7.9.0"
48
+ },
47
49
  "devDependencies": {
48
- "@redocly/cli": "^1.34.3",
50
+ "@redocly/cli": "^2.11.1",
49
51
  "@semantic-release/exec": "^7.1.0",
50
52
  "@semantic-release/git": "^10.0.1",
51
53
  "@semantic-release/github": "^11.0.3",