mcp-longjobs
mcp-longjobs
Dauerhafte, fortsetzbare Vorgänge für MCP – langlaufende Aufgaben und große Dateien, die Timeouts, Verbindungsabbrüche und Client-Neustarts überleben. Auf jedem Client, heute.
Das Problem
Drei Dinge lassen jeden MCP-Server scheitern, der echte Arbeit leistet:
Langlaufende Tool-Aufrufe laufen in einen Timeout. Clients setzen Timeouts pro Aufruf (oft 10–60 s). Ein Crawl, ein Build, ein Batch-Job schlägt fehl – und der „Retry“ des Modells startet die gesamte Operation von vorn.
Fehler sind nicht reparierbar. Ein fehlgeschlagener Aufruf gibt einen frei formulierten Fehler zurück, also rät das Modell: blind wiederholen oder aufgeben. Es kann nicht einen Parameter korrigieren und fortsetzen.
Große Dateien haben kein Übertragungskonzept. Binärinhalte sind base64-in-JSON (33 % Overhead, harte Nachrichtengrößen-Grenzen) oder eine nackte URL ohne Konventionen – kein Chunking, kein Fortsetzen, keine Integritätsprüfungen.
Die MCP-Spezifikation vom 2026-07-28 hat Tasks hinzugefügt – asynchrone Ausführung mit Eingaben während des Laufs und dauerhaften Handles. Aber noch unterstützt kein Client das, und die Spezifikation verlangt, dass Server Tasks für Clients ablehnen, die nicht zugestimmt haben. Jeder langlaufende Server braucht daher einen Fallback-Pfad, der auf heutigen Clients funktioniert. Das ist dieses Paket.
Related MCP server: Simple Streamable HTTP MCP Server
Was Sie bekommen
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" });Was das Modell auf heutigen Clients erlebt (keine Tasks-Unterstützung erforderlich):
crawl-sitegibt sofort einetaskIdund Anweisungen zurück,durable_task_getabzufragen – keine Timeouts mehr.Die Abfragen zeigen Live-Fortschritt:
{ "status": "working", "progress": { "message": "Crawled /pricing", "fraction": 0.4 } }.Fragen während des Laufs pausieren die Aufgabe als
input_required; das Modell antwortet überdurable_task_respond, und die Aufgabe wird an der Stelle fortgesetzt, an der sie gestoppt wurde.Client abgestürzt? Neue Sitzung?
durable_task_getmit derselbentaskIdfunktioniert weiterhin – der Zustand lebt im Store, nicht in der Verbindung.durable_task_cancelbricht die Arbeit kooperativ am nächsten Checkpoint ab.
Fehler sind Daten, keine Protokollfehler – eine strukturierte Hülle, die das Modell in einem einzigen Round-Trip reparieren kann:
{
"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 }
}
}Pakete (Subpath-Exporte)
Import | Zweck |
|
|
|
|
| Sitzungsmodell, austauschbare Stores (In-Memory, JSON-Datei), strukturierte Fehlerhülle |
Designhinweise
Bytes fließen nie durch das Modell. Das Modell sieht nur Metadaten: Handle, Größe, sha256, Fortschritt. Chunks über Tool-Aufrufe sind für kleine bis mittlere Nutzlasten gedacht; große Dateien sollten out-of-band übertragen werden (TUS-Endpunkt geplant), wobei das Modell die Integrität prüft.
Das Modell ist der Regisseur, nicht der Kurier. Die Ergebnisse der Fassaden-Tools enthalten ihre eigenen Anweisungen („Rufen Sie
durable_task_getmit dieser ID auf“, „Setzen Sie bei Offset N fort“), sodass jedes fähige Modell das Protokoll ohne jegliche Host-Unterstützung steuern kann.Fehler sind reparierbare Daten. Jeder Fehler enthält
code,retryable,recoveryHintundpartial.cursor– was schiefging, ob ein erneuter Versuch funktionieren kann, was stattdessen zu tun ist und was bereits erfolgreich war.Das Lebenszyklus-Vokabular entspricht der Spezifikation.
working / input_required / completed / failed / cancelled, sodass der native Adapter später ohne Breaking Changes eingefügt werden kann.
Status
Komponente | Status |
Tasks-Fallback-Fassade (Fortschritt / Eingabe / Abbruch) | ✅ implementiert |
Dauerhafte Sitzungs-Stores (In-Memory, JSON-Datei) | ✅ implementiert |
Chunk-Dateiübertragung mit Fortsetzen + Prüfsummen | ✅ implementiert |
Nativer ext-tasks-Adapter ( | 🔜 orientiert sich an der experimentellen Tasks-API des SDKs |
TUS-1.0-Out-of-Band-Endpunkt für große Dateien | 🔜 geplant – siehe mcp#189 |
Redis-/SQLite-Stores, Python-Port | 🔜 geplant |
Schnellstart
git clone https://github.com/ljppanda/mcp-longjobs
cd mcp-longjobs
npm install && npm run build
node dist/examples/report-generator.js(Sobald es auf npm veröffentlicht ist, läuft derselbe Server mit einem einzigen Befehl: npx mcp-longjobs.)
Richten Sie Ihren Client darauf aus (stdio):
{
"mcpServers": {
"report-generator": {
"command": "node",
"args": ["/absolute/path/to/mcp-longjobs/dist/examples/report-generator.js"]
}
}
}Fragen Sie dann: „Erstelle einen Bericht über EV-Batterien mit 3 Abschnitten.“ Beobachten Sie, wie das Modell den Auftrag startet, durable_task_get abfragt und das Ergebnis abholt. Beenden Sie den Client während des Laufs, starten Sie ihn neu und fragen Sie nach derselben taskId – der Vorgang wird fortgesetzt.
Entwicklung
npm install
npm test # vitest
npm run build # tsc -> dist/
npm run example # build + run the demo serverMitwirken
PRs sind willkommen – insbesondere: Store-Backends (SQLite/Redis), der native ext-tasks-Adapter und der TUS-Endpunkt. Bitte eröffnen Sie für größere Änderungen zuerst ein Issue.
Lizenz
Maintenance
Related MCP Servers
- AlicenseAqualityBmaintenanceAsync MCP server for running long-running AI tasks with real-time progress monitoring, enabling users to start, monitor, and manage complex AI workflows across multiple models.6345MIT
- FlicenseNot gradedqualityDmaintenanceA reference implementation demonstrating proper MCP server patterns with HTTP transport, featuring session management, progress notifications, and example tools for testing server functionality. Serves as a clean template for building MCP servers with streamable responses and comprehensive error handling.7
- AlicenseAqualityAmaintenanceA fire-and-poll MCP server that lets Claude Code run long background jobs without hitting tool-call timeouts.3MIT
- FlicenseNot gradedqualityBmaintenanceRemote MCP server that launches user-supplied scripts inside disposable Docker containers, returning task IDs for async tracking and bounded output tails.
Related MCP Connectors
MCP server for the FFmpeg Micro video transcoding API — create, monitor, download transcodes.
MCP protocol requiring task acceptance and provenance tags. Self-hosted only - see README.
Remote MCP server for RunComfy Serverless API (ComfyUI): deployments and async inference.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ljppanda/mcp-longjobs'
If you have feedback or need assistance with the MCP directory API, please join our Discord server