simple-job
mcp-simple-job
Übergib eine Teilaufgabe an ein lokales Modell auf einer anderen Maschine und prüfe das Ergebnis, bevor du es zurückgibst.
Gebaut für eine bestimmte Art von Problem: Der leistungsfähige, gemessene Assistent läuft auf der Maschine, vor der du sitzt, während eine völlig brauchbare GPU-Box nutzlos in der Ecke steht. Vierzig Dateien lesen, eine lange Seite zusammenfassen, einen Datensatz herunterladen – nichts davon braucht das teure Modell, und es im Kontext des Assistenten zu erledigen, verbraucht die eine Ressource, die wirklich knapp ist.
Gemessen am Setup des Autors, im Vergleich zu denselben vier Aufgaben im Kontext: ~2,7x schneller und 6,1x weniger Kontext verbraucht, weil die rohen Seiten ihn nie erreichen.
Die eine Regel
Ein Auftrag muss eine Prüfung mitbringen. Eine Aufgabe, die nicht angeben kann, woran man erkennen würde, dass sie funktioniert hat, wird abgelehnt – nicht gewarnt, abgelehnt.
Das ist kein Misstrauen gegenüber dem lokalen Modell. Es liegt daran, dass der Aufrufer es nicht erkennen kann. Wenn der Assistent eine Zusammenfassung delegiert und vierhundert selbstbewusste Wörter zurückbekommt, hat er keine unabhängige Möglichkeit zu wissen, ob diese Wörter das Dokument beschreiben oder etwas anderes. Delegieren ohne Prüfung fügt eine zweite Stelle hinzu, an der ein grünes Licht nichts bedeutet.
Prüfungen sind bewusst langweilig: nonempty, contains, regex, json_keys, line_count, shell (deine argv, Exit 0 besteht, Ausgabe wird an stdin gepipet) und summary_of (kürzer als die Quelle und keine Kopie davon).
Related MCP server: Forgehand
Die vier Teilaufgaben
tool | was es tut | wo die Arbeit passiert |
| ein einfacher Prompt mit eigener Prüfung | der Modell-Host |
| Text oder url/urls, zuerst geholt | Arbeitsmaschine (Fetch + Modell) |
| suchen, die Top-Seiten lesen, zusammenfassen | Suche wechselt Hosts, Rest auf der Arbeitsmaschine |
| eine Datei holen, Bytes + sha256 melden | standardmäßig Arbeitsmaschine, jeder konfigurierte Host |
simple_job_stats berichtet, wie alle tatsächlich gelaufen sind, aus einer Ledger-Zeile, die für jeden Auftrag geschrieben wird.
Ausführen
Voraussetzungen
Node 18+ auf der Maschine, die den MCP-Server ausführt.
Ein OpenAI-kompatibler Chat-Endpunkt. llama.cpps
llama-server, Ollama, vLLM, LM Studio oder eine gehostete API – alles, wasPOST /v1/chat/completionsbeantwortet.Python 3.9+ auf der Maschine, die das Holen übernimmt. Nur Standardbibliothek; keine pip-Installation, kein node, kein beautifulsoup.
SSH-Schlüssel-Authentifizierung zur zweiten Maschine, falls du eine verwendest. Sie ist optional (siehe unten).
Wie es auf den Maschinen des Autors verdrahtet ist
Zwei Computer:
Ein Mac mini – die tägliche Workstation. 16 GB, normalerweise ein paar Gigabyte im Swap. Er führt Claude Desktop und damit diesen MCP-Server aus.
Eine Pop!_OS-Box mit einer RTX 5070 Ti – das Labor. Sie führt ein 35B-Modell namens ornith unter
llama-serverauf Port 8080 aus und ist die meiste Zeit des Tages untätig.
Ein SSH-Tunnel lässt das entfernte Modell für den Mac lokal aussehen:
ssh -N -o ServerAliveInterval=30 -L 127.0.0.1:8081:127.0.0.1:8080 pop-ospop-os ist ein ~/.ssh/config-Alias mit einem Schlüssel und IdentitiesOnly yes, sodass der Server ihn nicht-interaktiv mit BatchMode=yes erreichen kann.
Der MCP-Client-Eintrag ist einfach:
{ "mcpServers": { "simple-job": { "command": "node", "args": ["/path/to/mcp-simple-job/index.js"] } } }Standardwerte erledigen den Rest: das Modell unter 127.0.0.1:8081, die Arbeitsmaschine unter pop-os und das Ledger in einem vorhandenen ~/Code/harness/, falls es eines gibt.
Nichts wird jemals von Hand aufgerufen. Der Assistent wählt das Tool – was ein schwierigeres Problem ist, als es klingt, und unten behandelt wird.
Ausführen auf deinem Setup
Zwei Maschinen, eine führt den Client aus, eine das Modell:
{
"mcpServers": {
"simple-job": {
"command": "node",
"args": ["/path/to/mcp-simple-job/index.js"],
"env": {
"ORNITH_URL": "http://127.0.0.1:8081/v1/chat/completions",
"ORNITH_MODEL": "your-model-name",
"POP_HOST": "your-ssh-alias"
}
}
}
}Eine Maschine – alles lokal, kein SSH irgendwohin:
{
"env": {
"ORNITH_URL": "http://127.0.0.1:11434/v1/chat/completions",
"ORNITH_MODEL": "qwen3:8b",
"SEARCH_HOSTS": "mac"
}
}SEARCH_HOSTS=mac ist der Schalter, der sagt: „Es gibt keine zweite Maschine". Holen, Herunterladen und Suchen passieren alle lokal, und die Suche hat einfach ein Ratenbudget statt zwei. Alles andere verhält sich gleich.
Umgebungsvariablen
variable | standard | was sie tut |
|
| der Chat-Endpunkt |
|
| Modellname, der in der Anfrage gesendet wird |
|
| SSH-Alias der Arbeitsmaschine |
|
| Maschinen, zwischen denen Suchen abwechseln; auf |
|
| Mindestabstand zwischen Suchen von einer Maschine |
|
| wie lange eine Maschine nach einer Drosselung aussetzt |
| neben | wo der Such-Timing-Zustand gespeichert wird |
|
| das SQLite-Ledger |
|
| optionale Trace-ID zum Stempeln auf Zeilen |
Das Ledger ist optional. Es wird bei der ersten Verwendung erstellt, und wenn es nicht beschrieben werden kann, laufen die Aufträge trotzdem – Protokollierung ist Best-Effort und blockiert nie Arbeit. HARNESS_TRACE ist ein Haken für die eigene Tracing-Einrichtung des Autors; ignoriere ihn und Zeilen haben einfach eine null-Trace-ID.
Damit es tatsächlich genutzt wird
Das ist der Teil, den die meisten überspringen, und es ist der Teil, der entscheidet, ob irgendetwas davon eine Rolle spielt.
Ein Tool, zu dem nichts weiterleitet, ist unsichtbar, egal wie gut es funktioniert. Der Autor hat einen separaten MCP-Server, der einwandfrei funktioniert und monatelang null Aufrufe hatte, nur weil nichts dem Assistenten je gesagt hat, danach zu greifen. Eine Fähigkeit zu bauen und dorthin weiterzuleiten sind zwei verschiedene Aufgaben, und die erste zu beenden fühlt sich an wie Fertigwerden.
Drei Möglichkeiten, diese Lücke zu schließen, die günstigste zuerst. Die meisten wollen die zweite.
1. Nichts tun und sehen. Manche Clients lesen Tool-Beschreibungen gut genug, dass eine ausreichend offensichtliche Anfrage – „fasse diese vierzig Seiten zusammen" – das Tool von selbst findet. Einen Tag wert, es auszuprobieren, bevor man Maschinerie hinzufügt. Beobachte, ob es tatsächlich aufgerufen wird.
2. Lege eine Regel dort ab, wo dein Client dauerhafte Anweisungen aufbewahrt. Claude-Desktop-Projektanweisungen, eine CLAUDE.md für Claude Code, .cursorrules, die Anweisungen eines benutzerdefinierten GPT – was auch immer dein Client bei jeder Runde liest. Etwa so:
Es gibt ein lokales Modell, das über
simple-jobverfügbar ist. Verwende es, wenn das Material noch nicht im Kontext ist und die Aufgabe mechanisch ist: Seiten oder Dateien zusammenfassen, Websuche plus Lesen, Downloads holen, Extrahieren und Neuformatieren. Es ist kostenlos und verbraucht keinen Kontext für die Quelle.Mach es selbst, wenn der Text bereits im Kontext ist, wenn die Aufgabe Interpretation statt Transkription braucht, oder wenn Richtigsein wichtiger ist als Prüfbarkeit. Delegiere niemals Ermessensentscheidungen, Code, der korrekt sein muss, oder Dateibearbeitungen.
Jeder Auftrag muss eine Prüfung mitbringen – der Server lehnt Arbeit ab, die er nicht verifizieren kann.
Verwende genauso viele Wörter für wann nicht zu delegieren wie für wann. Die Fehlerart beim Weiterleiten eines Delegierungstools ist Über-Delegierung, und ein Assistent, der alles nach unten schickt, wird dir treue Transkription liefern, wo du Urteilsvermögen wolltest.
3. Verdrahte es in einen Router, falls du einen hast. Wenn dein Setup bereits Situationen Tools zuordnet, füge einen Eintrag für „Massenlesen oder Holen von Material, das noch nicht im Kontext ist" hinzu. Der Vorteil gegenüber einer dauerhaften Anweisung ist, dass es messbar ist – du kannst zählen, ob es ausgelöst hat, als es hätte sollen. Eine dauerhafte Anweisung funktioniert entweder oder nicht, und nichts zeichnet auf, welches.
Was du nicht hinschicken solltest
Alles, wo „sieht richtig aus" der einzige Test ist. Ermessensentscheidungen. Code, der korrekt sein muss. Dateien bearbeiten.
Und eine Grenze, die durch Messung statt Geschmack gefunden wurde: Ein kleines lokales Modell transkribiert treu, interpretiert aber nicht. Im Test reproduzierte es die mehrdeutige Formulierung einer Quelle wörtlich, statt aufzulösen, was sie bedeutete, und fasste die Sternanzahl eines Repositorys so zusammen, als wäre sie Teil eines Fehlerberichts. Schick ihm Transkription. Behalte Interpretation.
Notizen vom Bauen
Alles unten ist eine Messung, keine Meinung. Die Zahlen stehen auch in den Code-Kommentaren.
Denken ist standardmäßig aus
Reasoning-Modelle geben ihre Überlegung und ihre Antwort aus demselben Token-Budget aus. Bei einem Zusammenfassungsauftrag, der dreimal identisch ausgeführt wurde, verbrauchten zwei von drei 5.500–6.000 Zeichen fürs Denken, trafen die Obergrenze und gaben eine leere Antwort mit HTTP 200 zurück.
max_tokens zu erhöhen behob es nicht. reasoning_effort: "low" behob es nicht. Ein /no_think-System-Tag behob es nicht. Nur chat_template_kwargs: {enable_thinking: false} tat es, und derselbe Auftrag antwortete dann in 258 Tokens. Übergib think: true für einen Auftrag, der wirklich Überlegung braucht, und erhöhe max_tokens damit.
Suche ist rationiert, und DuckDuckGo lügt darüber, warum
DuckDuckGo drosselt nicht höflich:
eine bediente Abfrage ist HTTP 200, ~28 KB, zehn Ergebnislinks
eine verweigerte ist HTTP 202, ~14,2 KB, und ihr Text lautet „Bitte löse die folgende Herausforderung... Wähle alle Quadrate aus, die eine Ente enthalten"
Es ist ein Captcha-Flag auf der IP, kein zeitliches Limit, und Abstände räumen eines nicht ab. Nach vier Minuten Stille waren sechs Abfragen im 30-s-Abstand von einer Maschine und sechs im 15-s-Abstand von der anderen 0 von 12. Abfragen alle 5 s während einer Sperre erholten sich nie in 162 s – Wiederholen füttert es. Das Flag verfiel von selbst in ungefähr zwanzig Minuten.
Also werden Suchen verteilt, über Maschinen abgewechselt (zwei IPs sind zwei Budgets), und eine Drosselung wird als throttled gemeldet, nie als „keine Ergebnisse". Diese bedeuten Gegenteiliges.
Lesen folgt der Frage
Eine lange Seite wird beschnitten, um ins Fenster des Modells zu passen, und das Beschneiden von oben beantwortet die falsche Frage stillschweigend. Gefragt nach „sparse gating and load balancing" auf einer 40.063-Zeichen-Seite mit einem 8.000-Zeichen-Fenster gab die erste Version eine flüssige Zusammenfassung der Eröffnung des Artikels zurück – in der „load balancing" nie vorkommt (es beginnt bei Zeichen 16.181) und „sparse" nie vorkommt (14.671).
Also steuert focus das Fenster: ein Kopf für den Kontext, dann die Passagen um jeden benannten Begriff, ein garantiertes Fenster pro Begriff, bevor ein Begriff ein zweites bekommt. Zwei frühere Versionen waren nicht genug – Substring-Abgleich fand „load" in „download" und meldete 42 Treffer Rauschen, und das Nehmen von Passagen in Dokumentreihenfolge verbrauchte das Budget, bevor es Zeichen 16.181 erreichte.
Wenn die Seite diese Wörter nie verwendet, gibt der Aufruf ok:false mit focus_not_found zurück. Null Treffer ist eine bessere Antwort als eine plausible Zusammenfassung anderen Materials.
Eine Seite, die größtenteils Skript ist, wird abgelehnt
Eine Website lieferte 68.896 Bytes mit 40 Zeichen Text („Loading..."), was der ursprüngliche if not text-Schutz passieren ließ – also ging die Shell als Quellmaterial in eine Zusammenfassung ein und das Modell schrieb eine selbstbewusste Benchmark-Zahl, die darauf verwies.
Jetzt zwei Tests, weil jeder allein getäuscht wird: eine absolute Untergrenze und ein Text-zu-Bytes-Verhältnis, das nur eine Seite verurteilt, die auch kurz ist. Ein GitHub-Issue ist 290.000 Bytes Markup um 3.896 Zeichen echter Diskussion, und das Verhältnis allein hat es verworfen.
Zitate sind nummeriert, damit sie überprüft werden können
search_and_summarize nummeriert die Seiten und fragt nach [1], [2] statt nach URLs. Auf URLs angesprochen, schrieb das Modell eine Zahl, die es in einem Blog gelesen hatte, einer Dokumentationsseite zu – die Tatsache war real und im Material vorhanden, die Zuordnung war es nicht, und summary_of kann das nicht erkennen, weil ein falsch beschrifteter Aufzählungspunkt die richtige Länge hat und keine Kopie ist.
Eine URL ist eine lange undurchsichtige Zeichenkette, die man korrekt kopieren muss. Eine Ganzzahl ist das nicht, und sie kann gegen die tatsächlich gelesenen Seiten auf ihren Bereich geprüft werden – was der Code tut, indem er den Aufruf bei einer Zahl außerhalb des Bereichs fehlschlagen lässt und Aufzählungspunkte ohne Quelle überhaupt zählt.
Welche Maschine ist schneller?
Verifiziert durch identische sha256 auf beiden Seiten:
Client-Maschine | Worker-Maschine | |
ssh-Roundtrip | — | ~185 ms pro Aufruf |
4 Seiten abrufen | ~1.7 s | ~2.0 s |
20 MB herunterladen | 17.5 MB/s | 12.6 MB/s |
Die Client-Maschine war bei beidem schneller. Geschwindigkeit ist nicht der Grund, Arbeit an den Worker zu senden. Die Gründe sind, dass sie das Modell enthält, dass sie im Leerlauf ist, während die andere Maschine benutzt wird, und dass eine zweite Maschine ein zweites Suchbudget ist. Wählen Sie den Host für einen Download danach, wo die Datei benötigt wird, nicht nach dem Durchsatz.
Tests
node test_e2e.mjs # 24 assertions, spawns the real server over JSON-RPC
node --test test/simple-job.test.mjs # 19 unit assertions on the checksDie End-to-End-Suite startet den tatsächlichen Server so, wie es ein Client tun würde, gegen ein Wegwerf-Ledger. Ein In-Process-Test würde einen PATH- oder Umgebungsfehler nicht erkennen, und genau diese treten nur nach einem Neustart auf.
Änderungen an index.js werden wirksam, wenn der Client den Server das nächste Mal startet. pop_agent.py wird bei jedem Aufruf neu gelesen, sodass Änderungen am Abrufen, Suchen und Herunterladen sofort live sind.
Available Tools
5 toolsdownloadA
Download a file to pop (default) or to this Mac. Returns the path, byte count and sha256 — a download that reports success without those is not verified. Put it on pop when pop will use it (models, datasets, anything for the GPU); put it on the mac when you will open it.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | http(s) url to download. | |
| dest | No | Directory on that machine. Default ~/Downloads. | |
| host | No | "pop" (default) or "mac". Measured 2026-08-21: the Mac is the faster of the two (17.5 vs 12.6 MB/s), so choose by where the file is needed, not by speed. | |
| max_mb | No | Refuse anything larger. Default 500. | |
| filename | No | Override the filename. | |
| overwrite | No | Replace an existing file. Default false — an existing file is an error, not a silent clobber. | |
| expect_sha256 | No | If given, the download fails unless the hash matches. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It clearly states the expected return values ('path, byte count and sha256') and adds the important caveat that success without these is not verified, which is a meaningful behavioral warning. It also implies the default host is pop. However, it does not describe failure behavior beyond the overwrite rule (which is in the parameter schema), nor does it mention whether downloads are atomic or what happens on network errors. Given the lack of annotations, this is a strong disclosure but not exhaustive, so a 4 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences long, front-loaded with the primary action and destination, followed by the return-value verification note and then the host-selection guidance. Every sentence carries meaningful information; there is no filler or redundancy. It is an excellent example of concise, high-signal writing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 7 parameters, no output schema, and no annotations, the description covers the core aspects: what it does, where it downloads, what it returns, and how to decide between hosts. It also adds the verification requirement that guards against silently bad downloads. It does not mention edge cases like how max_mb is enforced or what happens when an existing file blocks the download (though the parameter schema covers that), but these are secondary. Overall, an agent can call this tool safely and correctly, so a 4 is suitable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already describes all 7 parameters with 100% coverage, so the baseline is 3. The main description adds value by explaining the strategic choice of host ('Put it on pop when pop will use it...'), which reinforces the host parameter's purpose and provides context beyond its schema description. It also emphasizes the verification requirement, which ties into the expect_sha256 parameter. While the schema covers syntax, the description adds usage logic, so a 4 is justified.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb-and-resource pair — 'Download a file' — and specifies the two possible destinations ('to pop (default) or to this Mac'), which uniquely defines the tool's action. It also distinguishes it from the sibling tools (simple_job, summarize, etc.) which are entirely unrelated, so there is no ambiguity about what this tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit, actionable guidance on when to use each host: 'Put it on pop when pop will use it (models, datasets, anything for the GPU); put it on the mac when you will open it.' This directly tells an agent how to choose the destination based on the intended use, and the default is also stated. No alternative tools are relevant, so this guidance is complete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_and_summarizeA
Search the web (DuckDuckGo), read the top pages on pop, and have ornith summarise them — one call, no Claude context spent on the raw pages. THE ONLY SEARCH TOOL HERE, and deliberately: DuckDuckGo rate-limits hard, so searches are spaced and alternated between this Mac and pop. A throttle is reported as a throttle, never as "no results".
| Name | Required | Description | Default |
|---|---|---|---|
| check | No | Optional. Defaults to {type:"summary_of"} against the fetched pages. | |
| count | No | How many search results to list. Default 6. | |
| focus | No | What you actually want to know, if narrower than the query. | |
| model | No | Default ornith:35b. | |
| pages | No | How many top results to read. Default 3, max 8. More pages costs seconds, not money. | |
| query | Yes | The web search query. | |
| think | No | Let ornith reason before answering. Default false. Measured 2026-08-21: with reasoning on, 2 of 3 summarise runs returned an EMPTY answer after burning the whole token budget on thinking. Turn it on only for a job that genuinely needs deliberation, and raise max_tokens with it. | |
| max_words | No | Target summary length. Default 250. | |
| max_tokens | No | Default 2048. Ornith reasons before answering; too low returns an empty answer. | |
| temperature | No | ||
| results_only | No | Skip reading and summarising; just return the search results. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full responsibility and excels: it discloses the DuckDuckGo backend, the reading and summarization pipeline, the lack of Claude context use, the spacing of requests, and the crucial behavior that throttles are reported truthfully. It even documents a known failure mode with the 'think' parameter. This is exemplary transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description front-loads the purpose but then becomes a run-on sentence mixing operational details, typos, and policy notes. While information-dense and not excessively long, it could be split into clearer sentences to improve scannability. It feels a bit stream-of-consciousness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter tool with no output schema, the description covers the core use case, operational constraints, and a known gotcha ('think'). It doesn't describe the return value, but that's a reasonable trade-off given the already rich parameter documentation and the absence of an output schema. The description is sufficient for an agent to decide when to call this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is high (91%), so the baseline is 3. The description itself does not add parameter-level details beyond what's in the schema, and the schema already describes 10 of 11 parameters. No contradiction or gap that requires the description to compensate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Search the web (DuckDuckGo), read the top pages... and have ornith summarise them'. It also differentiates from siblings by declaring 'THE ONLY SEARCH TOOL HERE', making it unmistakable what this tool does relative to others. The typos ('pop', 'ornith') don't obscure the core verb-resource actions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly frames the tool as the only search option ('THE ONLY SEARCH TOOL HERE') and provides practical guidance on rate-limiting and throttle behavior. However, it doesn't explicitly state when *not* to use it (e.g., when you already have content to summarize, which sibling 'summarize' might handle), leaving exclusions to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
simple_jobA
Hand a plain subtask to ornith (35B, local, free) on pop and verify the result before returning it. REQUIRES a check — a task that cannot state how it would be known to have worked is refused. Good for: extraction against a schema, classifying, reformatting. Bad for: judgment calls, code that must be correct, editing files — do those yourself.
| Name | Required | Description | Default |
|---|---|---|---|
| task | Yes | What ornith should do. Be specific about the output format. | |
| check | Yes | How the result is verified. One of: {type:"nonempty"} | {type:"contains",text,case_sensitive?} | {type:"regex",pattern,flags?} | {type:"json_keys",required:[...]} | {type:"line_count",min?,max?} | {type:"shell",command:[argv...],timeout_ms?} (result is piped to stdin; exit 0 passes). | |
| model | No | Default ornith:35b. | |
| think | No | Let ornith reason before answering. Default false. Measured 2026-08-21: with reasoning on, 2 of 3 summarise runs returned an EMPTY answer after burning the whole token budget on thinking. Turn it on only for a job that genuinely needs deliberation, and raise max_tokens with it. | |
| context | No | Material for the task — the text, rows or code to work on. | |
| max_tokens | No | Default 2048. Ornith reasons before answering; too low returns an empty answer. | |
| temperature | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses key behaviors: it verifies the result before returning, refuses tasks without a check, and mentions limitations (bad for judgment calls, code, editing). However, it does not specify what happens if verification fails, error handling, or output format, leaving some behavioral aspects undisclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: it opens with the core action, then lists requirements and use cases. Every sentence adds value without redundancy, and the format is easy to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given there is no output schema, the description should explain the return value or error cases, but it only says 'returns it' without specifying format. It also omits details about parameter interactions (e.g., temperature affects creativity) and failure modes, leaving some operational context incomplete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides descriptions for all parameters (86% coverage). The description adds little beyond the note that a check is required (which is already in the schema). No additional semantic value is provided for parameters like temperature or max_tokens.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: delegating a subtask to ornith and verifying the result. It explicitly lists good and bad use cases (extraction, classification, reformatting vs. judgment calls, code, editing), making the purpose and scope unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides explicit guidance on when to use the tool: it requires a verifiable check, lists suitable tasks, and explicitly warns against unsuitable ones (e.g., judgment calls, code) with 'do those yourself.' This clearly differentiates it from the alternatives (doing it manually or using other tools).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
simple_job_statsB
How delegation has actually gone: jobs by kind, how often the check passed, and speed. Answers whether this server is earning its place.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the full burden of behavioral disclosure. It implies a read-only informational tool but does not explicitly state that it performs no mutations, requires no auth, or has any other behavioral caveats. The phrasing 'answers whether this server is earning its place' is not operationally informative.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is brief and front-loaded with the core subject, but the final clause 'Answers whether this server is earning its place' adds little operational value and is somewhat metaphorical. Still, it is concise overall with minimal waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter statistics tool, the description gives a reasonable sense of the returned dimensions: jobs by kind, check pass rate, and speed. However, it does not clarify the output format or precisely what 'speed' refers to, and it lacks any comparison to sibling tools, leaving some ambiguity for an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool accepts zero parameters, so the schema already fully covers the input surface. The description does not need to explain parameter details, and the baseline for zero-parameter tools applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description communicates that this tool reports statistics about job delegation, including breakdowns by kind, check pass rates, and speed. It is clear enough to identify the tool's purpose, though it lacks an explicit verb like 'returns' or 'computes' and does not explicitly differentiate itself from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus alternatives such as simple_job or summarize. No context, conditions, or exclusions are provided that would help an agent choose this tool correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
summarizeB
Summarise text with ornith on pop. Free, local, and it does not spend Claude context on the source. Pass the text directly, or a url/urls to fetch first (fetched on pop). The default check is a real one: the summary must be substantially shorter than the source and not a copy of it.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Fetch this page on pop and summarise it. | |
| text | No | The material to summarise. Either this or url/urls. | |
| urls | No | Fetch several pages on pop and summarise them together. | |
| check | No | Optional. Defaults to {type:"summary_of"} against the source text. | |
| focus | No | What the summary should be about, if not everything. e.g. "only the benchmark numbers". | |
| model | No | Default ornith:35b. | |
| style | No | "bullets" (default) or "paragraph". | |
| think | No | Let ornith reason before answering. Default false. Measured 2026-08-21: with reasoning on, 2 of 3 summarise runs returned an EMPTY answer after burning the whole token budget on thinking. Turn it on only for a job that genuinely needs deliberation, and raise max_tokens with it. | |
| max_words | No | Target length. Default 200. | |
| max_tokens | No | Default 2048. Ornith reasons before answering; too low returns an empty answer. | |
| temperature | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of disclosing behavior, and it does: free, local, avoids consuming Claude context, fetches URLs, and enforces a real anti-copy/shorter-than-source check. It does not cover failure modes or service dependencies, but the main behavioral traits that would affect an agent's invocation and expectation are present.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the main verb and purpose. Every sentence contributes useful information, but 'on pop' appears twice without definition, slightly hurting clarity. It is appropriately sized and not padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 11 parameters, a nested check object, and no output schema, the description covers the main usage and the default verification behavior but leaves gaps: return value shape, error/failure behavior with URLs, and what the check object supports beyond its default. The schema covers most parameters, but the missing output context is notable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is high at 91%, so the baseline is 3. The description adds a little context about text/url/urls usage and the default check, but mostly repeats what the schema already documents. It does not add meaningful detail for parameters like focus, style, model, or temperature.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the core action clearly with a specific verb and resource: 'Summarise text with ornith on pop.' It also clarifies the two input modes (direct text or URL/URLs) and differentiates itself via 'does not spend Claude context on the source.' However, 'on pop' is unexplained jargon, and it does not explicitly contrast with sibling search_and_summarize, so it is not a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains how to invoke the tool ('Pass the text directly, or a url/urls to fetch first') but provides no guidance on when to choose this tool over its siblings. search_and_summarize is a plausible alternative for search-then-summarize use cases, yet no exclusion or comparison is mentioned.
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.
5 tool updates
v1.0.0- First observed
download - First observed
search_and_summarize - First observed
simple_job - First observed
simple_job_stats - First observed
summarize
TDQS
Scored across 5 tools
Each tool has a clear, distinct purpose: simple_job delegates a generic subtask, summarize condenses text, search_and_summarize combines web search with summarization, simple_job_stats reports on job execution, and download retrieves files. No two tools overlap in functionality.
All tool names follow a consistent lowercase_with_underscores convention, and related tools (simple_job, simple_job_stats) share a common prefix while remaining descriptive. No mixed camelCase or other styles.
With 5 tools, the server is well-scoped—neither bare nor cluttered. Each tool serves a distinct, essential function, and the count aligns with the apparent purpose of task delegation and information retrieval.
The tool set covers the core operations needed for the server's domain: executing a job, summarizing, searching and summarizing, tracking job stats, and downloading files. No obvious missing functionality for the stated purpose.
Maintenance
Related MCP Connectors
Local ML: speech to text (SRT/VTT), text embeddings, reranking, similarity, entities, zero-shot.
Hand tasks, bugs and finished work to AI coding agents, and get back a write-up with evidence.
Exact IBAN, VAT, cron, regex answers; HTML/URL to hosted PDF or screenshot; agent memory; workflows.
LLM chat, text tools, image generation, editing, batch image jobs, and asynchronous video generation
Related MCP Servers
- AlicenseBqualityCmaintenanceDelegates heavy, repetitive, and verifiable tasks like PDF extraction, code analysis, and log processing to a local LLM to reduce token consumption for frontier AI models, while keeping decision-making with the main AI.8MIT
- AlicenseAqualityAmaintenanceEnables delegating complete coding tasks to a local OpenAI-compatible model through MCP, using bounded Git worktrees and compact receipts so conversation history is not carried.4MIT
- FlicenseNot gradedqualityCmaintenanceEnables delegating mechanical or high-volume subtasks to a local LLM through an MCP tool, letting the assistant query the local model without using its own output tokens for content.-
- AlicenseAqualityAmaintenanceEnables Codex to delegate bounded, low-risk text work such as extraction, summarization, translation, and code drafts to a local WorkBuddy installation, returning small inspectable drafts for the main agent to verify.5MIT