Skip to main content
Glama

manage-webhook

Subscribe, find, or unsubscribe webhooks for the 'orders/updated' topic on Shopify. Manage webhook subscriptions using a callback URL and webhook ID for streamlined integration.

Instructions

Subscribe, find, or unsubscribe webhooks

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYesAction to perform with webhook
callbackUrlYesWebhook callback URL
topicYesWebhook topic to subscribe to
webhookIdNoWebhook ID (required for unsubscribe)

Implementation Reference

  • src/index.ts:574-636 (registration)
    MCP tool registration for 'manage-webhook', including input schema validation and the main handler logic that dispatches to ShopifyClient methods based on action.
    server.tool( "manage-webhook", "Subscribe, find, or unsubscribe webhooks", { action: z .enum(["subscribe", "find", "unsubscribe"]) .describe("Action to perform with webhook"), callbackUrl: z.string().url().describe("Webhook callback URL"), topic: z .nativeEnum(ShopifyWebhookTopic) .describe("Webhook topic to subscribe to"), webhookId: z .string() .optional() .describe("Webhook ID (required for unsubscribe)"), }, async ({ action, callbackUrl, topic, webhookId }) => { const client = new ShopifyClient(); try { switch (action) { case "subscribe": { const webhook = await client.subscribeWebhook( SHOPIFY_ACCESS_TOKEN, MYSHOPIFY_DOMAIN, callbackUrl, topic ); return { content: [{ type: "text", text: JSON.stringify(webhook, null, 2) }], }; } case "find": { const webhook = await client.findWebhookByTopicAndCallbackUrl( SHOPIFY_ACCESS_TOKEN, MYSHOPIFY_DOMAIN, callbackUrl, topic ); return { content: [{ type: "text", text: JSON.stringify(webhook, null, 2) }], }; } case "unsubscribe": { if (!webhookId) { throw new Error("webhookId is required for unsubscribe action"); } await client.unsubscribeWebhook( SHOPIFY_ACCESS_TOKEN, MYSHOPIFY_DOMAIN, webhookId ); return { content: [ { type: "text", text: "Webhook unsubscribed successfully" }, ], }; } } } catch (error) { return handleError("Failed to manage webhook", error); } } );
  • Helper method to subscribe/create a new webhook subscription via Shopify GraphQL API.
    async subscribeWebhook( accessToken: string, shop: string, callbackUrl: string, topic: ShopifyWebhookTopic ): Promise<ShopifyWebhook> { const myshopifyDomain = await this.getMyShopifyDomain(accessToken, shop); const graphqlQuery = gql` mutation webhookSubscriptionCreate( $topic: WebhookSubscriptionTopic! $webhookSubscription: WebhookSubscriptionInput! ) { webhookSubscriptionCreate( topic: $topic webhookSubscription: $webhookSubscription ) { webhookSubscription { id topic endpoint { __typename ... on WebhookHttpEndpoint { callbackUrl } } } userErrors { field message } } } `; const res = await this.shopifyGraphqlRequest<{ data: { webhookSubscriptionCreate: { webhookSubscription: { id: string; topic: ShopifyWebhookTopicGraphql; endpoint: { callbackUrl: string; }; }; userErrors: Array<{ field: string[]; message: string; }>; }; }; }>({ url: `https://${myshopifyDomain}/admin/api/${this.SHOPIFY_API_VERSION}/graphql.json`, accessToken, query: graphqlQuery, variables: { topic: this.mapTopicToGraphqlTopic(topic), webhookSubscription: { callbackUrl, }, }, }); const webhookSubscription = res.data.data.webhookSubscriptionCreate.webhookSubscription; const userErrors = res.data.data.webhookSubscriptionCreate.userErrors; if (userErrors.length > 0) { throw getGraphqlShopifyUserError(userErrors, { shop, topic, callbackUrl: callbackUrl, }); } return { id: webhookSubscription.id, topic: this.mapGraphqlTopicToTopic(webhookSubscription.topic), callbackUrl: webhookSubscription.endpoint.callbackUrl, }; }
  • Helper method to find existing webhook by topic and callback URL via Shopify GraphQL API.
    async findWebhookByTopicAndCallbackUrl( accessToken: string, shop: string, callbackUrl: string, topic: ShopifyWebhookTopic ): Promise<ShopifyWebhook | null> { const myshopifyDomain = await this.getMyShopifyDomain(accessToken, shop); const graphqlQuery = gql` query webhookSubscriptions( $topics: [WebhookSubscriptionTopic!] $callbackUrl: URL! ) { webhookSubscriptions( first: 10 topics: $topics callbackUrl: $callbackUrl ) { edges { node { id topic endpoint { __typename ... on WebhookHttpEndpoint { callbackUrl } } } } } } `; const res = await this.shopifyGraphqlRequest<{ data: { webhookSubscriptions: { edges: { node: { id: string; topic: ShopifyWebhookTopicGraphql; endpoint: { callbackUrl: string; }; }; }[]; }; }; }>({ url: `https://${myshopifyDomain}/admin/api/${this.SHOPIFY_API_VERSION}/graphql.json`, accessToken, query: graphqlQuery, variables: { topics: [this.mapTopicToGraphqlTopic(topic)], callbackUrl, }, }); const webhookSubscriptions = res.data.data.webhookSubscriptions.edges; if (webhookSubscriptions.length === 0) { return null; } const webhookSubscription = webhookSubscriptions[0].node; return { id: webhookSubscription.id, topic: this.mapGraphqlTopicToTopic(webhookSubscription.topic), callbackUrl: webhookSubscription.endpoint.callbackUrl, }; }
  • Helper method to unsubscribe/delete a webhook by ID via Shopify GraphQL API.
    async unsubscribeWebhook( accessToken: string, shop: string, webhookId: string ): Promise<void> { const myshopifyDomain = await this.getMyShopifyDomain(accessToken, shop); const graphqlQuery = gql` mutation webhookSubscriptionDelete($id: ID!) { webhookSubscriptionDelete(id: $id) { userErrors { field message } deletedWebhookSubscriptionId } } `; const res = await this.shopifyGraphqlRequest<{ data: { webhookSubscriptionDelete: { deletedWebhookSubscriptionId: string; userErrors: Array<{ field: string[]; message: string; }>; }; }; }>({ url: `https://${myshopifyDomain}/admin/api/${this.SHOPIFY_API_VERSION}/graphql.json`, accessToken, query: graphqlQuery, variables: { id: webhookId, }, }); const userErrors = res.data.data.webhookSubscriptionDelete.userErrors; if (userErrors.length > 0) { throw getGraphqlShopifyUserError(userErrors, { shop, webhookId, }); } }
  • Type definitions and enums for webhook topics and ShopifyWebhook used in the tool schema and helpers.
    export enum ShopifyWebhookTopicGraphql { ORDERS_UPDATED = "ORDERS_UPDATED", } export enum ShopifyWebhookTopic { ORDERS_UPDATED = "orders/updated", } export type ShopifyWebhook = { id: string; callbackUrl: string; topic: ShopifyWebhookTopic; };

Other Tools

Related Tools

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/smithery-ai/shopify-mcp-server-main-1'

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