diff --git a/backend/mcp-bundles/softeria-ms-365-mcp-server/dist/endpoints.json b/backend/mcp-bundles/softeria-ms-365-mcp-server/dist/endpoints.json index 149e3905..b622008a 100644 --- a/backend/mcp-bundles/softeria-ms-365-mcp-server/dist/endpoints.json +++ b/backend/mcp-bundles/softeria-ms-365-mcp-server/dist/endpoints.json @@ -235,6 +235,34 @@ "scopes": ["MailboxSettings.ReadWrite"], "llmTip": "Deletes a message rule permanently. Use the Inbox folder ID (get it from list-mail-folders) for inbox rules." }, + { + "pathPattern": "/me/inferenceClassification/overrides", + "method": "get", + "toolName": "list-focused-inbox-overrides", + "scopes": ["Mail.Read"], + "llmTip": "Lists Focused Inbox classification overrides — explicit rules that force messages from a given sender (by SMTP address) into either the Focused or Other tab, regardless of what the Outlook ML classifier would predict. Each override has id, classifyAs ('focused' or 'other'), and senderEmailAddress {name, address}. Returns an empty collection if the user has never set an override." + }, + { + "pathPattern": "/me/inferenceClassification/overrides", + "method": "post", + "toolName": "create-focused-inbox-override", + "scopes": ["Mail.ReadWrite"], + "llmTip": "Creates a Focused Inbox override for a sender. Body: { classifyAs: 'focused', senderEmailAddress: { name: 'Display Name', address: 'sender@example.com' } }. classifyAs must be 'focused' or 'other'. If an override already exists for that SMTP address, POST updates the existing override's name and classifyAs (use this to rename a sender). Resolve the sender's address with list-users or by reading a recent mail header — do not invent SMTP addresses." + }, + { + "pathPattern": "/me/inferenceClassification/overrides/{inferenceClassificationOverride-id}", + "method": "patch", + "toolName": "update-focused-inbox-override", + "scopes": ["Mail.ReadWrite"], + "llmTip": "Updates the classifyAs field of an existing override. Body: { classifyAs: 'focused' } or { classifyAs: 'other' }. Per Graph API, PATCH cannot change senderEmailAddress — to change the SMTP address, delete and recreate the override. To rename the display name only, POST a new override with the same SMTP address (it will overwrite the name)." + }, + { + "pathPattern": "/me/inferenceClassification/overrides/{inferenceClassificationOverride-id}", + "method": "delete", + "toolName": "delete-focused-inbox-override", + "scopes": ["Mail.ReadWrite"], + "llmTip": "Deletes a Focused Inbox override. Future messages from that sender revert to the Outlook ML classifier's default behavior. Use list-focused-inbox-overrides to find the ID first." + }, { "pathPattern": "/me/events", "method": "get", @@ -521,6 +549,13 @@ "scopes": ["Files.Read"], "llmTip": "Generate a short-lived embeddable preview URL for a file (Office docs, PDFs, images). Body: { page?: number | string, zoom?: number, viewer?: 'onedrive' | 'office' }. Returns getUrl (interactive) and postUrl (form-post). Useful for surfacing inline previews in summary emails or chat messages without needing the recipient to open the file." }, + { + "pathPattern": "/drives/{drive-id}/items/{driveItem-id}/thumbnails", + "method": "get", + "toolName": "list-drive-item-thumbnails", + "scopes": ["Files.Read"], + "llmTip": "Lists thumbnail sets for a file. Each set contains small (96px), medium (176px), large (800px) thumbnails with url and dimensions. Returns empty for unsupported types (text docs). Use $select=small,medium,large or $expand=small($select=url) to fetch specific sizes. The returned URLs are short-lived — fetch the bytes immediately." + }, { "pathPattern": "/drives/{drive-id}/items/{driveItem-id}/permissions", "method": "get", @@ -1373,6 +1408,48 @@ "workScopes": ["Sites.ReadWrite.All"], "llmTip": "Deletes a list item permanently. This cannot be undone — the item is moved to the site recycle bin." }, + { + "pathPattern": "/sites/{site-id}/lists", + "method": "post", + "toolName": "create-sharepoint-list", + "workScopes": ["Sites.Manage.All"], + "llmTip": "Creates a new SharePoint list in a site. Body: { displayName: 'My List', description: 'Optional', list: { template: 'genericList' }, columns: [ { name: 'Status', text: {} }, { name: 'Due', dateTime: {} } ] }. Templates include genericList, documentLibrary, tasks, calendar, contacts, links, announcements, survey. Columns can be defined inline at creation; otherwise add them later via create-sharepoint-list-column. Use search-sharepoint-sites or get-sharepoint-site-by-path to find the site ID first." + }, + { + "pathPattern": "/sites/{site-id}/lists/{list-id}/columns", + "method": "get", + "toolName": "list-sharepoint-list-columns", + "workScopes": ["Sites.Read.All"], + "llmTip": "Lists column definitions for a SharePoint list. Returns each column's id, name, displayName, description, type indicator (text, number, choice, dateTime, person, lookup, boolean, calculated, hyperlinkOrPicture, etc.), required, indexed, hidden, readOnly. Use this to discover the schema before creating or updating list items." + }, + { + "pathPattern": "/sites/{site-id}/lists/{list-id}/columns", + "method": "post", + "toolName": "create-sharepoint-list-column", + "workScopes": ["Sites.Manage.All"], + "llmTip": "Creates a new column on a SharePoint list. Body must include name and exactly one column type property: { name: 'Priority', text: {} } or { name: 'DueDate', dateTime: { format: 'dateOnly' } } or { name: 'Status', choice: { choices: ['Open','In Progress','Done'] } }. Other types: number, boolean, currency, hyperlinkOrPicture, personOrGroup, lookup, calculated. Optional: displayName, description, required, indexed, enforceUniqueValues." + }, + { + "pathPattern": "/sites/{site-id}/lists/{list-id}/columns/{columnDefinition-id}", + "method": "get", + "toolName": "get-sharepoint-list-column", + "workScopes": ["Sites.Read.All"], + "llmTip": "Gets a specific column definition by ID, including its full type configuration (choices for choice columns, format for dateTime, etc.). Use list-sharepoint-list-columns first to find the column ID." + }, + { + "pathPattern": "/sites/{site-id}/lists/{list-id}/columns/{columnDefinition-id}", + "method": "patch", + "toolName": "update-sharepoint-list-column", + "workScopes": ["Sites.Manage.All"], + "llmTip": "Updates a column definition. Body: { displayName: 'New name', description: 'New description', required: true, ... }. The column type itself (text, choice, etc.) cannot be changed — only its metadata and per-type options (e.g. choices array for a choice column). Send only the fields you want to change." + }, + { + "pathPattern": "/sites/{site-id}/lists/{list-id}/columns/{columnDefinition-id}", + "method": "delete", + "toolName": "delete-sharepoint-list-column", + "workScopes": ["Sites.Manage.All"], + "llmTip": "Deletes a column from a SharePoint list. This is irreversible — all data stored in this column across every list item is lost. Confirm with the user before calling. Cannot delete built-in columns (Title, Created, Modified, etc.)." + }, { "pathPattern": "/sites/{site-id}/getByPath(path='{path}')", "method": "get", @@ -1757,5 +1834,33 @@ "toolName": "get-sensitivity-label", "workScopes": ["SensitivityLabel.Read"], "llmTip": "Gets a single MIP sensitivity label by id. Use list-sensitivity-labels to find ids. Not supported for personal Microsoft accounts." + }, + { + "pathPattern": "/me/messages/{message-id}/copy", + "method": "post", + "toolName": "copy-mail-message", + "scopes": ["Mail.ReadWrite"], + "llmTip": "Copies a message to another mail folder. Body: { DestinationId: '' }. Returns the newly created message (with a new id) in the destination folder. For moving instead of copying, use move-mail-message." + }, + { + "pathPattern": "/me/mailFolders/{mailFolder-id}/messages/delta()", + "method": "get", + "toolName": "list-mail-folder-messages-delta", + "scopes": ["Mail.Read"], + "llmTip": "Incremental sync of messages within a mail folder. Graph only supports delta scoped to a folder — use mailFolder-id = 'inbox' for the well-known inbox, or another folder id from list-mail-folders. First call returns all messages plus @odata.deltaLink; subsequent calls with that link return only changes (created/updated/deleted). @odata.nextLink paginates within a single delta window. Deltas expire after ~30 days of inactivity — start over if the server returns 410. Prefer this over full re-list for polling." + }, + { + "pathPattern": "/me/outlook/masterCategories", + "method": "get", + "toolName": "list-outlook-categories", + "scopes": ["MailboxSettings.Read"], + "llmTip": "Lists the user's Outlook categories (colored labels) used to tag messages, events, contacts, and tasks. Each category has displayName and color (preset0 through preset24, or 'none'). Use this to show available tags before applying via update-mail-message or update-calendar-event with body { categories: ['Category Name'] }." + }, + { + "pathPattern": "/me/outlook/masterCategories", + "method": "post", + "toolName": "create-outlook-category", + "scopes": ["MailboxSettings.ReadWrite"], + "llmTip": "Creates a new Outlook category. Body: { displayName (unique), color (one of: none, preset0 … preset24 — maps to red, orange, yellow, green, teal, olive, blue, purple, cranberry, steel, dark-steel, gray, dark-gray, black, dark-red, dark-orange, dark-yellow, dark-green, dark-teal, dark-olive, dark-blue, dark-purple, dark-cranberry) }. Category names are case-sensitive when applied to messages/events." } ] diff --git a/backend/mcp-bundles/softeria-ms-365-mcp-server/dist/index.js b/backend/mcp-bundles/softeria-ms-365-mcp-server/dist/index.js index 3ccf2199..4626ec66 100755 --- a/backend/mcp-bundles/softeria-ms-365-mcp-server/dist/index.js +++ b/backend/mcp-bundles/softeria-ms-365-mcp-server/dist/index.js @@ -13846,94 +13846,6 @@ var require_winston = __commonJS({ } }); -// node_modules/uuid/dist/esm-node/rng.js -function rng() { - if (poolPtr > rnds8Pool.length - 16) { - import_crypto.default.randomFillSync(rnds8Pool); - poolPtr = 0; - } - return rnds8Pool.slice(poolPtr, poolPtr += 16); -} -var import_crypto, rnds8Pool, poolPtr; -var init_rng = __esm({ - "node_modules/uuid/dist/esm-node/rng.js"() { - import_crypto = __toESM(require("crypto")); - rnds8Pool = new Uint8Array(256); - poolPtr = rnds8Pool.length; - } -}); - -// node_modules/uuid/dist/esm-node/regex.js -var regex_default; -var init_regex = __esm({ - "node_modules/uuid/dist/esm-node/regex.js"() { - regex_default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; - } -}); - -// node_modules/uuid/dist/esm-node/validate.js -function validate(uuid2) { - return typeof uuid2 === "string" && regex_default.test(uuid2); -} -var validate_default; -var init_validate = __esm({ - "node_modules/uuid/dist/esm-node/validate.js"() { - init_regex(); - validate_default = validate; - } -}); - -// node_modules/uuid/dist/esm-node/stringify.js -function stringify(arr, offset = 0) { - const uuid2 = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); - if (!validate_default(uuid2)) { - throw TypeError("Stringified UUID is invalid"); - } - return uuid2; -} -var byteToHex, stringify_default; -var init_stringify = __esm({ - "node_modules/uuid/dist/esm-node/stringify.js"() { - init_validate(); - byteToHex = []; - for (let i = 0; i < 256; ++i) { - byteToHex.push((i + 256).toString(16).substr(1)); - } - stringify_default = stringify; - } -}); - -// node_modules/uuid/dist/esm-node/v4.js -function v4(options, buf, offset) { - options = options || {}; - const rnds = options.random || (options.rng || rng)(); - rnds[6] = rnds[6] & 15 | 64; - rnds[8] = rnds[8] & 63 | 128; - if (buf) { - offset = offset || 0; - for (let i = 0; i < 16; ++i) { - buf[offset + i] = rnds[i]; - } - return buf; - } - return stringify_default(rnds); -} -var v4_default; -var init_v4 = __esm({ - "node_modules/uuid/dist/esm-node/v4.js"() { - init_rng(); - init_stringify(); - v4_default = v4; - } -}); - -// node_modules/uuid/dist/esm-node/index.js -var init_esm_node = __esm({ - "node_modules/uuid/dist/esm-node/index.js"() { - init_v4(); - } -}); - // node_modules/jws/lib/data-stream.js var require_data_stream = __commonJS({ "node_modules/jws/lib/data-stream.js"(exports2, module2) { @@ -20227,7 +20139,7 @@ var init_packageMetadata = __esm({ "node_modules/@azure/msal-common/dist/packageMetadata.mjs"() { "use strict"; name3 = "@azure/msal-common"; - version4 = "16.5.1"; + version4 = "16.5.2"; } }); @@ -20304,8 +20216,8 @@ var init_AccountInfo = __esm({ }); // node_modules/@azure/msal-common/dist/account/AuthToken.mjs -var AuthToken_exports = {}; -__export(AuthToken_exports, { +var AuthToken_exports2 = {}; +__export(AuthToken_exports2, { checkMaxAge: () => checkMaxAge2, extractTokenClaims: () => extractTokenClaims2, getJWSPayload: () => getJWSPayload2, @@ -20903,16 +20815,16 @@ var CacheManager2, DefaultStorageClass2; var init_CacheManager = __esm({ "node_modules/@azure/msal-common/dist/cache/CacheManager.mjs"() { "use strict"; - init_Constants(); - init_ScopeSet(); - init_ClientAuthError(); init_AccountInfo(); init_AuthToken(); - init_packageMetadata(); init_AuthorityMetadata(); - init_CacheError(); - init_AccountEntityUtils(); init_AuthError(); + init_CacheError(); + init_ClientAuthError(); + init_packageMetadata(); + init_ScopeSet(); + init_Constants(); + init_AccountEntityUtils(); init_ClientAuthErrorCodes(); CacheManager2 = class { constructor(clientId, cryptoImpl, logger31, performanceClient, staticAuthorityOptions) { @@ -20940,8 +20852,10 @@ var init_CacheManager = __esm({ } const allAccounts = this.getAllAccounts(accountFilter, correlationId); if (allAccounts.length > 1) { - const sortedAccounts = allAccounts.sort((account) => { - return account.idTokenClaims ? -1 : 1; + const sortedAccounts = allAccounts.sort((a, b) => { + const aHasClaims = a.idTokenClaims ? 1 : 0; + const bHasClaims = b.idTokenClaims ? 1 : 0; + return bHasClaims - aHasClaims; }); return sortedAccounts[0]; } else if (allAccounts.length === 1) { @@ -25818,19 +25732,18 @@ var init_Configuration = __esm({ }); // node_modules/@azure/identity/node_modules/@azure/msal-node/dist/crypto/GuidGenerator.mjs -var GuidGenerator2; +var import_node_crypto, GuidGenerator2; var init_GuidGenerator = __esm({ "node_modules/@azure/identity/node_modules/@azure/msal-node/dist/crypto/GuidGenerator.mjs"() { "use strict"; - init_esm_node(); + import_node_crypto = require("node:crypto"); GuidGenerator2 = class { /** - * - * RFC4122: The version 4 UUID is meant for generating UUIDs from truly-random or pseudo-random numbers. - * uuidv4 generates guids from cryprtographically-string random + * Generates a random [RFC 4122](https://www.rfc-editor.org/rfc/rfc4122.txt) version 4 UUID. The UUID is generated using a + * cryptographic pseudorandom number generator. */ generateGuid() { - return v4_default(); + return (0, import_node_crypto.randomUUID)(); } /** * verifies if a string is GUID @@ -26436,12 +26349,15 @@ var init_NodeStorage = __esm({ return [...Object.keys(cache)]; } /** - * Clears all cache entries created by MSAL (except tokens). + * Clears all cache entries created by MSAL except authority metadata.. */ clear() { this.logger.trace("Clearing cache entries created by MSAL", ""); const cacheKeys = this.getKeys(); cacheKeys.forEach((key) => { + if (this.isAuthorityMetadata(key)) { + return; + } this.removeItem(key); }); this.emitChange(); @@ -26898,7 +26814,7 @@ var init_packageMetadata2 = __esm({ "node_modules/@azure/identity/node_modules/@azure/msal-node/dist/packageMetadata.mjs"() { "use strict"; name4 = "@azure/msal-node"; - version5 = "5.1.4"; + version5 = "5.1.5"; } }); @@ -27423,7 +27339,7 @@ var init_ClientApplication = __esm({ return AuthorityFactory_exports2.createDiscoveredInstance(authorityUrl, this.config.system.networkClient, this.storage, authorityOptions, this.logger, requestCorrelationId, new StubPerformanceClient2()); } /** - * Clear the cache + * Clear the cache except for authority metadata. */ clearCache() { this.storage.clear(); @@ -28193,7 +28109,7 @@ var init_OnBehalfOfClient = __esm({ let idTokenClaims; let cachedAccount = null; if (cachedIdToken) { - idTokenClaims = AuthToken_exports.extractTokenClaims(cachedIdToken.secret, EncodingUtils2.base64Decode); + idTokenClaims = AuthToken_exports2.extractTokenClaims(cachedIdToken.secret, EncodingUtils2.base64Decode); const localAccountId = idTokenClaims.oid || idTokenClaims.sub; const accountInfo = { homeAccountId: cachedIdToken.homeAccountId, @@ -29962,7 +29878,7 @@ var init_sha256 = __esm({ }); // node_modules/@typespec/ts-http-runtime/dist/esm/util/uuidUtils.js -function randomUUID() { +function randomUUID2() { return crypto.randomUUID(); } var init_uuidUtils = __esm({ @@ -30721,7 +30637,7 @@ var init_pipelineRequest = __esm({ this.abortSignal = options.abortSignal; this.onUploadProgress = options.onUploadProgress; this.onDownloadProgress = options.onDownloadProgress; - this.requestId = options.requestId || randomUUID(); + this.requestId = options.requestId || randomUUID2(); this.allowInsecureConnection = options.allowInsecureConnection ?? false; this.enableBrowserStreams = options.enableBrowserStreams ?? false; this.requestOverrides = options.requestOverrides; @@ -33227,7 +33143,7 @@ var init_concat = __esm({ // node_modules/@typespec/ts-http-runtime/dist/esm/policies/multipartPolicy.js function generateBoundary() { - return `----AzSDKFormBoundary${randomUUID()}`; + return `----AzSDKFormBoundary${randomUUID2()}`; } function encodeHeaders(headers) { let result = ""; @@ -37497,8 +37413,8 @@ async function parseCertificate(certificateConfiguration, sendCertificateChain) if (publicKeys.length === 0) { throw new Error("The file at the specified path does not contain a PEM-encoded certificate."); } - const thumbprint = (0, import_node_crypto.createHash)("sha1").update(Buffer.from(publicKeys[0], "base64")).digest("hex").toUpperCase(); - const thumbprintSha256 = (0, import_node_crypto.createHash)("sha256").update(Buffer.from(publicKeys[0], "base64")).digest("hex").toUpperCase(); + const thumbprint = (0, import_node_crypto2.createHash)("sha1").update(Buffer.from(publicKeys[0], "base64")).digest("hex").toUpperCase(); + const thumbprintSha256 = (0, import_node_crypto2.createHash)("sha256").update(Buffer.from(publicKeys[0], "base64")).digest("hex").toUpperCase(); return { certificateContents, thumbprintSha256, @@ -37506,11 +37422,11 @@ async function parseCertificate(certificateConfiguration, sendCertificateChain) x5c }; } -var import_node_crypto, import_promises3, credentialName, logger8, ClientCertificateCredential; +var import_node_crypto2, import_promises3, credentialName, logger8, ClientCertificateCredential; var init_clientCertificateCredential = __esm({ "node_modules/@azure/identity/dist/esm/credentials/clientCertificateCredential.js"() { init_msalClient(); - import_node_crypto = require("node:crypto"); + import_node_crypto2 = require("node:crypto"); init_tenantIdUtils(); init_logging(); import_promises3 = require("node:fs/promises"); @@ -37569,7 +37485,7 @@ var init_clientCertificateCredential = __esm({ const parts = await parseCertificate(this.certificateConfiguration, this.sendCertificateChain ?? false); let privateKey; if (this.certificateConfiguration.certificatePassword !== void 0) { - privateKey = (0, import_node_crypto.createPrivateKey)({ + privateKey = (0, import_node_crypto2.createPrivateKey)({ key: parts.certificateContents, passphrase: this.certificateConfiguration.certificatePassword, format: "pem" @@ -39821,14 +39737,14 @@ var init_authorizationCodeCredential = __esm({ }); // node_modules/@azure/identity/dist/esm/credentials/onBehalfOfCredential.js -var import_node_crypto2, import_promises6, credentialName5, logger27, OnBehalfOfCredential; +var import_node_crypto3, import_promises6, credentialName5, logger27, OnBehalfOfCredential; var init_onBehalfOfCredential = __esm({ "node_modules/@azure/identity/dist/esm/credentials/onBehalfOfCredential.js"() { init_msalClient(); init_logging(); init_tenantIdUtils(); init_errors(); - import_node_crypto2 = require("node:crypto"); + import_node_crypto3 = require("node:crypto"); init_scopeUtils(); import_promises6 = require("node:fs/promises"); init_tracing(); @@ -39926,8 +39842,8 @@ var init_onBehalfOfCredential = __esm({ if (publicKeys.length === 0) { throw new Error("The file at the specified path does not contain a PEM-encoded certificate."); } - const thumbprint = (0, import_node_crypto2.createHash)("sha1").update(Buffer.from(publicKeys[0], "base64")).digest("hex").toUpperCase(); - const thumbprintSha256 = (0, import_node_crypto2.createHash)("sha256").update(Buffer.from(publicKeys[0], "base64")).digest("hex").toUpperCase(); + const thumbprint = (0, import_node_crypto3.createHash)("sha1").update(Buffer.from(publicKeys[0], "base64")).digest("hex").toUpperCase(); + const thumbprintSha256 = (0, import_node_crypto3.createHash)("sha256").update(Buffer.from(publicKeys[0], "base64")).digest("hex").toUpperCase(); return { certificateContents, thumbprintSha256, @@ -74885,6 +74801,9 @@ program2.name("ms-365-mcp-server").description("Microsoft 365 MCP Server").versi ).option( "--public-url ", "Public base URL (e.g. https://mcp.example.com) used in browser-facing OAuth redirects when running behind a reverse proxy. Server-to-server endpoints (token, register) stay on the request host." +).option( + "--obo", + "Enable On-Behalf-Of token exchange in HTTP mode. Exchanges the incoming bearer token for a Graph API token using the OBO flow. Requires MS365_MCP_CLIENT_SECRET." ).addOption( // DEPRECATED: kept only so existing deployments that set --base-url or // MS365_MCP_BASE_URL do not crash at startup. Use --public-url / @@ -74949,6 +74868,9 @@ function parseArgs() { options.enableDynamicRegistration = true; } } + if (process.env.MS365_MCP_OBO === "true" || process.env.MS365_MCP_OBO === "1") { + options.obo = true; + } if (options.cloud) { process.env.MS365_MCP_CLOUD_TYPE = options.cloud; } @@ -76656,6 +76578,13 @@ var AccountEntity = class _AccountEntity { }; // node_modules/@azure/msal-node/node_modules/@azure/msal-common/dist/account/AuthToken.mjs +var AuthToken_exports = {}; +__export(AuthToken_exports, { + checkMaxAge: () => checkMaxAge, + extractTokenClaims: () => extractTokenClaims, + getJWSPayload: () => getJWSPayload, + isKmsi: () => isKmsi +}); function extractTokenClaims(encodedToken, base64Decode) { const jswPayload = getJWSPayload(encodedToken); try { @@ -81997,6 +81926,8 @@ var ProxyStatus = { SUCCESS_RANGE_END: HttpStatus.SUCCESS_RANGE_END, SERVER_ERROR: HttpStatus.SERVER_ERROR }; +var REGION_ENVIRONMENT_VARIABLE = "REGION_NAME"; +var MSAL_FORCE_REGION = "MSAL_FORCE_REGION"; var RANDOM_OCTET_SIZE = 32; var Hash = { SHA256: "sha256" @@ -82547,8 +82478,59 @@ function buildAppConfiguration({ auth, broker, cache, system, telemetry }) { }; } +// node_modules/uuid/dist/esm-node/rng.js +var import_crypto = __toESM(require("crypto")); +var rnds8Pool = new Uint8Array(256); +var poolPtr = rnds8Pool.length; +function rng() { + if (poolPtr > rnds8Pool.length - 16) { + import_crypto.default.randomFillSync(rnds8Pool); + poolPtr = 0; + } + return rnds8Pool.slice(poolPtr, poolPtr += 16); +} + +// node_modules/uuid/dist/esm-node/regex.js +var regex_default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; + +// node_modules/uuid/dist/esm-node/validate.js +function validate(uuid2) { + return typeof uuid2 === "string" && regex_default.test(uuid2); +} +var validate_default = validate; + +// node_modules/uuid/dist/esm-node/stringify.js +var byteToHex = []; +for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 256).toString(16).substr(1)); +} +function stringify(arr, offset = 0) { + const uuid2 = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); + if (!validate_default(uuid2)) { + throw TypeError("Stringified UUID is invalid"); + } + return uuid2; +} +var stringify_default = stringify; + +// node_modules/uuid/dist/esm-node/v4.js +function v4(options, buf, offset) { + options = options || {}; + const rnds = options.random || (options.rng || rng)(); + rnds[6] = rnds[6] & 15 | 64; + rnds[8] = rnds[8] & 63 | 128; + if (buf) { + offset = offset || 0; + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + return buf; + } + return stringify_default(rnds); +} +var v4_default = v4; + // node_modules/@azure/msal-node/dist/crypto/GuidGenerator.mjs -init_esm_node(); var GuidGenerator = class { /** * @@ -84455,6 +84437,500 @@ var PublicClientApplication = class extends ClientApplication { } }; +// node_modules/@azure/msal-node/dist/client/ClientCredentialClient.mjs +var ClientCredentialClient = class extends BaseClient { + constructor(configuration, appTokenProvider) { + super(configuration); + this.appTokenProvider = appTokenProvider; + } + /** + * Public API to acquire a token with ClientCredential Flow for Confidential clients + * @param request - CommonClientCredentialRequest provided by the developer + */ + async acquireToken(request) { + if (request.skipCache || request.claims) { + return this.executeTokenRequest(request, this.authority); + } + const [cachedAuthenticationResult, lastCacheOutcome] = await this.getCachedAuthenticationResult(request, this.config, this.cryptoUtils, this.authority, this.cacheManager, this.serverTelemetryManager); + if (cachedAuthenticationResult) { + if (lastCacheOutcome === CacheOutcome.PROACTIVELY_REFRESHED) { + this.logger.info("ClientCredentialClient:getCachedAuthenticationResult - Cached access token's refreshOn property has been exceeded'. It's not expired, but must be refreshed."); + const refreshAccessToken2 = true; + await this.executeTokenRequest(request, this.authority, refreshAccessToken2); + } + return cachedAuthenticationResult; + } else { + return this.executeTokenRequest(request, this.authority); + } + } + /** + * looks up cache if the tokens are cached already + */ + async getCachedAuthenticationResult(request, config2, cryptoUtils, authority, cacheManager, serverTelemetryManager) { + const clientConfiguration = config2; + const managedIdentityConfiguration = config2; + let lastCacheOutcome = CacheOutcome.NOT_APPLICABLE; + let cacheContext; + if (clientConfiguration.serializableCache && clientConfiguration.persistencePlugin) { + cacheContext = new TokenCacheContext(clientConfiguration.serializableCache, false); + await clientConfiguration.persistencePlugin.beforeCacheAccess(cacheContext); + } + const cachedAccessToken = this.readAccessTokenFromCache(authority, managedIdentityConfiguration.managedIdentityId?.id || clientConfiguration.authOptions.clientId, new ScopeSet(request.scopes || []), cacheManager, request.correlationId); + if (clientConfiguration.serializableCache && clientConfiguration.persistencePlugin && cacheContext) { + await clientConfiguration.persistencePlugin.afterCacheAccess(cacheContext); + } + if (!cachedAccessToken) { + serverTelemetryManager?.setCacheOutcome(CacheOutcome.NO_CACHED_ACCESS_TOKEN); + return [null, CacheOutcome.NO_CACHED_ACCESS_TOKEN]; + } + if (TimeUtils_exports.isTokenExpired(cachedAccessToken.expiresOn, clientConfiguration.systemOptions?.tokenRenewalOffsetSeconds || DEFAULT_TOKEN_RENEWAL_OFFSET_SEC)) { + serverTelemetryManager?.setCacheOutcome(CacheOutcome.CACHED_ACCESS_TOKEN_EXPIRED); + return [null, CacheOutcome.CACHED_ACCESS_TOKEN_EXPIRED]; + } + if (cachedAccessToken.refreshOn && TimeUtils_exports.isTokenExpired(cachedAccessToken.refreshOn.toString(), 0)) { + lastCacheOutcome = CacheOutcome.PROACTIVELY_REFRESHED; + serverTelemetryManager?.setCacheOutcome(CacheOutcome.PROACTIVELY_REFRESHED); + } + return [ + await ResponseHandler.generateAuthenticationResult(cryptoUtils, authority, { + account: null, + idToken: null, + accessToken: cachedAccessToken, + refreshToken: null, + appMetadata: null + }, true, request), + lastCacheOutcome + ]; + } + /** + * Reads access token from the cache + */ + readAccessTokenFromCache(authority, id, scopeSet, cacheManager, correlationId) { + const accessTokenFilter = { + homeAccountId: Constants.EMPTY_STRING, + environment: authority.canonicalAuthorityUrlComponents.HostNameAndPort, + credentialType: CredentialType.ACCESS_TOKEN, + clientId: id, + realm: authority.tenant, + target: ScopeSet.createSearchScopes(scopeSet.asArray()) + }; + const accessTokens = cacheManager.getAccessTokensByFilter(accessTokenFilter, correlationId); + if (accessTokens.length < 1) { + return null; + } else if (accessTokens.length > 1) { + throw createClientAuthError(ClientAuthErrorCodes_exports.multipleMatchingTokens); + } + return accessTokens[0]; + } + /** + * Makes a network call to request the token from the service + * @param request - CommonClientCredentialRequest provided by the developer + * @param authority - authority object + */ + async executeTokenRequest(request, authority, refreshAccessToken2) { + let serverTokenResponse; + let reqTimestamp; + if (this.appTokenProvider) { + this.logger.info("Using appTokenProvider extensibility."); + const appTokenPropviderParameters = { + correlationId: request.correlationId, + tenantId: this.config.authOptions.authority.tenant, + scopes: request.scopes, + claims: request.claims + }; + reqTimestamp = TimeUtils_exports.nowSeconds(); + const appTokenProviderResult = await this.appTokenProvider(appTokenPropviderParameters); + serverTokenResponse = { + access_token: appTokenProviderResult.accessToken, + expires_in: appTokenProviderResult.expiresInSeconds, + refresh_in: appTokenProviderResult.refreshInSeconds, + token_type: AuthenticationScheme.BEARER + }; + } else { + const queryParametersString = this.createTokenQueryParameters(request); + const endpoint = UrlString.appendQueryString(authority.tokenEndpoint, queryParametersString); + const requestBody = await this.createTokenRequestBody(request); + const headers = this.createTokenRequestHeaders(); + const thumbprint = { + clientId: this.config.authOptions.clientId, + authority: request.authority, + scopes: request.scopes, + claims: request.claims, + authenticationScheme: request.authenticationScheme, + resourceRequestMethod: request.resourceRequestMethod, + resourceRequestUri: request.resourceRequestUri, + shrClaims: request.shrClaims, + sshKid: request.sshKid + }; + this.logger.info("Sending token request to endpoint: " + authority.tokenEndpoint); + reqTimestamp = TimeUtils_exports.nowSeconds(); + const response = await this.executePostToTokenEndpoint(endpoint, requestBody, headers, thumbprint, request.correlationId); + serverTokenResponse = response.body; + serverTokenResponse.status = response.status; + } + const responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin); + responseHandler.validateTokenResponse(serverTokenResponse, refreshAccessToken2); + const tokenResponse = await responseHandler.handleServerTokenResponse(serverTokenResponse, this.authority, reqTimestamp, request, ApiId.acquireTokenByClientCredential); + return tokenResponse; + } + /** + * generate the request to the server in the acceptable format + * @param request - CommonClientCredentialRequest provided by the developer + */ + async createTokenRequestBody(request) { + const parameters = /* @__PURE__ */ new Map(); + RequestParameterBuilder_exports.addClientId(parameters, this.config.authOptions.clientId); + RequestParameterBuilder_exports.addScopes(parameters, request.scopes, false); + RequestParameterBuilder_exports.addGrantType(parameters, GrantType.CLIENT_CREDENTIALS_GRANT); + RequestParameterBuilder_exports.addLibraryInfo(parameters, this.config.libraryInfo); + RequestParameterBuilder_exports.addApplicationTelemetry(parameters, this.config.telemetry.application); + RequestParameterBuilder_exports.addThrottling(parameters); + if (this.serverTelemetryManager) { + RequestParameterBuilder_exports.addServerTelemetry(parameters, this.serverTelemetryManager); + } + const correlationId = request.correlationId || this.config.cryptoInterface.createNewGuid(); + RequestParameterBuilder_exports.addCorrelationId(parameters, correlationId); + if (this.config.clientCredentials.clientSecret) { + RequestParameterBuilder_exports.addClientSecret(parameters, this.config.clientCredentials.clientSecret); + } + const clientAssertion = request.clientAssertion || this.config.clientCredentials.clientAssertion; + if (clientAssertion) { + RequestParameterBuilder_exports.addClientAssertion(parameters, await getClientAssertion(clientAssertion.assertion, this.config.authOptions.clientId, request.resourceRequestUri)); + RequestParameterBuilder_exports.addClientAssertionType(parameters, clientAssertion.assertionType); + } + if (!StringUtils.isEmptyObj(request.claims) || this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0) { + RequestParameterBuilder_exports.addClaims(parameters, request.claims, this.config.authOptions.clientCapabilities); + } + return UrlUtils_exports.mapToQueryString(parameters); + } +}; + +// node_modules/@azure/msal-node/dist/client/OnBehalfOfClient.mjs +var OnBehalfOfClient = class extends BaseClient { + constructor(configuration) { + super(configuration); + } + /** + * Public API to acquire tokens with on behalf of flow + * @param request - developer provided CommonOnBehalfOfRequest + */ + async acquireToken(request) { + this.scopeSet = new ScopeSet(request.scopes || []); + this.userAssertionHash = await this.cryptoUtils.hashString(request.oboAssertion); + if (request.skipCache || request.claims) { + return this.executeTokenRequest(request, this.authority, this.userAssertionHash); + } + try { + return await this.getCachedAuthenticationResult(request); + } catch (e) { + return await this.executeTokenRequest(request, this.authority, this.userAssertionHash); + } + } + /** + * look up cache for tokens + * Find idtoken in the cache + * Find accessToken based on user assertion and account info in the cache + * Please note we are not yet supported OBO tokens refreshed with long lived RT. User will have to send a new assertion if the current access token expires + * This is to prevent security issues when the assertion changes over time, however, longlived RT helps retaining the session + * @param request - developer provided CommonOnBehalfOfRequest + */ + async getCachedAuthenticationResult(request) { + const cachedAccessToken = this.readAccessTokenFromCacheForOBO(this.config.authOptions.clientId, request); + if (!cachedAccessToken) { + this.serverTelemetryManager?.setCacheOutcome(CacheOutcome.NO_CACHED_ACCESS_TOKEN); + this.logger.info("SilentFlowClient:acquireCachedToken - No access token found in cache for the given properties."); + throw createClientAuthError(ClientAuthErrorCodes_exports.tokenRefreshRequired); + } else if (TimeUtils_exports.isTokenExpired(cachedAccessToken.expiresOn, this.config.systemOptions.tokenRenewalOffsetSeconds)) { + this.serverTelemetryManager?.setCacheOutcome(CacheOutcome.CACHED_ACCESS_TOKEN_EXPIRED); + this.logger.info(`OnbehalfofFlow:getCachedAuthenticationResult - Cached access token is expired or will expire within ${this.config.systemOptions.tokenRenewalOffsetSeconds} seconds.`); + throw createClientAuthError(ClientAuthErrorCodes_exports.tokenRefreshRequired); + } + const cachedIdToken = this.readIdTokenFromCacheForOBO(cachedAccessToken.homeAccountId, request.correlationId); + let idTokenClaims; + let cachedAccount = null; + if (cachedIdToken) { + idTokenClaims = AuthToken_exports.extractTokenClaims(cachedIdToken.secret, EncodingUtils.base64Decode); + const localAccountId = idTokenClaims.oid || idTokenClaims.sub; + const accountInfo = { + homeAccountId: cachedIdToken.homeAccountId, + environment: cachedIdToken.environment, + tenantId: cachedIdToken.realm, + username: Constants.EMPTY_STRING, + localAccountId: localAccountId || Constants.EMPTY_STRING + }; + cachedAccount = this.cacheManager.getAccount(this.cacheManager.generateAccountKey(accountInfo), request.correlationId); + } + if (this.config.serverTelemetryManager) { + this.config.serverTelemetryManager.incrementCacheHits(); + } + return ResponseHandler.generateAuthenticationResult(this.cryptoUtils, this.authority, { + account: cachedAccount, + accessToken: cachedAccessToken, + idToken: cachedIdToken, + refreshToken: null, + appMetadata: null + }, true, request, idTokenClaims); + } + /** + * read idtoken from cache, this is a specific implementation for OBO as the requirements differ from a generic lookup in the cacheManager + * Certain use cases of OBO flow do not expect an idToken in the cache/or from the service + * @param atHomeAccountId - account id + */ + readIdTokenFromCacheForOBO(atHomeAccountId, correlationId) { + const idTokenFilter = { + homeAccountId: atHomeAccountId, + environment: this.authority.canonicalAuthorityUrlComponents.HostNameAndPort, + credentialType: CredentialType.ID_TOKEN, + clientId: this.config.authOptions.clientId, + realm: this.authority.tenant + }; + const idTokenMap = this.cacheManager.getIdTokensByFilter(idTokenFilter, correlationId); + if (Object.values(idTokenMap).length < 1) { + return null; + } + return Object.values(idTokenMap)[0]; + } + /** + * Fetches the cached access token based on incoming assertion + * @param clientId - client id + * @param request - developer provided CommonOnBehalfOfRequest + */ + readAccessTokenFromCacheForOBO(clientId, request) { + const authScheme = request.authenticationScheme || AuthenticationScheme.BEARER; + const credentialType = authScheme && authScheme.toLowerCase() !== AuthenticationScheme.BEARER.toLowerCase() ? CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME : CredentialType.ACCESS_TOKEN; + const accessTokenFilter = { + credentialType, + clientId, + target: ScopeSet.createSearchScopes(this.scopeSet.asArray()), + tokenType: authScheme, + keyId: request.sshKid, + requestedClaimsHash: request.requestedClaimsHash, + userAssertionHash: this.userAssertionHash + }; + const accessTokens = this.cacheManager.getAccessTokensByFilter(accessTokenFilter, request.correlationId); + const numAccessTokens = accessTokens.length; + if (numAccessTokens < 1) { + return null; + } else if (numAccessTokens > 1) { + throw createClientAuthError(ClientAuthErrorCodes_exports.multipleMatchingTokens); + } + return accessTokens[0]; + } + /** + * Make a network call to the server requesting credentials + * @param request - developer provided CommonOnBehalfOfRequest + * @param authority - authority object + */ + async executeTokenRequest(request, authority, userAssertionHash) { + const queryParametersString = this.createTokenQueryParameters(request); + const endpoint = UrlString.appendQueryString(authority.tokenEndpoint, queryParametersString); + const requestBody = await this.createTokenRequestBody(request); + const headers = this.createTokenRequestHeaders(); + const thumbprint = { + clientId: this.config.authOptions.clientId, + authority: request.authority, + scopes: request.scopes, + claims: request.claims, + authenticationScheme: request.authenticationScheme, + resourceRequestMethod: request.resourceRequestMethod, + resourceRequestUri: request.resourceRequestUri, + shrClaims: request.shrClaims, + sshKid: request.sshKid + }; + const reqTimestamp = TimeUtils_exports.nowSeconds(); + const response = await this.executePostToTokenEndpoint(endpoint, requestBody, headers, thumbprint, request.correlationId); + const responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin); + responseHandler.validateTokenResponse(response.body); + const tokenResponse = await responseHandler.handleServerTokenResponse(response.body, this.authority, reqTimestamp, request, ApiId.acquireTokenByOBO, void 0, userAssertionHash); + return tokenResponse; + } + /** + * generate a server request in accepable format + * @param request - developer provided CommonOnBehalfOfRequest + */ + async createTokenRequestBody(request) { + const parameters = /* @__PURE__ */ new Map(); + RequestParameterBuilder_exports.addClientId(parameters, this.config.authOptions.clientId); + RequestParameterBuilder_exports.addScopes(parameters, request.scopes); + RequestParameterBuilder_exports.addGrantType(parameters, GrantType.JWT_BEARER); + RequestParameterBuilder_exports.addClientInfo(parameters); + RequestParameterBuilder_exports.addLibraryInfo(parameters, this.config.libraryInfo); + RequestParameterBuilder_exports.addApplicationTelemetry(parameters, this.config.telemetry.application); + RequestParameterBuilder_exports.addThrottling(parameters); + if (this.serverTelemetryManager) { + RequestParameterBuilder_exports.addServerTelemetry(parameters, this.serverTelemetryManager); + } + const correlationId = request.correlationId || this.config.cryptoInterface.createNewGuid(); + RequestParameterBuilder_exports.addCorrelationId(parameters, correlationId); + RequestParameterBuilder_exports.addRequestTokenUse(parameters, AADServerParamKeys_exports.ON_BEHALF_OF); + RequestParameterBuilder_exports.addOboAssertion(parameters, request.oboAssertion); + if (this.config.clientCredentials.clientSecret) { + RequestParameterBuilder_exports.addClientSecret(parameters, this.config.clientCredentials.clientSecret); + } + const clientAssertion = this.config.clientCredentials.clientAssertion; + if (clientAssertion) { + RequestParameterBuilder_exports.addClientAssertion(parameters, await getClientAssertion(clientAssertion.assertion, this.config.authOptions.clientId, request.resourceRequestUri)); + RequestParameterBuilder_exports.addClientAssertionType(parameters, clientAssertion.assertionType); + } + if (request.claims || this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0) { + RequestParameterBuilder_exports.addClaims(parameters, request.claims, this.config.authOptions.clientCapabilities); + } + return UrlUtils_exports.mapToQueryString(parameters); + } +}; + +// node_modules/@azure/msal-node/dist/client/ConfidentialClientApplication.mjs +var ConfidentialClientApplication = class extends ClientApplication { + /** + * Constructor for the ConfidentialClientApplication + * + * Required attributes in the Configuration object are: + * - clientID: the application ID of your application. You can obtain one by registering your application with our application registration portal + * - authority: the authority URL for your application. + * - client credential: Must set either client secret, certificate, or assertion for confidential clients. You can obtain a client secret from the application registration portal. + * + * In Azure AD, authority is a URL indicating of the form https://login.microsoftonline.com/\{Enter_the_Tenant_Info_Here\}. + * If your application supports Accounts in one organizational directory, replace "Enter_the_Tenant_Info_Here" value with the Tenant Id or Tenant name (for example, contoso.microsoft.com). + * If your application supports Accounts in any organizational directory, replace "Enter_the_Tenant_Info_Here" value with organizations. + * If your application supports Accounts in any organizational directory and personal Microsoft accounts, replace "Enter_the_Tenant_Info_Here" value with common. + * To restrict support to Personal Microsoft accounts only, replace "Enter_the_Tenant_Info_Here" value with consumers. + * + * In Azure B2C, authority is of the form https://\{instance\}/tfp/\{tenant\}/\{policyName\}/ + * Full B2C functionality will be available in this library in future versions. + * + * @param Configuration - configuration object for the MSAL ConfidentialClientApplication instance + */ + constructor(configuration) { + super(configuration); + const clientSecretNotEmpty = !!this.config.auth.clientSecret; + const clientAssertionNotEmpty = !!this.config.auth.clientAssertion; + const certificateNotEmpty = (!!this.config.auth.clientCertificate?.thumbprint || !!this.config.auth.clientCertificate?.thumbprintSha256) && !!this.config.auth.clientCertificate?.privateKey; + if (this.appTokenProvider) { + return; + } + if (clientSecretNotEmpty && clientAssertionNotEmpty || clientAssertionNotEmpty && certificateNotEmpty || clientSecretNotEmpty && certificateNotEmpty) { + throw createClientAuthError(ClientAuthErrorCodes_exports.invalidClientCredential); + } + if (this.config.auth.clientSecret) { + this.clientSecret = this.config.auth.clientSecret; + return; + } + if (this.config.auth.clientAssertion) { + this.developerProvidedClientAssertion = this.config.auth.clientAssertion; + return; + } + if (!certificateNotEmpty) { + throw createClientAuthError(ClientAuthErrorCodes_exports.invalidClientCredential); + } else { + this.clientAssertion = !!this.config.auth.clientCertificate.thumbprintSha256 ? ClientAssertion.fromCertificateWithSha256Thumbprint(this.config.auth.clientCertificate.thumbprintSha256, this.config.auth.clientCertificate.privateKey, this.config.auth.clientCertificate.x5c) : ClientAssertion.fromCertificate( + // guaranteed to be a string, due to prior error checking in this function + this.config.auth.clientCertificate.thumbprint, + this.config.auth.clientCertificate.privateKey, + this.config.auth.clientCertificate.x5c + ); + } + this.appTokenProvider = void 0; + } + /** + * This extensibility point only works for the client_credential flow, i.e. acquireTokenByClientCredential and + * is meant for Azure SDK to enhance Managed Identity support. + * + * @param IAppTokenProvider - Extensibility interface, which allows the app developer to return a token from a custom source. + */ + SetAppTokenProvider(provider) { + this.appTokenProvider = provider; + } + /** + * Acquires tokens from the authority for the application (not for an end user). + */ + async acquireTokenByClientCredential(request) { + this.logger.info("acquireTokenByClientCredential called", request.correlationId); + let clientAssertion; + if (request.clientAssertion) { + clientAssertion = { + assertion: await getClientAssertion( + request.clientAssertion, + this.config.auth.clientId + // tokenEndpoint will be undefined. resourceRequestUri is omitted in ClientCredentialRequest + ), + assertionType: Constants2.JWT_BEARER_ASSERTION_TYPE + }; + } + const baseRequest = await this.initializeBaseRequest(request); + const validBaseRequest = { + ...baseRequest, + scopes: baseRequest.scopes.filter((scope) => !OIDC_DEFAULT_SCOPES.includes(scope)) + }; + const validRequest = { + ...request, + ...validBaseRequest, + clientAssertion + }; + const authority = new UrlString(validRequest.authority); + const tenantId = authority.getUrlComponents().PathSegments[0]; + if (Object.values(AADAuthorityConstants).includes(tenantId)) { + throw createClientAuthError(ClientAuthErrorCodes_exports.missingTenantIdError); + } + const ENV_MSAL_FORCE_REGION = process.env[MSAL_FORCE_REGION]; + let region; + if (validRequest.azureRegion !== "DisableMsalForceRegion") { + if (!validRequest.azureRegion && ENV_MSAL_FORCE_REGION) { + region = ENV_MSAL_FORCE_REGION; + } else { + region = validRequest.azureRegion; + } + } + const azureRegionConfiguration = { + azureRegion: region, + environmentRegion: process.env[REGION_ENVIRONMENT_VARIABLE] + }; + const serverTelemetryManager = this.initializeServerTelemetryManager(ApiId.acquireTokenByClientCredential, validRequest.correlationId, validRequest.skipCache); + try { + const discoveredAuthority = await this.createAuthority(validRequest.authority, validRequest.correlationId, azureRegionConfiguration, request.azureCloudOptions); + const clientCredentialConfig = await this.buildOauthClientConfiguration(discoveredAuthority, validRequest.correlationId, "", serverTelemetryManager); + const clientCredentialClient = new ClientCredentialClient(clientCredentialConfig, this.appTokenProvider); + this.logger.verbose("Client credential client created", validRequest.correlationId); + return await clientCredentialClient.acquireToken(validRequest); + } catch (e) { + if (e instanceof AuthError) { + e.setCorrelationId(validRequest.correlationId); + } + serverTelemetryManager.cacheFailedRequest(e); + throw e; + } + } + /** + * Acquires tokens from the authority for the application. + * + * Used in scenarios where the current app is a middle-tier service which was called with a token + * representing an end user. The current app can use the token (oboAssertion) to request another + * token to access downstream web API, on behalf of that user. + * + * The current middle-tier app has no user interaction to obtain consent. + * See how to gain consent upfront for your middle-tier app from this article. + * https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow#gaining-consent-for-the-middle-tier-application + */ + async acquireTokenOnBehalfOf(request) { + this.logger.info("acquireTokenOnBehalfOf called", request.correlationId); + const validRequest = { + ...request, + ...await this.initializeBaseRequest(request) + }; + try { + const discoveredAuthority = await this.createAuthority(validRequest.authority, validRequest.correlationId, void 0, request.azureCloudOptions); + const onBehalfOfConfig = await this.buildOauthClientConfiguration(discoveredAuthority, validRequest.correlationId, "", void 0); + const oboClient = new OnBehalfOfClient(onBehalfOfConfig); + this.logger.verbose("On behalf of client created", validRequest.correlationId); + return await oboClient.acquireToken(validRequest); + } catch (e) { + if (e instanceof AuthError) { + e.setCorrelationId(validRequest.correlationId); + } + throw e; + } + } +}; + // node_modules/@azure/msal-node/dist/utils/TimeUtils.mjs function isIso8601(dateString) { if (typeof dateString !== "string") { @@ -101258,7 +101734,7 @@ var OAuthTokenRevocationRequestSchema = object2({ }).strip(); // node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/handlers/register.js -var import_node_crypto4 = __toESM(require("node:crypto"), 1); +var import_node_crypto5 = __toESM(require("node:crypto"), 1); var import_cors = __toESM(require_lib3(), 1); // node_modules/express-rate-limit/dist/index.mjs @@ -101266,7 +101742,7 @@ var import_node_net = require("node:net"); var import_ip_address = __toESM(require_ip_address(), 1); var import_node_net2 = require("node:net"); var import_node_buffer3 = require("node:buffer"); -var import_node_crypto3 = require("node:crypto"); +var import_node_crypto4 = require("node:crypto"); var import_node_net3 = require("node:net"); function ipKeyGenerator(ip, ipv6Subnet = 56) { if ((0, import_node_net.isIPv6)(ip)) { @@ -101443,7 +101919,7 @@ var getResetSeconds = (windowMs, resetTime) => { return resetSeconds; }; var getPartitionKey = (key) => { - const hash = (0, import_node_crypto3.createHash)("sha256"); + const hash = (0, import_node_crypto4.createHash)("sha256"); hash.update(key); const partitionKey = hash.digest("hex").slice(0, 12); return import_node_buffer3.Buffer.from(partitionKey).toString("base64"); @@ -102335,7 +102811,7 @@ function clientRegistrationHandler({ clientsStore, clientSecretExpirySeconds = D } const clientMetadata = parseResult.data; const isPublicClient = clientMetadata.token_endpoint_auth_method === "none"; - const clientSecret = isPublicClient ? void 0 : import_node_crypto4.default.randomBytes(32).toString("hex"); + const clientSecret = isPublicClient ? void 0 : import_node_crypto5.default.randomBytes(32).toString("hex"); const clientIdIssuedAt = Math.floor(Date.now() / 1e3); const clientsDoExpire = clientSecretExpirySeconds > 0; const secretExpiryTime = clientsDoExpire ? clientIdIssuedAt + clientSecretExpirySeconds : 0; @@ -102346,7 +102822,7 @@ function clientRegistrationHandler({ clientsStore, clientSecretExpirySeconds = D client_secret_expires_at: clientSecretExpiresAt }; if (clientIdGeneration) { - clientInfo.client_id = import_node_crypto4.default.randomUUID(); + clientInfo.client_id = import_node_crypto5.default.randomUUID(); clientInfo.client_id_issued_at = clientIdIssuedAt; } clientInfo = await clientsStore.registerClient(clientInfo); @@ -103966,6 +104442,27 @@ var microsoft_graph_permissionCollectionResponse = external_exports.object({ "@odata.nextLink": external_exports.string().nullable(), value: external_exports.array(microsoft_graph_permission) }).partial().passthrough(); +var microsoft_graph_thumbnail = external_exports.object({ + content: external_exports.string().describe("The content stream for the thumbnail.").nullish(), + height: external_exports.number().gte(-2147483648).lte(2147483647).describe("The height of the thumbnail, in pixels.").nullish(), + sourceItemId: external_exports.string().describe( + "The unique identifier of the item that provided the thumbnail. This is only available when a folder thumbnail is requested." + ).nullish(), + url: external_exports.string().describe("The URL used to fetch the thumbnail content.").nullish(), + width: external_exports.number().gte(-2147483648).lte(2147483647).describe("The width of the thumbnail, in pixels.").nullish() +}).passthrough(); +var microsoft_graph_thumbnailSet = external_exports.object({ + id: external_exports.string().describe("The unique identifier for an entity. Read-only.").optional(), + large: microsoft_graph_thumbnail.optional(), + medium: microsoft_graph_thumbnail.optional(), + small: microsoft_graph_thumbnail.optional(), + source: microsoft_graph_thumbnail.optional() +}).passthrough(); +var microsoft_graph_thumbnailSetCollectionResponse = external_exports.object({ + "@odata.count": external_exports.number().int().nullable(), + "@odata.nextLink": external_exports.string().nullable(), + value: external_exports.array(microsoft_graph_thumbnailSet) +}).partial().passthrough(); var microsoft_graph_publicationFacet = external_exports.object({ checkedOutBy: microsoft_graph_identitySet.optional(), level: external_exports.string().describe( @@ -105614,6 +106111,17 @@ var decline_calendar_event_Body = external_exports.object({ }).partial().passthrough(); var forward_calendar_event_Body = external_exports.object({ ToRecipients: external_exports.array(microsoft_graph_recipient), Comment: external_exports.string().nullable() }).partial().passthrough(); var snooze_calendar_event_reminder_Body = external_exports.object({ NewReminderTime: microsoft_graph_dateTimeTimeZone }).partial().passthrough(); +var microsoft_graph_inferenceClassificationType = external_exports.enum(["focused", "other"]); +var microsoft_graph_inferenceClassificationOverride = external_exports.object({ + id: external_exports.string().describe("The unique identifier for an entity. Read-only.").optional(), + classifyAs: microsoft_graph_inferenceClassificationType.optional(), + senderEmailAddress: microsoft_graph_emailAddress.optional() +}).passthrough(); +var microsoft_graph_inferenceClassificationOverrideCollectionResponse = external_exports.object({ + "@odata.count": external_exports.number().int().nullable(), + "@odata.nextLink": external_exports.string().nullable(), + value: external_exports.array(microsoft_graph_inferenceClassificationOverride) +}).partial().passthrough(); var microsoft_graph_resourceReference = external_exports.object({ id: external_exports.string().describe("The item's unique identifier.").nullish(), type: external_exports.string().describe( @@ -106025,7 +106533,6 @@ var microsoft_graph_followupFlag = external_exports.object({ flagStatus: microsoft_graph_followupFlagStatus.optional(), startDateTime: microsoft_graph_dateTimeTimeZone.optional() }).passthrough(); -var microsoft_graph_inferenceClassificationType = external_exports.enum(["focused", "other"]); var microsoft_graph_internetMessageHeader = external_exports.object({ name: external_exports.string().describe("Represents the key in a key-value pair.").nullish(), value: external_exports.string().describe("The value in a key-value pair.").nullish() @@ -106526,6 +107033,46 @@ var microsoft_graph_callTranscriptCollectionResponse = external_exports.object({ "@odata.nextLink": external_exports.string().nullable(), value: external_exports.array(microsoft_graph_callTranscript) }).partial().passthrough(); +var microsoft_graph_categoryColor = external_exports.enum([ + "none", + "preset0", + "preset1", + "preset2", + "preset3", + "preset4", + "preset5", + "preset6", + "preset7", + "preset8", + "preset9", + "preset10", + "preset11", + "preset12", + "preset13", + "preset14", + "preset15", + "preset16", + "preset17", + "preset18", + "preset19", + "preset20", + "preset21", + "preset22", + "preset23", + "preset24" +]); +var microsoft_graph_outlookCategory = external_exports.object({ + id: external_exports.string().describe("The unique identifier for an entity. Read-only.").optional(), + color: microsoft_graph_categoryColor.optional(), + displayName: external_exports.string().describe( + "A unique name that identifies a category in the user's mailbox. After a category is created, the name cannot be changed. Read-only." + ).nullish() +}).passthrough(); +var microsoft_graph_outlookCategoryCollectionResponse = external_exports.object({ + "@odata.count": external_exports.number().int().nullable(), + "@odata.nextLink": external_exports.string().nullable(), + value: external_exports.array(microsoft_graph_outlookCategory) +}).partial().passthrough(); var microsoft_graph_personType = external_exports.object({ class: external_exports.string().describe("The type of data source, such as Person.").nullish(), subclass: external_exports.string().describe("The secondary type of data source, such as OrganizationUser.").nullish() @@ -107268,6 +107815,11 @@ var microsoft_graph_listCollectionResponse = external_exports.object({ "@odata.nextLink": external_exports.string().nullable(), value: external_exports.array(microsoft_graph_list) }).partial().passthrough(); +var microsoft_graph_columnDefinitionCollectionResponse = external_exports.object({ + "@odata.count": external_exports.number().int().nullable(), + "@odata.nextLink": external_exports.string().nullable(), + value: external_exports.array(microsoft_graph_columnDefinition) +}).partial().passthrough(); var microsoft_graph_listItemCollectionResponse = external_exports.object({ "@odata.count": external_exports.number().int().nullable(), "@odata.nextLink": external_exports.string().nullable(), @@ -108317,6 +108869,56 @@ Items with this property set should be removed from your local state.`, ], response: external_exports.void() }, + { + method: "get", + path: "/drives/:driveId/items/:driveItemId/thumbnails", + alias: "list-drive-item-thumbnails", + description: `Collection of thumbnailSet objects associated with the item. For more information, see getting thumbnails. Read-only. Nullable.`, + requestFormat: "json", + parameters: [ + { + name: "$top", + type: "Query", + schema: external_exports.number().int().gte(0).describe("Show only the first n items").optional() + }, + { + name: "$skip", + type: "Query", + schema: external_exports.number().int().gte(0).describe("Skip the first n items").optional() + }, + { + name: "$search", + type: "Query", + schema: external_exports.string().describe("Search items by search phrases").optional() + }, + { + name: "$filter", + type: "Query", + schema: external_exports.string().describe("Filter items by property values").optional() + }, + { + name: "$count", + type: "Query", + schema: external_exports.boolean().describe("Include count of items").optional() + }, + { + name: "$orderby", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Order items by property values").optional() + }, + { + name: "$select", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Select properties to be returned").optional() + }, + { + name: "$expand", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Expand related entities").optional() + } + ], + response: external_exports.void() + }, { method: "get", path: "/drives/:driveId/items/:driveItemId/versions", @@ -110927,6 +111529,105 @@ Based on this value, you can better adjust the parameters and call findMeetingTi ], response: external_exports.void() }, + { + method: "get", + path: "/me/inferenceClassification/overrides", + alias: "list-focused-inbox-overrides", + description: `Get the overrides that a user has set up to always classify messages from certain senders in specific ways. Each override corresponds to an SMTP address of a sender. Initially, a user does not have any overrides.`, + requestFormat: "json", + parameters: [ + { + name: "$top", + type: "Query", + schema: external_exports.number().int().gte(0).describe("Show only the first n items").optional() + }, + { + name: "$skip", + type: "Query", + schema: external_exports.number().int().gte(0).describe("Skip the first n items").optional() + }, + { + name: "$search", + type: "Query", + schema: external_exports.string().describe("Search items by search phrases").optional() + }, + { + name: "$filter", + type: "Query", + schema: external_exports.string().describe("Filter items by property values").optional() + }, + { + name: "$count", + type: "Query", + schema: external_exports.boolean().describe("Include count of items").optional() + }, + { + name: "$orderby", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Order items by property values").optional() + }, + { + name: "$select", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Select properties to be returned").optional() + }, + { + name: "$expand", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Expand related entities").optional() + } + ], + response: external_exports.void() + }, + { + method: "post", + path: "/me/inferenceClassification/overrides", + alias: "create-focused-inbox-override", + description: `Create an override for a sender identified by an SMTP address. Future messages from that SMTP address will be consistently classified +as specified in the override. Note`, + requestFormat: "json", + parameters: [ + { + name: "body", + description: `New navigation property`, + type: "Body", + schema: microsoft_graph_inferenceClassificationOverride + } + ], + response: external_exports.void() + }, + { + method: "patch", + path: "/me/inferenceClassification/overrides/:inferenceClassificationOverrideId", + alias: "update-focused-inbox-override", + description: `Change the classifyAs field of an override as specified. You cannot use PATCH to change any other fields in an inferenceClassificationOverride instance. If an override exists for a sender and the sender changes his/her display name, you can use POST to force an update to the name field in the existing override. If an override exists for a sender and the sender changes his/her SMTP address, deleting the existing override and creating a new one with +the new SMTP address is the only way to 'update' the override for this sender.`, + requestFormat: "json", + parameters: [ + { + name: "body", + description: `New navigation property values`, + type: "Body", + schema: microsoft_graph_inferenceClassificationOverride + } + ], + response: external_exports.void() + }, + { + method: "delete", + path: "/me/inferenceClassification/overrides/:inferenceClassificationOverrideId", + alias: "delete-focused-inbox-override", + description: `Delete an override specified by its ID.`, + requestFormat: "json", + parameters: [ + { + name: "If-Match", + type: "Header", + schema: external_exports.string().describe("ETag").optional() + } + ], + response: external_exports.void() + }, { method: "get", path: "/me/insights/trending", @@ -111384,6 +112085,66 @@ folder collection and navigate to another folder. By default, this operation doe ], response: external_exports.void() }, + { + method: "get", + path: "/me/mailFolders/:mailFolderId/messages/delta()", + alias: "list-mail-folder-messages-delta", + description: `Get a set of messages added, deleted, or updated in a specified folder. A delta function call for messages in a folder is similar to a GET request, except that by appropriately +applying state tokens in one or more of these calls, you can [query for incremental changes in the messages in +that folder](/graph/delta-query-messages). It allows you to maintain and synchronize a local store of a user's messages without +having to fetch the entire set of messages from the server every time.`, + requestFormat: "json", + parameters: [ + { + name: "changeType", + type: "Query", + schema: external_exports.string().describe( + "A custom query option to filter the delta response based on the type of change. Supported values are created, updated or deleted." + ).optional() + }, + { + name: "$top", + type: "Query", + schema: external_exports.number().int().gte(0).describe("Show only the first n items").optional() + }, + { + name: "$skip", + type: "Query", + schema: external_exports.number().int().gte(0).describe("Skip the first n items").optional() + }, + { + name: "$search", + type: "Query", + schema: external_exports.string().describe("Search items by search phrases").optional() + }, + { + name: "$filter", + type: "Query", + schema: external_exports.string().describe("Filter items by property values").optional() + }, + { + name: "$count", + type: "Query", + schema: external_exports.boolean().describe("Include count of items").optional() + }, + { + name: "$select", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Select properties to be returned").optional() + }, + { + name: "$orderby", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Order items by property values").optional() + }, + { + name: "$expand", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Expand related entities").optional() + } + ], + response: external_exports.void() + }, { method: "get", path: "/me/manager", @@ -111800,6 +112561,22 @@ resource.`, ], response: external_exports.void() }, + { + method: "post", + path: "/me/messages/:messageId/copy", + alias: "copy-mail-message", + description: `Copy a message to a folder within the user's mailbox.`, + requestFormat: "json", + parameters: [ + { + name: "body", + description: `Action parameters`, + type: "Body", + schema: external_exports.object({ DestinationId: external_exports.string() }).partial().passthrough() + } + ], + response: external_exports.void() + }, { method: "post", path: "/me/messages/:messageId/createForward", @@ -112694,6 +113471,72 @@ resource.`, requestFormat: "json", response: external_exports.void() }, + { + method: "get", + path: "/me/outlook/masterCategories", + alias: "list-outlook-categories", + description: `Get all the categories that have been defined for a user.`, + requestFormat: "json", + parameters: [ + { + name: "$top", + type: "Query", + schema: external_exports.number().int().gte(0).describe("Show only the first n items").optional() + }, + { + name: "$skip", + type: "Query", + schema: external_exports.number().int().gte(0).describe("Skip the first n items").optional() + }, + { + name: "$search", + type: "Query", + schema: external_exports.string().describe("Search items by search phrases").optional() + }, + { + name: "$filter", + type: "Query", + schema: external_exports.string().describe("Filter items by property values").optional() + }, + { + name: "$count", + type: "Query", + schema: external_exports.boolean().describe("Include count of items").optional() + }, + { + name: "$orderby", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Order items by property values").optional() + }, + { + name: "$select", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Select properties to be returned").optional() + }, + { + name: "$expand", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Expand related entities").optional() + } + ], + response: external_exports.void() + }, + { + method: "post", + path: "/me/outlook/masterCategories", + alias: "create-outlook-category", + description: `Create an outlookCategory object in the user's master list of categories.`, + requestFormat: "json", + parameters: [ + { + name: "body", + description: `New navigation property`, + type: "Body", + schema: microsoft_graph_outlookCategory + } + ], + response: external_exports.void() + }, { method: "get", path: "/me/people", @@ -113917,6 +114760,22 @@ To list them, include system in your $select statement.`, ], response: external_exports.void() }, + { + method: "post", + path: "/sites/:siteId/lists", + alias: "create-sharepoint-list", + description: `Create a new list in a site.`, + requestFormat: "json", + parameters: [ + { + name: "body", + description: `New navigation property`, + type: "Body", + schema: microsoft_graph_list + } + ], + response: external_exports.void() + }, { method: "get", path: "/sites/:siteId/lists/:listId", @@ -113937,6 +114796,191 @@ To list them, include system in your $select statement.`, ], response: external_exports.void() }, + { + method: "get", + path: "/sites/:siteId/lists/:listId/columns", + alias: "list-sharepoint-list-columns", + description: `Get the collection of columns represented as columnDefinition resources in a list.`, + requestFormat: "json", + parameters: [ + { + name: "$top", + type: "Query", + schema: external_exports.number().int().gte(0).describe("Show only the first n items").optional() + }, + { + name: "$skip", + type: "Query", + schema: external_exports.number().int().gte(0).describe("Skip the first n items").optional() + }, + { + name: "$search", + type: "Query", + schema: external_exports.string().describe("Search items by search phrases").optional() + }, + { + name: "$filter", + type: "Query", + schema: external_exports.string().describe("Filter items by property values").optional() + }, + { + name: "$count", + type: "Query", + schema: external_exports.boolean().describe("Include count of items").optional() + }, + { + name: "$orderby", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Order items by property values").optional() + }, + { + name: "$select", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Select properties to be returned").optional() + }, + { + name: "$expand", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Expand related entities").optional() + } + ], + response: external_exports.void() + }, + { + method: "post", + path: "/sites/:siteId/lists/:listId/columns", + alias: "create-sharepoint-list-column", + description: `Create a column for a list with a request that specifies a columnDefinition.`, + requestFormat: "json", + parameters: [ + { + name: "body", + description: `New navigation property`, + type: "Body", + schema: external_exports.object({ + id: external_exports.string().describe("The unique identifier for an entity. Read-only.").optional(), + name: external_exports.string().describe( + "The API-facing name of the column as it appears in the fields on a listItem. For the user-facing name, see displayName." + ).nullish(), + displayName: external_exports.string().describe("The user-facing name of the column.").nullish(), + description: external_exports.string().describe("The user-facing description of the column.").nullish(), + type: microsoft_graph_columnTypes.optional(), + boolean: microsoft_graph_booleanColumn.optional(), + calculated: microsoft_graph_calculatedColumn.optional(), + choice: microsoft_graph_choiceColumn.optional(), + columnGroup: external_exports.string().describe( + "For site columns, the name of the group this column belongs to. Helps organize related columns." + ).nullish(), + contentApprovalStatus: microsoft_graph_contentApprovalStatusColumn.optional(), + currency: microsoft_graph_currencyColumn.optional(), + dateTime: microsoft_graph_dateTimeColumn.optional(), + defaultValue: microsoft_graph_defaultColumnValue.optional(), + enforceUniqueValues: external_exports.boolean().describe("If true, no two list items may have the same value for this column.").nullish(), + geolocation: microsoft_graph_geolocationColumn.optional(), + hidden: external_exports.boolean().describe("Specifies whether the column is displayed in the user interface.").nullish(), + hyperlinkOrPicture: microsoft_graph_hyperlinkOrPictureColumn.optional(), + indexed: external_exports.boolean().describe( + "Specifies whether the column values can be used for sorting and searching." + ).nullish(), + isDeletable: external_exports.boolean().describe("Indicates whether this column can be deleted.").nullish(), + isReorderable: external_exports.boolean().describe("Indicates whether values in the column can be reordered. Read-only.").nullish(), + isSealed: external_exports.boolean().describe("Specifies whether the column can be changed.").nullish(), + lookup: microsoft_graph_lookupColumn.optional(), + number: microsoft_graph_numberColumn.optional(), + personOrGroup: microsoft_graph_personOrGroupColumn.optional(), + propagateChanges: external_exports.boolean().describe( + "If 'true', changes to this column will be propagated to lists that implement the column." + ).nullish() + }).passthrough().passthrough() + } + ], + response: external_exports.void() + }, + { + method: "get", + path: "/sites/:siteId/lists/:listId/columns/:columnDefinitionId", + alias: "get-sharepoint-list-column", + description: `The collection of field definitions for this list.`, + requestFormat: "json", + parameters: [ + { + name: "$select", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Select properties to be returned").optional() + }, + { + name: "$expand", + type: "Query", + schema: external_exports.array(external_exports.string()).describe("Expand related entities").optional() + } + ], + response: external_exports.void() + }, + { + method: "patch", + path: "/sites/:siteId/lists/:listId/columns/:columnDefinitionId", + alias: "update-sharepoint-list-column", + description: `Update the navigation property columns in sites`, + requestFormat: "json", + parameters: [ + { + name: "body", + description: `New navigation property values`, + type: "Body", + schema: external_exports.object({ + id: external_exports.string().describe("The unique identifier for an entity. Read-only.").optional(), + name: external_exports.string().describe( + "The API-facing name of the column as it appears in the fields on a listItem. For the user-facing name, see displayName." + ).nullish(), + displayName: external_exports.string().describe("The user-facing name of the column.").nullish(), + description: external_exports.string().describe("The user-facing description of the column.").nullish(), + type: microsoft_graph_columnTypes.optional(), + boolean: microsoft_graph_booleanColumn.optional(), + calculated: microsoft_graph_calculatedColumn.optional(), + choice: microsoft_graph_choiceColumn.optional(), + columnGroup: external_exports.string().describe( + "For site columns, the name of the group this column belongs to. Helps organize related columns." + ).nullish(), + contentApprovalStatus: microsoft_graph_contentApprovalStatusColumn.optional(), + currency: microsoft_graph_currencyColumn.optional(), + dateTime: microsoft_graph_dateTimeColumn.optional(), + defaultValue: microsoft_graph_defaultColumnValue.optional(), + enforceUniqueValues: external_exports.boolean().describe("If true, no two list items may have the same value for this column.").nullish(), + geolocation: microsoft_graph_geolocationColumn.optional(), + hidden: external_exports.boolean().describe("Specifies whether the column is displayed in the user interface.").nullish(), + hyperlinkOrPicture: microsoft_graph_hyperlinkOrPictureColumn.optional(), + indexed: external_exports.boolean().describe( + "Specifies whether the column values can be used for sorting and searching." + ).nullish(), + isDeletable: external_exports.boolean().describe("Indicates whether this column can be deleted.").nullish(), + isReorderable: external_exports.boolean().describe("Indicates whether values in the column can be reordered. Read-only.").nullish(), + isSealed: external_exports.boolean().describe("Specifies whether the column can be changed.").nullish(), + lookup: microsoft_graph_lookupColumn.optional(), + number: microsoft_graph_numberColumn.optional(), + personOrGroup: microsoft_graph_personOrGroupColumn.optional(), + propagateChanges: external_exports.boolean().describe( + "If 'true', changes to this column will be propagated to lists that implement the column." + ).nullish() + }).passthrough().passthrough() + } + ], + response: external_exports.void() + }, + { + method: "delete", + path: "/sites/:siteId/lists/:listId/columns/:columnDefinitionId", + alias: "delete-sharepoint-list-column", + description: `Delete navigation property columns for sites`, + requestFormat: "json", + parameters: [ + { + name: "If-Match", + type: "Header", + schema: external_exports.string().describe("ETag").optional() + } + ], + response: external_exports.void() + }, { method: "get", path: "/sites/:siteId/lists/:listId/items", @@ -117021,7 +118065,47 @@ async function refreshAccessToken(refreshToken, clientId, clientSecret, tenantId } // node_modules/@softeria/ms-365-mcp-server/dist/server.js -var import_node_crypto5 = __toESM(require("node:crypto"), 1); +var import_node_crypto6 = __toESM(require("node:crypto"), 1); + +// node_modules/@softeria/ms-365-mcp-server/dist/obo-client.js +var OboClient = class { + constructor(secrets) { + if (!secrets.clientSecret) { + throw new Error( + "On-Behalf-Of flow requires MS365_MCP_CLIENT_SECRET to be set (confidential client)." + ); + } + const cloudEndpoints = getCloudEndpoints(secrets.cloudType); + this.cca = new ConfidentialClientApplication({ + auth: { + clientId: secrets.clientId, + clientSecret: secrets.clientSecret, + authority: `${cloudEndpoints.authority}/${secrets.tenantId || "common"}` + } + }); + const graphBase = cloudEndpoints.graphApi.replace(/\/$/, ""); + this.graphScopes = [`${graphBase}/.default`]; + } + async exchangeToken(userAssertion) { + try { + const result = await this.cca.acquireTokenOnBehalfOf({ + oboAssertion: userAssertion, + scopes: this.graphScopes + }); + if (!result?.accessToken) { + throw new Error("OBO token exchange returned no access token"); + } + logger_default.info("OBO token exchange successful"); + return result.accessToken; + } catch (error2) { + logger_default.error(`OBO token exchange failed: ${error2.message}`); + throw error2; + } + } +}; +var obo_client_default = OboClient; + +// node_modules/@softeria/ms-365-mcp-server/dist/server.js function parseHttpOption(httpOption) { if (typeof httpOption === "boolean") { return { host: void 0, port: 3e3 }; @@ -117047,6 +118131,7 @@ var MicrosoftGraphServer = class { this.graphClient = null; this.server = null; this.secrets = null; + this.oboClient = null; } createMcpServer() { const server = new McpServer( @@ -117105,6 +118190,18 @@ var MicrosoftGraphServer = class { } catch (err) { logger_default.warn(`Failed to detect multi-account mode: ${err.message}`); } + if (this.options.obo) { + if (!this.options.http) { + throw new Error("--obo requires --http (On-Behalf-Of flow only works in HTTP mode)."); + } + if (!this.secrets.clientSecret) { + throw new Error( + "--obo requires MS365_MCP_CLIENT_SECRET to be set (confidential client required for On-Behalf-Of flow)." + ); + } + this.oboClient = new obo_client_default(this.secrets); + logger_default.info("On-Behalf-Of (OBO) flow enabled"); + } const outputFormat = this.options.toon ? "toon" : "json"; this.graphClient = new graph_client_default(this.authManager, this.secrets, outputFormat); if (!this.options.http) { @@ -117176,7 +118273,7 @@ var MicrosoftGraphServer = class { const protocol = req.secure ? "https" : "http"; const requestOrigin = `${protocol}://${req.get("host")}`; const browserBase = publicBase ?? requestOrigin; - const scopes = buildScopesFromEndpoints(this.options.orgMode, this.options.enabledTools); + const scopes = this.options.obo ? [`api://${this.secrets.clientId}/access_as_user`] : buildScopesFromEndpoints(this.options.orgMode, this.options.enabledTools); res.json({ resource: `${requestOrigin}/mcp`, authorization_servers: [browserBase], @@ -117229,8 +118326,8 @@ var MicrosoftGraphServer = class { } }); if (clientCodeChallenge && state3) { - const serverCodeVerifier = import_node_crypto5.default.randomBytes(32).toString("base64url"); - const serverCodeChallenge = import_node_crypto5.default.createHash("sha256").update(serverCodeVerifier).digest("base64url"); + const serverCodeVerifier = import_node_crypto6.default.randomBytes(32).toString("base64url"); + const serverCodeChallenge = import_node_crypto6.default.createHash("sha256").update(serverCodeVerifier).digest("base64url"); const now = Date.now(); const maxAge = 10 * 60 * 1e3; const maxEntries = 1e3; @@ -117322,7 +118419,7 @@ var MicrosoftGraphServer = class { let serverCodeVerifier; if (body.code_verifier) { const clientVerifier = body.code_verifier; - const clientChallengeComputed = import_node_crypto5.default.createHash("sha256").update(clientVerifier).digest("base64url"); + const clientChallengeComputed = import_node_crypto6.default.createHash("sha256").update(clientVerifier).digest("base64url"); for (const [state3, pkceData] of this.pkceStore) { if (pkceData.clientCodeChallenge === clientChallengeComputed) { serverCodeVerifier = pkceData.serverCodeVerifier; @@ -117400,7 +118497,11 @@ var MicrosoftGraphServer = class { }; try { if (req.microsoftAuth) { - await requestContext.run({ accessToken: req.microsoftAuth.accessToken }, handler); + let accessToken = req.microsoftAuth.accessToken; + if (this.oboClient) { + accessToken = await this.oboClient.exchangeToken(accessToken); + } + await requestContext.run({ accessToken }, handler); } else { await handler(); } @@ -117438,7 +118539,11 @@ var MicrosoftGraphServer = class { }; try { if (req.microsoftAuth) { - await requestContext.run({ accessToken: req.microsoftAuth.accessToken }, handler); + let accessToken = req.microsoftAuth.accessToken; + if (this.oboClient) { + accessToken = await this.oboClient.exchangeToken(accessToken); + } + await requestContext.run({ accessToken }, handler); } else { await handler(); } diff --git a/backend/mcp-bundles/softeria-ms-365-mcp-server/package.json b/backend/mcp-bundles/softeria-ms-365-mcp-server/package.json index c6377f84..b935f190 100644 --- a/backend/mcp-bundles/softeria-ms-365-mcp-server/package.json +++ b/backend/mcp-bundles/softeria-ms-365-mcp-server/package.json @@ -1 +1 @@ -{"name":"@softeria/ms-365-mcp-server","version":"0.90.0"} \ No newline at end of file +{"name":"@softeria/ms-365-mcp-server","version":"0.95.0"} \ No newline at end of file diff --git a/electron/package-lock.json b/electron/package-lock.json index 4513aa63..f9a11ba9 100644 --- a/electron/package-lock.json +++ b/electron/package-lock.json @@ -1,12 +1,12 @@ { "name": "openswarm", - "version": "1.0.27", + "version": "1.0.28", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "openswarm", - "version": "1.0.27", + "version": "1.0.28", "hasInstallScript": true, "dependencies": { "electron-updater": "^6.3.0", diff --git a/electron/package.json b/electron/package.json index 21ab89b0..dc0b9e73 100644 --- a/electron/package.json +++ b/electron/package.json @@ -1,6 +1,6 @@ { "name": "openswarm", - "version": "1.0.27", + "version": "1.0.28", "description": "OpenSwarm — AI Agent Orchestrator", "main": "main.js", "scripts": {