@softeria/ms-365-mcp-server 0.154.2 → 0.154.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.
@@ -7,6 +7,7 @@ import {
7
7
  getSharedBreaker,
8
8
  loadResilienceConfig
9
9
  } from "./lib/graph-resilience.js";
10
+ import { applyBatchContentType } from "./lib/batch-content-type.js";
10
11
  import { applyMessageSignoffToRequest } from "./lib/message-signoff.js";
11
12
  import { TRANSPORT_OK_MESSAGE } from "./lib/select-projection.js";
12
13
  import { open, stat, unlink } from "fs/promises";
@@ -297,7 +298,8 @@ class GraphClient {
297
298
  const url = `${cloudEndpoints.graphApi}/${apiVersion}${endpoint}`;
298
299
  logger.info(`[GRAPH CLIENT] Final URL being sent to Microsoft: ${url}`);
299
300
  const method = options.method || "GET";
300
- const body = applyMessageSignoffToRequest(method, endpoint, options.body);
301
+ const signedBody = applyMessageSignoffToRequest(method, endpoint, options.body);
302
+ const body = applyBatchContentType(method, endpoint, signedBody);
301
303
  const headers = {
302
304
  Authorization: `Bearer ${accessToken}`,
303
305
  "Content-Type": "application/json",
@@ -0,0 +1,52 @@
1
+ import logger from "../logger.js";
2
+ const JSON_CONTENT_TYPE = "application/json";
3
+ const NEVER_HAS_BODY = /* @__PURE__ */ new Set(["GET", "DELETE"]);
4
+ function isPlainObject(value) {
5
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6
+ }
7
+ function hasContentType(headers) {
8
+ return Object.keys(headers).some((key) => key.toLowerCase() === "content-type");
9
+ }
10
+ function fillSubRequest(entry) {
11
+ if (!isPlainObject(entry)) return entry;
12
+ if (typeof entry.method !== "string") return entry;
13
+ if (NEVER_HAS_BODY.has(entry.method.toUpperCase())) return entry;
14
+ if (!isPlainObject(entry.body)) return entry;
15
+ const headerKeys = Object.keys(entry).filter((key) => key.toLowerCase() === "headers");
16
+ if (headerKeys.length > 1) return entry;
17
+ const headersKey = headerKeys[0] ?? "headers";
18
+ const headers = entry[headersKey];
19
+ if (headers !== void 0 && !isPlainObject(headers)) return entry;
20
+ if (headers && hasContentType(headers)) return entry;
21
+ return { ...entry, [headersKey]: { ...headers, "Content-Type": JSON_CONTENT_TYPE } };
22
+ }
23
+ function normalizePath(path) {
24
+ let clean = path.split("?")[0].replace(/^\/(?:v1\.0|beta)(?=\/)/, "");
25
+ if (!clean.startsWith("/")) clean = `/${clean}`;
26
+ if (clean.length > 1 && clean.endsWith("/")) clean = clean.slice(0, -1);
27
+ return clean;
28
+ }
29
+ function subRequestLabel(entry, index) {
30
+ const id = isPlainObject(entry) ? entry.id : void 0;
31
+ return typeof id === "string" || typeof id === "number" ? String(id) : `index ${index}`;
32
+ }
33
+ function applyBatchContentType(method, path, body) {
34
+ if (typeof body !== "string") return body;
35
+ if (method.toUpperCase() !== "POST" || normalizePath(path) !== "/$batch") return body;
36
+ let payload;
37
+ try {
38
+ payload = JSON.parse(body);
39
+ } catch {
40
+ return body;
41
+ }
42
+ if (!isPlainObject(payload) || !Array.isArray(payload.requests)) return body;
43
+ const original = payload.requests;
44
+ const requests = original.map(fillSubRequest);
45
+ const filled = original.map((entry, index) => requests[index] === entry ? void 0 : subRequestLabel(entry, index)).filter((label) => label !== void 0);
46
+ if (filled.length === 0) return body;
47
+ logger.info(`Filled in missing $batch Content-Type for sub-request(s): ${filled.join(", ")}`);
48
+ return JSON.stringify({ ...payload, requests });
49
+ }
50
+ export {
51
+ applyBatchContentType
52
+ };
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.154.2",
4
+ "version": "0.154.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",