Skip to main content
Glama

transport-lit — literatura gris del transporte a través de MCP

(Renombrado de dot-lit el 2026-08-27; las variables de entorno DOT_LIT_* y el antiguo directorio de datos todavía se reconocen.)

transport-lit ofrece a un asistente de IA (Claude Desktop, Claude Code, cualquier cliente MCP) búsqueda por palabras clave sobre los informes de investigación del transporte que PubMed no indexa y Semantic Scholar cubre deficientemente. Comenzó con ROSA-P, el repositorio de la Biblioteca Nacional de Transporte de EE. UU. (informes NHTSA DOT HS, investigación de FHWA/FRA/FTA/FAA, UTC y DOT estatales; https://rosap.ntl.bts.gov), y ahora recolecta seis fuentes OAI-PMH en tres continentes además de lo que exportes desde TRID:

clave

fuente

registros

notas

dot

ROSA-P — Biblioteca Nacional de Transporte del DOT de EE. UU.

90,599

repositorio completo

vti

VTI — Instituto Nacional Sueco de Investigación de Carreteras y Transporte (DiVA)

11,460

informes, ponencias de congresos, artículos; en/sv

bast

BASt — Instituto Federal Alemán de Investigación de Carreteras (OPUS)

2,970

1,901 con enlaces directos a PDF; de/en

wbokr

Repositorio de Conocimiento Abierto del Banco Mundial

976

subconjunto filtrado por título de 40,332; precisión medida 18/20

ipea

IPEA (Brasil)

207

subconjunto filtrado de 14,400; pt; precisión ~16/20

cepal

CEPAL/ECLAC (América Latina)

1,165

subconjunto filtrado de 52,199; es/en; precisión ~15/20

openalex

OpenAlex — trabajos tipificados como informe en 10 temas de transporte (global)

11,448

temas: Seguridad Vial y de Tráfico, Transporte Urbano y Accesibilidad, Planificación del Transporte, …

cinii

CiNii Research (Japón) — artículos, tesis, elementos del repositorio IRDB

118,609

requiere un ID de aplicación NII gratuito (TRANSPORT_LIT_CINII_APPID); 20 consultas ja/en, límite de 10k cada una; las consultas CJK usan coincidencia de subcadenas

pubmed

PubMed — subconjunto de transporte/lesiones (estrategia MeSH + 12 revistas)

105,028

recolección E-utilities segmentada por fecha; TRANSPORT_LIT_PUBMED_TERM anula la estrategia

trid

exportaciones de TRID que importes (transport-lit import)

tuyos

ver más abajo

transport-lit sources los lista; transport-lit harvest --source <key>|all los recolecta; el filtro collection en search_reports selecciona uno (p. ej. "VTI", "BASt", "World Bank", "CEPAL", "TRID"). Añadir otro repositorio OAI-PMH es una entrada en src/transport_lit/sources.py.

Creé esto para mi propio uso académico y de investigación personal y me complace compartirlo con cualquier otra persona que lo encuentre útil. Agradezco comentarios sobre errores, necesidades de integración, mejoras y otras observaciones. Los revisaré periódicamente y los integraré en la medida de lo posible, y lo documentaré. Si te interesa ayudar a respaldar esto o tienes otras ideas, ¡son bienvenidas! — Alex Quistberg (abre un issue)

Lo hace de la única manera que funciona para una fuente OAI-PMH: recolecta los metadatos de todo el repositorio en una base de datos SQLite local, construye un índice de texto completo FTS5 sobre ellos y sirve las búsquedas desde ese índice. Nada se consulta en vivo excepto una descarga opcional de PDF para el texto completo. Las recolecciones posteriores son incrementales (from= en la solicitud OAI) y económicas.

Herramientas

Herramienta

Qué devuelve

search_reports(query, year_min?, year_max?, collection?, doc_type?, source?, limit?, offset?)

Resultados ordenados: id, título, autores, año, números de informe, DOI, URL de destino, fragmento del resumen, match_mode. Los prefijos de columna funcionan (title:pedestrian, authors:lynn)

lookup(identifier)

Coincidencia exacta por DOI, PMID, número de informe ("DOT HS 813 097"), id o URL de destino

get_report(id)

Registro de metadatos completo, incluido cada campo bruto tal como se recolectó

get_fulltext(id, max_chars?, offset?, refresh?)

Resuelve el PDF (página de destino de ROSA-P, enlaces directos de BASt/OpenAlex), extrae y almacena en caché el texto; pagina con offset

search_fulltext(query, limit?)

Busca dentro de todo el texto de PDF ya extraído, con fragmentos

find_similar(id, limit?)

Registros relacionados entre fuentes, por título y términos de materia

export_citations(ids, format?)

RIS (Zotero/EndNote/Mendeley) o BibTeX para una lista de ids

get_references(id, limit?, refresh?)

Obras que cita el registro (OpenAlex, en caché); las entradas llevan record_id cuando la obra citada está en este índice

get_citations(id, limit?, only_in_index?, refresh?)

Obras que citan el registro; only_in_index=True = "qué en este índice se ha basado en él"; el total cited_by_count de OpenAlex

whats_new(days?, source?, limit?)

Registros que entraron en el índice en los últimos N días, con recuentos por fuente — la materia prima para un resumen semanal

list_collections()

Colecciones y tipos de documento con recuentos

harvest_status()

Recuentos de registros por fuente, última ejecución y su estado/notas, cobertura por año

Además, un prompt, literature_scan(topic), que guía a un modelo a través de un escaneo de múltiples consultas con citas. Cada herramienta lleva anotaciones MCP (readOnlyHint, idempotentHint; solo get_fulltext es openWorldHint porque puede obtener un PDF).

id acepta dot:93144, 93144, oai:dot.stacks:dot:93144 o la URL de destino. Los registros importados usan otros prefijos (trid:813520, import:…).

Sintaxis de consulta: las palabras sueltas se combinan con AND primero; si menos de limit resultados coinciden con todos los términos, los espacios restantes se rellenan con coincidencias de cualquier término (match_mode = all_terms / any_terms). Entrecomilla frases ("driver improvement"), usa un * final para un prefijo. La clasificación es BM25 con título, número de informe y autor ponderados por encima del resumen.

Related MCP server: litedocs-mcp

Configuración

Requiere Python 3.12+ y uv.

git clone https://github.com/aquistbe/transport-lit && cd transport-lit
uv tool install .            # installs `transport-lit` (CLI) and `transport-lit-mcp` (server) on PATH
export TRANSPORT_LIT_CONTACT=you@example.org   # identifies your harvester to ROSA-P (put it in your shell profile)
transport-lit probe                # live check: Identify / ListMetadataFormats / ListSets
transport-lit harvest              # full harvest the first time (~15 min), incremental afterwards
transport-lit status               # counts, last run, coverage by year
transport-lit search driver improvement program evaluation

Para desarrollo usa uv sync y antepone uv run a los comandos (p. ej. uv run pytest).

Cualquier cliente MCP, cualquier modelo

El servidor habla MCP estándar a través de stdio (por defecto) y Streamable HTTP / SSE (transport-lit-mcp --transport streamable-http --port 8765, endpoint /mcp). transport-lit mcp-config [client] imprime un fragmento listo para pegar para: Claude Desktop, Claude Code, Cursor, VS Code (modo agente de Copilot), Zed, Continue, LM Studio, Goose, Open WebUI y LibreChat (los dos últimos a través de HTTP). Un Dockerfile construye una imagen de servidor HTTP con el índice en un volumen.

Modelos abiertos. Probado de extremo a extremo el 2026-08-26 con Ollama qwen2.5:3b (3 B parámetros) mediante tests/ollama_smoke.py: ante "encuentra informes sobre programas de mejora de conductores; lista 3 títulos con años e ids", el modelo llamó a search_reports({"query": "driver improvement", "limit": 3}) una vez y respondió con títulos, años, ids y URL de destino correctos de tres fuentes. Decisiones de diseño que hacen que los modelos pequeños funcionen: diez herramientas con descripciones de una línea al principio, argumentos JSON planos con valores por defecto, objetos de resultados compactos (sin metadatos brutos en los resultados de búsqueda) y una cadena instructions del servidor que nombra las fuentes y los filtros. Ejecuta la prueba de humo con cualquier modelo con capacidad de herramientas: OLLAMA_MODEL=llama3.1 uv run python tests/ollama_smoke.py "…".

Registrar en Claude Desktop

transport-lit install-claude-desktop          # prints the JSON to add
transport-lit install-claude-desktop --write  # merges it into claude_desktop_config.json (keeps a .bak)

La entrada que escribe es simplemente:

{ "mcpServers": { "transport-lit": { "command": "/Users/you/.local/bin/transport-lit-mcp", "args": [],
                               "env": { "TRANSPORT_LIT_DATA_DIR": "/Users/you/.local/share/transport-lit",
                                        "TRANSPORT_LIT_CONTACT": "you@example.org" } } } }

Reinicia Claude Desktop después. Para Claude Code: claude mcp add transport-lit -- transport-lit-mcp.

Configuración (variables de entorno)

Variable

Default

Propósito

TRANSPORT_LIT_DATA_DIR

~/.local/share/transport-lit

Base de datos SQLite, páginas OAI sin procesar (raw/), caché de PDF (pdf/)

TRANSPORT_LIT_CONTACT

(unset)

Tu correo electrónico, incluido en el User-Agent para que el repositorio pueda contactarte. Configúralo.

TRANSPORT_LIT_MIN_INTERVAL

1.0

Segundos mínimos entre peticiones salientes

TRANSPORT_LIT_HTTP_TIMEOUT

90

Tiempo de espera por petición (s)

TRANSPORT_LIT_MAX_PDF_BYTES

80 MB

Rechaza PDFs más grandes en get_fulltext

TRANSPORT_LIT_MAX_PDF_PAGES

600

Detiene la extracción después de este número de páginas

TRANSPORT_LIT_CINII_APPID

(unset)

ID de aplicación NII; necesario para cosechar CiNii (regístrate en support.nii.ac.jp/en/cinii/api/developer)

NCBI_API_KEY

(unset)

Opcional; aumenta la tasa de E-utilities de PubMed de 3 a 10 peticiones/s

TRANSPORT_LIT_PUBMED_TERM

built-in strategy

Reemplaza la estrategia de búsqueda de PubMed

TRANSPORT_LIT_EMBED_BACKEND / TRANSPORT_LIT_EMBED_MODEL / TRANSPORT_LIT_EMBED_DIM

fastembed / MiniLM-L12 / 1024

Backend de búsqueda semántica, modelo, truncamiento de Ollama

OLLAMA_HOST

http://localhost:11434

Endpoint de Ollama para el backend ollama

Las variables también pueden estar en ~/.config/transport-lit/env como líneas KEY=VALUE (las variables de entorno reales tienen prioridad); ahí es donde debe ir un ID de aplicación NII o una clave NCBI, para que los trabajos de launchd, el servidor MCP y las ejecuciones manuales lo vean. No se requieren credenciales; todos los endpoints son públicos.

Instalación desde PyPI (sin clonar)

uv tool install transport-lit            # CLI + MCP server on PATH
uvx --from transport-lit transport-lit-mcp   # or run the server ad hoc
uv tool install "transport-lit[semantic]"    # with the bundled embedding backend

Publicado en https://pypi.org/project/transport-lit/ mediante la publicación de confianza de GitHub: una etiqueta ejecuta release.yml (compilación, lanzamiento de GitHub), que luego lanza publish.yml — el único flujo de trabajo registrado como publicador de confianza — donde la subida espera la aprobación del mantenedor en el entorno pypi. PyPI rechaza tokens de flujos de trabajo reutilizables y compara el archivo de flujo de trabajo de nivel superior, por eso la publicación es un flujo de trabajo lanzado por separado en lugar de un trabajo dentro del lanzamiento. server.json es el manifiesto para el MCP Registry (registry.modelcontextprotocol.io), para enviar después de que exista el paquete en PyPI.

Versiones fijadas

Los lanzamientos son etiquetas git vMAJOR.MINOR.PATCH (versionado semántico: patch = correcciones, minor = nuevas herramientas/fuentes, major = un cambio que rompe la superficie de herramientas o el esquema de base de datos). Cada etiqueta activa el flujo de trabajo release, que ejecuta las pruebas, compila una wheel + sdist y los adjunta a un GitHub Release. Las dependencias de Python se fijan mediante el uv.lock confirmado; CI instala con uv sync --frozen, por lo que un lanzamiento siempre se ejecuta contra las versiones exactas con las que se probó. Para instalar una versión específica:

uv tool install "transport-lit==0.3.0"                            # a pinned PyPI release
uv tool install git+https://github.com/aquistbe/transport-lit@v0.3.0  # or the matching git tag
uv tool upgrade transport-lit                                     # move to the latest release

Cosecha

transport-lit harvest                     # ROSA-P; auto: incremental if a complete full harvest exists, else full
transport-lit harvest --source all        # every configured source (vti, bast, wbokr, ipea, cepal, rosap)
transport-lit harvest --mode full         # walk the whole repository again
transport-lit harvest --mode incremental  # from = start of last complete run − 1 h, until = now
transport-lit harvest --from 2026-08-01T00:00:00Z   # explicit window (full timestamp required)
transport-lit harvest --max-pages 3       # testing only; the run is recorded as failed/partial
transport-lit reindex                     # re-parse the cached raw pages (no network) after a parser change

Qué hace el cosechador y por qué (todo el comportamiento verificado contra ROSA-P el 2026-08-26):

  • ListRecords&metadataPrefix=oai_dc, 100 registros por página, siguiendo resumptionToken hasta que llegue una página sin uno. Solo entonces la ejecución se marca como complete; cualquier error la deja failed y no avanza el puntero de "última cosecha", por lo que harvest_status nunca afirma que un índice parcial esté completo.

  • Ritmo: una petición cada TRANSPORT_LIT_MIN_INTERVAL segundos (por defecto 1 s). Los tokens caducan unos 60 s después de emitirse, por lo que los reintentos usan una espera corta (2/4/6 s).

  • badResumptionToken, errores de transporte, XML truncado o un sobre vacío mientras un token está activo → la lista se vuelve a emitir. ROSA-P no devuelve los registros en un orden estable por fecha (comprobado en cada página), por lo que la recuperación reinicia la lista desde el principio; los upserts hacen que eso sea idempotente. Si el orden hubiera sido monótono, el cosechador reanudaría desde la fecha más pequeña vista mediante until=. Hasta 8 recuperaciones por ejecución, luego failed.

  • noRecordsMatch: ROSA-P no envía el código de error; una cosecha selectiva vacía regresa como un sobre OAI-PMH sin elemento <ListRecords>. Eso se interpreta como "nada que hacer" solo cuando no había ningún token en juego; a mitad de lista se trata como truncamiento.

  • Comprobaciones de truncamiento silencioso: el cursor del token se compara con el recuento local en cada página; una cosecha completa que devuelve >5 % menos registros que la cosecha completa anterior se marca en las notas de la ejecución. Ambos aparecen en harvest_status().last_harvest.notes.

  • Eliminaciones: el repositorio informa deletedRecord=no, por lo que nada se elimina localmente; un registro que desaparece de ROSA-P permanece en el índice hasta una re-cosecha completa en un TRANSPORT_LIT_DATA_DIR nuevo.

  • Caché: cada página OAI se almacena comprimida con gzip en raw/run<N>-p<page>.xml.gz, de modo que el analizador se puede cambiar y el índice reconstruir sin tocar la red; los PDF y su texto extraído se guardan en caché bajo pdf/ y en la tabla fulltext.

  • from/until se formatean según la granularity declarada por cada repositorio (leída de Identify): ROSA-P, DiVA y DSpace aceptan marcas de tiempo completas YYYY-MM-DDThh:mm:ssZ, OPUS (BASt) solo acepta YYYY-MM-DD y la ventana se amplía un día por cada lado.

  • Los repositorios amplios (World Bank, IPEA, CEPAL) se filtran en el momento de la cosecha mediante un vocabulario de transporte multilingüe (sources.TRANSPORT_RE, en/es/pt/de/fr/sv): un registro se conserva si aparece un término en el título, o (IPEA, CEPAL) si aparecen dos términos distintos entre los encabezamientos de materia. Los resúmenes se ignoran — la literatura sobre desarrollo menciona carreteras y puertos de pasada — y los temas de World Bank también se ignoran (más de 100 encabezamientos por registro). Esto se ajustó el 2026-08-26 contra muestras aleatorias de 20 títulos: la regla flexible de título+temas+resumen conservó 15 271 registros de World Bank con una precisión aproximada del 35–50 %; la regla final conserva 976 con 18/20, IPEA 207 con ~16/20, CEPAL 1 165 con ~15/20. El precio es la exhaustividad; afloja min_subject_hits en sources.py y ejecuta transport-lit reindex --source <key> (sin red) si prefieres la otra opción. Las notas de la ejecución registran conservados vs omitidos.

  • transport-lit doctor [--repair] comprueba la integridad de SQLite, ambos índices FTS, las ejecuciones atascadas en running, las marcas de tiempo imposibles y el tamaño del WAL, y repara lo que es seguro; el almacén también hace checkpoint del WAL al cerrar. transport-lit cite prefetch [--source …] resuelve cada registro con DOI/PMID/OpenAlex a su obra de OpenAlex en lote (50 por petición) para que cited_by_count se conozca sin una llamada por registro.

transport-lit reindex --source <key> vuelve a analizar las páginas en caché y poda los registros que el analizador/filtro actual ya no conserva, por lo que los cambios de filtro nunca requieren una re-cosecha.

Reconstrucción mensual y actualizaciones semanales (calendario de mantenimiento)

El corpus cambia lentamente, por lo que el ritmo es: cosecha incremental semanal y reconstrucción completa mensual. harvest --fresh hace una cosecha completa en un almacén temporal y luego reemplaza atómicamente los registros dot: en el índice activo — la única forma de que desaparezcan los registros que ROSA-P deja de servir (su endpoint OAI-PMH no rastrea eliminaciones). Las fuentes importadas (exportaciones de TRID) no se tocan, y una reconstrucción fallida no cambia nada.

transport-lit install-schedule          # shows the two launchd agents
transport-lit install-schedule --write  # installs them: Mon 06:00 `--source all` incremental, 1st 05:00 `--source all --fresh`

Los registros van a $TRANSPORT_LIT_DATA_DIR/logs/. En Linux usa las líneas cron que imprime el comando.

Lista de verificación de mantenimiento mensual (realizada con la reconstrucción): lee los nuevos issues de GitHub; uv lock --upgrade && uv run pytest; anota las correcciones en la sección de changelog del lanzamiento; incrementa version en pyproject.toml y src/transport_lit/__init__.py; git tag vX.Y.Z && git push --tags.

TRID: importa lo que exportas

TRID (https://trid.trb.org) es la bibliografía de transporte más completa y el complemento natural de ROSA-P, pero no tiene API, su FAQ dice que TRB "no concede acceso a los sistemas backend de TRID ni levanta las restricciones de exportación/descarga", y su robots.txt no permite rastreadores de IA. Lo que todo usuario puede hacer es buscar y exportar. Por lo tanto:

  1. Ejecuta tu búsqueda en TRID, elige Export → RIS (también se ofrecen CSV y XML).

  2. transport-lit import ~/Downloads/trid-driver-improvement.ris --collection "TRID: driver improvement"

Los registros reciben ids trid:<accession> de la URL de vista de TRID, van a la colección TRID (search_reports(..., collection="TRID")), y reimportar el mismo archivo es idempotente. El importador es RIS genérico, por lo que las exportaciones de Zotero/EndNote/Scopus funcionan igual con --source <prefix>. get_fulltext en un registro importado solo sigue un enlace directo .pdf; de lo contrario, usa landing_url.

Lo que ofrece el endpoint OAI-PMH de ROSA-P

https://rosap.ntl.bts.gov/fedora/oai — repositorio "DOT Stacks" (la plataforma CDC Stacks), protocolo 2.0, fecha más antigua 2008-07-02, sin seguimiento de eliminaciones, sin conjuntos OAI (ListSets está vacío), y oai_dc es el único formato de metadatos. No obstante, es un Dublin Core calificado disfrazado: elementos como dc:contributor.author, dc:description.abstract, dc:relation.isPartOf, dc:identifier.uri (DOI y números de informe, p. ej. DOT HS 813 827), dc:coverage.spatial, dc:title.alternative y dc:description.tableOfContents están todos presentes. El analizador (dc.py) conserva cada campo bruto y deriva de ellos las columnas tipadas. dc:relation.isPartOf (separado por punto y coma) es lo que usan list_collections / el filtro collection.

Los enlaces a PDF no están en los metadatos; get_fulltext lee citation_pdf_url de la página de destino y recurre a la convención de datastream /view/dot/{n}/dot_{n}_DS1.pdf.

Verificación (2026-08-26)

Búsqueda semántica v0.4.0. 342 462 vectores (fastembed multilingüe MiniLM-L12, 384-d, paralelo de datos a 94 registros/s en 8 núcleos — 60 min para el corpus). Comprobación entre idiomas: "elderly pedestrian crashes at night" en modo semantic devuelve, entre sus 8 primeros, tres informes CiNii en japonés (análisis de 夜間 高齢歩行者 死亡事故, 1995–2011) junto a elementos de PubMed y CiNii en inglés; comprobación de vocabulario: "point system for problem drivers license suspension recidivism" encuentra la evaluación de inmovilización de vehículos de California de 1997 y el informe de revocación administrativa de 1986 de ROSA-P, que no comparten palabras de la consulta. La latencia híbrida es de ≈ 0,6 s (domina la codificación de la consulta), la de palabras clave ≈ 25 ms. Lección operativa registrada aquí para que nadie la repita: nunca elimines un archivo -wal de SQLite mientras otro proceso (p. ej. un servidor MCP en ejecución) tenga la base de datos abierta — contiene datos confirmados aún no consolidados.

Fuentes de API v0.3.0. OpenAlex: 58 páginas, 11 448 informes (10 temas, type:report), 1 428 con enlaces PDF. CiNii: 730 páginas, 144 348 resultados en 20 consultas, 118 609 únicos. PubMed: 105 028 artículos en 17 segmentos de fecha (E-utilities limita retstart a 10 000, por lo que los segmentos se obtienen de forma recursiva). Comprobación con modelo abierto: Ollama qwen2.5:3b respondió a una pregunta sobre mejora de conductores con una llamada correcta a search_reports.

Cosecha multifuente v0.2.0. VTI: 120 páginas, 11 944 vistos, 11 460 únicos (DiVA sirve algunos registros en varios conjuntos), 0 reanudaciones. BASt: 30 páginas, 2 987 vistos, 2 970 únicos; 1 901 con enlaces PDF directos; se probó la ruta incremental de granularidad diaria (24 registros). World Bank: 404 páginas / 40 332 vistos; IPEA: 144 / 14 400; CEPAL: 522 / 52 199 — las tres terminaron en una página sin token con 0 reanudaciones; recuentos filtrados arriba. Búsquedas puntuales: Fußgänger Unfall (BASt) → reconstrucción de accidentes y estadísticas de accidentes en carreteras rurales; acidentes de trânsito mortalidade (IPEA) → «Mortalidade por acidentes de transporte terrestre e desigualdades interestaduais no Brasil»; seguridad vial peatones (CEPAL) → gobernanza de la seguridad vial y evaluaciones de campañas; pedestrian safety (VTI) → estudios de formación de niños peatones de los años 1990.

v0.1.0 (primera cosecha de ROSA-P)

Completitud de la cosecha. La ejecución 1 (full) recorrió 908 páginas / 90 706 registros en 15 min (00:03:59–00:19:11 UTC) con 0 reanudaciones, 0 desajustes de cursor, y terminó en una página de 6 registros sin token de reanudación — la definición OAI-PMH de una lista completa. 90 603 registros únicos están en el almacén; la diferencia de 103 registros es el mismo registro que aparece en dos páginas, lo que ocurre porque ROSA-P no devuelve los registros en un orden estable (el cosechador lo registra: "datestamp ordering violated on page 2"). Una segunda pasada completa independiente, 30 minutos más tarde, en un directorio separado, devolvió exactamente los mismos números — 908 páginas, 90 706 vistos, 90 603 únicos — y los dos conjuntos de ID son idénticos (0 registros exclusivos de cada pasada). Los 103 repetidos son el repositorio que sirve el mismo registro en dos páginas, no registros omitidos.

Cobertura por década (año presente en 74 448 = 82 %; los 16 155 restantes no tienen fecha en ningún campo de metadatos; year_source indica si el año procede de dc:date (48 658), de una línea de descripción con solo el año (22 205) o del título (3 585)):

década

registros

década

registros

años 1900–1930

3 243

años 1980

5 408

años 1940

2 618

años 1990

8 936

años 1950

2 627

años 2000

11 466

años 1960

2 947

años 2010

18 690

años 1970

5 057

años 2020

13 456

Recuperación de ítems conocidos (transport-lit search …, posición 1 salvo que se indique lo contrario):

Objetivo

Consulta

Resultado

NHTSA Countermeasures That Work

"countermeasures that work" guide highway safety offices

dot:1789 (2005), dot:1827 (3.ª ed. 2008), dot:40255 (1.ª ed. 2006), dot:1778 (2.ª ed. 2007); la 11.ª ed. de 2023 es dot:72947 (DOT HS 813 490), la 10.ª ed. dot:57466. La frase simple por sí sola sitúa en primer lugar los resúmenes de una página de Traffic Tech de CTW (los documentos cortos ganan en BM25), y después las guías.

Evaluación del Oregon DMV Driver Improvement Program (Strathman et al., 2007)

oregon driver improvement program strathman

dot:21848 «Evaluation of the Oregon DMV driver improvement program», Strathman, Kimpel, Leistner; informe n.º SPR 634. Sin fecha en los metadatos de ROSA-P.

Informes de mejora de conductores de Virginia (Lynn, 1982)

virginia driver improvement lynn

dot:18959 (informe de 12 meses), dot:18905 (efectos a corto plazo), dot:18969 (informe final de 24 meses), todos de Cheryl Lynn, Virginia Highway & Transportation Research Council. Sin fecha en los metadatos de ROSA-P.

Consulta real driver improvement program evaluation negligent operator (6 primeros de 10):

  1. dot:18905 — An evaluation of the short-term effects of the Virginia driver improvement program (Lynn) — all_terms

  2. dot:29326 — Review of NJ point system (Carnegie, Ozbay, Mudigonda, 2013; FHWA NJ-2013-004) — all_terms

  3. dot:18959 — …Virginia driver improvement program on negligent driving: 12-month report (Lynn)

  4. dot:18969 — …Virginia driver improvement program on negligent driving: 24-month report (Lynn)

  5. dot:17678 — Study of recidivism rates among drivers administratively sanctioned by the New Jersey MVC (Carnegie et al., 2009)

  6. dot:17677 — Study of the effects of plea bargaining motor vehicle offenses (Carnegie et al., 2009)

La extracción de texto completo se comprobó en dot:93144 (DOT HS 813 827, PDF de 3,7 MB, resuelto mediante citation_pdf_url). Pruebas unitarias: uv run pytest (analizador para ambos perfiles de metadatos, respaldo de año, búsqueda/filtros FTS, idempotencia de upsert, tokenizador de consultas, normalización de ID).

Estructura

src/transport_lit/
  config.py    paths, User-Agent, pacing, limits (env-overridable)
  oai.py       rate-limited OAI-PMH client; typed errors; raw-page cache
  dc.py        oai_dc record -> typed dict (authors, year, DOI, report numbers, collections …)
  store.py     SQLite schema, FTS5 index + triggers, search, stats, harvest-run bookkeeping
  harvest.py   full / incremental harvest with completeness + truncation handling
  fulltext.py  PDF resolution, download (size-capped), pypdf extraction, cache
  server.py    MCP tools (FastMCP / MCPServer)
  importers.py RIS import (TRID exports and any other reference-manager export)
  cli.py       transport-lit probe | harvest [--fresh] | import | reindex | status | search | get | fulltext
               | install-claude-desktop | install-schedule
.github/workflows/  ci.yml (tests on push/PR), release.yml (wheel + GitHub Release on tag)
tests/         unit tests (parser, store, query tokenizer)

Añadir una segunda fuente más adelante (p. ej., NHTSA crashstats)

El almacén es independiente de la fuente: records.id es una cadena con prefijo (dot:93144 hoy), harvest_runs.source registra qué cosechador escribió una ejecución, y al índice FTS no le importa de dónde procede una fila. Para añadir una fuente:

  1. Escribe src/transport_lit/sources/<name>.py que exponga harvest(store, *, mode, progress) y que genere dicts con la misma forma que produce dc.parse_record (id, title, authors, year, abstract, report_numbers, doi, landing_url, collections, raw, …) y llame a store.upsert_records(). Usa un nuevo prefijo de ID (nhtsa:812115) y pasa tu propio nombre de source a store.start_run() para que harvest_status pueda informar de él por separado.

  2. Reutiliza oai.RateLimiter y config.USER_AGENT por cortesía; guarda las respuestas sin procesar en raw/<source>/ para la reproducibilidad.

  3. Añade a harvest.status() un bloque por fuente (recuento por prefijo de id).

  4. Añade una opción --source a transport-lit harvest y, si

Fuente

Fondos

Acceso automatizado

Veredicto

VTI (Suecia) vía DiVA vti.diva-portal.org/dice/oai

7,474 registros, conjunto all-vti; instituto de investigación en seguridad vial

OAI-PMH, completeListSize, oai_dc + swepub_mods + MARC21

Cosecha — integración directa

BASt (Alemania) OPUS bast.opus.hbz-nrw.de/oai

2,987 registros; informes del instituto federal de investigación de carreteras

OAI-PMH, completeListSize, oai_dc + xMetaDissPlus

Cosecha — integración directa

World Bank Open Knowledge Repository openknowledge.worldbank.org/server/oai/request

40,332 registros; 1,787 resultados para "seguridad en el transporte"; el conjunto OAI transport solo contiene 100

OAI-PMH (DSpace 7) + DSpace REST discover/search

Cosechar todo, filtrar por materia; o consulta REST

WHO IRIS iris.who.int/oai/request

276,681 registros; 3,334 resultados para "tráfico vial"; sin conjuntos

OAI-PMH + búsqueda DSpace REST

Consulta REST por materia (el recorrido OAI completo son 2,800 páginas)

Repositorio de la CEPAL (América Latina) repositorio.cepal.org/server/oai/request

52,199 registros; sin conjuntos por materia

OAI-PMH + DSpace REST

Cosechar y filtrar por materia

MTT Chile Biblioteca Digital de Transportes biblioteca.mtt.gob.cl

5,820 filas de program_report con nombre, descripción, categoría y archivos

GraphQL de Hasura abierto en api.biblioteca.mtt.gob.cl/v1/graphql (introspección habilitada, lectura sin autenticación)

Cosechable vía GraphQL; confirmar primero los términos de uso con MTT

OpenAlex api.openalex.org

2,604 obras tipificadas como informe que coinciden con "seguridad vial"; 16,639 obras de cualquier tipo para "seguridad de peatones"

API REST gratuita, paginación por cursor

Mejor agregador global; usar como fuente para literatura gris no estadounidense y DOI

GOV.UK (DfT) gov.uk/api/search.json

4,998 elementos de DfT para "investigación en seguridad vial"

API de contenido gratuita

Cosechable; requiere filtrado por tipo de documento

España, Centro de Documentación del Transporte

66,000 registros bibliográficos (45,000 monografías) en AbsysNet

Solo OPAC; el sitio bloquea clientes que no son navegadores (HTTP 403)

Fuera de alcance a menos que el ministerio exponga OAI/Z39.50

TRIMIS (UE) trimis.ec.europa.eu

Proyectos y resultados de transporte financiados por la UE

Sitio activo; sin API documentada (existen volcados de datos abiertos masivos)

Evaluar el volcado de datos abiertos, no el sitio

Publicaciones del BID, CAF Scioteca

Informes de transporte de bancos de desarrollo

DSpace, pero bloqueado para bots (403 / página de verificación)

Fuera de alcance a menos que se conceda acceso

SWOV (Países Bajos)

Biblioteca del instituto de seguridad vial

Página de detección de bots en cada ruta

Fuera de alcance

ITF/OCDE

Informes del Foro Internacional de Transporte

HTTP 403 para clientes que no son navegadores; sin API

Fuera de alcance (la API de OECD iLibrary está bajo licencia)

Transport Data Commons portal.transport-data.org

Conjuntos de datos (32 instituciones, más de 120 países), PortalJS

No se encontró API (/api/3 devuelve 404)

No es literatura

ITDP Rapid Transit Database

Conjunto de datos (km de BRT/LRT/metro por ciudad); descarga de Google Sheet

Solo descarga

No es literatura

Base de datos AASHTO TERI

Declaraciones de necesidades de investigación, no informes completados

Ninguno

No es literatura

nismod/Africa-transport-database (GitHub)

Conjunto de datos GIS de infraestructura de transporte africana

Clon de Git

No es literatura

TRID

1,5 millones de registros bibliográficos, internacional

Ninguno; acceso a exportación/backend denegado por política

Fuera de alcance

Por región (pruebas realizadas el mismo día; "abierto" significa acceso automatizado sin autenticación confirmado):

Región

Qué existe

Acceso

Notas

Europa

VTI (SE), BASt (DE) — arriba; HAL (FR): 74 952 elementos en la colección de la Université Gustave Eiffel/IFSTTAR, 117 resultados de tipo REPORT para «sécurité routière»; OpenAIRE: 82 053 publicaciones sobre «road safety» (todos los tipos, agregador a escala europea); Cellar de la Oficina de Publicaciones de la UE SPARQL y CORDIS JSON de búsqueda responden ambos

HAL REST (abierto), OpenAIRE REST (abierto), Cellar SPARQL (abierto), CORDIS JSON (abierto); DTU Orbit OAI 500, TU Delft OAI no encontrado, TØI 403

El ITRD de ITF/OCDE se fusionó en TRID, por lo que el contenido de ITF solo es accesible a través de TRID

Australia / NZ

Figshare OAI-PMH + REST (Monash/MUARC y otras universidades australianas publican informes allí); páginas de informes de investigación de NZTA (HTML, 200); Austroads (403 para no navegadores); APO observatorio de literatura gris (403 para no navegadores); API de Trove (requiere clave)

Figshare abierto; Trove con clave; APO/Austroads bloqueados para bots

La búsqueda en Figshare de informes sobre «road safety» devuelve sobre todo conjuntos de datos/código: es necesario filtrar por tipo de elemento e institución para que sea útil

Japón

IRDB (irdb.nii.ac.jp/oai, agregador nacional de repositorios institucionales; JPCOAR 2.0 + oai_dc, 9 conjuntos); CiNii Research OpenSearch: 16 547 resultados para 交通安全; J-STAGE WebAPI: 9 786 para «traffic safety» (revistas, incl. IATSS Research)

Todo abierto, sin clave

IRDB es la vía de literatura gris (tesis, informes técnicos de universidades); los informes ministeriales de NILIM/PWRI son solo web

India

OAI de Shodhganga no encontrado en rutas DSpace; el sitio de CSIR-CRRI es HTML estático; IRC/MoRTH solo web

No se encontró ninguno

La mejor cobertura es OpenAlex/OpenAIRE para la producción de revistas indias; no se ha identificado ninguna fuente de literatura gris cosechable

China

No hay repositorio abierto de informes de MOT/RIOH; el sitio de RIOH es estático; CNKI tiene licencia

No se encontró ninguno

OpenAlex devuelve 15 416 obras de instituciones CN para «traffic safety» (literatura de revistas): esa es la vía realista

América Latina

IPEA (BR) repositorio.ipea.gov.br/server/oai/request: 14 400 registros, 8 021 resultados REST para «transporte»; CEPAL — arriba; MTT Chile GraphQL — arriba; las publicaciones técnicas del IMT México son listas HTML/PDF

OAI de IPEA/CEPAL abierto; GraphQL de MTT abierto; IDB/CAF bloqueados para bots; OAI de LA Referencia no encontrado en las URL probadas

No se encontraron endpoints OAI de SciELO en las rutas heredadas (revistas, en cualquier caso)

Los tres repositorios OAI-PMH con completeListSize (VTI, BASt, World Bank OKR) encajan en el cosechador existente con un prefijo de fuente y un metadataPrefix por fuente; los sitios DSpace 7 también toleran from/until y devuelven noRecordsMatch correctamente, por lo que las peculiaridades de ROSA-P en oai.py ya son el caso más difícil.

TRID queda fuera del alcance

TRID (https://trid.trb.org) no tiene API pública, ni endpoint OAI-PMH, ni exportación masiva. Su FAQ afirma que «TRB no concede acceso a los sistemas internos de TRID ni levanta las restricciones de exportación/descarga para individuos u organizaciones» y que la base de datos no puede utilizarse para entrenar LLM. Por ello, no se hace scraping deliberadamente.

Orden de v2 (acordado el 2026-08-26)

  1. VTI + BASt (hecho, v0.2.0) — 2. World Bank OKR, IPEA, CEPAL (hecho, v0.2.0) —

  2. IRDB Japón — 4. OpenAlex type:report como respaldo global — 5. un subconjunto de transporte de PubMed (ver más abajo). Nota sobre VTI: el oai_dc de DiVA no incluye enlace al texto completo; cambiar esa fuente a swepub_mods/mets_kb daría a get_fulltext la URL FULLTEXT01.pdf.

PubMed: un subconjunto de transporte/lesiones, no todo PubMed

Las E-utilities de PubMed (esearch/efetch, gratuitas, 3 req/s sin clave) pueden mantener un subconjunto local a partir de una estrategia fija, actualizado con mindate/maxdate con la misma cadencia semanal/mensual. Dos filtros complementarios, combinados con OR:

  • Estrategia MeSH — "Accidents, Traffic"[MeSH] OR "Pedestrians"[MeSH] OR "Bicycling"[MeSH] OR "Automobile Driving"[MeSH] OR "Motorcycles"[MeSH] OR "Wounds and Injuries"[MeSH] AND ("Transportation"[MeSH] OR "Built Environment"[MeSH] OR "City Planning"[MeSH]) — capta artículos de transporte en revistas generales y clínicas.

  • Lista de revistas — Accident Analysis & Prevention, Traffic Injury Prevention, Journal of Safety Research, Injury Prevention, Injury Epidemiology, Journal of Transport & Health, Safety Science, Transportation Research Part F, Transport Reviews, BMC Public Health (solo las etiquetadas como transporte), etc. — capta artículos de transporte indexados sin los términos MeSH.

SafetyLit (safetylit.org, el boletín semanal de literatura sobre lesiones afiliado a la OMS) mantiene exactamente esa lista de revistas y clasifica manualmente los artículos por tema, lo que lo convertiría en la mejor semilla para el filtro de revistas; su sitio no era accesible (se rechazó la conexión en todos los nombres de host) cuando se comprobó el 2026-08-26, por lo que su estado actual no está confirmado.

Resumen semanal (un boletín estilo SafetyLit)

transport-lit digest --days 7 [--abstracts] imprime un boletín en Markdown de todo lo que entró en el índice durante la última semana, agrupado por fuente, con recuentos. Se basa en first_seen_at, que se establece la primera vez que se ve un registro y se conserva entre reconstrucciones completas, de modo que una reconstrucción mensual no haga que todo el índice parezca nuevo. La herramienta whats_new expone los mismos datos a un modelo, que puede entonces redactar los resúmenes: el paso editorial que SafetyLit hacía a mano.

Comparación con otros MCP de literatura

Los servidores MCP de PubMed, Semantic Scholar, OpenAlex y arXiv hacen de proxy de consultas en vivo a una API. transport-lit se diferencia en tres aspectos: indexa literatura gris que los agregadores no tienen (informes de agencias, evaluaciones de departamentos de transporte estatales, institutos que contribuyen a ITRD), funciona sin conexión sobre un índice local tras la cosecha (sin límites de tasa en el momento de la consulta, sin clave), y es multifuente con un único esquema de id, de modo que un modelo puede buscar en todo a la vez y exportar citas. Lo que esos servidores tienen y este aún no: grafos de citas (quién cita a quién), desambiguación de autores y búsqueda semántica (embeddings) — ver más abajo.

Grafo de citas (v0.5)

get_references / get_citations (CLI: transport-lit cite refs|cites <id> [--in-index]) adjuntan el grafo de citas de OpenAlex al índice. Un registro se empareja con una obra de OpenAlex por su id de OpenAlex, DOI, PMID o —para los muchos informes de agencias sin fecha y sin DOI— por un título normalizado exacto con el año dentro de ±1 (match en el resultado indica cuál). Las aristas se obtienen en la primera solicitud y se guardan en caché en las tablas citations/works; las listas de citas se actualizan después de 90 días, las referencias nunca cambian. Las obras citadas que están a su vez en el índice devuelven su record_id, y los resultados de búsqueda incluyen cited_by_count una vez conocido.

Verificado el 2026-08-27: la evaluación DIP del DMV de Oregón (dot:21848, sin DOI, sin fecha en ROSA-P) se resolvió por título y lista 6 obras que la citan, entre ellas la evaluación DIP de Iowa y el estudio de reincidencia de Nueva Jersey; el informe de Lynn de 1982 sobre Virginia a 24 meses es citado por la revisión Cochrane de 2003 sobre educación de conductores tras la obtención del permiso (pubmed:12917984, en el índice); un artículo de 2020 sobre peatones mayores en Seúl tiene 57 referencias, 19 en el índice. OpenAlex resuelve los DOI 10.21949/… de NTL (15 493 registros de ROSA-P llevan uno); los registros sin ningún DOI —73 000 de los 90 599 de ROSA-P— dependen de la coincidencia por título, que acepta un título normalizado exacto, una relación de prefijo (colas de edición o subtítulo), o una superposición de tokens ≥ 0,8, siempre con el año dentro de ±1. La literatura gris que nadie ha citado en medios indexados seguirá mostrando cero; eso es una propiedad de los datos de citas, no del índice. OpenCitations y Semantic Scholar podrían añadirse como respaldo en las mismas tablas.

Búsqueda semántica (v0.4)

La búsqueda por palabras clave es FTS5/BM25. Añadir vectores convierte search_reports en una búsqueda híbrida (BM25 y coseno fusionados por rango recíproco) que encuentra registros por significado y entre idiomas: una consulta en inglés llega a registros en sueco, alemán, español, portugués o japonés. Todo se ejecuta localmente; sin cuenta, sin GPU.

uv tool install "transport-lit[semantic]"   # adds fastembed (ONNX runtime), ~60 MB
transport-lit embed                         # default backend: fastembed, multilingual MiniLM-L12 (384-d, 220 MB model, one-time download)
transport-lit embed --backend ollama --model qwen3-embedding:8b     # opt-in: any Ollama embedding model, truncated to 1024-d
transport-lit search "programa de mejoramiento de conductores" --mode semantic

Los resultados semánticos están diversificados por fuente: ninguna fuente puede ocupar más de la mitad de los resultados solicitados a menos que source/collection acote la búsqueda (TRANSPORT_LIT_SEMANTIC_PER_SOURCE). Razón medida: CiNii es un tercio del índice y contiene miles de títulos cortos en inglés («Pedestrian safety problems and countermeasures») que están más cerca de una consulta corta que cualquier registro con resumen; la diferencia de coseno con/sin resumen es solo de ~0,01, así que esto es composición del corpus, no un artefacto de longitud, y un límite es el remedio honesto. mode="semantic" es el ajuste especializado; hybrid sigue siendo el predeterminado.

La fusión híbrida pondera la lista de palabras clave con 1.0 y la lista semántica con 0.7 (TRANSPORT_LIT_SEMANTIC_WEIGHT), y un candidato solo semántico debe superar un coseno de 0.5 (TRANSPORT_LIT_SEMANTIC_MIN); eso mantiene precisas las consultas precisas mientras mode="semantic" sigue siendo el ajuste de recuperación / entre idiomas.

embed solo procesa registros que aún no tienen vector, así que tras la primera pasada la cosecha semanal añade segundos. Los vectores viven en $TRANSPORT_LIT_DATA_DIR/vectors/<backend-model>/ como una matriz float16 mapeada en memoria (342k × 384 ≈ 260 MB); la búsqueda es un producto punto por bloques, sin extensión. El conjunto de vectores activo se registra en el índice, de modo que search_reports(mode=…) usa el backend que lo haya producido: hybrid (predeterminado), keyword o semantic; mode_used en cada resultado indica qué se ejecutó, y se degrada a keyword cuando no existen vectores. harvest_status() informa del backend, modelo, dimensión y cobertura.

Backends medidos el 2026-08-26 en un portátil Apple Silicon de 10 núcleos, 256 registros reales (título + resumen): fastembed MiniLM-L12 ≈ 30 registros/s en CPU (el proveedor CoreML no es más rápido); Ollama qwen3-embedding:0.6b ≈ 20/s (1024-d), qwen3-embedding:8b ≈ 1.4/s (4096-d, truncado a 1024). Así que la primera pasada completa sobre 342k registros es una operación única de ~3 h con el modelo predeterminado; el incremento semanal es cuestión de segundos. Use --source para incrustar una fuente con un modelo más pesado. Tenga en cuenta que el modelo MiniLM lee como máximo 128 tokens (título más las primeras ~90 palabras del resumen); Qwen lee la ventana completa de 1.500 caracteres y recibe el prefijo de instrucción de recuperación del modelo en las consultas. La mayoría de los usuarios deberían instalar una instantánea (abajo) y no ejecutar la pasada completa en absoluto.

Instantáneas: omitir la recolección

uv tool install "transport-lit[semantic]"
transport-lit snapshot install https://github.com/aquistbe/transport-lit/releases/download/v0.4.0/transport-lit-2026-08.tar.gz
transport-lit mcp-config claude-desktop     # or install-claude-desktop --write

Eso es una instalación completa y buscable en minutos: 224k registros (todo excepto CiNii y TRID) con vectores. transport-lit snapshot build <file.tar.gz> empaqueta el índice SQLite junto con los vectores activos; snapshot install <url-or-file> desempaqueta una instantánea en un TRANSPORT_LIT_DATA_DIR nuevo, tras lo cual las recolecciones incrementales semanales mantienen la instalación al día (la instantánea incluye el registro de recolección, por lo que harvest --source all sabe dónde reanudar). Las instantáneas omiten CiNii (sus términos de API requieren registro y no mencionan la redistribución) y las importaciones de TRID (los términos de TRB); los usuarios recolectan esas fuentes ellos mismos. Las versiones incluyen una instantánea cuando se ha creado una.

Available Tools

12 tools
export_citationsA
Read-onlyIdempotent

Export records as RIS (Zotero/EndNote/Mendeley) or BibTeX. Pass transport-lit ids.

NameRequiredDescriptionDefault
idsYes
formatNoris

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds useful behavioral context by naming the exact output encodings and the required ID source ('transport-lit ids'). It does not discuss rate limits or edge cases, but the annotations lower the burden here.

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?

A single, front-loaded sentence with no filler. It immediately states the operation, the output formats, and the key input requirement. Every clause earns its place.

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 simple two-parameter tool, the description is mostly complete: annotations cover safety and idempotence, the output schema covers return shape, and the description covers formats and ID source. The main missing piece is guidance for choosing this over sibling citation/retrieval tools.

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?

Schema description coverage is 0%, so the description must compensate. It does by clarifying that ids should be 'transport-lit ids' and that format accepts RIS or BibTeX. This adds real meaning beyond the bare schema, though it could be more explicit about ID syntax or format case-sensitivity.

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 uses a specific verb and resource: 'Export records as RIS (Zotero/EndNote/Mendeley) or BibTeX.' This clearly distinguishes it from sibling retrieval tools like get_citations or get_references. The format list makes the deliverable concrete.

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 only usage guidance is 'Pass transport-lit ids,' which is an operational requirement rather than a when-to-use statement. It does not mention when to choose export_citations over alternatives such as get_citations, nor does it state exclusions or prerequisites. No alternatives are named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_similarB
Read-onlyIdempotent

Records similar to a given one (by title and subject terms), across all sources.

NameRequiredDescriptionDefault
idYes
limitNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover safety (readOnly, idempotent, non-destructive). The description adds useful context by specifying how similarity is determined ('by title and subject terms') and that it searches 'across all sources,' which implies no user, workspace, or source filtering. No contradictions with annotations, but no additional detail beyond that.

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 a single sentence with no filler. The core action and key modifiers are front-loaded, and every word adds information. It is appropriately concise without sacrificing necessary meaning.

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?

An output schema exists, so return values need not be described. The tool is simple and annotations cover its safety profile. However, the description leaves parameter semantics entirely unaddressed and does not provide enough context for an agent to confidently call it correctly, especially regarding what 'limit' does.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description does not compensate. It never mentions the 'id' parameter or the 'limit' parameter, nor does it explain what they mean. An agent must infer that 'a given one' refers to the required id and cannot know what limit controls. This is a significant gap.

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 a specific function: finding records similar to a given one, with explicit criteria ('by title and subject terms') and scope ('across all sources'). It is not a tautology and gives a clear sense of what the tool does. However, it does not explicitly distinguish itself from sibling tools such as search_reports or lookup, so it stops short of 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 Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage: when you have a record id and want similar records, use this tool. It does not provide any explicit when-not-to-use guidance or point to alternatives among the sibling tools. This is enough to infer context but lacks direct routing to alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_citationsA
Read-onlyIdempotent

Works that cite a record, via OpenAlex, cached locally (refreshed after 90 days). only_in_index=True returns just citing works that are in this index — 'what has built on this report'. cited_by_count_openalex is OpenAlex's total.

NameRequiredDescriptionDefault
idYes
limitNo
refreshNo
only_in_indexNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the tool read-only, idempotent, open-world, and non-destructive, so the description does not need to restate that. It adds valuable behavioral context: local caching with a 90-day refresh cycle, a distinction between index-only citing works and OpenAlex totals, and the meaning of cited_by_count_openalex. There is no contradiction with the annotations.

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 three tightly written sentences with the core behavior front-loaded and parameter notes kept compact. Every sentence earns its place, and there is no redundant restatement of the tool name or schema. The structure is ideal for a read-only cached query.

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?

Given the rich annotations and the presence of an output schema, the description covers the essential contextual elements: data source, caching behavior, the only_in_index filter, and a key output field. The refresh parameter's explicit behavior is not stated, but the 90-day refresh note makes it reasonably inferable. Overall, an agent has enough context to invoke the tool correctly.

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 0%, so the description carries the burden of parameter semantics. It does this well for only_in_index, explaining both the filter behavior and its conceptual significance. However, it does not explain id, the explicit effect of refresh=True, or limit, leaving a partial gap in parameter understanding.

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 tool returns works that cite a record, sourced via OpenAlex and cached locally. It makes the inbound-citation direction clear, which implicitly distinguishes it from the sibling get_references, though it does not explicitly name that sibling. The verb and resource are specific enough for an agent to understand the core function.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The only_in_index option provides a clear conditional scoping rule with an interpretive gloss ('what has built on this report'), and the 90-day refresh note sets expectations about data freshness. However, there is no explicit guidance on when to use this tool versus siblings like get_references or export_citations, and no exclusions are stated. Usage context is implied rather than fully spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_fulltextA
Read-onlyIdempotent

Resolve the report's PDF on ROSA-P, extract its text and return it (cached locally after the first call). Page through long documents with offset. Text is marked with [[page N]] separators. Scanned PDFs return status 'no_text'.

NameRequiredDescriptionDefault
idYes
offsetNo
refreshNo
max_charsNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnly, idempotent, openWorld), the description discloses caching behavior, page separator format, and scanned-PDF status 'no_text'. This adds substantive behavioral detail that an agent would not otherwise know.

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 three focused sentences with the core action front-loaded, followed by cache behavior, pagination, page markers, and a failure mode. No wasted words.

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?

The description covers the main call path, paging, cache behavior, and scanned-PDF status, and the output schema exists so return values need no explanation. However, the behavior of 'refresh' and 'max_chars' is not explained, so the description is not fully complete for all parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains 'offset' for paging, but does not clarify 'refresh' or 'max_chars'; 'id' is only implied by 'the report's PDF'. The description adds some meaning but leaves several parameter semantics undocumented.

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 uses a specific verb ('Resolve', 'extract') and a specific resource ('the report's PDF on ROSA-P'), clearly distinguishing this from siblings like search_fulltext or get_report. The exact scope of the tool is immediately understandable.

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 gives clear operational context: paging long documents with offset, local caching, and special handling for scanned PDFs. It does not explicitly mention alternatives or exclusions ('use search_fulltext instead'), but the use case is clear enough for an agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_referencesB
Read-onlyIdempotent

Works a record cites (its reference list), via OpenAlex, cached locally. Each entry carries record_id when the cited work is itself in this index. match says how the record was matched to OpenAlex (openalex, doi, pmid, or title).

NameRequiredDescriptionDefault
idYes
limitNo
refreshNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior. The description adds meaningful context beyond those: it explains the OpenAlex source, local caching, presence of record_id for in-index works, and the match field's allowed values. No contradiction with annotations.

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?

Three sentences with little filler; it packs source, caching, record_id, and match semantics efficiently. The grammar issue in the first sentence hurts clarity slightly, but the description is appropriately sized.

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?

The output schema plus annotations cover return values and safety, and the description explains the most important output nuance. However, it omits refresh/limit behavior and does not explicitly distinguish this reference-list tool from the get_citations sibling, leaving meaningful gaps for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the burden for the three parameters, but it does not explain id, limit, or refresh. The cache mention loosely relates to refresh and 'a record' implies id, but the semantics of refresh and limit are left undocumented.

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 identifies the resource as a record's reference list and adds useful source context (OpenAlex, cached locally). It is clear enough, though the opening phrase 'Works a record cites' is ungrammatical and lacks an explicit verb; the tool name helps compensate.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool: when you need the works cited by a record. It does not explicitly contrast it with siblings like get_citations, nor does it state when not to use it, leaving some routing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_reportA
Read-onlyIdempotent

Full metadata record for one report. Accepts 'dot:93144', '93144', the OAI identifier, or the ROSA-P landing URL. Includes every raw Dublin Core field.

NameRequiredDescriptionDefault
idYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the operation read-only, idempotent, and non-destructive, and the description adds useful context about accepted identifier formats and the raw Dublin Core content. However, it does not disclose any other behavioral traits such as not-found behavior or normalization, though the output schema covers the return shape.

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?

Three short sentences front-load the core purpose and then immediately give the parameter formats and content guarantee. There is no repetition of schema or annotation information and no filler.

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 single-parameter read-only tool with an output schema, the description is nearly complete: it explains what the tool returns and what the parameter can be. The only missing piece is explicit guidance about when to choose this tool over its siblings, but the low complexity and rich annotations keep this from being a major gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by specifying the accepted forms of the single 'id' parameter: dot-prefixed, bare numeric, OAI identifier, or ROSA-P landing URL. This is essential information an agent would otherwise lack, and it directly clarifies the parameter semantics.

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 identifies the resource as a metadata record for one report and states it includes every raw Dublin Core field, which clearly conveys what the tool returns. It implicitly distinguishes itself from siblings like search_reports and get_fulltext, but it never explicitly names an alternative or explains how it differs from them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool is used when a specific report identifier is available and full metadata is needed, but it offers no explicit when-to-use vs alternative guidance. Sibling names such as search_reports, lookup, and get_fulltext signal neighboring use cases, but the description does not route between them.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

harvest_statusA
Read-onlyIdempotent

Record counts per source, last harvest time/status and notes, coverage by year. If a source's last run is not 'complete' its part of the index may be partial.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish read-only, idempotent, non-destructive behavior. The description adds a meaningful behavioral detail beyond annotations: if the last run status is not 'complete,' the source's index portion may be partial, which warns agents about interpreting the data.

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?

Two sentences with no filler: the first front-loads every reported dimension and the second adds the essential interpretation caveat. Every clause contributes meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a parameterless read-only tool with an output schema, the description is complete. It tells the agent what information is available and warns about partial-index implications, leaving no obvious call-time decision unclear.

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 has zero parameters, so there is no parameter meaning for the description to add; the 100% schema coverage is vacuously satisfied. The description's focus on returned content is appropriate and needs no parameter elaboration.

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 enumerates what the tool exposes (per-source record counts, last harvest time/status, notes, and yearly coverage) and adds a precise partial-index caveat, so the resource is clear. It lacks an explicit 'get/retrieve' verb and does not differentiate from siblings, but the listed fields are specific enough to identify the purpose.

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 content makes the intended context clear: any need to inspect harvest runs, per-source counts, status, or coverage by year. It does not name alternatives or give when-not-to-use guidance, but the straightforward read-only status-report scope leaves little ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_collectionsA
Read-onlyIdempotent

Collections (ROSA-P relation.isPartOf values) with record counts, plus document types. ROSA-P's OAI-PMH endpoint exposes no OAI sets, so these are derived from the harvested metadata and are what the collection filter matches against.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds useful provenance behavior: values are derived from harvested metadata rather than OAI sets, which is non-obvious and affects interpretation of the returned data.

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?

Two dense sentences with no filler. The core output is stated first, and the provenance/usage note earns its place by clarifying why these collections exist and how they are used.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter read-only listing with an output schema present, the description fully covers purpose, data provenance, and the filtering use case. Nothing an agent needs to call or interpret this tool correctly is missing.

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 has zero parameters, so the schema leaves nothing undocumented and the described meaning of the return values is the main semantic contribution. No parameter-specific guidance is needed.

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 names a concrete resource (ROSA-P relation.isPartOf collection values), the returned information (record counts and document types), and the source of the data. This is specific enough to distinguish it from any sibling tool without opening schemas.

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?

It explains that the endpoint exposes no OAI sets and that these derived values are what the collection filter matches against, which tells an agent when this lookup is relevant. It does not explicitly list alternatives or exclusion conditions, but no sibling appears to be a direct collection-listing alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

lookupA
Read-onlyIdempotent

Exact lookup by DOI, PMID, report number (e.g. "DOT HS 813 097"), transport-lit id, or landing URL. Use this instead of search when you already have an identifier.

NameRequiredDescriptionDefault
identifierYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the tool read-only, idempotent, and non-destructive, so the description does not need to repeat those properties. It adds the behavioral trait of exact matching and enumerates identifier formats, but it does not disclose not-found behavior or side effects. An output schema exists, so return-value details are not required, but the behavioral disclosure is adequate rather than rich.

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?

Two sentences with no filler. The operation and accepted identifier types are front-loaded, and the routing rule is appended efficiently. Every clause adds information.

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 single-parameter lookup with rich annotations and an output schema, the description covers the essential selection and invocation information. It is slightly incomplete only in not clarifying boundaries against get_report/get_fulltext and in not stating what happens when a supplied identifier is not found.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema only defines an 'identifier' string with no description (0% coverage), so the description carries the full burden of explaining the parameter. It compensates exceptionally well by enumerating accepted forms: DOI, PMID, report number with a concrete example, transport-lit id, or landing URL. This gives an agent the concrete vocabulary needed to populate the parameter correctly.

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 opens with a concrete operation and resource: 'Exact lookup by DOI, PMID, report number (e.g. "DOT HS 813 097"), transport-lit id, or landing URL.' This clearly identifies what the tool does and the identifier forms it accepts. It also distinguishes itself from the search siblings with 'Use this instead of search when you already have an identifier,' though it does not differentiate from get_report or get_fulltext, which may also operate on identifiers.

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?

It explicitly states the condition to use this tool: 'Use this instead of search when you already have an identifier,' which is useful routing guidance. However, it gives no guidance on when lookup should be preferred over report- or fulltext-retrieval siblings, so the alternative-selection advice is partially incomplete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_fulltextA
Read-onlyIdempotent

Search inside the PDF text that get_fulltext has already extracted and cached (only documents someone fetched before). Returns snippets with [term] markers.

NameRequiredDescriptionDefault
limitNo
queryYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds useful behavioral context beyond annotations: search is limited to previously fetched/cached documents, and results are returned as snippets with [term] markers. It does not discuss edge cases like empty caches or query syntax, but it adds meaningful non-obvious behavior.

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?

Two short sentences with no filler. The core action and unique cached-only constraint are front-loaded, and every clause adds useful information. It is concise without sacrificing clarity.

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?

Given the low parameter count, rich annotations, and presence of an output schema, the description covers the essential invocation context: the cached-document prerequisite and the snippet output format. It is slightly light on query syntax expectations, but for a simple one-required-parameter search tool, the overall picture is sufficiently complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the burden of explaining parameters, but it only implies that 'query' is a term to search for via '[term] markers.' It never explicitly explains the query parameter semantics, matching behavior, or the meaning/effect of the 'limit' parameter. This leaves the agent reliant on parameter names alone.

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 names a specific action ('Search inside the PDF text'), a clear resource (text already extracted and cached by get_fulltext), and the output shape (snippets with [term] markers). It also distinguishes itself from get_fulltext and other siblings by noting it operates only on cached content, not raw PDFs.

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 clearly conveys when to use the tool: only after get_fulltext has fetched and cached a document, and only for documents someone previously fetched. It does not explicitly name alternative tools or exclusions (e.g., using search_reports for metadata searches), so it stops short of full when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_reportsA
Read-onlyIdempotent

Search titles, abstracts, subjects, authors and report numbers across all sources.

Args:
    query: Keywords. Quote phrases ("driver improvement"); trailing * = prefix;
        column prefixes work: title:pedestrian, authors:lynn, report_numbers:"813 097".
    year_min / year_max: Inclusive publication-year filter.
    collection: Substring filter on collection name (see list_collections), e.g. "NHTSA",
        "VTI", "BASt", "World Bank", "CEPAL", "TRID", "PubMed".
    doc_type: Substring filter on document type, e.g. "Tech Report", "Dataset".
    source: Comma-separated id prefixes to restrict to, e.g. "dot,vti" (dot = ROSA-P,
        vti, bast, wbokr, ipea, cepal, openalex, cinii, pubmed, trid).
    limit: Max hits (1-100). offset: for paging.
    mode: "hybrid" (default: keyword BM25 fused with semantic vectors when an embedding
        index exists), "keyword", or "semantic" (meaning-based, cross-language). Semantic
        results are capped at 50% from any one source unless `source`/`collection` is
        set; use `source` to search one corpus by meaning. ``mode_used`` says what ran.
Returns ranked hits; ``match_mode`` says whether all query terms matched (all_terms),
the hit came from the any-term fallback, or from the semantic index.
NameRequiredDescriptionDefault
modeNohybrid
limitNo
queryYes
offsetNo
sourceNo
doc_typeNo
year_maxNo
year_minNo
collectionNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the read-only/idempotent annotations, the description discloses important runtime behavior: hybrid mode fuses BM25 with semantic vectors, semantic results are capped at 50% from one source, mode_used reports which mode actually ran, and match_mode distinguishes all_terms, any-term fallback, and semantic matches. This is rich, non-obvious behavioral context.

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 structured as a clear Args list with the purpose front-loaded. It is dense but not wordy, and every sentence adds necessary information such as syntax rules, examples, source mappings, and mode behavior. The length is justified by 9 parameters and no schema-level descriptions.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of this search tool, the description covers all parameters, syntax variants, behavioral caveats, and output signals like match_mode and mode_used. An output schema exists, so return-value documentation is not required in the description. Nothing needed to invoke the tool correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description documents every parameter in detail: query syntax with examples, inclusive year filters, substring semantics for collection/doc_type, comma-separated source prefixes with corpus mappings, limit bounds, offset for paging, and mode semantics. It fully compensates for the schema's lack of descriptions.

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 opening sentence names a specific verb ('Search'), a clear resource ('titles, abstracts, subjects, authors and report numbers'), and scope ('across all sources'). It distinguishes this from siblings like search_fulltext, which presumably searches full text, and from lookup/find_similar, which are different operations.

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 gives extensive usage guidance: query syntax, quoting, prefix wildcards, column prefixes, date filtering, collection/source filtering, mode selection, and paging. It does not explicitly name alternatives or state when not to use this tool, but the context is clear enough for an agent to decide when search_reports is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

whats_newA
Read-onlyIdempotent

Records that entered the index in the last N days (from the weekly incremental harvests), newest first, with counts by source. The raw material for a digest.

NameRequiredDescriptionDefault
daysNo
limitNo
sourceNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, and non-destructive behavior, so the safety profile is covered. The description adds meaningful behavior beyond that: ordering by newest first, aggregation by source, and provenance from weekly incremental harvests. No contradiction with annotations exists.

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?

Two sentences deliver the core behavior, ordering, grouping, data provenance, and intended use case with no filler. Each clause adds information an agent needs to select and invoke the tool correctly.

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 simple, read-only query tool with no required parameters and an output schema present, the description covers the essential semantics: time window, ordering, grouping, and source. It could be more explicit about when to choose this over sibling tools and about the limit parameter, but these are moderate gaps rather than severe ones.

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 0%, so the description carries the burden. It explains the 'days' parameter via 'last N days' and the 'source' parameter via 'counts by source', but it does not clarify the 'limit' parameter semantics beyond its schema default. Partial compensation, not complete.

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 clearly identifies the resource (records in the index) and the temporal scope (last N days), and adds distinctive details like 'newest first' and 'counts by source' that separate it from generic lookup or search siblings. It lacks an explicit action verb like 'list' or 'retrieve', but the intended behavior is clear enough.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'raw material for a digest' implies when to use this tool, and 'from the weekly incremental harvests' situates it in a specific data flow. However, it does not explicitly state when not to use it or name alternative tools such as search_reports or get_fulltext for other needs.

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. 12 tool updatesv0.5.1
    • First observedexport_citations
    • First observedfind_similar
    • First observedget_citations
    • First observedget_fulltext
    • First observedget_references
    • First observedget_report
    • First observedharvest_status
    • First observedlist_collections
    • First observedlookup
    • First observedsearch_fulltext
    • First observedsearch_reports
    • First observedwhats_new

TDQS

A3.9/5.0

Scored across 12 tools

Disambiguation4/5

Most tools have clearly distinct roles: search, metadata retrieval, fulltext extraction, citation lookup, and export. The only real ambiguity is between get_report and lookup, which both accept identifiers and landing URLs, though get_report is specifically for full Dublin Core metadata on ROSA-P records.

Naming Consistency4/5

The majority of tools follow a verb_noun pattern (get_report, search_reports, export_citations, get_citations). Minor deviations include lookup, harvest_status, and whats_new, which are noun-like or less conventional but still readable and not confusing.

Tool Count5/5

Twelve tools is a well-scoped set for a literature discovery and citation-analysis server. Each tool covers a distinct part of the workflow without redundancy or bloat.

Completeness5/5

The surface covers search, retrieval, fulltext access, citation graph exploration, export, collection browsing, and harvest status. For a read-only repository, there are no obvious dead ends or missing core operations.

Maintenance

ActivityStale
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables agents to search a local, fully offline personal document library (Markdown/txt/PDF/docx) via SQLite FTS5 trigram search with subject-terminology expansion, returning every hit with its domain, document title, section path, and page or offset provenance. It also exposes domain statistics, incremental ingestion, and document deprecation as tools, alongside a read-only, runtime-persona-scoped ask/coverage mode.
    -
  • A
    license
    A
    quality
    C
    maintenance
    Enables AI agents to search a local folder of Markdown, AsciiDoc, and text files through a SQLite FTS5 keyword index, returning the most relevant sections with file paths, line ranges, and heading breadcrumbs instead of grepping through a repo. It also exposes tools to list indexed documents and refresh the index incrementally, all offline with no dependencies, network calls, or embeddings.
    3
    MIT
  • F
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents and MCP-compatible hosts to search, ask, and retrieve section-level citations from scattered local notes, docs, PDFs, Word files, web pages, org files, and chat logs using hybrid vector and BM25 retrieval.
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables agents to run full-text search inside Word, PowerPoint, Excel, PDF, and plain-text files by extracting their contents into a single local SQLite FTS5 index. Exposes tools to search documents with ranked highlighted snippets and human-readable locators, list indexed files, and incrementally build or refresh the index.
    MIT