@softeria/ms-365-mcp-server 0.116.1 → 0.117.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 +2 -0
- package/dist/server.js +35 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -577,6 +577,8 @@ Environment variables:
|
|
|
577
577
|
- `MS365_MCP_MAX_ITEMS=<n>`: Maximum number of items accumulated when `fetchAllPages: true` (positive integer, default `10000`). Pagination stops and the response is truncated once this many items are collected.
|
|
578
578
|
- `MS365_MCP_ALLOW_PAGINATION=0|false|no`: Disable multi-page following entirely. When set, the `fetchAllPages` parameter is not advertised on tools, and any request that still passes it returns only the first page (default: pagination enabled).
|
|
579
579
|
- `MS365_MCP_BODY_FORMAT=html`: Return email bodies as HTML instead of plain text (default: text)
|
|
580
|
+
- `MS365_MCP_RATE_LIMIT_DISABLED=true|1`: Disable per-IP rate limiting in HTTP mode (default: enabled — 30 req/min on `/authorize`, `/token`, `/register`; 120 req/min on `/mcp`)
|
|
581
|
+
- `MS365_MCP_TRUST_PROXY_HOPS=<n>`: Number of trusted reverse-proxy hops in HTTP mode (default `1`). Accurate per-IP rate limiting depends on this matching your deployment — set to the number of proxies in front of the server, `0` to use the raw socket peer IP, or a comma-separated subnet list
|
|
580
582
|
- `MS365_MCP_CLOUD_TYPE=global|china`: Microsoft cloud environment (alternative to --cloud flag)
|
|
581
583
|
- `LOG_LEVEL`: Set logging level (default: 'info')
|
|
582
584
|
- `SILENT=true|1`: Disable console output
|
package/dist/server.js
CHANGED
|
@@ -3,6 +3,8 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
3
3
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
4
4
|
import { mcpAuthRouter } from "@modelcontextprotocol/sdk/server/auth/router.js";
|
|
5
5
|
import express from "express";
|
|
6
|
+
import helmet from "helmet";
|
|
7
|
+
import rateLimit from "express-rate-limit";
|
|
6
8
|
import logger, { enableConsoleLogging } from "./logger.js";
|
|
7
9
|
import { registerAuthTools } from "./auth-tools.js";
|
|
8
10
|
import { registerGraphTools, registerDiscoveryTools } from "./graph-tools.js";
|
|
@@ -167,7 +169,20 @@ class MicrosoftGraphServer {
|
|
|
167
169
|
if (this.options.http) {
|
|
168
170
|
const { host, port } = parseHttpOption(this.options.http);
|
|
169
171
|
const app = express();
|
|
170
|
-
|
|
172
|
+
const trustProxyEnv = process.env.MS365_MCP_TRUST_PROXY_HOPS;
|
|
173
|
+
if (trustProxyEnv !== void 0 && trustProxyEnv !== "") {
|
|
174
|
+
const asNum = Number(trustProxyEnv);
|
|
175
|
+
app.set("trust proxy", Number.isFinite(asNum) ? asNum : trustProxyEnv);
|
|
176
|
+
} else {
|
|
177
|
+
app.set("trust proxy", 1);
|
|
178
|
+
}
|
|
179
|
+
app.use(
|
|
180
|
+
helmet({
|
|
181
|
+
contentSecurityPolicy: false,
|
|
182
|
+
crossOriginEmbedderPolicy: false,
|
|
183
|
+
hsts: { maxAge: 31536e3, includeSubDomains: true, preload: true }
|
|
184
|
+
})
|
|
185
|
+
);
|
|
171
186
|
app.use(express.json());
|
|
172
187
|
app.use(express.urlencoded({ extended: true }));
|
|
173
188
|
const corsOrigin = process.env.MS365_MCP_CORS_ORIGIN || "http://localhost:3000";
|
|
@@ -184,6 +199,25 @@ class MicrosoftGraphServer {
|
|
|
184
199
|
}
|
|
185
200
|
next();
|
|
186
201
|
});
|
|
202
|
+
const rateLimitDisabled = process.env.MS365_MCP_RATE_LIMIT_DISABLED === "true" || process.env.MS365_MCP_RATE_LIMIT_DISABLED === "1";
|
|
203
|
+
if (!rateLimitDisabled) {
|
|
204
|
+
const authLimiter = rateLimit({
|
|
205
|
+
windowMs: 6e4,
|
|
206
|
+
max: 30,
|
|
207
|
+
standardHeaders: "draft-7",
|
|
208
|
+
legacyHeaders: false
|
|
209
|
+
});
|
|
210
|
+
const mcpLimiter = rateLimit({
|
|
211
|
+
windowMs: 6e4,
|
|
212
|
+
max: 120,
|
|
213
|
+
standardHeaders: "draft-7",
|
|
214
|
+
legacyHeaders: false
|
|
215
|
+
});
|
|
216
|
+
app.use("/authorize", authLimiter);
|
|
217
|
+
app.use("/token", authLimiter);
|
|
218
|
+
app.use("/register", authLimiter);
|
|
219
|
+
app.use("/mcp", mcpLimiter);
|
|
220
|
+
}
|
|
187
221
|
const oauthProvider = new MicrosoftOAuthProvider(this.authManager, this.secrets);
|
|
188
222
|
const publicUrlRaw = this.options.publicUrl || process.env.MS365_MCP_PUBLIC_URL || this.options.baseUrl || process.env.MS365_MCP_BASE_URL || null;
|
|
189
223
|
const publicBase = publicUrlRaw ? new URL(publicUrlRaw).href.replace(/\/$/, "") : null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softeria/ms-365-mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.117.0",
|
|
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",
|
|
@@ -39,6 +39,8 @@
|
|
|
39
39
|
"commander": "^11.1.0",
|
|
40
40
|
"dotenv": "^17.0.1",
|
|
41
41
|
"express": "^5.2.1",
|
|
42
|
+
"express-rate-limit": "^7.5.1",
|
|
43
|
+
"helmet": "^8.1.0",
|
|
42
44
|
"js-yaml": "^4.1.0",
|
|
43
45
|
"open": "^11.0.0",
|
|
44
46
|
"winston": "^3.17.0",
|