Skip to main content
Glama

mcp-simple-job

Pasa una subtarea a un modelo local en otra máquina y verifica el resultado antes de devolverlo.

Construido para una forma concreta de problema: el asistente capaz y medido se ejecuta en la máquina ante la que estás sentado, mientras una caja con GPU perfectamente buena permanece inactiva en un rincón. Leer cuarenta archivos, resumir una página larga, descargar un conjunto de datos — nada de eso necesita el modelo caro, y hacerlo en el contexto del asistente gasta el único recurso que es genuinamente escaso.

Medido en la configuración del autor, frente a hacer los mismos cuatro trabajos en contexto: ~2,7 veces más rápido, y 6,1 veces menos contexto gastado, porque las páginas en bruto nunca entran en él.

La única regla

Un trabajo debe venir con una verificación. Una tarea que no pueda decir cómo se sabría que ha funcionado es rechazada — no advertida, rechazada.

Esto no es desconfianza del modelo local. Es que el que llama no puede saberlo. Cuando el asistente delega un resumen y recibe cuatrocientas palabras confiadas, no tiene ninguna forma independiente de saber si esas palabras describen el documento o algo más. Delegar sin una verificación añade un segundo punto donde una luz verde no significa nada.

Las verificaciones son deliberadamente aburridas: nonempty, contains, regex, json_keys, line_count, shell (tu argv, salida 0 pasa, salida canalizada a stdin) y summary_of (más corto que la fuente y no una copia de ella).

Related MCP server: Forgehand

Las cuatro subtareas

tool

qué hace

dónde ocurre el trabajo

simple_job

una solicitud sencilla con tu propia verificación

el host del modelo

summarize

texto, o URL(s) obtenidas primero

máquina trabajadora (obtención + modelo)

search_and_summarize

buscar, leer las páginas principales, resumir

la búsqueda alterna hosts, el resto en la máquina trabajadora

download

obtener un archivo, informar bytes + sha256

máquina trabajadora por defecto, cualquier host configurado

simple_job_stats informa de cómo han ido realmente todos ellos, a partir de una fila del registro escrita para cada trabajo.


Poniéndolo en marcha

Requisitos

  • Node 18+ en la máquina que ejecuta el servidor MCP.

  • Un endpoint de chat compatible con OpenAI. llama-server de llama.cpp, Ollama, vLLM, LM Studio o una API alojada: cualquier cosa que responda a POST /v1/chat/completions.

  • Python 3.9+ en cualquier máquina que haga la obtención. Solo biblioteca estándar; sin pip install, sin node, sin beautifulsoup.

  • Autenticación por clave SSH a la segunda máquina, si usas una. Es opcional (ver más abajo).

Cómo está conectado en las máquinas del autor

Dos ordenadores:

  • Un Mac mini — la estación de trabajo diaria. 16 GB, normalmente unos pocos gigabytes en swap. Ejecuta Claude Desktop y, por tanto, este servidor MCP.

  • Una máquina Pop!_OS con una RTX 5070 Ti — el laboratorio. Ejecuta un modelo de 35B llamado ornith bajo llama-server en el puerto 8080, y está inactiva la mayor parte del día.

Un túnel SSH hace que el modelo remoto parezca local para el Mac:

ssh -N -o ServerAliveInterval=30 -L 127.0.0.1:8081:127.0.0.1:8080 pop-os

pop-os es un alias de ~/.ssh/config con una clave y IdentitiesOnly yes, de modo que el servidor puede alcanzarlo de forma no interactiva con BatchMode=yes.

La entrada del cliente MCP es simplemente:

{ "mcpServers": { "simple-job": { "command": "node", "args": ["/path/to/mcp-simple-job/index.js"] } } }

Los valores por defecto hacen el resto: el modelo en 127.0.0.1:8081, la máquina trabajadora en pop-os y el registro en un ~/Code/harness/ existente, si lo hay.

Nada se llama nunca a mano. El asistente elige la herramienta — que es un problema más difícil de lo que parece, y se cubre más abajo.

Ejecutándolo en las tuyas

Dos máquinas, una que ejecuta el cliente y otra que ejecuta el modelo:

{
  "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"
      }
    }
  }
}

Una sola máquina — todo local, sin SSH en ningún sitio:

{
  "env": {
    "ORNITH_URL": "http://127.0.0.1:11434/v1/chat/completions",
    "ORNITH_MODEL": "qwen3:8b",
    "SEARCH_HOSTS": "mac"
  }
}

SEARCH_HOSTS=mac es el interruptor que dice «no hay segunda máquina». La obtención, la descarga y la búsqueda suceden todas localmente, y la búsqueda simplemente tiene un presupuesto de frecuencia en lugar de dos. Todo lo demás se comporta igual.

Variables de entorno

variable

valor por defecto

qué hace

ORNITH_URL

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

el endpoint de chat

ORNITH_MODEL

ornith:35b

nombre del modelo enviado en la solicitud

POP_HOST

pop-os

alias SSH de la máquina trabajadora

SEARCH_HOSTS

mac,pop

máquinas entre las que alternar las búsquedas; establece mac para una instalación de una sola máquina

SEARCH_GAP_MS

30000

intervalo mínimo entre búsquedas desde una misma máquina

SEARCH_BLOCK_MS

300000

cuánto tiempo permanece fuera una máquina tras ser limitada

SIMPLE_JOB_STATE

junto a index.js

dónde se guarda el estado de temporización de la búsqueda

HARNESS_LEDGER

~/Code/harness/ledger.db si ese directorio existe; si no, ~/.mcp-simple-job/ledger.db

el registro SQLite

HARNESS_TRACE

~/Code/harness/current_trace.txt

identificador de traza opcional para estampar en las filas

El registro es opcional. Se crea en el primer uso, y si no se puede escribir los trabajos siguen ejecutándose: el registro se hace con el mejor esfuerzo y nunca bloquea el trabajo. HARNESS_TRACE es un gancho para la configuración de trazado del propio autor; ignóralo y las filas simplemente tendrán un identificador de traza nulo.

Conseguir que se use de verdad

Esta es la parte que la mayoría de la gente se salta, y es la parte que decide si todo lo anterior importa.

Una herramienta a la que nada enruta es invisible, por muy bien que funcione. El autor tiene un servidor MCP aparte que funciona perfectamente y tuvo cero llamadas en meses, puramente porque nada le dijo nunca al asistente que lo utilizara. Construir una capacidad y enrutar hacia ella son dos trabajos distintos, y terminar el primero se siente como terminar.

Hay tres maneras de cerrar esa brecha, la más barata primero. La mayoría de la gente quiere la segunda.

1. No hagas nada, y observa. Algunos clientes leen las descripciones de herramientas lo bastante bien como para que una solicitud suficientemente obvia — «resume estas cuarenta páginas» — encuentre la herramienta por sí sola. Vale la pena probarlo durante un día antes de añadir mecanismos. Observa si realmente se llama.

2. Pon una regla donde tu cliente guarde las instrucciones permanentes. Instrucciones de proyecto de Claude Desktop, un CLAUDE.md para Claude Code, .cursorrules, las instrucciones de un GPT personalizado — lo que sea que tu cliente lea en cada turno. Algo así:

Hay un modelo local disponible a través de simple-job. Úsalo cuando el material no esté ya en contexto y el trabajo sea mecánico: resumir páginas o archivos, búsqueda web más lectura, descargar archivos, extracción y reformateo. Es gratis y no gasta contexto en la fuente.

Hazlo tú mismo cuando el texto ya esté en contexto, cuando el trabajo necesite interpretación en lugar de transcripción, o cuando acertar importe más que poder verificarlo. Nunca delegues decisiones de criterio, código que deba ser correcto o edición de archivos.

Cada trabajo debe llevar una verificación: el servidor rechaza el trabajo que no puede verificar.

Dedica tantas palabras a cuándo no delegar como a cuándo hacerlo. El modo de fallo de enrutar hacia una herramienta de delegación es la sobredelegación, y un asistente que lo envía todo cuesta abajo te entregará una transcripción fiel donde querías criterio.

3. Conéctalo a un enrutador, si tienes uno. Si tu configuración ya hace corresponder situaciones con herramientas, añade una entrada para «lectura masiva u obtención de material aún no en contexto». La ventaja sobre una instrucción permanente es que es medible: puedes contar si se activó cuando debería. Una instrucción permanente o funciona o no, y nada registra cuál de las dos.

Qué no enviarle

Cualquier cosa donde «tiene buena pinta» sea la única prueba. Decisiones de criterio. Código que deba ser correcto. Editar archivos.

Y un límite encontrado por medición más que por gusto: un modelo local pequeño transcribe fielmente pero no interpreta. En las pruebas reprodujo literalmente el fraseo ambiguo de una fuente en lugar de resolver lo que significaba, y resumió el número de estrellas de un repositorio como si formara parte de un informe de error. Envíale transcripción. Conserva la interpretación.


Notas al construirlo

Todo lo que sigue es una medición, no una opinión. Los números están también en los comentarios del código.

El razonamiento está desactivado por defecto

Los modelos de razonamiento emiten su deliberación y su respuesta desde el mismo presupuesto de tokens. En un trabajo de resumen ejecutado tres veces de forma idéntica, dos de las tres veces gastaron 5.500–6.000 caracteres pensando, alcanzaron el límite y devolvieron una respuesta vacía con HTTP 200.

Subir max_tokens no lo arregló. reasoning_effort: "low" no lo arregló. Una etiqueta de sistema /no_think no lo arregló. Solo chat_template_kwargs: {enable_thinking: false} lo hizo, y el mismo trabajo respondió entonces en 258 tokens. Pasa think: true para un trabajo que realmente necesite deliberación, y sube max_tokens con él.

La búsqueda está racionada, y DuckDuckGo miente sobre el motivo

DuckDuckGo no limita la tasa de forma educada:

  • una consulta atendida es HTTP 200, ~28 KB, diez enlaces de resultados

  • una rechazada es HTTP 202, ~14,2 KB, y su texto dice "Please complete the following challenge... Select all squares containing a duck"

Es una marca de captcha en la IP, no un límite temporal, y espaciar no la elimina. Después de cuatro minutos de silencio, seis consultas con 30 s de separación desde una máquina y seis con 15 s desde la otra fueron 0 de 12. El sondeo cada 5 s durante un bloque no se recuperó en 162 s — reintentar la alimenta. La marca se disipó por sí sola en unos veinte minutos.

Por eso las búsquedas se espacian, se alternan entre máquinas (dos IP son dos presupuestos), y una limitación se informa como throttled, nunca como «sin resultados». Esas dos cosas significan lo contrario.

La lectura sigue a la pregunta

Una página larga se recorta para que quepa en la ventana del modelo, y recortar desde arriba responde a la pregunta equivocada en silencio. Al preguntar por "sparse gating and load balancing" en una página de 40.063 caracteres con una ventana de 8.000 caracteres, la primera versión devolvió un resumen fluido del inicio del artículo — en el que "load balancing" nunca aparece (empieza en el carácter 16.181) y "sparse" nunca aparece (14.671).

Así que focus dirige la ventana: una cabecera para el contexto, luego los pasajes alrededor de cada término nombrado, una ventana garantizada por término antes de que ningún término tenga una segunda. Dos versiones anteriores no fueron suficientes: la coincidencia de subcadenas encontró "load" dentro de "download" e informó de 42 coincidencias de ruido, y tomar los pasajes en orden del documento gastó el presupuesto antes de llegar al carácter 16.181.

Si la página nunca usa esas palabras, la llamada devuelve ok:false con focus_not_found. Cero coincidencias es una respuesta mejor que un resumen plausible de otro material.

Una página que es mayormente script es rechazada

Un sitio sirvió 68.896 bytes que contenían 40 caracteres de texto ("Loading..."), que el guard if not text original dejó pasar, así que el armazón entró en un resumen como material fuente y el modelo escribió con total confianza una cifra de referencia citándolo.

Ahora hay dos pruebas, porque cada una por separado se deja engañar: un mínimo absoluto y una proporción de texto a bytes que solo condena a una página que también es corta. Un issue de GitHub son 290.000 bytes de marcado alrededor de 3.896 caracteres de discusión real, y la proporción por sí sola lo descartó.

Las citas están numeradas para poder comprobarse

search_and_summarize numera las páginas y pide [1], [2] en lugar de urls. Al pedirle urls, el modelo atribuyó una cifra que había leído en un blog a una página de documentación: el dato era real y estaba en el material, la atribución no lo era, y summary_of no puede verlo porque una viñeta mal etiquetada tiene la longitud correcta y no es una copia.

Una url es una cadena larga y opaca de copiar correctamente. Un entero no lo es, y se puede comprobar su rango contra las páginas realmente leídas, lo que el código hace, fallando la llamada si el número está fuera de rango y contando las viñetas sin ninguna fuente.

¿Qué máquina es más rápida?

Verificado con sha256 idéntico en ambos lados:

máquina cliente

máquina trabajadora

ida y vuelta de ssh

—

~185 ms por llamada

obtener 4 páginas

~1,7 s

~2,0 s

descargar 20 MB

17,5 MB/s

12,6 MB/s

La máquina cliente fue más rápida en ambas. La velocidad no es la razón para enviar trabajo a la trabajadora. Las razones son que contiene el modelo, que está inactiva mientras la otra máquina está en uso, y que una segunda máquina es un segundo presupuesto de búsqueda. Elige el host de una descarga según dónde se necesite el archivo, no según el rendimiento.

Pruebas

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

La suite de extremo a extremo lanza el servidor real de la misma manera que lo haría un cliente, contra un libro de contabilidad desechable. Una prueba en proceso no detectaría un error de PATH o de entorno, y esos son exactamente los que solo aparecen después de un reinicio.

Los cambios en index.js surten efecto la próxima vez que el cliente inicie el servidor. pop_agent.py se vuelve a leer en cada llamada, por lo que los cambios en la obtención, la búsqueda y la descarga se aplican de inmediato.

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