@softeria/ms-365-mcp-server 0.169.2 → 0.169.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.
@@ -3,10 +3,29 @@ const USER_ENTITY_PATH = /^\/users(?:\/[^/]+)?\/?$/i;
3
3
  const DIRECTORY_NAVIGATION_PATH = /^(?:\/me|\/users\/[^/]+)\/(?:manager|directReports)\/?$|^\/groups\/[^/]+\/(?:members|owners)\/?$/i;
4
4
  const EXPAND_USER_PATH = /^\/me\/?$|^\/groups(?:\/[^/]+)?\/?$/i;
5
5
  function normalizePath(path) {
6
- const withoutQuery = path.split("?")[0];
6
+ let withoutQuery = path.split("?")[0];
7
+ for (let i = 0; i < 4; i++) {
8
+ const next = withoutQuery.replace(
9
+ /%([0-9a-f]{2})/gi,
10
+ (_, hex) => String.fromCharCode(parseInt(hex, 16))
11
+ );
12
+ if (next === withoutQuery) break;
13
+ withoutQuery = next;
14
+ }
7
15
  return withoutQuery.startsWith("/") ? withoutQuery : `/${withoutQuery}`;
8
16
  }
17
+ const ENCODED_SEPARATOR = /%(?:25)*(?:2f|5c)/i;
18
+ function deleteOdataOption(params, name) {
19
+ const values = [];
20
+ for (const key of [...new Set(params.keys())]) {
21
+ if (key.replace(/^\$/, "").toLowerCase() !== name) continue;
22
+ values.push(...params.getAll(key));
23
+ params.delete(key);
24
+ }
25
+ return values;
26
+ }
9
27
  function userFieldEnforcement(path) {
28
+ if (ENCODED_SEPARATOR.test(path.split("?")[0])) return "request-and-response";
10
29
  const normalized = normalizePath(path);
11
30
  if (USER_ENTITY_PATH.test(normalized)) return "request-and-response";
12
31
  if (DIRECTORY_NAVIGATION_PATH.test(normalized)) return "response-only";
@@ -23,8 +42,7 @@ function stripUserFieldExpandFromUrl(url) {
23
42
  const [path, query = ""] = url.split("?");
24
43
  if (!shouldStripUserFieldExpand(path) || query === "") return url;
25
44
  const params = new URLSearchParams(query);
26
- if (!params.has("$expand")) return url;
27
- params.delete("$expand");
45
+ if (deleteOdataOption(params, "expand").length === 0) return url;
28
46
  const rebuilt = params.toString();
29
47
  if (rebuilt === "") return path;
30
48
  return `${path}?${rebuilt.replace(/%24/gi, "$").replace(/%2C/gi, ",")}`;
@@ -46,14 +64,15 @@ function restrictUserFieldQuery(queryParams, allowlist, enforcement) {
46
64
  function restrictUserFieldUrl(url, allowlist, enforcement) {
47
65
  const [path, query = ""] = url.split("?");
48
66
  const params = new URLSearchParams(query);
67
+ const requested = enforcement === "request-and-response" ? deleteOdataOption(params, "select") : params.getAll("$select");
49
68
  const fields = effectiveUserFields(
50
- parseSelectFields(params.get("$select") ?? void 0),
69
+ parseSelectFields(requested.join(",") || void 0),
51
70
  allowlist
52
71
  );
53
72
  if (enforcement === "request-and-response") {
54
73
  params.set("$select", fields.join(","));
55
74
  }
56
- params.delete("$expand");
75
+ deleteOdataOption(params, "expand");
57
76
  const rebuilt = params.toString();
58
77
  if (rebuilt === "") return { url: path, fields };
59
78
  return { url: `${path}?${rebuilt.replace(/%24/gi, "$").replace(/%2C/gi, ",")}`, fields };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@softeria/ms-365-mcp-server",
3
3
  "mcpName": "io.github.Softeria/ms-365-mcp-server",
4
- "version": "0.169.2",
4
+ "version": "0.169.3",
5
5
  "description": " A Model Context Protocol (MCP) server for interacting with Microsoft 365 and Office services through the Graph API",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",