BullMQ & Redis MCP Server
Manage BullMQ queues and monitor Redis from ChatGPT, Claude and Codex with Durabull. Inspect jobs, workers, cron schedules, alerts and failure evidence, then recover work with scoped tools.
Durabull exposes a Model Context Protocol (MCP) server on the same origin as the web app and API. The default consent bundle contains read scopes; a small set of non-destructive write tools sits behind dedicated scopes you approve explicitly.
{APP_BASE_URL}/mcpExample: https://app.durabull.io/mcp
MCP runs inside the unified Durabull API process. The server implements protocol 2026-07-28 with the stable TypeScript SDK v2, and supports older Streamable HTTP clients through a stateless initialize handshake. No transport session ID is required. Clients should reconnect after upgrading; session GET/DELETE return 405.
Connect your assistant
- Add a remote MCP server in your client with URL
{APP_BASE_URL}/mcp. - Complete the browser sign-in and consent flow when the client opens it.
- Start with
ping, thenlist_connections, and pass the chosenconnectionIdto queue tools. - Request write scopes only for the actions you intend to authorize. Retrying or promoting a job can run application side effects again; review the job before approving those actions.
In Durabull Cloud, use https://app.durabull.io/mcp. For a self-hosted instance, use its public
app origin. Clients that support remote OAuth can handle discovery and registration; the
authentication section describes the protocol for custom clients.
Claude, ChatGPT, and Codex
Connect the HTTPS endpoint above through Claude's connector settings or ChatGPT's Plugins → Add custom MCP server, then complete OAuth. Start with “Show my Durabull connections.” In MCP Apps hosts, list_connections opens the queue explorer with connection health, queues, jobs, logs, alerts and metrics. It supports light/dark themes, pagination, refresh and fullscreen when the host allows it. ChatGPT Work also exposes sidebar and conversation-panel entrypoints on supported surfaces. Claude Code is text-only; the tools and bundled skills work there without the embedded UI.
The portable plugin and Claude compatibility package live together at plugins/durabull. Install locally in Claude Code with claude --plugin-dir ./plugins/durabull. For Codex/ChatGPT desktop, use the repository marketplace at .agents/plugins/marketplace.json. These files are source packages, not claims of public-directory approval.
For self-hosting, generate both platform configurations from the same endpoint:
bun run mcp:plugin --endpoint https://queues.example.com/mcp --out /tmp/durabull-pluginThe plugin includes nine focused skills:
| Workflow | Try asking |
|---|---|
| Setup | “Connect Durabull and show my environments.” |
| Fleet health | “Which production queues need attention?” |
| Queue triage | “Why is the receipt queue backing up?” |
| Job inspection | “Find job 1042 and explain why it failed.” |
| Recurring schedules | “Show cron jobs, timezones and next runs.” |
| Redis health | “Is Redis memory pressure affecting our workers?” |
| Alert triage | “Why did this incident's notification fail?” |
| Job recovery | “Retry this failed job once.” |
| Queue control | “Pause this queue during maintenance.” |
The visual explorer includes exact job-ID search across queues, scheduler details, alert delivery attempts, incident breakdowns and rule inspection. Redis views show capacity, CPU, clients, evictions, rejected connections and history coverage; unavailable samples remain gaps. Alert triage also supports requested acknowledgement, resolution and timed rule snoozes.
UI buttons labeled “Ask to…” send a request to the assistant; data-changing tools retain their dedicated scopes and host approval flow. No browser credentials or direct Redis access are used.
What MCP provides
Every tool has a description, behavioral annotations (readOnlyHint, destructiveHint,
idempotentHint), and a JSON input schema. All tools except ping also have a JSON output schema
and return structuredContent alongside JSON text.
GA status: MCP is implemented on the unified deployment. Before announcing production use, complete the release checklist (staging smoke, config verification). Full GA doc set: GA index (ADR, compliance, security closure, validation evidence).
Read tools
| Tool | Scope | Purpose |
|---|---|---|
ping | mcp:discover | Transport smoke check |
list_connections | mcp:jobs:read | Connections visible to the principal |
list_queues | mcp:jobs:read | Queue inventory with live counts |
get_queue | mcp:jobs:read | Queue detail, counts, workers |
get_connection_overview | mcp:jobs:read (+ optional mcp:failures:read, mcp:diagnostics:read) | One-call health check across up to 100 queues |
list_jobs | mcp:jobs:read | Paginated job summaries with state/name/id filters |
find_job | mcp:jobs:read | Locate a job id across queues |
get_job | mcp:jobs:read | Safe job detail (redacted payload) |
get_job_logs | mcp:logs:read | Paginated job logs |
get_job_stacktraces | mcp:logs:read | Attempt-indexed stacktraces |
explain_job_failure | mcp:diagnostics:read + mcp:jobs:read (+ optional mcp:logs:read, mcp:failures:read) | Deterministic failure summary; reports skipped evidence |
list_scheduled_jobs | mcp:jobs:read | Job schedulers per queue or across the connection |
get_scheduled_job | mcp:jobs:read | One scheduler with template and failure stats |
get_workers | mcp:jobs:read | Worker snapshots |
get_queue_metrics | mcp:diagnostics:read | Throughput metrics window |
get_redis_health | mcp:diagnostics:read | Redis health sample, thresholds, bounded history |
get_failure_events | mcp:failures:read | Alert/failure events with filters |
get_alert_event | mcp:failures:read | Event detail with acknowledgement and deliveries |
get_alert_summary | mcp:failures:read | Open alert counts by queue and rule |
list_alert_rules | mcp:failures:read | Alert rules with state and open counts |
get_alert_rule | mcp:failures:read | One rule with recent events |
Write tools
Write tools are annotated as non-destructive. State-sensitive actions refuse the wrong state (conflict). They never change job payloads. Removing or purging jobs, obliterating queues, editing job data, and managing schedulers or rules have no MCP scope and cannot be granted.
| Tool | Scope | Purpose |
|---|---|---|
retry_job | mcp:jobs:retry | Re-enqueue a failed job |
promote_job | mcp:jobs:promote | Run a delayed job now |
pause_queue / resume_queue | mcp:queues:pause | Pause or resume a queue |
resolve_alert_event | mcp:failures:write | Manually resolve a firing alert |
acknowledge_alert_event | mcp:failures:write | Acknowledge on behalf of the signed-in user (user tokens only) |
unacknowledge_alert_event | mcp:failures:write | Clear an acknowledgement (user or service-account tokens) |
snooze_alert_rule / unsnooze_alert_rule | mcp:failures:write | Silence a rule for up to 7 days |
Resources and prompts
Resources use durabull:// URIs and are authorized with the same scopes as tools: durabull://server (catalog and granted scopes), durabull://connections, durabull://connections/{connectionId}/queues, durabull://connections/{connectionId}/queues/{queueName}, durabull://connections/{connectionId}/alerts.
ui://durabull/queue-explorer-v1.html is the static MCP App resource (text/html;profile=mcp-app). It requires authenticated discovery access and contains no customer data. Every data request from the app passes the normal tool authorization, redaction, rate limits and audit path.
Prompts package common workflows: triage_failed_jobs, investigate_queue_backlog, alert_activity_review, connection_health_check.
Authentication
Remote MCP clients authenticate with OAuth 2.1 bearer tokens issued by Durabull (Better Auth MCP plugin).
- Discover protected resource metadata at
GET /.well-known/oauth-protected-resource(or/api/auth/.well-known/oauth-protected-resource). - Register an OAuth client (
POST /api/auth/mcp/register). On internet-facing deployments, registration is unauthenticated (rate-limited only) — monitor volume at the edge and prefer pre-provisioned clients where possible. - Send the user through authorization code + PKCE at
/api/auth/mcp/authorizewithprompt=consentandresource={APP_BASE_URL}/mcp. - The user signs in (if needed) and approves scopes on
/consent. - Exchange the authorization code at
/api/auth/mcp/tokenwith the sameresourcevalue. - Call MCP with
Authorization: Bearer <access_token>.
Canonical resource URI:
{APP_BASE_URL}/mcpAPP_BASE_URL must match the public origin clients use to reach /mcp (including port in local dev). Missing operation scopes return 403 with a WWW-Authenticate: Bearer insufficient-scope challenge. Reconnect with the required scopes; tenant and service-account policy denials cannot be fixed by adding scopes alone.
See the MCP OAuth operator guide for HTTP status semantics and discovery endpoints.
Scopes
| Scope | Grants |
|---|---|
mcp:discover | Transport, ping, prompts, durabull://server |
mcp:jobs:read | Connection/queue/job/worker/scheduler reads |
mcp:logs:read | Logs and stacktraces |
mcp:failures:read | Alert events, rules, summaries |
mcp:diagnostics:read | Queue metrics and Redis health; required (with mcp:jobs:read) for explain_job_failure |
mcp:jobs:retry | retry_job |
mcp:jobs:promote | promote_job |
mcp:queues:pause | pause_queue, resume_queue |
mcp:failures:write | Resolve, acknowledge, and snooze alerts |
Authorization requests for the canonical MCP resource always include the five read scopes. Write scopes must be requested explicitly and appear on the consent screen marked "can make changes". Delegated users receive scopes from OAuth consent. Service accounts additionally require explicit policy bindings per tool/scope.
Upgrading from the initial diagnostic release: resolve_alert_event now requires mcp:failures:write. Re-authorize the client with that scope to keep using it; all read tools continue to work with existing tokens.
Safety controls
Authenticated callers still receive:
- Output redaction — known sensitive keys and URL/token patterns redacted;
_mcpSafety.redactionCountwhen redactions occur - Rate limits (production) — independent, continuously refilled budgets for setup/discovery (120 burst, 10/sec), ordinary reads (180 burst, 6/sec), diagnostics (90 burst, 3/sec), and writes (30 burst, 1/sec), keyed by validated user and OAuth client. HTTP ingress has a 600-request burst and 20/sec refill. A 429 reports the next-token delay in
Retry-After; it does not impose a fixed one-minute lockout. Limits are per process, and OAuth registration retains its separate limit. - Typed errors — tool failures return
{ error: { code, message } }withcodeinnot_found,validation_error,conflict,forbidden,internal_error; messages are redacted before they leave the server - Audit — best-effort
mcp_audit_eventrows for tool calls (may drop under backpressure; see runbook)
Operators: telemetry signals, SQL examples, and incident playbooks are in the MCP operations runbook.
Local development
Authless mode (DURABULL_AUTHLESS=true) is for local/private setups only. Never enable authless mode on Durabull Cloud. If authless is reachable from a network, set a strong MCP_AUTHLESS_BEARER_TOKEN — the non-production default token is for localhost dev only.
For monorepo dev with the Vite app, set APP_BASE_URL to the web origin (http://localhost:5173) so /mcp and OAuth discovery share one origin (the dev server proxies to the API). For API-only smoke scripts, use the API port (http://localhost:3001 or http://localhost:3000 in Docker).
For test commands and CI evidence, see validation evidence. Run mcp:e2e only against local or staging databases (see runbook).
Deployment and operations
MCP is always on when the Durabull API runs. Platform-specific deploy notes:
Post-deploy smoke and operations: MCP operations runbook.