MCP Server

August 20, 2026 ยท View on GitHub

PgQueuer ships an optional Model Context Protocol (MCP) server that gives AI agents read-only access to your queue state, statistics, and schedules. All queries are predefined; the server does not accept arbitrary SQL.

Installation

=== "uv"

```bash
uv add pgqueuer[mcp]
```

=== "pip"

```bash
pip install pgqueuer[mcp]
```

This pulls in mcp>=1.0 and asyncpg>=0.30.0.

Quick start

The server connects to PostgreSQL using the same libpq environment variables you already use (PGHOST, PGPORT, PGUSER, PGPASSWORD, PGDATABASE), or a full DSN from PGQUEUER_DSN/PGDSN. Pool sizing and connection extras come from PGQUEUER_* variables (PGQUEUER_POOL_MIN_SIZE, PGQUEUER_POOL_MAX_SIZE, PGQUEUER_CONNECT_TIMEOUT, PGQUEUER_APPLICATION_NAME; defaults: min 1, max 5):

=== "uv"

```bash
uv run python -m pgqueuer.adapters.mcp
```

=== "pip"

```bash
python -m pgqueuer.adapters.mcp
```

This starts a stdio-based MCP server that any MCP client (Claude Desktop, Claude Code, Cursor, etc.) can connect to.

Claude Desktop / Claude Code

Add to your MCP client configuration:

=== "uv"

```json
{
  "mcpServers": {
    "pgqueuer": {
      "command": "uv",
      "args": ["run", "python", "-m", "pgqueuer.adapters.mcp"],
      "env": {
        "PGHOST": "localhost",
        "PGPORT": "5432",
        "PGUSER": "myuser",
        "PGPASSWORD": "mypassword",
        "PGDATABASE": "mydb"
      }
    }
  }
}
```

=== "pip"

```json
{
  "mcpServers": {
    "pgqueuer": {
      "command": "python",
      "args": ["-m", "pgqueuer.adapters.mcp"],
      "env": {
        "PGHOST": "localhost",
        "PGPORT": "5432",
        "PGUSER": "myuser",
        "PGPASSWORD": "mypassword",
        "PGDATABASE": "mydb"
      }
    }
  }
}
```

Explicit DSN

If you prefer a connection string over environment variables, use the factory function directly:

from pgqueuer.adapters.mcp.server import create_mcp_server

server = create_mcp_server(dsn="postgresql://user:pass@host:5432/mydb")
server.run(transport="stdio")

Custom table prefix or schema

If you use PGQUEUER_PREFIX or PGQUEUER_SCHEMA to namespace your tables, pass custom settings:

from pgqueuer.adapters.mcp.server import create_mcp_server
from pgqueuer.adapters.persistence.qb import DBSettings

# reads PGQUEUER_PREFIX / PGQUEUER_SCHEMA
server = create_mcp_server(settings=DBSettings())
server.run(transport="stdio")

Available tools

All tools are read-only and use predefined static SQL queries. They cannot modify queue data.

Queue overview

ToolDescription
queue_sizeCurrent job counts grouped by entrypoint, status, and priority. Start here for a quick health check.
queue_table_infoBrowse raw queue rows with pagination. Shows payloads, headers, worker assignments, and timestamps.

Throughput & statistics

ToolDescription
queue_statsPer-second time-series of job state transitions. Supports a time-window filter (period).
throughput_summaryHigh-level totals per entrypoint and status. Easier to read than queue_stats when you just want aggregate counts.

Failure investigation

ToolDescription
failed_jobsRecent jobs that ended with an exception, including full Python tracebacks as JSON.

Worker health

ToolDescription
active_workersWhich workers are alive, how many jobs each holds, and their heartbeat timestamps.
stale_jobsJobs stuck in picked status with a heartbeat older than a configurable threshold. Indicates dead or hung workers.
queue_ageAge of the oldest waiting job per entrypoint. Measures backlog depth and whether workers are keeping up.

Schedules

ToolDescription
schedulesAll cron-based recurring task definitions with next/last run times and status.

Audit & schema

ToolDescription
queue_logFull event log of every job state transition (enqueue, pick, complete, fail, cancel).
schema_infoPgQueuer table metadata: existence, LOGGED/UNLOGGED durability, disk size, estimated row counts.

Programmatic usage

The create_mcp_server factory returns a FastMCP instance with no module-level globals, so you can create multiple servers or embed one in a larger application:

from pgqueuer.adapters.mcp.server import create_mcp_server

# All parameters are optional; the DSN comes from PGQUEUER_DSN/PGDSN,
# else asyncpg reads libpq env vars. Pool sizing from PGQUEUER_* env vars.
server = create_mcp_server()

# Or pass an explicit DSN and/or custom settings
server = create_mcp_server(dsn="postgresql://...")

# Pool sizing/timeouts can also be passed explicitly
from pgqueuer.domain.settings import ConnectionSettings

server = create_mcp_server(
    dsn="postgresql://...",
    connection_settings=ConnectionSettings(pool_min_size=2, pool_max_size=10),
)

server.run(transport="stdio")

Architecture

The MCP server lives in the adapter layer (pgqueuer/adapters/mcp/) and follows the same hexagonal architecture as the rest of PgQueuer:

  • server.py: create_mcp_server() factory, PgQueuerDatabase wrapper, all tool registrations.
  • __main__.py: python -m pgqueuer.adapters.mcp entry point.
  • All SQL queries are defined as build_* methods in pgqueuer/adapters/persistence/qb.py: no SQL is constructed at runtime.
  • The server uses an asyncpg connection pool managed by FastMCP's lifespan.