simple-job
Provides web search capabilities via DuckDuckGo, used in the search_and_summarize tool to find and read relevant pages before summarization.
Allows using Ollama as the local model endpoint, sending prompts to its OpenAI-compatible API for tasks like summarization, extraction, and reformatting.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@simple-jobDownload https://example.com/data.csv and verify the sha256 checksum matches the published one."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-simple-job
Hand a subtask to a local model on another machine, and verify the result before returning it.
Built for a specific shape of problem: the capable, metered assistant runs on the machine you sit in front of, while a perfectly good GPU box sits idle in the corner. Reading forty files, summarising a long page, pulling down a dataset — none of that needs the expensive model, and doing it in the assistant's context spends the one resource that is genuinely scarce.
Measured on the author's setup, against doing the same four jobs in-context: ~2.7x faster, and 6.1x less context spent, because the raw pages never enter it.
The one rule
A job must come with a check. A task that cannot state how it would be known to have worked is refused — not warned about, refused.
This is not distrust of the local model. It is that the caller cannot tell. When the assistant delegates a summary and gets back four hundred confident words, it has no independent way to know whether those words describe the document or something else. Delegating without a check adds a second place where a green light means nothing.
Checks are deliberately boring: nonempty, contains, regex, json_keys,
line_count, shell (your argv, exit 0 passes, output piped to stdin), and summary_of
(shorter than the source and not a copy of it).
Related MCP server: Local Worker MCP
The four subtasks
tool | what it does | where the work happens |
| a plain prompt with your own check | the model host |
| text, or url/urls fetched first | worker machine (fetch + model) |
| search, read the top pages, summarise | search alternates hosts, rest on the worker |
| fetch a file, report bytes + sha256 | worker by default, any configured host |
simple_job_stats reports how all of them have actually gone, from a ledger row written
for every job.
Running it
Requirements
Node 18+ on the machine running the MCP server.
An OpenAI-compatible chat endpoint. llama.cpp's
llama-server, Ollama, vLLM, LM Studio, or a hosted API — anything that answersPOST /v1/chat/completions.Python 3.9+ on whichever machine does the fetching. Standard library only; no pip install, no node, no beautifulsoup.
SSH key auth to the second machine, if you use one. It is optional (see below).
How it is wired on the author's machines
Two computers:
A Mac mini — the daily workstation. 16 GB, usually a few gigabytes into swap. It runs Claude Desktop and therefore this MCP server.
A Pop!_OS box with an RTX 5070 Ti — the laboratory. It runs a 35B model called ornith under
llama-serveron port 8080, and is idle most of the day.
An SSH tunnel makes the remote model look local to the Mac:
ssh -N -o ServerAliveInterval=30 -L 127.0.0.1:8081:127.0.0.1:8080 pop-ospop-os is a ~/.ssh/config alias with a key and IdentitiesOnly yes, so the server can
reach it non-interactively with BatchMode=yes.
The MCP client entry is just:
{ "mcpServers": { "simple-job": { "command": "node", "args": ["/path/to/mcp-simple-job/index.js"] } } }Defaults do the rest: the model at 127.0.0.1:8081, the worker machine at pop-os, and
the ledger in an existing ~/Code/harness/ if there is one.
Nothing is ever called by hand. The assistant picks the tool — which is a harder problem than it sounds, and is covered below.
Running it on yours
Two machines, one running the client and one running the model:
{
"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"
}
}
}
}One machine — everything local, no SSH anywhere:
{
"env": {
"ORNITH_URL": "http://127.0.0.1:11434/v1/chat/completions",
"ORNITH_MODEL": "qwen3:8b",
"SEARCH_HOSTS": "mac"
}
}SEARCH_HOSTS=mac is the switch that says "there is no second machine". Fetching,
downloading and searching all happen locally, and search simply has one rate budget
instead of two. Everything else behaves the same.
Environment variables
variable | default | what it does |
|
| the chat endpoint |
|
| model name sent in the request |
|
| SSH alias of the worker machine |
|
| machines to alternate searches across; set to |
|
| minimum gap between searches from one machine |
|
| how long a machine sits out after being throttled |
| next to | where search timing state is kept |
|
| the SQLite ledger |
|
| optional trace id to stamp on rows |
The ledger is optional. It is created on first use, and if it cannot be written the
jobs still run — logging is best-effort and never blocks work. HARNESS_TRACE is a hook
for the author's own tracing setup; ignore it and rows simply have a null trace id.
Getting it actually used
This is the part most people skip, and it is the part that decides whether any of the above matters.
A tool that nothing routes to is invisible no matter how well it works. The author has a separate MCP server that works perfectly and had zero calls in months, purely because nothing ever told the assistant to reach for it. Building a capability and routing to it are two different jobs, and finishing the first one feels like finishing.
Three ways to close that gap, cheapest first. Most people want the second one.
1. Do nothing, and see. Some clients read tool descriptions well enough that a sufficiently obvious request — "summarise these forty pages" — finds the tool on its own. Worth trying for a day before adding machinery. Watch whether it actually gets called.
2. Put a rule where your client keeps standing instructions. Claude Desktop project
instructions, a CLAUDE.md for Claude Code, .cursorrules, a custom GPT's instructions —
whatever your client reads on every turn. Something like:
There is a local model available through
simple-job. Use it when the material is not already in context and the job is mechanical: summarising pages or files, web search plus reading, fetching downloads, extraction and reformatting. It is free and does not spend context on the source.Do it yourself when the text is already in context, when the job needs interpretation rather than transcription, or when being right matters more than being checkable. Never delegate judgment calls, code that must be correct, or file edits.
Every job must carry a check — the server refuses work it cannot verify.
Spend as many words on when not to delegate as on when to. The failure mode of routing a delegation tool is over-delegation, and an assistant that ships everything downhill will hand you faithful transcription where you wanted judgment.
3. Wire it into a router, if you have one. If your setup already matches situations to tools, add an entry for "bulk reading or fetching material not yet in context". The advantage over a standing instruction is that it is measurable — you can count whether it fired when it should have. A standing instruction either works or it does not, and nothing records which.
What not to send it
Anything where "looks right" is the only test. Judgment calls. Code that must be correct. Editing files.
And one boundary found by measurement rather than taste: a small local model transcribes faithfully but does not interpret. In testing it reproduced a source's ambiguous phrasing verbatim instead of resolving what it meant, and summarised a repository's star count as though it were part of a bug report. Send it transcription. Keep interpretation.
Notes from building it
Everything below is a measurement, not an opinion. The numbers are in the code comments too.
Thinking is off by default
Reasoning models emit their deliberation and their answer from the same token budget. On one summarising job run three times identically, two of the three spent 5,500–6,000 characters thinking, hit the ceiling, and returned an empty answer with HTTP 200.
Raising max_tokens did not fix it. reasoning_effort: "low" did not fix it. A
/no_think system tag did not fix it. Only chat_template_kwargs: {enable_thinking: false} did, and the same job then answered in 258 tokens. Pass think: true for a job
that genuinely needs deliberation, and raise max_tokens with it.
Search is rationed, and DuckDuckGo lies about why
DuckDuckGo does not rate-limit politely:
a served query is HTTP 200, ~28 KB, ten result links
a refused one is HTTP 202, ~14.2 KB, and its text reads "Please complete the following challenge... Select all squares containing a duck"
It is a captcha flag on the IP, not a timed limit, and spacing does not clear one. After four minutes of silence, six queries at 30 s spacing from one machine and six at 15 s from the other were 0 for 12. Polling every 5 s during a block never recovered in 162 s — retrying feeds it. The flag decayed on its own in roughly twenty minutes.
So searches are spaced, alternated across machines (two IPs are two budgets), and a
throttle is reported as throttled, never as "no results". Those mean opposite things.
Reading follows the question
A long page gets cut to fit the model's window, and cutting from the top answers the wrong question silently. Asked about "sparse gating and load balancing" in a 40,063-character page with an 8,000-character window, the first version returned a fluent summary of the article's opening — in which "load balancing" never appears (it starts at character 16,181) and "sparse" never appears (14,671).
So focus steers the window: a head for context, then the passages around each named
term, one window guaranteed per term before any term gets a second. Two earlier
versions were not enough — substring matching found "load" inside "download" and reported
42 hits of noise, and taking passages in document order spent the budget before reaching
character 16,181.
If the page never uses those words, the call returns ok:false with focus_not_found.
Zero hits is a better answer than a plausible summary of other material.
A page that is mostly script is refused
One site served 68,896 bytes containing 40 characters of text ("Loading..."), which the
original if not text guard passed — so the shell went into a summary as source material
and the model wrote a confident benchmark figure citing it.
Two tests now, because either alone is fooled: an absolute floor, and a text-to-bytes ratio that only condemns a page which is also short. A GitHub issue is 290,000 bytes of markup around 3,896 characters of real discussion, and the ratio alone threw it away.
Citations are numbered so they can be checked
search_and_summarize numbers the pages and asks for [1], [2] rather than urls. Asked
for urls, the model attributed a figure it had read in a blog to a documentation page —
the fact was real and in the material, the attribution was not, and summary_of cannot
see that because a mislabelled bullet is the right length and is not a copy.
A url is a long opaque string to copy correctly. An integer is not, and it can be range-checked against the pages actually read — which the code does, failing the call on an out-of-range number and counting bullets with no source at all.
Which machine is faster?
Verified by identical sha256 on both sides:
client machine | worker machine | |
ssh round-trip | — | ~185 ms per call |
fetch 4 pages | ~1.7 s | ~2.0 s |
download 20 MB | 17.5 MB/s | 12.6 MB/s |
The client machine was faster at both. Speed is not the reason to send work to the worker. The reasons are that it holds the model, that it is idle while the other machine is in use, and that a second machine is a second search budget. Choose a download's host by where the file is needed, not by throughput.
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 checksThe end-to-end suite spawns the actual server the way a client would, against a throwaway ledger. An in-process test would not catch a PATH or environment bug, and those are exactly the ones that only appear after a restart.
Changes to index.js take effect when the client next starts the server. pop_agent.py
is re-read on every call, so changes to fetching, searching and downloading are live
immediately.
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
Exact IBAN, VAT, cron, regex answers; HTML/URL to hosted PDF or screenshot; agent memory; workflows.
Verifies AI agent work end to end: real artifacts and outcomes checked, not self-reported success.
Verified 2-3 step AI-agent missions with whole-transaction success-only charging.
Watchdog for unattended AI agents: alerts, evidence checks and a verifiable proof per run.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables Claude Code to delegate mechanical tasks (summaries, boilerplate, reformatting) to local models running in LM Studio.1MIT
- 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
- AlicenseAqualityBmaintenanceLets a frontier coding agent delegate research, cataloguing, and long-running computation to a local LLM with guarded filesystem, web, and Python execution tools, preserving the agent's context and tokens.6MIT
- 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