MCP Longjobs

Communauté Cartes, voyage et météo

Durable, resumable MCP operations: background tool execution with progress polling, mid-flight input, cancellation and resumable chunked file transfers.

Installation

Les étapes d'installation sont dans la documentation ci-dessous. Documentation

Documentation

Tirée du README du projet sur GitHub, actualisée chaque semaine. Les liens ouvrent GitHub.

Sommaire
  1. mcp-longjobs
  2. The problem
  3. What you get
  4. Packages (subpath exports)
  5. Design notes
  6. Status
  7. Quickstart
  8. Development
  9. Contributing
  10. License

mcp-longjobs

Durable, resumable operations for MCP — long-running tasks and large files that survive timeouts, disconnects, and client restarts. On every client, today.

中文文档

The problem

Three things break every MCP server that does real work:

  • Long-running tool calls time out. Clients impose per-call timeouts (often 10–60s). A crawl, a build, a batch job fails — and the model's "retry" restarts the whole operation from scratch.
  • Failures are unrepairable. A failed call returns a freeform error, so the model guesses: retry blindly, or give up. It can't fix one parameter and resume.
  • Large files have no transfer story. Binary content is base64-in-JSON (33% overhead, hard message-size caps) or a bare URL with zero conventions — no chunking, no resume, no integrity checks.

The 2026-07-28 MCP spec added Tasks — async execution with mid-flight input and durable handles. But no client supports it yet, and the spec requires servers to refuse tasks for clients that didn't opt in. Every long-running server therefore needs a fallback path that works on today's clients. That is this package.

What you get

import { z } from "zod";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { JsonFileSessionStore, withTasks, withFileTransfer, asToolRegistrar } from "mcp-longjobs";

const mcp = new McpServer({ name: "my-server", version: "1.0.0" });
const registrar = asToolRegistrar(mcp);
const store = new JsonFileSessionStore("./state/sessions.json");

const tasks = withTasks(registrar, { store });

tasks.taskTool("crawl-site", {
  description: "Crawl a site and produce a report (takes minutes)",
  inputSchema: { url: z.string(), maxPages: z.number().default(50) },
}, async (args, ctx) => {
  for (const page of pages) {
    if (ctx.signal.aborted) throw new Error("cancelled");
    await ctx.progress(`Crawled ${page.url}`, done / total);

    if (needsConfirmation(page)) {
      const answer = await ctx.needInput({ prompt: `Include ${page.url}?`, choices: ["yes", "no"] });
      if (answer === "no") continue;
    }
  }
  return { summary, reportPath }; // small result for the model; big artifacts go through file transfer
});

withFileTransfer(registrar, { store, storageDir: "./state/blobs" });

What the model experiences on today's clients (no Tasks support required):

  1. crawl-site returns instantly with a taskId and instructions to poll durable_task_get — no more timeouts.
  2. Polls show live progress: { "status": "working", "progress": { "message": "Crawled /pricing", "fraction": 0.4 } }.
  3. Mid-flight questions pause the task as input_required; the model answers via durable_task_respond and the task continues where it stopped.
  4. Client crash? New session? durable_task_get with the same taskId still works — state lives in the store, not in the connection.
  5. durable_task_cancel aborts the work cooperatively at its next checkpoint.

Failures are data, not protocol errors — a structured envelope the model can repair in one round-trip:

{
  "status": "failed",
  "error": {
    "code": "offset_mismatch",
    "message": "Expected offset 131072, got 0.",
    "retryable": true,
    "recoveryHint": "Do NOT resend the whole file. Re-send this chunk starting at offset 131072.",
    "partial": { "cursor": 131072 }
  }
}

Packages (subpath exports)

ImportPurpose
mcp-longjobs/taskswithTasks() + the durable_task_* facade: background execution, progress, mid-flight input, cooperative cancellation
mcp-longjobs/fileswithFileTransfer(): chunked upload/download, resume cursor, sha256 verification, path-safety roots
mcp-longjobs/coreSession model, pluggable stores (memory, JSON file), structured error envelope

Design notes

  • Bytes never flow through the model. The model sees metadata only: handle, size, sha256, progress. Chunks through tool calls are for small-to-medium payloads; large files should move out-of-band (TUS endpoint planned) with the model verifying integrity.
  • The model is the director, not the courier. Facade tool results carry their own instructions ("call durable_task_get with this id", "resume at offset N"), so any capable model can drive the protocol with zero host-side support.
  • Failures are repairable data. Every failure carries code, retryable, recoveryHint, and partial.cursor — what went wrong, whether a retry can work, what to do instead, and what already succeeded.
  • Lifecycle vocabulary matches the spec. working / input_required / completed / failed / cancelled, so the native adapter can slot in later without breaking changes.

Status

ComponentStatus
Tasks fallback facade (progress / input / cancel)✅ implemented
Durable session stores (memory, JSON file, SQLite)✅ implemented
Session TTL expiry (lazy, repairable envelope)✅ implemented
Chunked file transfer with resume + checksums✅ implemented
Native ext-tasks adapter (CreateTaskResult / tasks/get)🔜 tracks the SDK's experimental Tasks API
TUS 1.0 out-of-band endpoint for large files🔜 planned — see mcp#189
Redis store, Python port🔜 planned

Quickstart

git clone https://github.com/ljppanda/mcp-longjobs
cd mcp-longjobs
npm install && npm run build
node dist/examples/report-generator.js

(Once published to npm, the same server runs with a single command: npx mcp-longjobs.)

Point your client at it (stdio):

{
  "mcpServers": {
    "report-generator": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-longjobs/dist/examples/report-generator.js"]
    }
  }
}

Then ask: "Generate a report on EV batteries with 3 sections." Watch the model start the job, poll durable_task_get, and pick up the result. Kill the client mid-run, restart it, and ask for the same taskId — it resumes.

Development

npm install
npm test         # vitest
npm run build    # tsc -> dist/
npm run example  # build + run the demo server

Contributing

PRs welcome — especially: store backends (SQLite/Redis), the native ext-tasks adapter, and the TUS endpoint. Please open an issue first for anything larger.

License

MIT

Questions fréquentes

Qu'est-ce que MCP Longjobs ?

Durable, resumable MCP operations: background tool execution with progress polling, mid-flight input, cancellation and resumable chunked file transfers.

Comment installer MCP Longjobs ?

Suivez les étapes d'installation de sa documentation, affichée sur cette page et dans son dépôt.

MCP Longjobs est-il open source ?

Oui. Son code est sur GitHub sous licence MIT.

Qui maintient MCP Longjobs ?

Il est publié par ljppanda. AI.tn le référence sans le maintenir ni le recommander.

Issu des listes communautaires awesome-mcp-servers et du dépôt GitHub du projet. Être listé n'est pas une recommandation : vérifiez le code et les permissions d'un serveur avant de lui donner accès à vos données.