dot-lit
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 |
| ROSA-P — Biblioteca Nacional de Transporte del DOT de EE. UU. | 90,599 | repositorio completo |
| VTI — Instituto Nacional Sueco de Investigación de Carreteras y Transporte (DiVA) | 11,460 | informes, ponencias de congresos, artículos; en/sv |
| BASt — Instituto Federal Alemán de Investigación de Carreteras (OPUS) | 2,970 | 1,901 con enlaces directos a PDF; de/en |
| Repositorio de Conocimiento Abierto del Banco Mundial | 976 | subconjunto filtrado por título de 40,332; precisión medida 18/20 |
| IPEA (Brasil) | 207 | subconjunto filtrado de 14,400; pt; precisión ~16/20 |
| CEPAL/ECLAC (América Latina) | 1,165 | subconjunto filtrado de 52,199; es/en; precisión ~15/20 |
| 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 Research (Japón) — artículos, tesis, elementos del repositorio IRDB | 118,609 | requiere un ID de aplicación NII gratuito ( |
| PubMed — subconjunto de transporte/lesiones (estrategia MeSH + 12 revistas) | 105,028 | recolección E-utilities segmentada por fecha; |
| exportaciones de TRID que importes ( | 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 |
| Resultados ordenados: id, título, autores, año, números de informe, DOI, URL de destino, fragmento del resumen, |
| Coincidencia exacta por DOI, PMID, número de informe ("DOT HS 813 097"), id o URL de destino |
| Registro de metadatos completo, incluido cada campo bruto tal como se recolectó |
| Resuelve el PDF (página de destino de ROSA-P, enlaces directos de BASt/OpenAlex), extrae y almacena en caché el texto; pagina con |
| Busca dentro de todo el texto de PDF ya extraído, con fragmentos |
| Registros relacionados entre fuentes, por título y términos de materia |
| RIS (Zotero/EndNote/Mendeley) o BibTeX para una lista de ids |
| Obras que cita el registro (OpenAlex, en caché); las entradas llevan |
| Obras que citan el registro; |
| Registros que entraron en el índice en los últimos N días, con recuentos por fuente — la materia prima para un resumen semanal |
| Colecciones y tipos de documento con recuentos |
| 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: Personal Research Assistant 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 evaluationPara 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 |
|
| Base de datos SQLite, páginas OAI sin procesar ( |
| (unset) | Tu correo electrónico, incluido en el User-Agent para que el repositorio pueda contactarte. Configúralo. |
|
| Segundos mínimos entre peticiones salientes |
|
| Tiempo de espera por petición (s) |
| 80 MB | Rechaza PDFs más grandes en |
| 600 | Detiene la extracción después de este número de páginas |
| (unset) | ID de aplicación NII; necesario para cosechar CiNii (regístrate en support.nii.ac.jp/en/cinii/api/developer) |
| (unset) | Opcional; aumenta la tasa de E-utilities de PubMed de 3 a 10 peticiones/s |
| built-in strategy | Reemplaza la estrategia de búsqueda de PubMed |
| fastembed / MiniLM-L12 / 1024 | Backend de búsqueda semántica, modelo, truncamiento de Ollama |
|
| Endpoint de Ollama para el backend |
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 backendPublicado 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 releaseCosecha
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 changeQué 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, siguiendoresumptionTokenhasta que llegue una página sin uno. Solo entonces la ejecución se marca comocomplete; cualquier error la dejafailedy no avanza el puntero de "última cosecha", por lo queharvest_statusnunca afirma que un índice parcial esté completo.Ritmo: una petición cada
TRANSPORT_LIT_MIN_INTERVALsegundos (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 medianteuntil=. Hasta 8 recuperaciones por ejecución, luegofailed.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
cursordel 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 enharvest_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 unTRANSPORT_LIT_DATA_DIRnuevo.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é bajopdf/y en la tablafulltext.from/untilse formatean según lagranularitydeclarada por cada repositorio (leída deIdentify): ROSA-P, DiVA y DSpace aceptan marcas de tiempo completasYYYY-MM-DDThh:mm:ssZ, OPUS (BASt) solo aceptaYYYY-MM-DDy 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; aflojamin_subject_hitsensources.pyy ejecutatransport-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 enrunning, 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 quecited_by_countse 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:
Ejecuta tu búsqueda en TRID, elige Export → RIS (también se ofrecen CSV y XML).
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 |
| 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) |
| 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) |
| 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):
dot:18905 — An evaluation of the short-term effects of the Virginia driver improvement program (Lynn) — all_terms
dot:29326 — Review of NJ point system (Carnegie, Ozbay, Mudigonda, 2013; FHWA NJ-2013-004) — all_terms
dot:18959 — …Virginia driver improvement program on negligent driving: 12-month report (Lynn)
dot:18969 — …Virginia driver improvement program on negligent driving: 24-month report (Lynn)
dot:17678 — Study of recidivism rates among drivers administratively sanctioned by the New Jersey MVC (Carnegie et al., 2009)
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:
Escribe
src/transport_lit/sources/<name>.pyque expongaharvest(store, *, mode, progress)y que genere dicts con la misma forma que producedc.parse_record(id,title,authors,year,abstract,report_numbers,doi,landing_url,collections,raw, …) y llame astore.upsert_records(). Usa un nuevo prefijo de ID (nhtsa:812115) y pasa tu propio nombre desourceastore.start_run()para queharvest_statuspueda informar de él por separado.Reutiliza
oai.RateLimiteryconfig.USER_AGENTpor cortesía; guarda las respuestas sin procesar enraw/<source>/para la reproducibilidad.Añade a
harvest.status()un bloque por fuente (recuento por prefijo deid).Añade una opción
--sourceatransport-lit harvesty, si
Fuente | Fondos | Acceso automatizado | Veredicto |
VTI (Suecia) vía DiVA | 7,474 registros, conjunto | OAI-PMH, | Cosecha — integración directa |
BASt (Alemania) OPUS | 2,987 registros; informes del instituto federal de investigación de carreteras | OAI-PMH, | Cosecha — integración directa |
World Bank Open Knowledge Repository | 40,332 registros; 1,787 resultados para "seguridad en el transporte"; el conjunto OAI | OAI-PMH (DSpace 7) + DSpace REST | Cosechar todo, filtrar por materia; o consulta REST |
WHO IRIS | 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) | 52,199 registros; sin conjuntos por materia | OAI-PMH + DSpace REST | Cosechar y filtrar por materia |
MTT Chile Biblioteca Digital de Transportes | 5,820 filas de | GraphQL de Hasura abierto en | Cosechable vía GraphQL; confirmar primero los términos de uso con MTT |
OpenAlex | 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) | 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) | 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 | Conjuntos de datos (32 instituciones, más de 120 países), PortalJS | No se encontró API ( | 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 | 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 ( | 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) | 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)
VTI + BASt(hecho, v0.2.0) — 2.World Bank OKR, IPEA, CEPAL(hecho, v0.2.0) —IRDB Japón — 4. OpenAlex
type:reportcomo respaldo global — 5. un subconjunto de transporte de PubMed (ver más abajo). Nota sobre VTI: eloai_dcde DiVA no incluye enlace al texto completo; cambiar esa fuente aswepub_mods/mets_kbdaría aget_fulltextla URLFULLTEXT01.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 semanticLos 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 --writeEso 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.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Search arXiv/Semantic Scholar/OpenAlex + medical evidence (PubMed/Europe PMC) + LaTeX/PDF tools.
Search, fetch (with provenance), scan, and convert AI instruction files for agents.
Search US grants + federal contracts (Grants.gov + SAM.gov) from any LLM.
Search your knowledge bases from any AI assistant using hybrid RAG.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to search and query PDF documents through a local RAG system with vector embeddings. Provides semantic document search capabilities while keeping all data stored locally without external dependencies.
- FlicenseNot gradedqualityDmaintenanceEnables semantic search and conversational querying across a personal research library of PDFs, DOCX, and other documents using a vector database. It provides tools for document summarization, finding related papers, and high-accuracy retrieval for AI clients like Claude Desktop.
- FlicenseAqualityDmaintenanceProvides LLMs with direct access to official vendor PDF documentation for electronics components (TI, ST, ADI) via a local SQLite full-text index and PDF retrieval tools.61
- AlicenseNot gradedqualityCmaintenanceBuilds searchable SQLite databases from PDFs, preserving inline image locations for AI agents to discover and caption visual content. Supports full-text search over text, image placeholders, and saved captions.1MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/aquistbe/transport-lit'
If you have feedback or need assistance with the MCP directory API, please join our Discord server