Skip to main content
Version: Next

Webhooks Integration

This guide explains how to use the webhook endpoint, wire up handlers, and run the system locally or with a queue backend.

See also

For endpoint shape and payload examples, see ClickUp Webhook Endpoint.

Event processing modes

The endpoint converts the incoming DTO to a domain event ClickUpWebhookEvent and forwards it to an Event Sink selected by QUEUE_BACKEND.

  • QUEUE_BACKEND=local
    • Uses LocalEventSink, dispatches directly to in-process handlers via the registry.
  • QUEUE_BACKEND=<backend> (e.g. kafka, redis)
    • Uses QueueEventSink from abstract-backend to publish to topic clickup.webhooks.
    • A separate consumer process handles the events.

Environment variables

  • QUEUE_BACKEND
    • local for in-process handling (default).
    • Any other supported backend name (provided by the abstract-backend plugin) enables queue mode.
  • CLICKUP_WEBHOOK_HANDLER_MODULES
    • Comma-separated module list to import at startup. Importing registers handlers.
    • Example: CLICKUP_WEBHOOK_HANDLER_MODULES="myproj.clickup_handlers.oop,myproj.clickup_handlers.func"

Writing handlers

You can author handlers using either OOP or decorator style. Both register into the central registry and work in both modes.

OOP style

from clickup_mcp.web_server.event.handler.oop import BaseClickUpWebhookHandler
from clickup_mcp.web_server.event.models import ClickUpWebhookEvent

class MyHandler(BaseClickUpWebhookHandler):
async def on_task_status_updated(self, event: ClickUpWebhookEvent) -> None:
# your logic
...

async def on_task_created(self, event: ClickUpWebhookEvent) -> None:
...

Decorator style

from clickup_mcp.web_server.event.handler.decorators import clickup_event
from clickup_mcp.web_server.event.models.enums import ClickUpWebhookEventType
from clickup_mcp.web_server.event.models import ClickUpWebhookEvent, ClickUpWebhookContext

@clickup_event(ClickUpWebhookEventType.TASK_STATUS_UPDATED)
async def handle_status(evt: ClickUpWebhookEvent, ctx: ClickUpWebhookContext) -> None:
...

@clickup_event.task_created
async def handle_created(evt: ClickUpWebhookEvent, ctx: ClickUpWebhookContext) -> None:
...

Running locally

export QUEUE_BACKEND=local
export CLICKUP_WEBHOOK_HANDLER_MODULES="myproj.clickup_handlers.oop,myproj.clickup_handlers.func"

# Start your server (example CLI)
clickup-mcp-server --integrated --transport sse --port 8000

Running with a queue

Install and configure an abstract-backend queue plugin (e.g. Kafka/Redis) and set its env variables as required by the plugin.

  1. Webhook server (publishes to queue):
export QUEUE_BACKEND=kafka
export CLICKUP_WEBHOOK_HANDLER_MODULES="myproj.clickup_handlers.oop,myproj.clickup_handlers.func"
# plus plugin-specific env vars like brokers, credentials, etc.

clickup-mcp-server --integrated --transport sse --port 8000
  1. Consumer (subscribes and dispatches):
export QUEUE_BACKEND=kafka
export CLICKUP_WEBHOOK_HANDLER_MODULES="myproj.clickup_handlers.oop,myproj.clickup_handlers.func"

clickup-webhook-consumer --queue-backend kafka

Pluggable queue backends (abstract-backend)

This project uses the Python library abstract-backend to load a message queue backend at runtime. That means you can quickly swap the queue implementation without code changes.

  • Switching backends is just package management + environment variables:
    • Deprecate current backend: pip uninstall <message-queue-backend>
    • Install a new backend: pip install <message-queue-backend>
    • Point the system to it: export QUEUE_BACKEND=<backend-name>
    • Provide any backend-specific environment variables (brokers, DSNs, creds), per the backend plugin.

Quick switch example (Kafka → Redis)

# Remove Kafka backend plugin
pip uninstall abe-kafka

# Install Redis backend plugin
pip install abe-redis

# Tell the system to use Redis
export QUEUE_BACKEND=redis

# (Optional) Backend-specific envs, e.g. for Redis
export REDIS_URL=redis://localhost:6379/0

# Start server and consumer as usual
clickup-mcp-server --integrated --transport sse --port 8000
clickup-webhook-consumer --queue-backend "$QUEUE_BACKEND"

Notes:

  • QUEUE_BACKEND=local keeps everything in-process (no external queue required).
  • Any non-local value activates queue mode using the installed abstract-backend plugin.
  • Backend package names above are examples; consult your chosen plugin for exact names and environment variables.
See more
  • abstract-backend: A lightweight plugin framework that loads message queue backends at runtime. It exposes a simple publish/consume interface and selects the backend via environment (e.g., QUEUE_BACKEND).
  • abe-redis: A Redis-backed implementation for abstract-backend providing message queue semantics over Redis. Ideal for local dev or lightweight deployments.

Event types

Supported ClickUpWebhookEventType values include all task/list/folder/space/goal/keyResult events mirrored from ClickUp docs and fixtures, for example:

  • Task: taskCreated, taskUpdated, taskDeleted, taskStatusUpdated, taskAssigneeUpdated, taskDueDateUpdated, taskTagUpdated, taskMoved, taskCommentPosted, taskCommentUpdated, taskTimeEstimateUpdated, taskTimeTrackedUpdated, taskPriorityUpdated
  • List: listCreated, listUpdated, listDeleted
  • Folder: folderCreated, folderUpdated, folderDeleted
  • Space: spaceCreated, spaceUpdated, spaceDeleted
  • Goal: goalCreated, goalUpdated, goalDeleted
  • Key Result: keyResultCreated, keyResultUpdated, keyResultDeleted