@softeria/ms-365-mcp-server 0.11.3 → 0.11.5

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/dist/server.js CHANGED
@@ -1,277 +1,290 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
- import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
4
- import { mcpAuthRouter } from '@modelcontextprotocol/sdk/server/auth/router.js';
5
- import express from 'express';
6
- import crypto from 'crypto';
7
- import logger, { enableConsoleLogging } from './logger.js';
8
- import { registerAuthTools } from './auth-tools.js';
9
- import { registerGraphTools } from './graph-tools.js';
10
- import GraphClient from './graph-client.js';
11
- import { MicrosoftOAuthProvider } from './oauth-provider.js';
12
- import { microsoftBearerTokenAuthMiddleware, exchangeCodeForToken, refreshAccessToken } from './lib/microsoft-auth.js';
13
- const registeredClients = new Map();
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
4
+ import { mcpAuthRouter } from "@modelcontextprotocol/sdk/server/auth/router.js";
5
+ import express from "express";
6
+ import crypto from "crypto";
7
+ import logger, { enableConsoleLogging } from "./logger.js";
8
+ import { registerAuthTools } from "./auth-tools.js";
9
+ import { registerGraphTools } from "./graph-tools.js";
10
+ import GraphClient from "./graph-client.js";
11
+ import { MicrosoftOAuthProvider } from "./oauth-provider.js";
12
+ import { microsoftBearerTokenAuthMiddleware, exchangeCodeForToken, refreshAccessToken } from "./lib/microsoft-auth.js";
13
+ const registeredClients = /* @__PURE__ */ new Map();
14
14
  class MicrosoftGraphServer {
15
- constructor(authManager, options = {}) {
16
- this.authManager = authManager;
17
- this.options = options;
18
- this.graphClient = new GraphClient(authManager);
19
- this.server = null;
15
+ constructor(authManager, options = {}) {
16
+ this.authManager = authManager;
17
+ this.options = options;
18
+ this.graphClient = new GraphClient(authManager);
19
+ this.server = null;
20
+ }
21
+ async initialize(version) {
22
+ this.server = new McpServer({
23
+ name: "Microsoft365MCP",
24
+ version
25
+ });
26
+ const shouldRegisterAuthTools = !this.options.http || this.options.enableAuthTools;
27
+ if (shouldRegisterAuthTools) {
28
+ registerAuthTools(this.server, this.authManager);
20
29
  }
21
- async initialize(version) {
22
- this.server = new McpServer({
23
- name: 'Microsoft365MCP',
24
- version,
25
- });
26
- const shouldRegisterAuthTools = !this.options.http || this.options.enableAuthTools;
27
- if (shouldRegisterAuthTools) {
28
- registerAuthTools(this.server, this.authManager);
29
- }
30
- registerGraphTools(this.server, this.graphClient, this.options.readOnly, this.options.enabledTools);
30
+ registerGraphTools(
31
+ this.server,
32
+ this.graphClient,
33
+ this.options.readOnly,
34
+ this.options.enabledTools
35
+ );
36
+ }
37
+ async start() {
38
+ if (this.options.v) {
39
+ enableConsoleLogging();
31
40
  }
32
- async start() {
33
- if (this.options.v) {
34
- enableConsoleLogging();
41
+ logger.info("Microsoft 365 MCP Server starting...");
42
+ logger.info("Environment Variables Check:", {
43
+ CLIENT_ID: process.env.MS365_MCP_CLIENT_ID ? `${process.env.MS365_MCP_CLIENT_ID.substring(0, 8)}...` : "NOT SET",
44
+ CLIENT_SECRET: process.env.MS365_MCP_CLIENT_SECRET ? `${process.env.MS365_MCP_CLIENT_SECRET.substring(0, 8)}...` : "NOT SET",
45
+ TENANT_ID: process.env.MS365_MCP_TENANT_ID || "NOT SET",
46
+ NODE_ENV: process.env.NODE_ENV || "NOT SET"
47
+ });
48
+ if (this.options.readOnly) {
49
+ logger.info("Server running in READ-ONLY mode. Write operations are disabled.");
50
+ }
51
+ if (this.options.http) {
52
+ const port = typeof this.options.http === "string" ? parseInt(this.options.http) : 3e3;
53
+ const app = express();
54
+ app.use(express.json());
55
+ app.use(express.urlencoded({ extended: true }));
56
+ app.use((req, res, next) => {
57
+ res.header("Access-Control-Allow-Origin", "*");
58
+ res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
59
+ res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, mcp-protocol-version");
60
+ if (req.method === "OPTIONS") {
61
+ res.sendStatus(200);
62
+ return;
35
63
  }
36
- logger.info('Microsoft 365 MCP Server starting...');
37
- // Debug: Check if environment variables are loaded
38
- logger.info('Environment Variables Check:', {
39
- CLIENT_ID: process.env.MS365_MCP_CLIENT_ID ? `${process.env.MS365_MCP_CLIENT_ID.substring(0, 8)}...` : 'NOT SET',
40
- CLIENT_SECRET: process.env.MS365_MCP_CLIENT_SECRET ? `${process.env.MS365_MCP_CLIENT_SECRET.substring(0, 8)}...` : 'NOT SET',
41
- TENANT_ID: process.env.MS365_MCP_TENANT_ID || 'NOT SET',
42
- NODE_ENV: process.env.NODE_ENV || 'NOT SET'
64
+ next();
65
+ });
66
+ const oauthProvider = new MicrosoftOAuthProvider(this.authManager);
67
+ app.get("/.well-known/oauth-authorization-server", async (req, res) => {
68
+ const url = new URL(`${req.protocol}://${req.get("host")}`);
69
+ res.json({
70
+ issuer: url.origin,
71
+ authorization_endpoint: `${url.origin}/authorize`,
72
+ token_endpoint: `${url.origin}/token`,
73
+ registration_endpoint: `${url.origin}/register`,
74
+ response_types_supported: ["code"],
75
+ response_modes_supported: ["query"],
76
+ grant_types_supported: ["authorization_code", "refresh_token"],
77
+ token_endpoint_auth_methods_supported: ["none"],
78
+ code_challenge_methods_supported: ["S256"],
79
+ scopes_supported: [
80
+ "User.Read",
81
+ "Files.Read",
82
+ "Mail.Read"
83
+ ]
84
+ });
85
+ });
86
+ app.get("/.well-known/oauth-protected-resource", async (req, res) => {
87
+ const url = new URL(`${req.protocol}://${req.get("host")}`);
88
+ res.json({
89
+ resource: `${url.origin}/mcp`,
90
+ authorization_servers: [url.origin],
91
+ scopes_supported: [
92
+ "User.Read",
93
+ "Files.Read",
94
+ "Mail.Read"
95
+ ],
96
+ bearer_methods_supported: ["header"],
97
+ resource_documentation: `${url.origin}`
98
+ });
99
+ });
100
+ app.post("/register", async (req, res) => {
101
+ const body = req.body;
102
+ const clientId = crypto.randomUUID();
103
+ registeredClients.set(clientId, {
104
+ client_id: clientId,
105
+ client_name: body.client_name || "MCP Client",
106
+ redirect_uris: body.redirect_uris || [],
107
+ grant_types: body.grant_types || ["authorization_code", "refresh_token"],
108
+ response_types: body.response_types || ["code"],
109
+ scope: body.scope,
110
+ token_endpoint_auth_method: "none",
111
+ created_at: Date.now()
112
+ });
113
+ res.status(201).json({
114
+ client_id: clientId,
115
+ client_name: body.client_name || "MCP Client",
116
+ redirect_uris: body.redirect_uris || [],
117
+ grant_types: body.grant_types || ["authorization_code", "refresh_token"],
118
+ response_types: body.response_types || ["code"],
119
+ scope: body.scope,
120
+ token_endpoint_auth_method: "none"
121
+ });
122
+ });
123
+ app.get("/authorize", async (req, res) => {
124
+ const url = new URL(req.url, `${req.protocol}://${req.get("host")}`);
125
+ const tenantId = process.env.MS365_MCP_TENANT_ID || "common";
126
+ const clientId = process.env.MS365_MCP_CLIENT_ID || "084a3e9f-a9f4-43f7-89f9-d229cf97853e";
127
+ const microsoftAuthUrl = new URL(`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/authorize`);
128
+ const allowedParams = [
129
+ "response_type",
130
+ "redirect_uri",
131
+ "scope",
132
+ "state",
133
+ "response_mode",
134
+ "code_challenge",
135
+ "code_challenge_method",
136
+ "prompt",
137
+ "login_hint",
138
+ "domain_hint"
139
+ ];
140
+ allowedParams.forEach((param) => {
141
+ const value = url.searchParams.get(param);
142
+ if (value) {
143
+ microsoftAuthUrl.searchParams.set(param, value);
144
+ }
43
145
  });
44
- if (this.options.readOnly) {
45
- logger.info('Server running in READ-ONLY mode. Write operations are disabled.');
146
+ microsoftAuthUrl.searchParams.set("client_id", clientId);
147
+ if (!microsoftAuthUrl.searchParams.get("scope")) {
148
+ microsoftAuthUrl.searchParams.set("scope", "User.Read Files.Read Mail.Read");
46
149
  }
47
- if (this.options.http) {
48
- const port = typeof this.options.http === 'string' ? parseInt(this.options.http) : 3000;
49
- const app = express();
50
- app.use(express.json());
51
- app.use(express.urlencoded({ extended: true }));
52
- // Add CORS headers for all routes
53
- app.use((req, res, next) => {
54
- res.header('Access-Control-Allow-Origin', '*');
55
- res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
56
- res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization, mcp-protocol-version');
57
- // Handle preflight requests
58
- if (req.method === 'OPTIONS') {
59
- res.sendStatus(200);
60
- return;
61
- }
62
- next();
150
+ res.redirect(microsoftAuthUrl.toString());
151
+ });
152
+ app.post("/token", async (req, res) => {
153
+ try {
154
+ logger.info("Token endpoint called", {
155
+ method: req.method,
156
+ url: req.url,
157
+ headers: req.headers,
158
+ bodyType: typeof req.body,
159
+ body: req.body,
160
+ rawBody: JSON.stringify(req.body),
161
+ contentType: req.get("Content-Type")
162
+ });
163
+ const body = req.body;
164
+ if (!body) {
165
+ logger.error("Token endpoint: Request body is undefined");
166
+ res.status(400).json({
167
+ error: "invalid_request",
168
+ error_description: "Request body is required"
63
169
  });
64
- const oauthProvider = new MicrosoftOAuthProvider(this.authManager);
65
- // OAuth Authorization Server Discovery
66
- app.get('/.well-known/oauth-authorization-server', async (req, res) => {
67
- const url = new URL(`${req.protocol}://${req.get('host')}`);
68
- res.json({
69
- issuer: url.origin,
70
- authorization_endpoint: `${url.origin}/authorize`,
71
- token_endpoint: `${url.origin}/token`,
72
- registration_endpoint: `${url.origin}/register`,
73
- response_types_supported: ['code'],
74
- response_modes_supported: ['query'],
75
- grant_types_supported: ['authorization_code', 'refresh_token'],
76
- token_endpoint_auth_methods_supported: ['none'],
77
- code_challenge_methods_supported: ['S256'],
78
- scopes_supported: [
79
- 'User.Read', 'Files.Read', 'Mail.Read'
80
- ],
81
- });
170
+ return;
171
+ }
172
+ if (!body.grant_type) {
173
+ logger.error("Token endpoint: grant_type is missing", { body });
174
+ res.status(400).json({
175
+ error: "invalid_request",
176
+ error_description: "grant_type parameter is required"
82
177
  });
83
- // OAuth Protected Resource Discovery
84
- app.get('/.well-known/oauth-protected-resource', async (req, res) => {
85
- const url = new URL(`${req.protocol}://${req.get('host')}`);
86
- res.json({
87
- resource: `${url.origin}/mcp`,
88
- authorization_servers: [url.origin],
89
- scopes_supported: [
90
- 'User.Read', 'Files.Read', 'Mail.Read'
91
- ],
92
- bearer_methods_supported: ['header'],
93
- resource_documentation: `${url.origin}`,
94
- });
95
- });
96
- // Dynamic Client Registration endpoint
97
- app.post('/register', async (req, res) => {
98
- const body = req.body;
99
- // Generate a client ID
100
- const clientId = crypto.randomUUID();
101
- // Store the client registration
102
- registeredClients.set(clientId, {
103
- client_id: clientId,
104
- client_name: body.client_name || 'MCP Client',
105
- redirect_uris: body.redirect_uris || [],
106
- grant_types: body.grant_types || ['authorization_code', 'refresh_token'],
107
- response_types: body.response_types || ['code'],
108
- scope: body.scope,
109
- token_endpoint_auth_method: 'none',
110
- created_at: Date.now()
111
- });
112
- // Return the client registration response
113
- res.status(201).json({
114
- client_id: clientId,
115
- client_name: body.client_name || 'MCP Client',
116
- redirect_uris: body.redirect_uris || [],
117
- grant_types: body.grant_types || ['authorization_code', 'refresh_token'],
118
- response_types: body.response_types || ['code'],
119
- scope: body.scope,
120
- token_endpoint_auth_method: 'none'
121
- });
122
- });
123
- // Authorization endpoint - redirects to Microsoft
124
- app.get('/authorize', async (req, res) => {
125
- const url = new URL(req.url, `${req.protocol}://${req.get('host')}`);
126
- const tenantId = process.env.MS365_MCP_TENANT_ID || 'common';
127
- const clientId = process.env.MS365_MCP_CLIENT_ID || '084a3e9f-a9f4-43f7-89f9-d229cf97853e';
128
- const microsoftAuthUrl = new URL(`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/authorize`);
129
- // Only forward parameters that Microsoft OAuth 2.0 v2.0 supports
130
- const allowedParams = [
131
- 'response_type', 'redirect_uri', 'scope', 'state', 'response_mode',
132
- 'code_challenge', 'code_challenge_method', 'prompt', 'login_hint', 'domain_hint'
133
- ];
134
- allowedParams.forEach(param => {
135
- const value = url.searchParams.get(param);
136
- if (value) {
137
- microsoftAuthUrl.searchParams.set(param, value);
138
- }
139
- });
140
- // Use our Microsoft app's client_id
141
- microsoftAuthUrl.searchParams.set('client_id', clientId);
142
- // Ensure we have the minimal required scopes if none provided
143
- if (!microsoftAuthUrl.searchParams.get('scope')) {
144
- microsoftAuthUrl.searchParams.set('scope', 'User.Read Files.Read Mail.Read');
145
- }
146
- // Redirect to Microsoft's authorization page
147
- res.redirect(microsoftAuthUrl.toString());
148
- });
149
- // Token exchange endpoint
150
- app.post('/token', async (req, res) => {
151
- try {
152
- // Comprehensive debugging
153
- logger.info('Token endpoint called', {
154
- method: req.method,
155
- url: req.url,
156
- headers: req.headers,
157
- bodyType: typeof req.body,
158
- body: req.body,
159
- rawBody: JSON.stringify(req.body),
160
- contentType: req.get('Content-Type')
161
- });
162
- const body = req.body;
163
- // Add debugging and validation
164
- if (!body) {
165
- logger.error('Token endpoint: Request body is undefined');
166
- res.status(400).json({
167
- error: 'invalid_request',
168
- error_description: 'Request body is required'
169
- });
170
- return;
171
- }
172
- if (!body.grant_type) {
173
- logger.error('Token endpoint: grant_type is missing', { body });
174
- res.status(400).json({
175
- error: 'invalid_request',
176
- error_description: 'grant_type parameter is required'
177
- });
178
- return;
179
- }
180
- if (body.grant_type === 'authorization_code') {
181
- const tenantId = process.env.MS365_MCP_TENANT_ID || 'common';
182
- const clientId = process.env.MS365_MCP_CLIENT_ID || '084a3e9f-a9f4-43f7-89f9-d229cf97853e';
183
- const clientSecret = process.env.MS365_MCP_CLIENT_SECRET;
184
- if (!clientSecret) {
185
- logger.error('Token endpoint: MS365_MCP_CLIENT_SECRET is not configured');
186
- res.status(500).json({
187
- error: 'server_error',
188
- error_description: 'Server configuration error'
189
- });
190
- return;
191
- }
192
- const result = await exchangeCodeForToken(body.code, body.redirect_uri, clientId, clientSecret, tenantId, body.code_verifier);
193
- res.json(result);
194
- }
195
- else if (body.grant_type === 'refresh_token') {
196
- const tenantId = process.env.MS365_MCP_TENANT_ID || 'common';
197
- const clientId = process.env.MS365_MCP_CLIENT_ID || '084a3e9f-a9f4-43f7-89f9-d229cf97853e';
198
- const clientSecret = process.env.MS365_MCP_CLIENT_SECRET;
199
- if (!clientSecret) {
200
- logger.error('Token endpoint: MS365_MCP_CLIENT_SECRET is not configured');
201
- res.status(500).json({
202
- error: 'server_error',
203
- error_description: 'Server configuration error'
204
- });
205
- return;
206
- }
207
- const result = await refreshAccessToken(body.refresh_token, clientId, clientSecret, tenantId);
208
- res.json(result);
209
- }
210
- else {
211
- res.status(400).json({
212
- error: 'unsupported_grant_type',
213
- error_description: `Grant type '${body.grant_type}' is not supported`
214
- });
215
- }
216
- }
217
- catch (error) {
218
- logger.error('Token endpoint error:', error);
219
- res.status(500).json({
220
- error: 'server_error',
221
- error_description: 'Internal server error during token exchange'
222
- });
223
- }
224
- });
225
- app.use(mcpAuthRouter({
226
- provider: oauthProvider,
227
- issuerUrl: new URL(`http://localhost:${port}`),
228
- }));
229
- // Microsoft Graph MCP endpoints with bearer token auth
230
- app.post('/mcp', microsoftBearerTokenAuthMiddleware, async (req, res) => {
231
- try {
232
- // Set OAuth tokens in the GraphClient if available
233
- if (req.microsoftAuth) {
234
- this.graphClient.setOAuthTokens(req.microsoftAuth.accessToken, req.microsoftAuth.refreshToken);
235
- }
236
- const transport = new StreamableHTTPServerTransport({
237
- sessionIdGenerator: undefined, // Stateless mode
238
- });
239
- res.on('close', () => {
240
- transport.close();
241
- });
242
- await this.server.connect(transport);
243
- await transport.handleRequest(req, res, req.body);
244
- }
245
- catch (error) {
246
- logger.error('Error handling MCP request:', error);
247
- if (!res.headersSent) {
248
- res.status(500).json({
249
- jsonrpc: '2.0',
250
- error: {
251
- code: -32603,
252
- message: 'Internal server error',
253
- },
254
- id: null,
255
- });
256
- }
257
- }
258
- });
259
- // Health check endpoint
260
- app.get('/', (req, res) => {
261
- res.send('Microsoft 365 MCP Server is running');
262
- });
263
- app.listen(port, () => {
264
- logger.info(`Server listening on HTTP port ${port}`);
265
- logger.info(` - MCP endpoint: http://localhost:${port}/mcp`);
266
- logger.info(` - OAuth endpoints: http://localhost:${port}/auth/*`);
267
- logger.info(` - OAuth discovery: http://localhost:${port}/.well-known/oauth-authorization-server`);
178
+ return;
179
+ }
180
+ if (body.grant_type === "authorization_code") {
181
+ const tenantId = process.env.MS365_MCP_TENANT_ID || "common";
182
+ const clientId = process.env.MS365_MCP_CLIENT_ID || "084a3e9f-a9f4-43f7-89f9-d229cf97853e";
183
+ const clientSecret = process.env.MS365_MCP_CLIENT_SECRET;
184
+ if (!clientSecret) {
185
+ logger.error("Token endpoint: MS365_MCP_CLIENT_SECRET is not configured");
186
+ res.status(500).json({
187
+ error: "server_error",
188
+ error_description: "Server configuration error"
189
+ });
190
+ return;
191
+ }
192
+ const result = await exchangeCodeForToken(
193
+ body.code,
194
+ body.redirect_uri,
195
+ clientId,
196
+ clientSecret,
197
+ tenantId,
198
+ body.code_verifier
199
+ );
200
+ res.json(result);
201
+ } else if (body.grant_type === "refresh_token") {
202
+ const tenantId = process.env.MS365_MCP_TENANT_ID || "common";
203
+ const clientId = process.env.MS365_MCP_CLIENT_ID || "084a3e9f-a9f4-43f7-89f9-d229cf97853e";
204
+ const clientSecret = process.env.MS365_MCP_CLIENT_SECRET;
205
+ if (!clientSecret) {
206
+ logger.error("Token endpoint: MS365_MCP_CLIENT_SECRET is not configured");
207
+ res.status(500).json({
208
+ error: "server_error",
209
+ error_description: "Server configuration error"
210
+ });
211
+ return;
212
+ }
213
+ const result = await refreshAccessToken(
214
+ body.refresh_token,
215
+ clientId,
216
+ clientSecret,
217
+ tenantId
218
+ );
219
+ res.json(result);
220
+ } else {
221
+ res.status(400).json({
222
+ error: "unsupported_grant_type",
223
+ error_description: `Grant type '${body.grant_type}' is not supported`
268
224
  });
225
+ }
226
+ } catch (error) {
227
+ logger.error("Token endpoint error:", error);
228
+ res.status(500).json({
229
+ error: "server_error",
230
+ error_description: "Internal server error during token exchange"
231
+ });
269
232
  }
270
- else {
271
- const transport = new StdioServerTransport();
272
- await this.server.connect(transport);
273
- logger.info('Server connected to stdio transport');
233
+ });
234
+ app.use(
235
+ mcpAuthRouter({
236
+ provider: oauthProvider,
237
+ issuerUrl: new URL(`http://localhost:${port}`)
238
+ })
239
+ );
240
+ app.post("/mcp", microsoftBearerTokenAuthMiddleware, async (req, res) => {
241
+ try {
242
+ if (req.microsoftAuth) {
243
+ this.graphClient.setOAuthTokens(
244
+ req.microsoftAuth.accessToken,
245
+ req.microsoftAuth.refreshToken
246
+ );
247
+ }
248
+ const transport = new StreamableHTTPServerTransport({
249
+ sessionIdGenerator: void 0
250
+ // Stateless mode
251
+ });
252
+ res.on("close", () => {
253
+ transport.close();
254
+ });
255
+ await this.server.connect(transport);
256
+ await transport.handleRequest(req, res, req.body);
257
+ } catch (error) {
258
+ logger.error("Error handling MCP request:", error);
259
+ if (!res.headersSent) {
260
+ res.status(500).json({
261
+ jsonrpc: "2.0",
262
+ error: {
263
+ code: -32603,
264
+ message: "Internal server error"
265
+ },
266
+ id: null
267
+ });
268
+ }
274
269
  }
270
+ });
271
+ app.get("/", (req, res) => {
272
+ res.send("Microsoft 365 MCP Server is running");
273
+ });
274
+ app.listen(port, () => {
275
+ logger.info(`Server listening on HTTP port ${port}`);
276
+ logger.info(` - MCP endpoint: http://localhost:${port}/mcp`);
277
+ logger.info(` - OAuth endpoints: http://localhost:${port}/auth/*`);
278
+ logger.info(` - OAuth discovery: http://localhost:${port}/.well-known/oauth-authorization-server`);
279
+ });
280
+ } else {
281
+ const transport = new StdioServerTransport();
282
+ await this.server.connect(transport);
283
+ logger.info("Server connected to stdio transport");
275
284
  }
285
+ }
276
286
  }
277
- export default MicrosoftGraphServer;
287
+ var server_default = MicrosoftGraphServer;
288
+ export {
289
+ server_default as default
290
+ };
package/dist/version.js CHANGED
@@ -1,7 +1,10 @@
1
- import { readFileSync } from 'fs';
2
- import path from 'path';
3
- import { fileURLToPath } from 'url';
1
+ import { readFileSync } from "fs";
2
+ import path from "path";
3
+ import { fileURLToPath } from "url";
4
4
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
5
- const packageJsonPath = path.join(__dirname, '..', 'package.json');
6
- const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
7
- export const version = packageJson.version;
5
+ const packageJsonPath = path.join(__dirname, "..", "package.json");
6
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
7
+ const version = packageJson.version;
8
+ export {
9
+ version
10
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softeria/ms-365-mcp-server",
3
- "version": "0.11.3",
3
+ "version": "0.11.5",
4
4
  "description": "Microsoft 365 MCP Server",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -8,13 +8,12 @@
8
8
  "ms-365-mcp-server": "dist/index.js"
9
9
  },
10
10
  "scripts": {
11
- "build": "tsc && chmod +x dist/index.js",
11
+ "build": "tsup",
12
12
  "test": "vitest run",
13
13
  "test:watch": "vitest",
14
14
  "dev": "tsx src/index.ts",
15
15
  "dev:http": "tsx --watch src/index.ts --http 3000 -v",
16
16
  "format": "prettier --write \"**/*.{ts,mts,js,mjs,json,md}\"",
17
- "release": "ts-node --esm bin/release.mts",
18
17
  "inspect": "npx @modelcontextprotocol/inspector tsx src/index.ts",
19
18
  "prepublishOnly": "npm run build"
20
19
  },
@@ -42,13 +41,22 @@
42
41
  },
43
42
  "devDependencies": {
44
43
  "@redocly/cli": "^1.34.3",
44
+ "@semantic-release/exec": "^7.1.0",
45
+ "@semantic-release/git": "^10.0.1",
46
+ "@semantic-release/github": "^11.0.3",
47
+ "@semantic-release/npm": "^12.0.2",
45
48
  "@types/express": "^5.0.3",
46
49
  "@types/node": "^22.15.15",
47
50
  "prettier": "^3.5.3",
51
+ "semantic-release": "^24.2.7",
52
+ "tsup": "^8.5.0",
48
53
  "tsx": "^4.19.4",
49
54
  "typescript": "^5.8.3",
50
55
  "vitest": "^3.1.1"
51
56
  },
57
+ "engines": {
58
+ "node": ">=18"
59
+ },
52
60
  "repository": {
53
61
  "type": "git",
54
62
  "url": "https://github.com/softeria/ms-365-mcp-server.git"
package/tsup.config.ts ADDED
@@ -0,0 +1,30 @@
1
+ import { defineConfig } from 'tsup';
2
+
3
+ export default defineConfig({
4
+ entry: ['src/**/*.ts', 'src/endpoints.json'],
5
+ format: ['esm'],
6
+ target: 'es2020',
7
+ outDir: 'dist',
8
+ clean: true,
9
+ bundle: false,
10
+ splitting: false,
11
+ sourcemap: false,
12
+ dts: false,
13
+ publicDir: false,
14
+ onSuccess: 'chmod +x dist/index.js',
15
+ loader: {
16
+ '.json': 'copy',
17
+ },
18
+ noExternal: [],
19
+ external: [
20
+ '@azure/msal-node',
21
+ '@modelcontextprotocol/sdk',
22
+ 'commander',
23
+ 'dotenv',
24
+ 'express',
25
+ 'js-yaml',
26
+ 'keytar',
27
+ 'winston',
28
+ 'zod',
29
+ ],
30
+ });