Skip to main content
Glama
DynamicEndpoints

Microsoft 365 Core MCP Server

manage_graph_subscriptions

Create, update, delete, or list webhook subscriptions to receive real-time notifications for changes in Microsoft Graph resources.

Instructions

Manage webhook subscriptions for real-time change notifications from Microsoft Graph resources.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYesSubscription management action
subscriptionIdNoSubscription ID for update/delete operations
subscriptionNoSubscription details for create/update
updatesNoUpdates for existing subscription

Implementation Reference

  • Registers the manage_graph_subscriptions tool with inline handler logic that uses GraphAdvancedFeatures class methods based on the 'action' parameter (create, update, delete, list). Includes inline input schema.
    const graphSubscriptionsMeta = getToolMetadata("manage_graph_subscriptions")!;
    this.server.tool(
      "manage_graph_subscriptions",
      graphSubscriptionsMeta.description,
      z.object({
        action: z.enum(['create', 'update', 'delete', 'list']).describe('Subscription management action'),
        subscriptionId: z.string().optional().describe('Subscription ID for update/delete operations'),
        subscription: webhookSubscriptionSchema.optional().describe('Subscription details for create/update'),
        updates: webhookSubscriptionSchema.partial().optional().describe('Updates for existing subscription')
      }).shape,
      graphSubscriptionsMeta.annotations || {},
      wrapToolHandler(async (args: any) => {
        this.validateCredentials();
        try {
          const advancedFeatures = new GraphAdvancedFeatures(this.getGraphClient(), this.getAccessToken.bind(this));
          let result: any;
    
          switch (args.action) {
            case 'create':
              if (!args.subscription) {
                throw new McpError(ErrorCode.InvalidParams, 'Subscription details required for create action');
              }
              result = await advancedFeatures.createSubscription(args.subscription);
              break;
            case 'update':
              if (!args.subscriptionId || !args.updates) {
                throw new McpError(ErrorCode.InvalidParams, 'Subscription ID and updates required for update action');
              }
              result = await advancedFeatures.updateSubscription(args.subscriptionId, args.updates);
              break;
            case 'delete':
              if (!args.subscriptionId) {
                throw new McpError(ErrorCode.InvalidParams, 'Subscription ID required for delete action');
              }
              result = await advancedFeatures.deleteSubscription(args.subscriptionId);
              break;
            case 'list':
              result = await advancedFeatures.listSubscriptions();
              break;
            default:
              throw new McpError(ErrorCode.InvalidParams, `Invalid action: ${args.action}`);
          }
    
          return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
        } catch (error) {
          if (error instanceof McpError) {
            throw error;
          }
          throw new McpError(
            ErrorCode.InternalError,
            `Error managing subscriptions: ${error instanceof Error ? error.message : 'Unknown error'}`
          );
        }
      })
    );
  • Core handler methods in GraphAdvancedFeatures class for managing Microsoft Graph webhook subscriptions: createSubscription, updateSubscription, deleteSubscription, listSubscriptions. Called by the tool handler in server.ts.
    async createSubscription(subscription: WebhookSubscription): Promise<SubscriptionResponse> {
      const subscriptionPayload: any = {
        changeType: subscription.changeTypes.join(','),
        notificationUrl: subscription.notificationUrl,
        resource: subscription.resource,
        expirationDateTime: subscription.expirationDateTime || this.getDefaultExpiration(),
        clientState: subscription.clientState,
        latestSupportedTlsVersion: subscription.tlsVersion || 'v1_2'
      };
    
      // Add lifecycle notification URL if provided
      if (subscription.lifecycleNotificationUrl) {
        subscriptionPayload.lifecycleNotificationUrl = subscription.lifecycleNotificationUrl;
      }
    
      try {
        const response = await this.graphClient
          .api('/subscriptions')
          .post(subscriptionPayload);
    
        return {
          id: response.id,
          resource: response.resource,
          changeType: response.changeType,
          notificationUrl: response.notificationUrl,
          expirationDateTime: response.expirationDateTime,
          clientState: response.clientState,
          createdAt: new Date().toISOString()
        };
      } catch (error) {
        throw new McpError(
          ErrorCode.InternalError,
          `Failed to create subscription: ${error instanceof Error ? error.message : 'Unknown error'}`
        );
      }
    }
    
    // Update existing subscription
    async updateSubscription(subscriptionId: string, updates: Partial<WebhookSubscription>): Promise<SubscriptionResponse> {
      const updatePayload: any = {};
    
      if (updates.expirationDateTime) {
        updatePayload.expirationDateTime = updates.expirationDateTime;
      }
    
      if (updates.notificationUrl) {
        updatePayload.notificationUrl = updates.notificationUrl;
      }
    
      try {
        const response = await this.graphClient
          .api(`/subscriptions/${subscriptionId}`)
          .patch(updatePayload);
    
        return {
          id: response.id,
          resource: response.resource,
          changeType: response.changeType,
          notificationUrl: response.notificationUrl,
          expirationDateTime: response.expirationDateTime,
          clientState: response.clientState,
          updatedAt: new Date().toISOString()
        };
      } catch (error) {
        throw new McpError(
          ErrorCode.InternalError,
          `Failed to update subscription: ${error instanceof Error ? error.message : 'Unknown error'}`
        );
      }
    }
    
    // Delete subscription
    async deleteSubscription(subscriptionId: string): Promise<{ deleted: boolean; deletedAt: string }> {
      try {
        await this.graphClient
          .api(`/subscriptions/${subscriptionId}`)
          .delete();
    
        return {
          deleted: true,
          deletedAt: new Date().toISOString()
        };
      } catch (error) {
        throw new McpError(
          ErrorCode.InternalError,
          `Failed to delete subscription: ${error instanceof Error ? error.message : 'Unknown error'}`
        );
      }
    }
    
    // List all subscriptions
    async listSubscriptions(): Promise<SubscriptionResponse[]> {
      try {
        const response = await this.graphClient
          .api('/subscriptions')
          .get();
    
        return response.value.map((sub: any) => ({
          id: sub.id,
          resource: sub.resource,
          changeType: sub.changeType,
          notificationUrl: sub.notificationUrl,
          expirationDateTime: sub.expirationDateTime,
          clientState: sub.clientState
        }));
      } catch (error) {
        throw new McpError(
          ErrorCode.InternalError,
          `Failed to list subscriptions: ${error instanceof Error ? error.message : 'Unknown error'}`
        );
      }
    }
  • Zod schema for WebhookSubscription input parameters, used directly in the tool's inline schema (as subscription and updates).
    export const webhookSubscriptionSchema = z.object({
      resource: z.string().describe('Graph resource to monitor'),
      changeTypes: z.array(z.enum(['created', 'updated', 'deleted'])).describe('Types of changes to monitor'),
      notificationUrl: z.string().url().describe('Webhook endpoint URL'),
      expirationDateTime: z.string().optional().describe('Subscription expiration (ISO 8601)'),
      clientState: z.string().optional().describe('Client state for validation'),
      lifecycleNotificationUrl: z.string().url().optional().describe('Lifecycle notification URL'),
      tlsVersion: z.enum(['v1_0', 'v1_1', 'v1_2', 'v1_3']).optional().describe('Minimum TLS version')
    });
  • TypeScript interfaces for WebhookSubscription input and SubscriptionResponse output used by the subscription management methods.
    export interface WebhookSubscription {
      resource: string;
      changeTypes: ('created' | 'updated' | 'deleted')[];
      notificationUrl: string;
      expirationDateTime?: string;
      clientState?: string;
      lifecycleNotificationUrl?: string;
      tlsVersion?: 'v1_0' | 'v1_1' | 'v1_2' | 'v1_3';
    }
    
    export interface SubscriptionResponse {
      id: string;
      resource: string;
      changeType: string;
      notificationUrl: string;
      expirationDateTime: string;
      clientState?: string;
      createdAt?: string;
      updatedAt?: string;
    }
  • Tool metadata registration providing description, title, and annotations (readOnlyHint, destructiveHint, etc.) for the manage_graph_subscriptions tool, used during tool registration in server.ts.
    manage_graph_subscriptions: {
      description: "Manage webhook subscriptions for real-time change notifications from Microsoft Graph resources.",
      title: "Graph Subscription Manager",
      annotations: { title: "Graph Subscription Manager", readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true }
    },

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