Skip to main content
Glama
security-policy-handlers.ts16.5 kB
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js'; import { Client } from '@microsoft/microsoft-graph-client'; import { DefenderPolicyArgs, TeamsPolicyArgs, ExchangePolicyArgs, SharePointGovernancePolicyArgs, SecurityAlertPolicyArgs } from '../types/policy-types.js'; // Microsoft Defender for Office 365 Policy Handler export async function handleDefenderPolicies( graphClient: Client, args: DefenderPolicyArgs ): Promise<{ content: { type: string; text: string }[] }> { let apiPath = ''; let result: any; // Map policy types to API endpoints const policyEndpoints = { safeAttachments: '/security/attackSimulation/safeAttachmentPolicies', safeLinks: '/security/attackSimulation/safeLinksPolicies', antiPhishing: '/security/antiPhishingPolicies', antiMalware: '/security/antiMalwarePolicies', antiSpam: '/security/antiSpamPolicies' }; const endpoint = policyEndpoints[args.policyType]; if (!endpoint) { throw new McpError(ErrorCode.InvalidParams, `Unsupported policy type: ${args.policyType}`); } switch (args.action) { case 'list': apiPath = endpoint; result = await graphClient.api(apiPath).get(); break; case 'get': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for get action'); } apiPath = `${endpoint}/${args.policyId}`; result = await graphClient.api(apiPath).get(); break; case 'create': if (!args.displayName) { throw new McpError(ErrorCode.InvalidParams, 'displayName is required for create action'); } const defenderPolicyPayload: any = { displayName: args.displayName, description: args.description || '', isEnabled: args.isEnabled !== undefined ? args.isEnabled : true, settings: args.settings || {}, appliedTo: args.appliedTo || {} }; apiPath = endpoint; result = await graphClient.api(apiPath).post(defenderPolicyPayload); break; case 'update': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for update action'); } const updatePayload: any = {}; if (args.displayName) updatePayload.displayName = args.displayName; if (args.description) updatePayload.description = args.description; if (args.isEnabled !== undefined) updatePayload.isEnabled = args.isEnabled; if (args.settings) updatePayload.settings = args.settings; if (args.appliedTo) updatePayload.appliedTo = args.appliedTo; apiPath = `${endpoint}/${args.policyId}`; result = await graphClient.api(apiPath).patch(updatePayload); break; case 'delete': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for delete action'); } apiPath = `${endpoint}/${args.policyId}`; await graphClient.api(apiPath).delete(); result = { message: `${args.policyType} policy ${args.policyId} deleted successfully` }; break; default: throw new McpError(ErrorCode.InvalidParams, `Unknown action: ${args.action}`); } return { content: [{ type: 'text', text: `Defender ${args.policyType} Policy ${args.action} operation completed:\n\n${JSON.stringify(result, null, 2)}` }] }; } // Microsoft Teams Policy Handler export async function handleTeamsPolicies( graphClient: Client, args: TeamsPolicyArgs ): Promise<{ content: { type: string; text: string }[] }> { let apiPath = ''; let result: any; // Map policy types to API endpoints const policyEndpoints = { messaging: '/admin/serviceAnnouncement/policies/messaging', meeting: '/admin/serviceAnnouncement/policies/meeting', calling: '/admin/serviceAnnouncement/policies/calling', appSetup: '/admin/serviceAnnouncement/policies/appSetup', updateManagement: '/admin/serviceAnnouncement/policies/updateManagement' }; const endpoint = policyEndpoints[args.policyType]; if (!endpoint) { throw new McpError(ErrorCode.InvalidParams, `Unsupported policy type: ${args.policyType}`); } switch (args.action) { case 'list': apiPath = endpoint; result = await graphClient.api(apiPath).get(); break; case 'get': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for get action'); } apiPath = `${endpoint}/${args.policyId}`; result = await graphClient.api(apiPath).get(); break; case 'create': if (!args.displayName) { throw new McpError(ErrorCode.InvalidParams, 'displayName is required for create action'); } const teamsPolicyPayload: any = { displayName: args.displayName, description: args.description || '', settings: args.settings || {} }; apiPath = endpoint; result = await graphClient.api(apiPath).post(teamsPolicyPayload); break; case 'update': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for update action'); } const updatePayload: any = {}; if (args.displayName) updatePayload.displayName = args.displayName; if (args.description) updatePayload.description = args.description; if (args.settings) updatePayload.settings = args.settings; apiPath = `${endpoint}/${args.policyId}`; result = await graphClient.api(apiPath).patch(updatePayload); break; case 'delete': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for delete action'); } apiPath = `${endpoint}/${args.policyId}`; await graphClient.api(apiPath).delete(); result = { message: `Teams ${args.policyType} policy ${args.policyId} deleted successfully` }; break; case 'assign': if (!args.policyId || !args.assignTo) { throw new McpError(ErrorCode.InvalidParams, 'policyId and assignTo are required for assign action'); } const assignPayload: any = { assignments: [] }; if (args.assignTo.users) { args.assignTo.users.forEach(userId => { assignPayload.assignments.push({ target: { '@odata.type': '#microsoft.graph.userTarget', userId: userId } }); }); } if (args.assignTo.groups) { args.assignTo.groups.forEach(groupId => { assignPayload.assignments.push({ target: { '@odata.type': '#microsoft.graph.groupTarget', groupId: groupId } }); }); } apiPath = `${endpoint}/${args.policyId}/assign`; result = await graphClient.api(apiPath).post(assignPayload); break; default: throw new McpError(ErrorCode.InvalidParams, `Unknown action: ${args.action}`); } return { content: [{ type: 'text', text: `Teams ${args.policyType} Policy ${args.action} operation completed:\n\n${JSON.stringify(result, null, 2)}` }] }; } // Exchange Online Policy Handler export async function handleExchangePolicies( graphClient: Client, args: ExchangePolicyArgs ): Promise<{ content: { type: string; text: string }[] }> { let apiPath = ''; let result: any; // Map policy types to API endpoints const policyEndpoints = { addressBook: '/admin/exchange/addressBookPolicies', outlookWebApp: '/admin/exchange/owaMailboxPolicies', activeSyncMailbox: '/admin/exchange/activeSyncMailboxPolicies', retentionPolicy: '/admin/exchange/retentionPolicies', dlpPolicy: '/admin/exchange/dataLossPreventionPolicies' }; const endpoint = policyEndpoints[args.policyType]; if (!endpoint) { throw new McpError(ErrorCode.InvalidParams, `Unsupported policy type: ${args.policyType}`); } switch (args.action) { case 'list': apiPath = endpoint; result = await graphClient.api(apiPath).get(); break; case 'get': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for get action'); } apiPath = `${endpoint}/${args.policyId}`; result = await graphClient.api(apiPath).get(); break; case 'create': if (!args.displayName) { throw new McpError(ErrorCode.InvalidParams, 'displayName is required for create action'); } const exchangePolicyPayload: any = { displayName: args.displayName, description: args.description || '', isDefault: args.isDefault || false, settings: args.settings || {}, appliedTo: args.appliedTo || {} }; apiPath = endpoint; result = await graphClient.api(apiPath).post(exchangePolicyPayload); break; case 'update': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for update action'); } const updatePayload: any = {}; if (args.displayName) updatePayload.displayName = args.displayName; if (args.description) updatePayload.description = args.description; if (args.isDefault !== undefined) updatePayload.isDefault = args.isDefault; if (args.settings) updatePayload.settings = args.settings; if (args.appliedTo) updatePayload.appliedTo = args.appliedTo; apiPath = `${endpoint}/${args.policyId}`; result = await graphClient.api(apiPath).patch(updatePayload); break; case 'delete': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for delete action'); } apiPath = `${endpoint}/${args.policyId}`; await graphClient.api(apiPath).delete(); result = { message: `Exchange ${args.policyType} policy ${args.policyId} deleted successfully` }; break; default: throw new McpError(ErrorCode.InvalidParams, `Unknown action: ${args.action}`); } return { content: [{ type: 'text', text: `Exchange ${args.policyType} Policy ${args.action} operation completed:\n\n${JSON.stringify(result, null, 2)}` }] }; } // SharePoint Governance Policy Handler export async function handleSharePointGovernancePolicies( graphClient: Client, args: SharePointGovernancePolicyArgs ): Promise<{ content: { type: string; text: string }[] }> { let apiPath = ''; let result: any; // Map policy types to API endpoints const policyEndpoints = { sharingPolicy: '/admin/sharepoint/settings/sharing', accessPolicy: '/admin/sharepoint/settings/conditionalAccess', informationBarrier: '/admin/sharepoint/settings/informationBarriers', retentionLabel: '/admin/sharepoint/settings/retentionLabels' }; const endpoint = policyEndpoints[args.policyType]; if (!endpoint) { throw new McpError(ErrorCode.InvalidParams, `Unsupported policy type: ${args.policyType}`); } switch (args.action) { case 'list': apiPath = endpoint; result = await graphClient.api(apiPath).get(); break; case 'get': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for get action'); } apiPath = `${endpoint}/${args.policyId}`; result = await graphClient.api(apiPath).get(); break; case 'create': if (!args.displayName) { throw new McpError(ErrorCode.InvalidParams, 'displayName is required for create action'); } const spPolicyPayload: any = { displayName: args.displayName, description: args.description || '', scope: args.scope || {}, settings: args.settings || {} }; apiPath = endpoint; result = await graphClient.api(apiPath).post(spPolicyPayload); break; case 'update': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for update action'); } const updatePayload: any = {}; if (args.displayName) updatePayload.displayName = args.displayName; if (args.description) updatePayload.description = args.description; if (args.scope) updatePayload.scope = args.scope; if (args.settings) updatePayload.settings = args.settings; apiPath = `${endpoint}/${args.policyId}`; result = await graphClient.api(apiPath).patch(updatePayload); break; case 'delete': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for delete action'); } apiPath = `${endpoint}/${args.policyId}`; await graphClient.api(apiPath).delete(); result = { message: `SharePoint ${args.policyType} policy ${args.policyId} deleted successfully` }; break; default: throw new McpError(ErrorCode.InvalidParams, `Unknown action: ${args.action}`); } return { content: [{ type: 'text', text: `SharePoint ${args.policyType} Policy ${args.action} operation completed:\n\n${JSON.stringify(result, null, 2)}` }] }; } // Security and Compliance Alert Policy Handler export async function handleSecurityAlertPolicies( graphClient: Client, args: SecurityAlertPolicyArgs ): Promise<{ content: { type: string; text: string }[] }> { let apiPath = ''; let result: any; switch (args.action) { case 'list': apiPath = '/security/alerts/policies'; result = await graphClient.api(apiPath).get(); break; case 'get': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for get action'); } apiPath = `/security/alerts/policies/${args.policyId}`; result = await graphClient.api(apiPath).get(); break; case 'create': if (!args.displayName) { throw new McpError(ErrorCode.InvalidParams, 'displayName is required for create action'); } const alertPolicyPayload: any = { displayName: args.displayName, description: args.description || '', category: args.category || 'Others', severity: args.severity || 'Medium', isEnabled: args.isEnabled !== undefined ? args.isEnabled : true, conditions: args.conditions || {}, actions: args.actions || {} }; apiPath = '/security/alerts/policies'; result = await graphClient.api(apiPath).post(alertPolicyPayload); break; case 'update': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for update action'); } const updatePayload: any = {}; if (args.displayName) updatePayload.displayName = args.displayName; if (args.description) updatePayload.description = args.description; if (args.category) updatePayload.category = args.category; if (args.severity) updatePayload.severity = args.severity; if (args.isEnabled !== undefined) updatePayload.isEnabled = args.isEnabled; if (args.conditions) updatePayload.conditions = args.conditions; if (args.actions) updatePayload.actions = args.actions; apiPath = `/security/alerts/policies/${args.policyId}`; result = await graphClient.api(apiPath).patch(updatePayload); break; case 'delete': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for delete action'); } apiPath = `/security/alerts/policies/${args.policyId}`; await graphClient.api(apiPath).delete(); result = { message: `Security alert policy ${args.policyId} deleted successfully` }; break; case 'enable': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for enable action'); } apiPath = `/security/alerts/policies/${args.policyId}`; result = await graphClient.api(apiPath).patch({ isEnabled: true }); break; case 'disable': if (!args.policyId) { throw new McpError(ErrorCode.InvalidParams, 'policyId is required for disable action'); } apiPath = `/security/alerts/policies/${args.policyId}`; result = await graphClient.api(apiPath).patch({ isEnabled: false }); break; default: throw new McpError(ErrorCode.InvalidParams, `Unknown action: ${args.action}`); } return { content: [{ type: 'text', text: `Security Alert Policy ${args.action} operation completed:\n\n${JSON.stringify(result, null, 2)}` }] }; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/DynamicEndpoints/m365-core-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server