Skip to main content
Glama
tommypj

mcp-job-queue

by tommypj

mcp-job-queue

A production MCP server + worker daemon for long-running jobs: durable SQLite queue, isolated child-process execution, per-job timeouts, retries with backoff, and backpressure.

LLM agents are great at deciding to do work and terrible at holding it. The moment a tool call kicks off something slow — render a video, transcode audio, crawl a site, call a flaky API — an in-process tool blocks the conversation, and if the process dies the work vanishes with no record. mcp-job-queue is the durable backbone for that: agents submit_job and get an id back instantly; a separate worker daemon runs each job in its own OS process under a hard timeout, retries transient failures, bounds concurrency, and survives restarts. It's the difference between "the agent ran a script" and "the agent dispatched a job to a system that will actually finish it."

Node TypeScript License MCP


Features

  • Durable queue — jobs live in SQLite (WAL via the built-in node:sqlite, zero native deps). Submit, crash, restart — nothing is lost.

  • Decoupled server & worker — the MCP server only enqueues/reads; the worker only claims/runs. Either restarts independently; they meet only at the database file.

  • Isolated execution — every job runs in its own forked child process, so a handler that hangs, leaks, or segfaults can't take down the worker.

  • Hard timeouts — a per-job wall-clock timeout that ends in a real SIGKILL, not a hopeful AbortController the job can ignore.

  • Retries with backoff — failed jobs are re-queued with exponential backoff until maxAttempts is reached, then fail terminally.

  • Backpressure — a maxConcurrency cap means a flood of submissions can never exhaust CPU/memory; excess work waits in the queue.

  • Crash recovery — on startup the worker re-queues jobs orphaned mid-run by a previous crash (or fails them if out of attempts).

  • Allowlisted handlers — clients can only submit a registered job type; there is no arbitrary command execution. This is the worker's security boundary.

  • Typed errors & JSON logs — tools return structured {code, message, retryable} instead of throwing; the worker emits one structured log line per job.


Related MCP server: Awaitless

Architecture

        submit_job / get_job / list_jobs / cancel_job / get_stats
 ┌────────────┐                          ┌──────────────────────┐
 │ MCP client │ ──stdio──▶ ┌──────────┐  │   worker daemon       │
 │ (Claude…)  │            │ MCP       │  │  ┌────────────────┐   │
 └────────────┘            │ server    │  │  │ poll + claim   │   │
                           │ (enqueue/ │  │  │  (BEGIN        │   │
                           │  read)    │  │  │   IMMEDIATE)   │   │
                           └────┬──────┘  │  └───────┬────────┘   │
                                │         │          │ fork       │
                                ▼         │          ▼            │
                       ┌───────────────────────┐  ┌────────────┐  │
                       │   SQLite (WAL) queue   │  │ child proc │  │
                       │  jobs: state machine   │◀─│  handler   │  │
                       └───────────────────────┘  │ (timeout/  │  │
                                ▲                  │  SIGKILL)  │  │
                                │   artifact +     └─────┬──────┘  │
                                │   result/status        │        │
                                └────────────────────────┘  ▼      │
                                                      artifacts/   │
                                                      <id>.json    │
                                                      └────────────┘

The queue is the only shared state. The server process and the worker process never talk directly — they coordinate entirely through atomic SQLite transactions.


Production handling, not a demo

Five patterns pulled straight from the source.

1. Atomic claim — a job goes to exactly one worker

The claim is wrapped in BEGIN IMMEDIATE, which takes SQLite's write lock up front. Even with several workers polling the same database, no two can grab the same job.

// db.ts
this.db.exec("BEGIN IMMEDIATE");
try {
  const candidate = this.db
    .prepare(
      `SELECT id FROM jobs WHERE status = 'queued' AND next_run_at <= ?
       ORDER BY priority DESC, created_at ASC LIMIT 1`,
    )
    .get(now);
  if (!candidate) {
    this.db.exec("COMMIT");
    return undefined;
  }
  this.db
    .prepare(`UPDATE jobs SET status = 'running', attempts = attempts + 1, ... WHERE id = ?`)
    .run(/* ... */ candidate.id);
  this.db.exec("COMMIT");
  return this.get(candidate.id);
} catch (err) {
  this.db.exec("ROLLBACK");
  throw err;
}

Why it matters: this is what makes the queue safe to scale horizontally and safe against double-execution — the hardest correctness property a job queue has to get right.

2. Isolation with a real timeout kill

Each job is a separate process; the timeout ends in SIGKILL, so even a tight CPU loop that ignores cooperative cancellation is stopped.

// runner.ts
const child = spawn(command, [...baseArgs, childScript], { stdio: ["pipe", "pipe", "pipe"] });
const onAbort = () => {
  child.kill("SIGKILL");
  finish({ ok: false, error: "job exceeded timeout and was killed", timedOut: true });
};
signal.addEventListener("abort", onAbort, { once: true });
child.stdin.write(JSON.stringify({ type: job.type, payload: safeParse(job.payload) }));

Why it matters: a worker that can't guarantee it reclaims resources from a stuck job will slowly grind to a halt. Process isolation + SIGKILL is the only reliable answer.

3. Retry with exponential backoff, or terminal failure

On failure the queue decides — re-queue with growing backoff while attempts remain, otherwise fail terminally. One method, one source of truth.

// db.ts
if (job.attempts < job.max_attempts) {
  const backoff = this.backoffMs(job.attempts); // base * 2^(attempts-1) + jitter
  this.db
    .prepare(`UPDATE jobs SET status = 'queued', error = ?, next_run_at = ? ... WHERE id = ?`)
    .run(errorMessage, now + backoff, /* ... */ id);
  return { job: this.get(id)!, retried: true };
}
this.db
  .prepare(`UPDATE jobs SET status = 'failed', error = ?, finished_at = ? ... WHERE id = ?`)
  .run(errorMessage, now, /* ... */ id);
return { job: this.get(id)!, retried: false };

4. Crash recovery on startup

A worker that dies mid-job leaves rows stuck in running. On boot we reclaim them — re-queue if attempts remain, fail otherwise — so a crash never silently strands work.

// db.ts — called once when the worker starts
recoverOrphaned(): number {
  const orphans = this.db.prepare("SELECT * FROM jobs WHERE status = 'running'").all();
  for (const job of orphans) {
    if (job.attempts < job.max_attempts) /* re-queue */;
    else /* terminal fail: "orphaned after worker crash" */;
  }
  return orphans.length;
}

Why it matters: most "simple" queues skip this and quietly lose in-flight jobs on every deploy or crash. Recovery is what makes "durable" actually true.

5. Allowlisted handlers — no arbitrary execution

A client can only submit a type that exists in the handler registry. There is no path from an MCP message to an arbitrary shell command.

// handlers.ts
export const HANDLERS: Record<string, JobHandler> = {
  echo: async (payload) => ({ echoed: payload }),
  wait: async (payload) => {
    /* sleep — exercise timeouts */
  },
  hash: async (payload) => ({ digest: sha256(payload.text) }),
  fibonacci: async (payload) => ({ value: fib(payload.n).toString() }),
  fail: async (payload) => {
    throw new Error(/* exercise retries */);
  },
};

Why it matters: "let the agent run a job" must never mean "let the agent run anything." Real work (render/transcode/scrape) is added as a new handler here — the queue machinery around it never changes.


Quickstart

Requires Node ≥ 22 (for the built-in node:sqlite).

git clone https://github.com/tommypj/mcp-job-queue.git
cd mcp-job-queue
npm install
npm run build

The system is two processes that share a queue file. Start the worker:

npm run worker        # node --experimental-sqlite dist/worker.js

Then run the MCP server (normally launched by your MCP client, see below):

npm run server        # node --experimental-sqlite dist/server.js  (stdio)

The --experimental-sqlite flag is required on Node 22 and accepted (harmless) on Node 24+.

For local hacking without a build, use the dev scripts: npm run dev:worker and npm run dev:server (run TypeScript directly via tsx).


Use it in Claude Desktop / Claude Code

Add this to claude_desktop_config.json (mirrors examples/claude_desktop_config.json) and run the worker separately:

{
  "mcpServers": {
    "job-queue": {
      "command": "node",
      "args": ["--experimental-sqlite", "/absolute/path/to/mcp-job-queue/dist/server.js"],
      "env": {
        "JOBQ_DB_PATH": "/absolute/path/to/queue.db",
        "JOBQ_ARTIFACT_DIR": "/absolute/path/to/artifacts"
      }
    }
  }
}

Config file locations:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

  • Claude Code: claude mcp add job-queue -- node --experimental-sqlite /absolute/path/to/mcp-job-queue/dist/server.js

The server and the worker must point at the same JOBQ_DB_PATH.


Tools reference

submit_job(type, payload?, priority?, maxAttempts?, timeoutMs?)

Enqueue a job; returns it in status queued. type must be a registered handler (echo, wait, hash, fibonacci, fail). timeoutMs/maxAttempts are clamped to safe ceilings.

  • Errors: UNKNOWN_JOB_TYPE.

// submit_job { "type": "hash", "payload": { "text": "hello world" } }
{
  "id": "081beee6-…",
  "type": "hash",
  "status": "queued",
  "attempts": 0,
  "maxAttempts": 3,
  "timeoutMs": 30000,
  "payload": { "text": "hello world" },
}

get_job(id)

Fetch one job: status, result, error, artifact path, timestamps. Errors: JOB_NOT_FOUND.

list_jobs(status?, limit?)

Recent jobs (newest first), optionally filtered by status (queued|running|succeeded|failed|cancelled).

cancel_job(id)

Cancel a still-queued job. Errors: JOB_NOT_FOUND, NOT_CANCELLABLE (running/finished jobs can't be cancelled).

get_stats()

Queue health: counts by status, total, age of the oldest queued job, and active config.

{
  "countsByStatus": { "queued": 0, "running": 1, "succeeded": 12, "failed": 1, "cancelled": 0 },
  "total": 14,
  "oldestQueuedAgeMs": null,
  "config": {
    "maxConcurrency": 4,
    "defaultTimeoutMs": 30000,
    "registeredHandlers": ["echo", "wait", "hash", "fibonacci", "fail"],
  },
}

Configuration

Environment variables, all prefixed JOBQ_ (see .env.example). The server and worker must share JOBQ_DB_PATH.

Variable

Default

Description

JOBQ_DB_PATH

~/.mcp-job-queue/queue.db

SQLite (WAL) queue file

JOBQ_ARTIFACT_DIR

~/.mcp-job-queue/artifacts

Where result artifacts are written

JOBQ_MAX_CONCURRENCY

4

Max jobs a worker runs at once (backpressure)

JOBQ_POLL_INTERVAL_MS

250

Idle poll interval

JOBQ_DEFAULT_TIMEOUT_MS

30000

Default per-job timeout

JOBQ_MAX_TIMEOUT_MS

600000

Hard ceiling for a per-job timeout

JOBQ_DEFAULT_MAX_ATTEMPTS

3

Default attempts incl. the first

JOBQ_MAX_ATTEMPTS_CEILING

10

Hard ceiling for attempts

JOBQ_RETRY_BASE_DELAY_MS

500

Base delay for exponential backoff

JOBQ_LOG_LEVEL

info

debug / info / warn / error


Testing

npm test            # 30 tests (vitest), incl. a real forked-child integration test
npm run lint        # eslint + prettier --check

Coverage targets the production paths: atomic claim + priority ordering, retry-vs-terminal transitions, orphan recovery, cancel rules, queue stats, the worker pool (success, timeout-kill, retry, and a strict concurrency-cap assertion), every handler, the real fork runner (spawns a child, captures failure, SIGKILLs on overrun), and the full MCP tool surface through an in-memory client.


Design decisions

  • node:sqlite, not better-sqlite3 — the built-in module means zero native compilation (no node-gyp), which makes the repo trivial to clone and run. WAL mode gives concurrent readers while the worker writes.

  • Two processes, not one — decoupling the MCP server from the worker is the core design choice: it lets the agent-facing surface and the compute surface scale, deploy, and crash independently. The queue file is the contract.

  • Child process per job, not a worker thread — a separate OS process is the only isolation strong enough to survive native crashes and guarantee a timeout via SIGKILL. Worker threads share a heap and can't be force-killed cleanly.

  • Handlers are an allowlist — no arbitrary command execution by design; this is the security boundary and the extension point in one. Plugging in real work is a one-function change.

  • Errors as values — tools return typed {code, message, retryable} so an agent can branch programmatically, and the server never crashes on bad input.

  • Cancelling running jobs is intentionally out of scope (v1) — it would require the worker to poll a cancel flag and coordinate the kill; queued-cancel covers the common case cleanly. Documented rather than half-built.

  • Deterministic jitter — retry backoff uses a small deterministic jitter so tests are reproducible while retries still spread; true randomness isn't needed for correctness here.


License

MIT © Dan Tomescu. See LICENSE.

Available Tools

5 tools
cancel_jobCancel a jobA

Cancel a job that is still queued. Running or already-finished jobs cannot be cancelled and return a NOT_CANCELLABLE error.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesThe job id to cancel.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations, so description discloses cancellation constraint and error for invalid states. Could add idempotency or success side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two efficient sentences, front-loaded with primary action then limitation, no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Adequate but missing success behavior (e.g., confirmation, status change). No output schema, so return value is unclear.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with clear parameter description. Description adds no extra meaning beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clear verb 'cancel' with specific resource 'job' and condition 'still queued'. Explicitly distinguishes from siblings like get_job, submit_job, etc.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States when to use (queued jobs) and when not (running/finished) with error behavior. No explicit alternative tool mention, but context suffices.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_jobGet a jobA

Fetch a single job by id, including its status, result, and artifact path.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesThe job id returned by submit_job.

TDQS

A3.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description must carry behavioral burden. It only mentions returned fields, not whether the operation is read-only, safe, or requires authentication. Lacks disclosure of side effects or error scenarios.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is a single concise sentence, front-loaded with the core action. No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple get-by-id tool with one parameter and no output schema, the description covers the main purpose and key returned fields. Could mention synchronization or response format, but sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with one parameter described. The description adds no extra meaning beyond the schema, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool fetches a single job by id, with a specific verb and resource. It distinguishes from siblings like list_jobs and submit_job.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit when-to-use or when-not-to-use guidance. The description implies usage for retrieving a specific job, but does not contrast with alternatives like list_jobs or cancel_job.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_statsQueue statsA

Return queue health: job counts by status, total, age of the oldest queued job, and the active configuration. No sensitive data.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden for behavioral disclosure. It explicitly states 'No sensitive data,' indicating privacy concern. However, it does not disclose other traits like idempotency, caching, or whether the data is real-time. The read-only nature is implied but not explicitly stated. Overall adequate but missing some detail.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description consists of two concise sentences that front-load the core purpose and then add a critical note about data sensitivity. Every word is necessary; no redundancy or filler. It is optimally sized for an agent to quickly understand the tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description must explain return values, which it does thoroughly: job counts by status, total, age of oldest queued job, and active configuration. This covers all expected outputs for a queue health tool. No gaps are apparent given the tool's simplicity and the absence of parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has no parameters (100% schema coverage by default). The description adds no parameter info because none is needed. The tool's purpose is fully explained without requiring parameter elaboration, and the baseline of 3 is exceeded due to the simplicity and clarity.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns queue health metrics including job counts by status, total, age of oldest queued job, and active configuration. The verb 'Return' and specific resource 'queue health' make purpose unambiguous, and it distinguishes from sibling tools (cancel_job, get_job, list_jobs, submit_job) which focus on individual jobs or operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for obtaining an overview of queue health but provides no explicit guidance on when to use this tool versus alternatives like list_jobs or get_job. No when-not-to-use conditions are mentioned, leaving the agent to infer context from the tool name and sibling list.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_jobsList jobsA

List recent jobs (newest first), optionally filtered by status.

ParametersJSON Schema
NameRequiredDescriptionDefault
statusNoFilter by status.
limitNoMax rows (default 50).

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the burden. It mentions sorting and optional filter but lacks details on pagination limits, result format, or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single concise sentence that efficiently conveys the core information without extraneous words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple list operation with no output schema, the description covers key aspects (ordering, filtering) but misses details on result structure and handling large result sets beyond the limit parameter.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with descriptions for both parameters; the tool description adds no extra meaning beyond what the schema provides, so baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists jobs in newest-first order with optional status filtering, distinguishing it from sibling tools like submit_job or cancel_job.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for listing jobs but does not specify when to prefer this over get_job (which retrieves a single job) or other sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

submit_jobSubmit a jobA

Enqueue a job for asynchronous execution by the worker. Returns the created job (status 'queued'). Valid type values are the registered handlers: echo, wait, hash, fibonacci, fail. The job runs in an isolated process under a timeout, with automatic retries.

ParametersJSON Schema
NameRequiredDescriptionDefault
typeYesJob type; must be a registered handler name.
payloadNoArbitrary JSON object passed to the handler.
priorityNoHigher runs first (default 0).
maxAttemptsNoTotal attempts incl. the first (default 3).
timeoutMsNoPer-job wall-clock timeout in ms (default 30000).

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden. It discloses key behaviors: asynchronous, isolated process, timeout, automatic retries, and return value. However, it does not mention error handling or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with main action, then return, then details. No extraneous words or repetition. Highly efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema and 5 parameters, the description covers essential aspects: async behavior, timeout, retries. Paired with full schema coverage, it is complete for an agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, baseline 3. The description adds value by listing valid 'type' values explicitly and explaining 'payload' as arbitrary JSON. For other params, it provides minimal extra context beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses clear verb 'enqueue' and resource 'job', and distinguishes from siblings by specifying asynchronous execution and return of created job with status 'queued'. It also lists valid handler types, making the tool's scope unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for async execution with valid types, but lacks explicit guidance on when to use this tool versus alternatives (e.g., cancel_job, list_jobs) and does not mention when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv0.1.0
    • First observedcancel_job
    • First observedget_job
    • First observedget_stats
    • First observedlist_jobs
    • First observedsubmit_job

TDQS

A4.2/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a distinct and clear purpose: submitting, getting, listing, canceling jobs, and fetching queue statistics. No overlap or ambiguity.

Naming Consistency5/5

All tool names follow the verb_noun pattern (cancel_job, get_job, get_stats, list_jobs, submit_job) with consistent snake_case styling.

Tool Count5/5

With 5 tools covering essential job queue operations, the count is well-scoped and not excessive or insufficient.

Completeness5/5

The tool set covers all fundamental CRUD-like operations for a job queue: submit, get, list, cancel, and health statistics. No obvious gaps.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Durable MCP server for managing long-running jobs locally, over SSH, or on Slurm clusters. Jobs survive client disconnects and return exit codes, bounded logs, and JSON artifacts.
    11
    41 PyPI
    1
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables agents to submit and manage persistent, dependency-aware task graphs with immutable artifacts, resource reservations, durable event streaming, and retryable process execution over MCP.
    12
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables MCP clients to run Google Antigravity CLI (agy) as durable, detached asynchronous jobs with a permission gate and broker-computed verdicts that do not trust agy's own exit code.
    9
    272 npm
    MIT