# MCP Server: Let AI Agents Drive the Queue

Connect Claude, Cursor or any MCP client to bunqueue with one command. Agents get 73 tools to add jobs, schedule crons, retry failures and monitor queues.

Canonical: https://bunqueue.dev/guide/mcp/

---

import { Aside } from '@astrojs/starlight/components';
import McpArchitecture from '../../../components/McpArchitecture.astro';
import HttpHandlerFlow from '../../../components/HttpHandlerFlow.astro';

<div class="bq-wrap bq-hero">
  <span class="bq-eyebrow">guide · mcp</span>
  <h1 class="bq-hero-h1 bq-bench-h1">Your queue, driven by <em>agents.</em></h1>
  <p class="bq-hero-sub">bunqueue ships a built-in MCP server, so AI agents like Claude and Cursor can add jobs, schedule crons and monitor queues by talking to it. One command to connect, no code to write.</p>
</div>

MCP (Model Context Protocol) is the open standard that lets AI agents call external tools. bunqueue exposes its whole queue surface as 73 MCP tools, so anything you can do with the SDK or CLI, an agent can do from a chat prompt.

## Quick start

Three commands. `bunqueue-mcp` is a binary bundled inside the `bunqueue` package, and the MCP SDK is an optional peer dependency you install once:

```bash
bun add -g bunqueue                      # provides the bunqueue-mcp binary
bun add -g @modelcontextprotocol/sdk     # required by the MCP server only
claude mcp add bunqueue -- bunx --package=bunqueue bunqueue-mcp
```

Then just ask your agent:

> "Add a job to the emails queue"

It works immediately. No server to start, no database to configure. The queue runs inside the MCP process (embedded mode); set `DATA_PATH` in the server's `env` to persist jobs to a SQLite file, otherwise state lives in memory for the session.

## What can an agent do?

Some real prompts and the tools they trigger:

| You say | The agent calls |
|---------|-----------------|
| "Add 3 notification jobs: push, email, sms" | `bunqueue_add_jobs_bulk` |
| "Schedule session cleanup every hour" | `bunqueue_add_cron` |
| "Rate limit notifications to 50 per second" | `bunqueue_set_rate_limit` |
| "Why are jobs stuck? Check the emails queue" | `bunqueue_debug_queue` prompt, then stats and DLQ tools |
| "Retry everything in the dead letter queue" | `bunqueue_retry_dlq` |
| "Create a pipeline: validate payment, send receipt, update inventory" | `bunqueue_add_flow_chain` |

## Setup for other clients

Claude Desktop, Cursor and Windsurf all use the same JSON block. Config file locations: `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS), `%APPDATA%\Claude\claude_desktop_config.json` (Windows), `~/.config/Claude/claude_desktop_config.json` (Linux), or your editor's MCP settings.

```json
{
  "mcpServers": {
    "bunqueue": {
      "command": "bunx",
      "args": ["--package=bunqueue", "bunqueue-mcp"]
    }
  }
}
```

`bunx --package=bunqueue bunqueue-mcp` resolves the bundled binary straight from the `bunqueue` package, so it works even without a global install. It does not auto-install the optional `@modelcontextprotocol/sdk` peer dependency, install that yourself once.

## Two modes: embedded and TCP

<McpArchitecture />

| | Embedded (default) | TCP (remote) |
| --- | --- | --- |
| **How it works** | Queue runs inside the MCP process, in memory or direct SQLite | MCP server forwards to a running bunqueue server |
| **Setup** | Zero config | Set `BUNQUEUE_MODE=tcp` plus host/port |
| **Best for** | Local dev, single machine | Production queues shared by real workers |
| **Data** | In-memory, or a SQLite file via `DATA_PATH` | The remote server owns memory/SQLite or PostgreSQL storage |

To manage a production server, point the MCP server at it:

```json
{
  "mcpServers": {
    "bunqueue": {
      "command": "bunx",
      "args": ["--package=bunqueue", "bunqueue-mcp"],
      "env": {
        "BUNQUEUE_MODE": "tcp",
        "BUNQUEUE_HOST": "your-server.com",
        "BUNQUEUE_PORT": "6789",
        "BUNQUEUE_TOKEN": "your-auth-token"
      }
    }
  }
}
```

All 73 tools work in both modes.

## HTTP Handlers

Agents can schedule jobs, but they cannot run a long-lived worker process to execute them. HTTP handlers close that gap: the agent registers a URL on a queue, and the MCP server spawns an embedded worker that pulls each job and calls that URL. The HTTP response becomes the job result; a non-2xx response or timeout fails the job into the normal retry and dead letter flow.

```bash
$ claude

> Register a GET handler on "meteo" that calls the OpenWeather API

✓ bunqueue_register_handler
  Worker started. Jobs in "meteo" will be processed via GET.

> Create a cron that pushes a job every 10 seconds

✓ bunqueue_add_cron
  name: "check-meteo", repeatEvery: 10000

# Every 10s: cron creates a job → worker calls the API → response saved as result
```

<HttpHandlerFlow />

`bunqueue_register_handler` parameters:

| Parameter | Required | Description |
|-----------|----------|-------------|
| `queue` | Yes | Queue to attach the handler to |
| `url` | Yes | Endpoint to call for each job |
| `method` | Yes | `GET`, `POST`, `PUT`, or `DELETE` |
| `headers` | No | Custom HTTP headers (e.g. `Authorization`) |
| `body` | No | Fixed body for POST/PUT; defaults to the job's data as JSON |
| `timeoutMs` | No | Request timeout (default 30000, range 1000 to 120000) |

Use handlers when processing is just an HTTP call (API polling, webhook forwarding, health checks). For custom logic (database writes, file processing), deploy a normal [Worker](/guide/worker/) instead; the agent still orchestrates jobs and crons, the worker executes them.

<Aside type="caution">
  Handlers live inside the MCP server process. When the agent session ends, the process exits and all handlers stop. Re-register them in the next session if needed.
</Aside>

## Tool reference

73 tools covering the full queue surface. The agent discovers them automatically, so you rarely need this table; it is here so you know what is on the menu.

| Category | Tools | Examples |
|----------|-------|----------|
| Jobs: add and query | 11 | `add_job`, `add_jobs_bulk`, `get_job`, `get_job_result`, `wait_for_job` |
| Jobs: manage | 6 | `update_job_data`, `change_job_priority`, `move_to_delayed`, `discard_job` |
| Jobs: consume | 8 | `pull_job`, `ack_job`, `fail_job`, `job_heartbeat`, `extend_lock` |
| Queue control | 11 | `list_queues`, `pause_queue`, `drain_queue`, `clean_queue`, `get_job_counts` |
| Dead letter queue | 4 | `get_dlq`, `retry_dlq`, `purge_dlq`, `retry_completed` |
| Cron scheduling | 4 | `add_cron`, `list_crons`, `get_cron`, `delete_cron` |
| Rate limits and concurrency | 4 | `set_rate_limit`, `clear_rate_limit`, `set_concurrency`, `clear_concurrency` |
| Webhooks | 4 | `add_webhook`, `remove_webhook`, `list_webhooks`, `set_webhook_enabled` |
| Workers | 3 | `register_worker`, `unregister_worker`, `worker_heartbeat` |
| Monitoring | 11 | `get_stats`, `get_queue_stats`, `get_job_logs`, `get_prometheus_metrics` |
| Workflows | 4 | `add_flow`, `add_flow_chain`, `add_flow_bulk_then`, `get_flow` |
| HTTP handlers | 3 | `register_handler`, `unregister_handler`, `list_handlers` |

Every tool name is prefixed `bunqueue_`. All tools return structured errors (`isError: true` with a plain message, never a stack trace).

### Prompts and resources

The server also ships 3 pre-built diagnostic prompts, `bunqueue_health_report` (full health check with OK/WARNING/CRITICAL levels), `bunqueue_debug_queue` (deep dive on one queue) and `bunqueue_incident_response` (a triage playbook for "jobs not processing"), plus 5 read-only resources the agent can read at any time: `bunqueue://stats`, `bunqueue://queues`, `bunqueue://crons`, `bunqueue://workers`, `bunqueue://webhooks`.

## Environment variables

| Variable | Default | Description |
|----------|---------|-------------|
| `BUNQUEUE_MODE` | `embedded` | `embedded` or `tcp` |
| `BUNQUEUE_HOST` | `localhost` | TCP server host |
| `BUNQUEUE_PORT` | `6789` | TCP server port |
| `BUNQUEUE_TOKEN` | (none) | Auth token for TCP |
| `DATA_PATH` | (none, in-memory) | SQLite path for embedded mode (`BUNQUEUE_DATA_PATH` and `BQ_DATA_PATH` take priority). Unset means jobs are not persisted |

## Troubleshooting

**`bunx bunqueue-mcp` returns a 404.** `bunqueue-mcp` is not a standalone npm package, it is a binary inside `bunqueue`. Install `bunqueue` first, or use `bunx --package=bunqueue bunqueue-mcp` which always resolves correctly.

**The server exits with `requires "@modelcontextprotocol/sdk"`.** Since v2.8.1 the MCP SDK is an optional peer dependency (so queue-only users get a 94% smaller install). Install it once where the server runs: `bun add @modelcontextprotocol/sdk`.

**The agent does not see the tools.** Restart your MCP client, check the config JSON is valid, then run `bunx --package=bunqueue bunqueue-mcp` manually to see the actual error.

**Jobs sit in `waiting` forever.** Nothing is processing the queue. Ask the agent to register an HTTP handler, or run a [Worker](/guide/worker/).