dot-lit
transport-lit — MCP를 통한 교통 그레이 문헌
(2026-08-27에 dot-lit에서 이름이 변경되었으며, DOT_LIT_* 환경 변수와 이전 데이터 디렉터리는 여전히 인식됩니다.)
transport-lit는 PubMed가 색인하지 않고 Semantic Scholar가 제대로 다루지 못하는 교통 연구 보고서에 대해 AI 어시스턴트(Claude Desktop, Claude Code, 모든 MCP 클라이언트)에 키워드 검색을 제공합니다. 이 프로젝트는 미국 National Transportation Library의 저장소인 ROSA-P(NHTSA DOT HS 보고서, FHWA/FRA/FTA/FAA, UTC 및 주 DOT 연구; https://rosap.ntl.bts.gov)에서 시작하여, 현재는 세 대륙의 6개 OAI-PMH 소스와 TRID에서 내보낸 모든 자료를 수집합니다:
key | source | records | notes |
| ROSA-P — U.S. DOT National Transportation Library | 90,599 | 전체 저장소 |
| VTI — Swedish National Road and Transport Research Institute (DiVA) | 11,460 | 보고서, 학술대회 논문, 논문; en/sv |
| BASt — German Federal Highway Research Institute (OPUS) | 2,970 | 1,901건은 직접 PDF 링크 포함; de/en |
| World Bank Open Knowledge Repository | 976 | 40,332건 중 제목 필터링된 하위 집합; 측정 정밀도 18/20 |
| IPEA (브라질) | 207 | 14,400건 중 필터링된 하위 집합; pt; 정밀도 ~16/20 |
| CEPAL/ECLAC (라틴 아메리카) | 1,165 | 52,199건 중 필터링된 하위 집합; es/en; 정밀도 ~15/20 |
| OpenAlex — report 유형으로 분류된 10개 교통 주제의 저작물(전 세계) | 11,448 | 주제: 교통 및 도로 안전, 도시 교통 및 접근성, 교통 계획, … |
| CiNii Research (일본) — 논문, 학위논문, IRDB 저장소 항목 | 118,609 | 무료 NII 애플리케이션 ID( |
| PubMed — 교통/손상 하위 집합(MeSH 전략 + 12개 저널) | 105,028 | 날짜별로 분할된 E-utilities 수집; |
| 직접 가져오는 TRID 내보내기( | 사용자 소유 | 아래 참조 |
transport-lit sources는 이들을 나열하고, transport-lit harvest --source <key>|all은 이들을 수집합니다. search_reports의 collection 필터는 하나를 선택합니다(예: "VTI", "BASt", "World Bank", "CEPAL", "TRID"). 다른 OAI-PMH 저장소를 추가하는 것은 src/transport_lit/sources.py의 한 항목입니다.
저는 이 프로젝트를 개인적인 학술 및 연구 목적으로 만들었으며, 유용하게 사용하실 다른 분들과 공유하게 되어 기쁩니다. 오류, 통합 요구 사항, 개선 사항 및 기타 의견을 환영합니다. 정기적으로 확인하고 가능한 한 통합한 후 문서화하겠습니다. 이 프로젝트를 지원하거나 다른 아이디어가 있으시다면 언제든지 환영합니다! — Alex Quistberg (이슈 열기)
이 작업은 OAI-PMH 소스에 유일하게 작동하는 방식으로 수행됩니다. 즉, 전체 저장소의 메타데이터를 로컬 SQLite 데이터베이스로 수집하고, 그 위에 FTS5 전문(full-text) 인덱스를 구축한 다음, 해당 인덱스에서 검색을 제공합니다. 전체 텍스트를 위한 선택적 PDF 가져오기를 제외하고는 실시간으로 쿼리되는 것이 없습니다. 재수집은 증분 방식(OAI 요청의 from=)이며 비용이 저렴합니다.
도구 목록
Tool | What it returns |
| 순위가 매겨진 검색 결과: id, 제목, 저자, 연도, 보고서 번호, DOI, 랜딩 URL, 초록 발췌, |
| DOI, PMID, 보고서 번호("DOT HS 813 097"), id 또는 랜딩 URL로 정확히 일치 |
| 수집된 모든 원시 필드를 포함한 전체 메타데이터 레코드 |
| PDF를 확인하고(ROSA-P 랜딩 페이지, BASt/OpenAlex 직접 링크) 텍스트를 추출하여 캐시합니다. |
| 이미 추출된 모든 PDF 텍스트 내부를 스니펫과 함께 검색합니다. |
| 제목과 주제 용어를 기준으로 소스 전반의 관련 레코드 |
| id 목록에 대한 RIS(Zotero/EndNote/Mendeley) 또는 BibTeX |
| 레코드가 인용한 저작물(OpenAlex, 캐시됨). 인용된 저작물이 이 인덱스에 있으면 항목에 |
| 레코드를 인용한 저작물. |
| 지난 N일 동안 인덱스에 추가된 레코드와 소스별 개수 — 주간 다이제스트의 기초 자료 |
| 컬렉션과 문서 유형 및 개수 |
| 소스별 레코드 수, 마지막 실행 및 상태/메모, 연도별 적용 범위 |
여기에 하나의 프롬프트인 literature_scan(topic)이 추가로 있는데, 이는 모델이 인용과 함께 다중 쿼리 스캔을 수행하도록 안내합니다. 모든 도구에는 MCP 주석(readOnlyHint, idempotentHint)이 포함되어 있습니다. get_fulltext만 openWorldHint인데, PDF 하나를 가져올 수 있기 때문입니다.
id는 dot:93144, 93144, oai:dot.stacks:dot:93144 또는 랜딩 URL을 허용합니다. 가져온 레코드는 다른 접두사를 사용합니다(trid:813520, import:…).
쿼리 구문: 단독 단어는 먼저 AND로 결합됩니다. limit보다 적은 수의 결과가 모든 용어와 일치하면 나머지 자리는 임의의 용어 일치로 채워집니다(match_mode = all_terms / any_terms). 구문은 따옴표로 묶고("driver improvement"), 접두어에는 끝에 *를 사용합니다. 순위는 BM25이며 제목, 보고서 번호, 저자가 초록보다 높은 가중치를 갖습니다.
Related MCP server: litedocs-mcp
설정
Python 3.12+ 및 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개발 시에는 uv sync를 사용하고 명령어 앞에 uv run을 붙이세요(예: uv run pytest).
모든 MCP 클라이언트, 모든 모델
서버는 stdio(기본값)와 Streamable HTTP / SSE를 통해 표준 MCP를 사용합니다(transport-lit-mcp --transport streamable-http --port 8765, 엔드포인트 /mcp). transport-lit mcp-config [client]는 붙여넣기만 하면 되는 스니펫을 출력합니다: Claude Desktop, Claude Code, Cursor, VS Code(Copilot 에이전트 모드), Zed, Continue, LM Studio, Goose, Open WebUI 및 LibreChat(마지막 두 개는 HTTP 사용). Dockerfile은 인덱스를 볼륨에 저장하는 HTTP 서버 이미지를 빌드합니다.
오픈 모델. 2026-08-26에 Ollama qwen2.5:3b(3 B 파라미터)를 tests/ollama_smoke.py를 통해 종단 간 테스트했습니다. "운전자 향상 프로그램에 관한 보고서를 찾아서 제목 3개를 연도와 id와 함께 나열하세요"라는 요청에 모델은 search_reports({"query": "driver improvement", "limit": 3})를 한 번 호출하고 세 소스에서 올바른 제목, 연도, id 및 랜딩 URL로 답변했습니다. 작은 모델이 작동하도록 만드는 설계 선택: 한 줄 우선 설명이 있는 10개의 도구, 기본값이 있는 평면 JSON 인수, 간결한 결과 객체(검색 결과에 원시 메타데이터 없음), 소스와 필터를 명명하는 서버 instructions 문자열. 도구를 사용할 수 있는 모든 모델로 스모크 테스트를 실행하세요: OLLAMA_MODEL=llama3.1 uv run python tests/ollama_smoke.py "…".
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)작성하는 항목은 단순히 다음과 같습니다:
{ "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" } } } }그 후 Claude Desktop을 다시 시작하세요. Claude Code의 경우: claude mcp add transport-lit -- transport-lit-mcp.
구성(환경 변수)
변수 | 기본값 | 용도 |
|
| SQLite DB, 원본 OAI 페이지( |
| (설정 안 됨) | User-Agent에 포함되어 저장소가 연락할 수 있게 하는 이메일. 설정하세요. |
|
| 아웃바운드 요청 사이의 최소 간격(초) |
|
| 요청별 타임아웃(초) |
| 80 MB |
|
| 600 | 이 페이지 수 이후에는 추출 중단 |
| (설정 안 됨) | NII 애플리케이션 ID. CiNii 수집에 필요(support.nii.ac.jp/en/cinii/api/developer에서 등록) |
| (설정 안 됨) | 선택 사항. PubMed E-utilities 요청률을 3에서 10 req/s로 상향 |
| 내장 전략 | PubMed 검색 전략을 대체 |
| fastembed / MiniLM-L12 / 1024 | 의미 검색 백엔드, 모델, Ollama 절단(truncation) |
|
|
|
변수는 ~/.config/transport-lit/env에 KEY=VALUE 줄로도 저장할 수 있습니다(실제 환경 변수가 우선). NII 애플리케이션 ID나 NCBI 키는 여기에 두면 launchd 작업, MCP 서버, 수동 실행 모두에서 볼 수 있습니다. 자격 증명은 필요 없습니다. 모든 엔드포인트는 공개입니다.
PyPI에서 설치(클론 없이)
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 backendhttps://pypi.org/project/transport-lit/에 GitHub의 신뢰된 퍼블리싱(trusted publishing)을 통해 게시됩니다. 태그가 release.yml(빌드, GitHub 릴리스)을 실행하면 publish.yml이 디스패치되는데, 이 워크플로가 신뢰된 퍼블리셔로 등록된 유일한 워크플로이며, 업로드는 pypi 환경에서 관리자의 승인을 기다립니다. PyPI는 재사용 가능한 워크플로의 토큰을 거부하고 최상위 워크플로 파일과 일치해야 하므로, 퍼블리싱은 릴리스 내부의 작업이 아니라 별도의 디스패치된 워크플로입니다. server.json은 MCP 레지스트리(registry.modelcontextprotocol.io)용 매니페스트로, PyPI 패키지가 생성된 후 제출합니다.
고정된 버전
릴리스는 git 태그 vMAJOR.MINOR.PATCH입니다(시맨틱 버저닝: patch = 수정, minor = 새 도구/소스, major = 도구 표면 또는 데이터베이스 스키마의 호환성 깨짐). 각 태그는 테스트를 실행하고 wheel + sdist를 빌드하여 GitHub 릴리스에 첨부하는 release 워크플로를 트리거합니다. Python 의존성은 커밋된 uv.lock으로 고정되며, CI는 uv sync --frozen으로 설치하므로 릴리스는 항상 테스트된 정확한 버전으로 실행됩니다. 특정 버전을 설치하려면:
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수집(Harvesting)
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수집기가 수행하는 작업과 그 이유(모든 동작은 2026-08-26에 ROSA-P에 대해 검증됨):
ListRecords&metadataPrefix=oai_dc, 페이지당 100개 레코드,resumptionToken을 따라가며 토큰 없이 페이지가 도착할 때까지 계속합니다. 그래야만 실행이complete로 표시됩니다. 오류가 발생하면failed로 남고 "마지막 수집" 포인터가 진행되지 않으므로harvest_status가 부분 인덱스를 완료로 주장하지 않습니다.페이싱(Pacing):
TRANSPORT_LIT_MIN_INTERVAL초(기본 1초)마다 요청 1회. 토큰은 발급 후 약 60초 후에 만료되므로 재시도는 짧은 백오프(2/4/6초)를 사용합니다.badResumptionToken, 전송 오류, 잘린 XML, 또는 토큰이 유효한 동안 빈 봉투(envelope) → 목록이 재발급됩니다. ROSA-P는 레코드를 안정적인 datestamp 순서로 반환하지 않으므로(모든 페이지에서 확인됨) 복구는 목록을 처음부터 다시 시작합니다. upsert 덕분에 멱등적입니다. 순서가 단조적이었다면 수집기는 대신until=을 통해 본 가장 작은 datestamp부터 재개했을 것입니다. 실행당 최대 8회 복구 후failed가 됩니다.noRecordsMatch: ROSA-P는 오류 코드를 보내지 않습니다. 빈 선택 수집은<ListRecords>요소가 없는 OAI-PMH 봉투로 반환됩니다. 이는 토큰이 작동 중이지 않을 때만 "할 일 없음"으로 매핑되며, 목록 중간에서는 잘림으로 처리됩니다.조용한 잘림 검사: 토큰의
cursor가 모든 페이지에서 로컬 개수와 비교됩니다. 이전 전체 수집보다 5% 이상 적은 레코드를 반환하는 전체 수집은 실행 노트에 플래그가 지정됩니다. 둘 다harvest_status().last_harvest.notes에 나타납니다.삭제: 저장소는
deletedRecord=no를 보고하므로 로컬에서 삭제되는 것은 없습니다. ROSA-P에서 사라진 레코드는 새TRANSPORT_LIT_DATA_DIR에 대한 전체 재수집이 있을 때까지 인덱스에 남아 있습니다.캐싱: 모든 OAI 페이지는
raw/run<N>-p<page>.xml.gz아래에 gzip으로 저장되므로 파서를 변경하고 네트워크에 접촉하지 않고 인덱스를 재구축할 수 있습니다. PDF와 추출된 텍스트는pdf/와fulltext테이블에 캐시됩니다.from/until은 각 저장소가 선언한granularity(Identify에서 읽음)에 맞게 형식화됩니다. ROSA-P, DiVA, DSpace는 전체YYYY-MM-DDThh:mm:ssZ타임스탬프를 사용하고, OPUS(BASt)는YYYY-MM-DD만 사용하며 창은 양쪽으로 하루씩 넓혀집니다.광범위한 저장소(World Bank, IPEA, CEPAL)는 수집 시 다국어 교통 어휘(
sources.TRANSPORT_RE, en/es/pt/de/fr/sv)로 필터링됩니다. 제목에 용어가 나타나거나(IPEA, CEPAL의 경우) 주제 표제 중에 서로 다른 용어 두 개가 나타나면 레코드가 유지됩니다. 초록은 무시됩니다(개발 문헌은 도로와 항구를 지나가는 말로 언급함). World Bank 주제도 무시됩니다(레코드당 100개 이상의 표제). 이는 2026-08-26에 무작위 20개 제목 샘플로 조정되었습니다. 느슨한 제목+주제+초록 규칙은 약 35–50% 정밀도로 World Bank 레코드 15,271개를 유지했습니다. 최종 규칙은 18/20에서 976개, IPEA는 ~16/20에서 207개, CEPAL은 ~15/20에서 1,165개를 유지합니다. 재현율이 대가입니다. 다른 트레이드오프를 원하면sources.py에서min_subject_hits를 느슨하게 하고transport-lit reindex --source <key>(네트워크 없음)를 실행하세요. 실행 노트는 유지 vs 건너뜀을 기록합니다.transport-lit doctor [--repair]는 SQLite 무결성, 두 FTS 인덱스,running상태로 멈춘 실행, 불가능한 타임스탬프, WAL 크기를 확인하고 안전한 항목을 복구합니다. 저장소는 닫을 때 WAL도 체크포인트합니다.transport-lit cite prefetch [--source …]는 DOI/PMID/OpenAlex가 있는 모든 레코드를 일괄적으로(요청당 50개) OpenAlex 작업으로 해석하여 레코드별 호출 없이cited_by_count를 알 수 있게 합니다.
transport-lit reindex --source <key>는 캐시된 페이지를 다시 파싱하고 **현재 파서/필터가 더 이상 유지하지 않는 레코드를 정리(prune)**하므로 필터 변경 시 재수집이 필요 없습니다.
월간 재구축 및 주간 업데이트(유지보수 일정)
코퍼스는 천천히 변하므로 주기는 주간 증분 수집과 월간 새 재구축입니다. harvest --fresh는 임시 저장소에 전체 수집한 다음 라이브 인덱스의 dot: 레코드를 원자적으로 교체합니다. 이는 ROSA-P가 더 이상 제공하지 않는 레코드가 사라지는 유일한 방법입니다(ROSA-P의 OAI-PMH 엔드포인트는 삭제를 추적하지 않음). 가져온 소스(TRID 내보내기)는 건드리지 않으며, 실패한 재구축은 아무것도 변경하지 않습니다.
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`로그는 $TRANSPORT_LIT_DATA_DIR/logs/에 저장됩니다. Linux에서는 명령이 출력하는 cron 줄을 사용하세요.
월간 유지보수 체크리스트(재구축과 함께 수행): 새 GitHub 이슈 읽기; uv lock --upgrade && uv run pytest; 릴리스의 변경 로그 섹션에 수정 사항 기록; pyproject.toml과 src/transport_lit/__init__.py의 version 올리기; git tag vX.Y.Z && git push --tags.
TRID: 내보낸 것을 가져오기
TRID(https://trid.trb.org)는 가장 완전한 교통 서지 데이터베이스이며 ROSA-P의 자연스러운 보완재이지만 API가 없고, FAQ에 따르면 TRB는 "TRID 백엔드 시스템에 대한 접근을 허용하지 않으며 내보내기/다운로드 제한을 해제하지 않는다"고 하며, robots.txt는 AI 크롤러를 금지합니다. 모든 사용자가 할 수 있는 것은 검색과 내보내기입니다. 따라서:
TRID에서 검색을 실행하고 Export → RIS를 선택합니다(CSV와 XML도 제공됨).
transport-lit import ~/Downloads/trid-driver-improvement.ris --collection "TRID: driver improvement"
레코드는 TRID 보기 URL에서 trid:<accession> ID를 받아 TRID 컬렉션(search_reports(..., collection="TRID"))에 들어가며, 같은 파일을 다시 가져와도 멱등적입니다. 임포터는 일반적인 RIS이므로 Zotero/EndNote/Scopus 내보내기도 --source <prefix>로 동일하게 작동합니다. 가져온 레코드의 get_fulltext는 직접 .pdf 링크만 따릅니다. 그 외에는 landing_url을 사용하세요.
ROSA-P의 OAI-PMH 엔드포인트가 제공하는 것
https://rosap.ntl.bts.gov/fedora/oai — 저장소 "DOT Stacks"(CDC Stacks 플랫폼), 프로토콜 2.0, 가장 이른 datestamp 2008-07-02, 삭제 추적 없음, OAI 세트 없음(ListSets는 비어 있음), 그리고 oai_dc가 유일한 메타데이터 형식입니다. 그러나 이는 위장된 정규화된 Dublin Core입니다. dc:contributor.author, dc:description.abstract, dc:relation.isPartOf, dc:identifier.uri(DOI 및 보고서 번호, 예: DOT HS 813 827), dc:coverage.spatial, dc:title.alternative, dc:description.tableOfContents와 같은 요소가 모두 존재합니다. 파서(dc.py)는 모든 원시 필드를 유지하고 여기에서 유형화된 열을 파생합니다. dc:relation.isPartOf(세미콜론으로 구분)가 list_collections / collection 필터가 사용하는 것입니다.
PDF 링크는 메타데이터에 없습니다. get_fulltext는 랜딩 페이지에서 citation_pdf_url을 읽고 데이터스트림 규칙 /view/dot/{n}/dot_{n}_DS1.pdf로 폴백합니다.
검증(2026-08-26)
v0.4.0 의미 검색. 342,462개 벡터(fastembed 다국어 MiniLM-L12, 384차원, 8코어에서 94 records/s 데이터 병렬 — 코퍼스에 60분). 교차 언어 확인: semantic 모드의 "elderly pedestrian crashes at night"는 상위 8개 중 PubMed 및 영어 CiNii 항목 옆에 일본어 CiNii 보고서 3개(夜間 高齢歩行者 死亡事故 분석, 1995–2011)를 반환합니다. 어휘 확인: "point system for problem drivers license suspension recidivism"은 쿼리 단어를 공유하지 않는 ROSA-P의 1997년 캘리포니아 차량 압수 평가와 1986년 행정 면허 취소 보고서를 찾습니다. 하이브리드 지연 시간 ≈ 0.6초(쿼리 인코딩이 지배적), 키워드 ≈ 25ms. 아무도 반복하지 않도록 여기에 기록하는 운영 교훈: 다른 프로세스(예: 실행 중인 MCP 서버)가 데이터베이스를 열어 둔 상태에서 SQLite -wal 파일을 절대 삭제하지 마세요. 아직 체크포인트되지 않은 커밋된 데이터를 보유하고 있습니다.
v0.3.0 API 소스. OpenAlex: 58페이지, 11,448건의 보고서(10개 토픽, type:report), 그중 1,428건에 PDF 링크. CiNii: 730페이지, 20개 쿼리에서 144,348건의 적중, 118,609건 고유. PubMed: 17개 날짜 슬라이스에서 105,028건의 논문(E-utilities는 retstart를 10,000으로 제한하므로 슬라이스를 재귀적으로 찾음). 오픈 모델 확인: Ollama qwen2.5:3b가 운전자 개선 질문에 search_reports 호출 한 번으로 정확히 응답했다.
v0.2.0 다중 소스 수집. VTI: 120페이지, 11,944건 확인, 11,460건 고유(DiVA는 일부 레코드를 여러 세트로 제공), 재개 0회. BASt: 30페이지, 2,987건 확인, 2,970건 고유; 1,901건은 직접 PDF 링크 보유; 일 단위 증분 경로를 실행했다(24건). World Bank: 404페이지 / 40,332건 확인; IPEA: 144 / 14,400; CEPAL: 522 / 52,199 — 모두 토큰 없는 페이지에서 종료되었고 재개 0회; 위 수치는 필터링 후의 수치. 표적 검색: Fußgänger Unfall(BASt) → 충돌 재구성 및 지방도로 충돌 통계; acidentes de trânsito mortalidade(IPEA) → "Mortalidade por acidentes de transporte terrestre e desigualdades interestaduais no Brasil"; seguridad vial peatones(CEPAL) → 도로안전 거버넌스 및 캠페인 평가; pedestrian safety(VTI) → 1990년대 아동 보행자 훈련 연구.
v0.1.0 (첫 ROSA-P 수집)
수집 완전성. 1차 실행(full)은 15분(00:03:59–00:19:11 UTC) 동안 908페이지 / 90,706개 레코드를 순회했고, 재개 0회, 커서 불일치 0회였으며, 재개 토큰이 없는 6개 레코드 페이지에서 종료되었다 — 이는 OAI-PMH가 정의하는 완전한 목록이다. 스토어에는 90,603개의 고유 레코드가 있다. 103건의 차이는 동일한 레코드가 두 페이지에 나타나기 때문이며, 이는 ROSA-P가 레코드를 안정적인 순서로 반환하지 않아서 발생한다(하베스터는 이를 "2페이지에서 날짜 스탬프 정렬 위반"으로 로그에 남긴다). 30분 후 별도 디렉터리로 수행한 두 번째 독립 전체 패스도 정확히 같은 수치를 반환했다 — 908페이지, 90,706건 확인, 90,603건 고유 — 그리고 두 ID 집합은 동일하다(어느 패스에만 있는 레코드도 0건). 103건의 중복은 저장소가 동일한 레코드를 두 페이지에 제공하기 때문이며, 레코드가 건너뛰어진 것이 아니다.
연대별 커버리지 (74,448건 = 82%에 연도가 있으며, 나머지 16,155건은 어떤 메타데이터 필드에도 날짜가 없다. year_source는 연도가 dc:date(48,658건), 연도만 있는 설명 줄(22,205건), 또는 제목(3,585건)에서 왔는지 나타낸다):
연대 | 레코드 | 연대 | 레코드 |
1900s–1930s | 3,243 | 1980s | 5,408 |
1940s | 2,618 | 1990s | 8,936 |
1950s | 2,627 | 2000s | 11,466 |
1960s | 2,947 | 2010s | 18,690 |
1970s | 5,057 | 2020s | 13,456 |
알려진 항목 검색 (transport-lit search …, 별도 표시가 없으면 1순위):
대상 | 쿼리 | 결과 |
NHTSA Countermeasures That Work |
| dot:1789(2005), dot:1827(3판 2008), dot:40255(1판 2006), dot:1778(2판 2007); 11판 2023은 dot:72947(DOT HS 813 490), 10판은 dot:57466. 해당 구문만으로는 CTW의 한 페이지 분량 Traffic Tech 요약본이 먼저 순위에 오르고(BM25에서는 짧은 문서가 유리함), 그다음 가이드가 온다. |
Oregon DMV Driver Improvement Program evaluation (Strathman et al., 2007) |
| dot:21848 "Evaluation of the Oregon DMV driver improvement program", Strathman, Kimpel, Leistner; 보고서 번호 SPR 634. ROSA-P 메타데이터에는 날짜 없음. |
Virginia driver improvement reports (Lynn, 1982) |
| dot:18959(12개월 보고서), dot:18905(단기 효과), dot:18969(24개월 최종 보고서), 모두 Cheryl Lynn, Virginia Highway & Transportation Research Council. ROSA-P 메타데이터에는 날짜 없음. |
실제 쿼리 driver improvement program evaluation negligent operator (상위 6/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)
전문(full-text) 추출은 dot:93144(DOT HS 813 827, 3.7MB PDF, citation_pdf_url로 확인)에서 검증했다. 단위 테스트: uv run pytest(두 메타데이터 프로필용 파서, 연도 폴백, FTS 검색/필터, upsert 멱등성, 쿼리 토크나이저, ID 정규화).
레이아웃
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)나중에 두 번째 소스 추가하기 (예: NHTSA crashstats)
스토어는 소스에 구애받지 않는다: records.id는 접두사가 붙은 문자열이고(현재는 dot:93144), harvest_runs.source는 어떤 하베스터가 실행을 기록했는지 저장하며, FTS 인덱스는 행이 어디서 왔는지 상관하지 않는다. 소스를 추가하려면:
src/transport_lit/sources/<name>.py를 작성하여harvest(store, *, mode, progress)를 노출한다. 이 함수는dc.parse_record가 생성하는 것과 동일한 형태의 dict(id,title,authors,year,abstract,report_numbers,doi,landing_url,collections,raw, …)를 생성하고store.upsert_records()를 호출한다. 새 ID 접두사(nhtsa:812115)를 사용하고store.start_run()에 고유한source이름을 전달하여harvest_status가 별도로 보고할 수 있게 한다.예의를 위해
oai.RateLimiter와config.USER_AGENT를 재사용하고, 재현성을 위해 원시 응답을raw/<source>/아래에 저장한다.harvest.status()에 소스별 블록을 추가한다(id접두사로 집계).transport-lit harvest에--source옵션을 추가하고, 소스에 고유한 패싯이 있으면search_reports에 해당 필터를 추가한다.ROSA-P와의 중복 제거는 제목이 아니라 DOI / 보고서 번호(
records.doi,records.report_numbers)로 수행한다. NHTSA 보고서는 두 곳에 모두 있는 경우가 많다.
NHTSA crashstats 소스에 대해 검증된 사실은 다음과 같으니 누구도 다시 도출하지 않아도 된다: https://crashstats.nhtsa.dot.gov/Api/Public/Publication/{id}는 PDF를 직접 반환한다(812115 → NMVCCS critical-reasons 보고서, application/pdf, ~0.5MB). 이는 검색이나 목록 API가 아니라 문서 검색 엔드포인트이므로, 커넥터는 크롤링 대신 열거 전략(예: ROSA-P report_numbers에 이미 있는 DOT HS 번호)이 필요하다.
미국 외: 평가된 후보 소스 (2026-08-26)
실제로 (a) 보유 자료가 데이터셋이 아니라 문헌인지, (b) 이 하베스터에 맞는 기계 접근이 가능한지를 살펴보았다. 수치는 해당일 엔드포인트가 보고한 값이다.
Source | Holdings | Machine access | Verdict |
VTI (스웨덴) DiVA 경유 | 레코드 7,474건, 세트 | OAI-PMH, | 수집 — 드롭인 |
BASt (독일) OPUS | 레코드 2,987건; 연방 고속도로 연구소 보고서 | OAI-PMH, | 수집 — 드롭인 |
World Bank Open Knowledge Repository | 레코드 40,332건; "transport safety" 검색 결과 1,787건; OAI 세트 | OAI-PMH (DSpace 7) + DSpace REST | 전체 수집, 주제별 선별; 또는 REST 쿼리 |
WHO IRIS | 레코드 276,681건; "road traffic" 검색 결과 3,334건; 세트 없음 | OAI-PMH + DSpace REST 검색 | 주제별 REST 쿼리 (전체 OAI 순회는 2,800페이지) |
CEPAL 리포지토리 (라틴아메리카) | 레코드 52,199건; 주제 세트 없음 | OAI-PMH + DSpace REST | 수집 후 주제별 필터링 |
MTT Chile Biblioteca Digital de Transportes | 이름, 설명, 카테고리, 파일이 있는 |
| GraphQL로 수집 가능, 먼저 MTT와 이용 약관 확인 |
OpenAlex | "road safety"와 일치하는 report 유형 저작 2,604건; "pedestrian safety"에 대한 모든 유형의 저작 16,639건 | 무료 REST API, 커서 페이지네이션 | 최고의 글로벌 애그리게이터, 비미국 그레이 문헌 및 DOI 소스로 사용 |
GOV.UK (DfT) | "road safety research"에 대한 DfT 항목 4,998건 | 무료 콘텐츠 API | 수집 가능, 문서 유형 필터링 필요 |
스페인, Centro de Documentación del Transporte | AbsysNet의 서지 레코드 66,000건 (단행본 45,000건) | OPAC만 가능, 사이트가 비브라우저 클라이언트 차단 (HTTP 403) | 해당 부처가 OAI/Z39.50을 제공하지 않는 한 범위 외 |
TRIMIS (EU) | EU 자금 지원 교통 프로젝트 및 결과 | 사이트 정상, 문서화된 API 없음 (대량 오픈데이터 덤프 존재) | 사이트가 아닌 오픈데이터 덤프를 평가 |
IDB Publications, CAF Scioteca | 개발은행 교통 보고서 | DSpace, 그러나 봇 차단됨 (403 / 챌린지 페이지) | 접근이 허용되지 않는 한 범위 외 |
SWOV (네덜란드) | 도로 안전 연구소 도서관 | 모든 경로에 봇 탐지 페이지 | 범위 외 |
ITF/OECD | International Transport Forum 보고서 | 비브라우저 클라이언트에 HTTP 403, API 없음 | 범위 외 (OECD iLibrary API는 라이선스 필요) |
Transport Data Commons | 데이터셋 (기관 32곳, 120개 이상 국가), PortalJS | API를 찾을 수 없음 ( | 문헌 아님 |
ITDP Rapid Transit Database | 데이터셋 (도시별 BRT/LRT/지하철 km), Google Sheet 다운로드 | 다운로드만 가능 | 문헌 아님 |
AASHTO TERI database | 연구 필요성 진술문, 완성된 보고서 아님 | 없음 | 문헌 아님 |
nismod/Africa-transport-database (GitHub) | 아프리카 교통 인프라의 GIS 데이터셋 | Git clone | 문헌 아님 |
TRID | 국제 서지 레코드 150만 건 | 없음, 정책상 내보내기/백엔드 접근 거부 | 범위 외 |
지역별 (당일 프로브, "open"은 인증 없는 기계 접근이 확인되었음을 의미):
지역 | 기존 자료 | 접근 방식 | 비고 |
유럽 | VTI(스웨덴), BASt(독일) — 위 참조; HAL(프랑스): Université Gustave Eiffel/IFSTTAR 컬렉션에 74,952건, "sécurité routière" 검색 시 | HAL REST(공개), OpenAIRE REST(공개), Cellar SPARQL(공개), CORDIS JSON(공개); DTU Orbit OAI 500, TU Delft OAI 미발견, TØI 403 | ITF/OECD의 ITRD가 TRID에 통합되어 ITF 콘텐츠는 TRID를 통해서만 접근 가능 |
호주 / 뉴질랜드 | Figshare OAI-PMH + REST(Monash/MUARC 및 기타 호주 대학이 보고서 게시); NZTA 연구 보고서 페이지(HTML, 200); Austroads(비브라우저 접근 시 403); APO 그레이 문헌 관측소(비브라우저 접근 시 403); Trove API(키 필요) | Figshare 공개; Trove 키 필요; APO/Austroads 봇 차단 | Figshare에서 "road safety" 보고서 검색 시 대부분 데이터셋/코드 반환 — 유용하려면 항목 유형 + 기관 필터링 필요 |
일본 | IRDB( | 모두 공개, 키 불필요 | IRDB가 그레이 문헌 경로(대학 학위논문, 기술보고서); NILIM/PWRI 부처 보고서는 웹 전용 |
인도 | Shodhganga OAI가 DSpace 경로에서 미발견; CSIR-CRRI 사이트는 정적 HTML; IRC/MoRTH 웹 전용 | 발견된 것 없음 | 인도 학술지 성과는 OpenAlex/OpenAIRE가 최선; 수확 가능한 그레이 문헌 소스 미확인 |
중국 | MOT/RIOH 보고서 공개 리포지토리 없음; RIOH 사이트 정적; CNKI는 라이선스 필요 | 발견된 것 없음 | OpenAlex가 "traffic safety" 관련 중국 기관 15,416건 반환(학술지 문헌) — 이것이 현실적 경로 |
라틴 아메리카 | IPEA(브라질) | IPEA/CEPAL OAI 공개; MTT GraphQL 공개; IDB/CAF 봇 차단; LA Referencia OAI는 추정 URL에서 미발견 | SciELO OAI 엔드포인트가 기존 경로에서 미발견(어차피 학술지임) |
completeListSize를 지원하는 세 개의 OAI-PMH 리포지토리(VTI, BASt, World Bank OKR)는
소스 접두어와 소스별 metadataPrefix로 기존 하베스터에 맞습니다. DSpace 7
사이트도 from/until을 허용하고 올바른 noRecordsMatch를 반환하므로,
oai.py의 ROSA-P 특이사항이 이미 더 까다로운 사례입니다.
TRID는 범위 외
TRID(https://trid.trb.org)는 공개 API, OAI-PMH 엔드포인트, 대량 내보내기가 없습니다. FAQ에 따르면 "TRB는 개인이나 조직에 TRID 백엔드 시스템 접근을 허용하지 않으며 내보내기/다운로드 제한을 해제하지 않는다"고 하고, 데이터베이스는 LLM 학습에 사용할 수 없습니다. 따라서 여기서 의도적으로 스크래핑하지 않습니다.
v2 순서(2026-08-26 합의)
VTI + BASt(완료, v0.2.0) — 2.World Bank OKR, IPEA, CEPAL(완료, v0.2.0) —IRDB 일본 — 4. OpenAlex
type:report를 글로벌 백스톱으로 — 5. PubMed 교통 하위 집합(아래 참조). VTI 참고: DiVA의oai_dc는 전문 링크를 포함하지 않음; 해당 소스를swepub_mods/mets_kb로 전환하면get_fulltext가FULLTEXT01.pdfURL을 얻을 수 있음.
PubMed: 전체가 아닌 교통/상해 하위 집합
PubMed의 E-utilities(esearch/efetch, 무료, 키 없이 초당 3회 요청)는 고정 전략에서
로컬 하위 집합을 유지할 수 있으며, 동일한 주간/월간 주기로 mindate/maxdate로
새로고침합니다. OR로 결합된 두 가지 보완 필터:
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])— 일반 및 임상 학술지의 교통 논문을 포착.학술지 목록 — 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 (교통 태그만) 등 — MeSH 용어 없이 색인된 교통 논문을 포착.
SafetyLit(safetylit.org, WHO 제휴 주간 상해 문헌 게시판)은 정확히 그러한 학술지 목록을 유지하고 주제별로 수동 분류하므로 학술지 필터의 최상의 시드가 될 수 있습니다. 2026-08-26 확인 시 사이트에 접속할 수 없었고(모든 호스트 이름에서 연결 거부), 현재 상태는 확인되지 않았습니다.
주간 다이제스트(SafetyLit 스타일 게시판)
transport-lit digest --days 7 [--abstracts]는 지난주에 인덱스에 들어온 모든 항목의
Markdown 게시판을 소스별로 그룹화하고 개수와 함께 출력합니다. 이는 레코드가 처음
발견된 시점에 설정되고 새 빌드에서도 유지되는 first_seen_at으로 구동되므로,
월간 재빌드가 전체 인덱스를 새 것처럼 보이게 하지 않습니다. whats_new 도구는
동일한 데이터를 모델에 노출하며, 모델이 요약을 작성할 수 있습니다 — SafetyLit이
수동으로 수행하던 편집 단계입니다.
다른 문헌 MCP와 비교
PubMed, Semantic Scholar, OpenAlex 및 arXiv MCP 서버는 단일 API에 실시간 쿼리를
프록시합니다. transport-lit는 세 가지 면에서 다릅니다: 통합자가 갖지 못한 그레이 문헌(기관
보고서, 주 DOT 평가, ITRD 기여 기관)을 색인하고, 수확 후 로컬 인덱스에서 오프라인으로
실행되며(쿼리 시 속도 제한 없음, 키 불필요), 다중 소스를 단일 ID 체계로
통합하므로 모델이 모든 것을 한 번에 검색하고 인용을 내보낼 수 있습니다. 이들 서버가
가지고 있지만 이 도구에 아직 없는 것: 인용 그래프(누가 누구를 인용하는지), 저자
동일성 판별, 의미(임베딩) 검색 — 아래 참조.
인용 그래프(v0.5)
get_references / get_citations(CLI: transport-lit cite refs|cites <id> [--in-index])는
OpenAlex의 인용 그래프를 인덱스에 연결합니다. 레코드는 OpenAlex ID, DOI, PMID 또는 —
날짜가 없고 DOI가 없는 많은 기관 보고서의 경우 — 연도 ±1 범위의 정규화된 정확한 제목으로
OpenAlex 작업과 일치합니다(결과의 match가 어떤 방식인지 표시). 엣지는
첫 요청 시 가져와 citations/works 테이블에 캐시됩니다. 인용 목록은
90일 후 새로고침되고, 참조는 변경되지 않습니다. 인덱스에 있는 인용된 작업은
record_id와 함께 반환되며, 검색 결과는 cited_by_count가 알려지면 이를 포함합니다.
2026-08-27 검증: Oregon DMV DIP 평가(dot:21848, DOI 없음, ROSA-P에 날짜 없음)가
제목으로 해석되어 6건의 인용 작업을 나열했으며, 그중 Iowa의 DIP 평가와 NJ
재범 연구가 포함됨; Lynn의 1982년 Virginia 24개월 보고서는 2003년 Cochrane
운전면허 후 교육 검토(pubmed:12917984, 인덱스에 있음)에 인용됨; 2020년 서울
노인 보행자 논문은 참조 57건 중 19건이 인덱스에 있음. OpenAlex는 NTL의
10.21949/… DOI를 해석함(ROSA-P 레코드 15,493건이 보유); DOI가 없는 레코드 —
ROSA-P 90,599건 중 73,000건 — 는 제목 일치에 의존하며, 정규화된 정확한 제목,
접두어 관계(판본 또는 부제 꼬리), 또는 ≥ 0.8 토큰 중첩을 허용하며 항상 연도
±1 범위입니다. 색인된 매체에서 아무도 인용하지 않은 그레이 문헌은 여전히 0으로
표시됩니다. 이는 인덱스가 아닌 인용 데이터의 속성입니다. OpenCitations와 Semantic
Scholar는 동일한 테이블에 폴백으로 추가할 수 있습니다.
의미 검색(v0.4)
키워드 검색은 FTS5/BM25입니다. 벡터를 추가하면 search_reports가 하이브리드 검색
(BM25와 코사인을 상호 순위로 융합)으로 바뀌어 의미와 언어를 넘어 레코드를 찾습니다 —
영어 쿼리가 스웨덴어, 독일어, 스페인어, 포르투갈어 또는 일본어 레코드에 도달합니다.
모든 것이 로컬에서 실행됩니다. 계정 없음, 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의미 검색 결과는 소스별로 다양화됩니다. source/collection으로 검색을 좁히지
않는 한 단일 소스가 요청된 결과의 절반 이상을 채울 수 없습니다
(TRANSPORT_LIT_SEMANTIC_PER_SOURCE). 측정된 이유: CiNii는 인덱스의 3분의 1을 차지하며
초록이 있는 레코드보다 짧은 쿼리에 더 가까운 수천 개의 짧은 영어 제목("Pedestrian safety
problems and countermeasures")을 보유합니다. 초록 유무 코사인 격차는 ~0.01에 불과하므로
이는 길이 아티팩트가 아닌 말뭉치 구성 문제이며, 상한선이 정직한 해결책입니다.
mode="semantic"은 전문가용 설정이고 hybrid가 기본값으로 유지됩니다.
하이브리드 융합은 키워드 목록에 1.0, 의미 목록에 0.7의 가중치를 부여하며
(TRANSPORT_LIT_SEMANTIC_WEIGHT), 의미 전용 후보는 코사인 0.5를 넘어야 합니다
(TRANSPORT_LIT_SEMANTIC_MIN). 이는 정밀 쿼리의 정밀도를 유지하면서
mode="semantic"은 재현율/교차 언어 설정으로 남습니다.
embed는 아직 벡터가 없는 레코드만 처리하므로 첫 패스 이후 주간
수확은 몇 초만 추가됩니다. 벡터는 $TRANSPORT_LIT_DATA_DIR/vectors/<backend-model>/에
메모리 매핑 float16 행렬(342k × 384 ≈ 260 MB)로 저장됩니다. 검색은 청크 내적이며
확장 기능이 없습니다. 활성 벡터 세트는 인덱스에 기록되므로 search_reports(mode=…)는
이를 생성한 백엔드를 사용합니다: hybrid(기본값), keyword, 또는 semantic;
모든 결과의 mode_used는 무엇이 실행되었는지 표시하며, 벡터가 없으면 키워드로
저하됩니다. harvest_status()는 백엔드, 모델, 차원 및 적용 범위를 보고합니다.
백엔드는 2026-08-26에 10코어 Apple Silicon 노트북에서 실제 레코드 256개(제목 + 초록)로 측정되었습니다. fastembed MiniLM-L12는 CPU에서 ≈ 30 records/s입니다(CoreML 제공자는 더 빠르지 않습니다). Ollama qwen3-embedding:0.6b ≈ 20/s(1024차원), qwen3-embedding:8b ≈ 1.4/s(4096차원, 1024로 절단)입니다. 따라서 기본 모델로 342k 레코드를 처음 전체 처리하는 데는 한 번에 약 3시간이 걸리며, 주간 증분은 수초에 불과합니다. --source를 사용하면 더 무거운 모델로 하나의 소스를 임베딩할 수 있습니다. MiniLM 모델은 최대 128토큰(제목과 초록의 첫 약 90단어)만 읽습니다. Qwen은 전체 1,500자 창을 읽고 쿼리에는 모델의 검색 명령 접두사가 붙습니다. 대부분의 사용자는 (아래의) snapshot을 설치하고 전체 처리를 아예 실행하지 않아야 합니다.
Snapshots: harvest 건너뛰기
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이것은 몇 분 안에 완료되는 완전하고 검색 가능한 설치입니다. 벡터가 포함된 224k 레코드(CiNii와 TRID를 제외한 모든 것)입니다. transport-lit snapshot build <file.tar.gz>는 SQLite 인덱스와 활성 벡터를 함께 패킹합니다. snapshot install <url-or-file>은 이를 새 TRANSPORT_LIT_DATA_DIR에 풀며, 이후 주간 증분 harvest가 최신 상태를 유지합니다(snapshot은 harvest 북키핑을 포함하므로 harvest --source all이 어디서 재개할지 압니다). Snapshots는 CiNii(해당 API 약관은 등록을 요구하고 재배포에 대해 침묵합니다)와 TRID 가져오기(TRB의 약관)를 제외합니다. 사용자는 이를 직접 harvest해야 합니다. 릴리스에는 snapshot이 빌드된 경우 해당 snapshot이 포함됩니다.
Available Tools
12 toolsexport_citationsARead-onlyIdempotent
Export records as RIS (Zotero/EndNote/Mendeley) or BibTeX. Pass transport-lit ids.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | ||
| format | No | ris |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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_similarBRead-onlyIdempotent
Records similar to a given one (by title and subject terms), across all sources.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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_citationsARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| limit | No | ||
| refresh | No | ||
| only_in_index | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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_fulltextARead-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'.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| offset | No | ||
| refresh | No | ||
| max_chars | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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_referencesBRead-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).
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| limit | No | ||
| refresh | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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_reportARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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_statusARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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_collectionsARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
lookupARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| identifier | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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_fulltextARead-onlyIdempotent
Search inside the PDF text that get_fulltext has already extracted and cached (only documents someone fetched before). Returns snippets with [term] markers.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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_reportsARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | hybrid | |
| limit | No | ||
| query | Yes | ||
| offset | No | ||
| source | No | ||
| doc_type | No | ||
| year_max | No | ||
| year_min | No | ||
| collection | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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_newARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | ||
| limit | No | ||
| source | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
12 tool updates
v0.5.1- First observed
export_citations - First observed
find_similar - First observed
get_citations - First observed
get_fulltext - First observed
get_references - First observed
get_report - First observed
harvest_status - First observed
list_collections - First observed
lookup - First observed
search_fulltext - First observed
search_reports - First observed
whats_new
TDQS
Scored across 12 tools
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.
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.
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.
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
Related MCP Connectors
Search arXiv/Semantic Scholar/OpenAlex + medical evidence (PubMed/Europe PMC) + LaTeX/PDF tools.
License-checked research archive and technical-spec search for AI agents. Pay per call via x402.
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 gradedqualityCmaintenanceEnables 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.-
- AlicenseAqualityCmaintenanceEnables 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.3MIT
- FlicenseNot gradedqualityAmaintenanceEnables 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.-
- AlicenseNot gradedqualityAmaintenanceEnables 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