ljppanda/mcp-longjobs
БесплатноПоддерживаетсяDurable, resumable operations for MCP servers via a client-agnostic facade: background tool execution with progress polling, mid-flight input, cooperative cance
Описание
Durable, resumable operations for MCP servers via a client-agnostic facade: background tool execution with progress polling, mid-flight input, cooperative cancellation, plus chunked file transfers with resume cursors and sha256 verification. Works on every MCP client today — no Tasks-extension support required.
README
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):
crawl-sitereturns instantly with ataskIdand instructions to polldurable_task_get— no more timeouts.- Polls show live progress:
{ "status": "working", "progress": { "message": "Crawled /pricing", "fraction": 0.4 } }. - Mid-flight questions pause the task as
input_required; the model answers viadurable_task_respondand the task continues where it stopped. - Client crash? New session?
durable_task_getwith the sametaskIdstill works — state lives in the store, not in the connection. durable_task_cancelaborts 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)
| Import | Purpose |
|---|---|
mcp-longjobs/tasks |
withTasks() + the durable_task_* facade: background execution, progress, mid-flight input, cooperative cancellation |
mcp-longjobs/files |
withFileTransfer(): chunked upload/download, resume cursor, sha256 verification, path-safety roots |
mcp-longjobs/core |
Session 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_getwith 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, andpartial.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
| Component | Status |
|---|---|
| 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
Установка ljppanda/mcp-longjobs
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/ljppanda/mcp-longjobsFAQ
ljppanda/mcp-longjobs MCP бесплатный?
Да, ljppanda/mcp-longjobs MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для ljppanda/mcp-longjobs?
Нет, ljppanda/mcp-longjobs работает без API-ключей и переменных окружения.
ljppanda/mcp-longjobs — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить ljppanda/mcp-longjobs в Claude Desktop, Claude Code или Cursor?
Открой ljppanda/mcp-longjobs на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectAmap Maps Mcp Server
MCP server for using the AMap Maps API
автор: duxiaohuiSupabase
Database, auth and storage
автор: SupabaseEverything
Reference / test server with prompts, resources, and tools.
Git
Tools to read, search, and manipulate Git repositories.
Sequential Thinking
Dynamic and reflective problem-solving through thought sequences.
Time
Time and timezone conversion capabilities.
Compare ljppanda/mcp-longjobs with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
