Skip to main content
Glama

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

simple_job

ein einfacher Prompt mit eigener Prüfung

der Modell-Host

summarize

Text oder url/urls, zuerst geholt

Arbeitsmaschine (Fetch + Modell)

search_and_summarize

suchen, die Top-Seiten lesen, zusammenfassen

Suche wechselt Hosts, Rest auf der Arbeitsmaschine

download

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, was POST /v1/chat/completions beantwortet.

  • 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-server auf 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-os

pop-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

ORNITH_URL

http://127.0.0.1:8081/v1/chat/completions

der Chat-Endpunkt

ORNITH_MODEL

ornith:35b

Modellname, der in der Anfrage gesendet wird

POP_HOST

pop-os

SSH-Alias der Arbeitsmaschine

SEARCH_HOSTS

mac,pop

Maschinen, zwischen denen Suchen abwechseln; auf mac setzen für eine Ein-Maschinen-Installation

SEARCH_GAP_MS

30000

Mindestabstand zwischen Suchen von einer Maschine

SEARCH_BLOCK_MS

300000

wie lange eine Maschine nach einer Drosselung aussetzt

SIMPLE_JOB_STATE

neben index.js

wo der Such-Timing-Zustand gespeichert wird

HARNESS_LEDGER

~/Code/harness/ledger.db, falls dieses Verzeichnis existiert, sonst ~/.mcp-simple-job/ledger.db

das SQLite-Ledger

HARNESS_TRACE

~/Code/harness/current_trace.txt

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-job verfü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 checks

Die 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 tools
downloadA

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYeshttp(s) url to download.
destNoDirectory on that machine. Default ~/Downloads.
hostNo"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_mbNoRefuse anything larger. Default 500.
filenameNoOverride the filename.
overwriteNoReplace an existing file. Default false — an existing file is an error, not a silent clobber.
expect_sha256NoIf given, the download fails unless the hash matches.

TDQS

A4.6/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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".

ParametersJSON Schema
NameRequiredDescriptionDefault
checkNoOptional. Defaults to {type:"summary_of"} against the fetched pages.
countNoHow many search results to list. Default 6.
focusNoWhat you actually want to know, if narrower than the query.
modelNoDefault ornith:35b.
pagesNoHow many top results to read. Default 3, max 8. More pages costs seconds, not money.
queryYesThe web search query.
thinkNoLet 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_wordsNoTarget summary length. Default 250.
max_tokensNoDefault 2048. Ornith reasons before answering; too low returns an empty answer.
temperatureNo
results_onlyNoSkip reading and summarising; just return the search results.

TDQS

A4.2/5.0
Behavior5/5

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.

Conciseness3/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
taskYesWhat ornith should do. Be specific about the output format.
checkYesHow 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).
modelNoDefault ornith:35b.
thinkNoLet 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.
contextNoMaterial for the task — the text, rows or code to work on.
max_tokensNoDefault 2048. Ornith reasons before answering; too low returns an empty answer.
temperatureNo

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.1/5.0
Behavior2/5

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.

Conciseness4/5

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.

Completeness3/5

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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoFetch this page on pop and summarise it.
textNoThe material to summarise. Either this or url/urls.
urlsNoFetch several pages on pop and summarise them together.
checkNoOptional. Defaults to {type:"summary_of"} against the source text.
focusNoWhat the summary should be about, if not everything. e.g. "only the benchmark numbers".
modelNoDefault ornith:35b.
styleNo"bullets" (default) or "paragraph".
thinkNoLet 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_wordsNoTarget length. Default 200.
max_tokensNoDefault 2048. Ornith reasons before answering; too low returns an empty answer.
temperatureNo

TDQS

B3.4/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness3/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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.

  1. 5 tool updatesv1.0.0
    • First observeddownload
    • First observedsearch_and_summarize
    • First observedsimple_job
    • First observedsimple_job_stats
    • First observedsummarize

TDQS

A4/5.0

Scored across 5 tools

Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness5/5

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

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers