Crossref MCP コネクタ v0.1.0

STEP 2068 rei-aios-85 tab 2026-09-16

Crossref REST API を 測定器 として扱う read-only MCP コネクタ。 STEP 2067 の ranking-disagreement viewer装置がページ として完成したものを、呼べる道具 へ格上げした land。

系譜 (2 STEP arc)

STEPtab成果
2067 rei-aios-6e cowork Claude session 制作の public/tools/ranking-disagreement/ viewer land + scripts/fetch-journal-metrics.py で Crossref 実データ 11 誌 2,954 本を取得。装置が ページ として完成
2068 rei-aios-85 装置を 呼べる道具 へ格上げ: 4 tool を露出する MCP コネクタ、MODULE_INFO DRAFT → STEP 1676 8-key 契約準拠、tests 33 → 39 assertion

4 tool

tool返すもの
crossref_module_info自己記述 (STEP 1676 8-key 契約準拠) と reject 語彙
crossref_journal_info題名・出版社・分野・ISSN Portal URL
crossref_journal_metrics1 誌の被引用中央値 / 著者中央値 / 最大著者数 / 著者按分被引用
crossref_disagreement複数誌を 2 指標で別々に順位付けし、ずれだけを返す

crossref_disagreement合計も総合スコアも返さない。 2 指標の合成には重みが要り、その重みを決める根拠が無いため。読みは moved / max_shift / top3_overlap

reject 語彙 (7 種、閉じている)

ISSN_NOT_FOUND / WINDOW_EMPTY / NO_AUTHOR_DATA / SAMPLE_TOO_SMALL / UPSTREAM_UNAVAILABLE / RATE_LIMITED / BAD_REQUEST

未定義の code で Reject を作ろうとすると ValueError。 「取れなかった」ではなく 「どの ISSN の・どの期間で・何件しか取れず・最低何件必要だったか」 を返す。

MODULE_INFO 契約 (STEP 1676 8-key)

MODULE_INFOsrc/aios/self-description-contract/SelfDescriptionContract 8 key に voluntary 準拠:

Nuance (chat-Claude cowork session が明示指摘): STEP 1676 enumerate.tssougou-external-connectorsevolutionKind: 'function-add' = out-of-scope に分類している。 本 connector が 8-key shape を採用するのは契約からの逸脱ではなく、voluntary conformance (良い自己記述 discipline なので採用)。verify_module_info() は TypeScript verifyModuleInfo() の Python 港として core.py に同梱、test 側で issues == [] = CONFORM を assertion する。

self-test (2 層、装置設計の原則 ②)

種別件数失敗時の意味
層 1 offline fixture (HTTP 注入式) 39 assertion (33 元 + 6 MODULE_INFO 契約) コネクタのバグ
層 2 live (Crossref 実疎通) 1 assertion (Ann. Math.) Crossref 側の問題として SKIP (FAIL でない)

異常系だけでなく 正常系の fixture を必ず含めている (異常系だけだと、常に reject を返す実装が満点を取るため)。

python tests/test_core.py            # 39 PASS / 0 FAIL, live PASS
REI_SKIP_LIVE=1 python tests/test_core.py   # ネット遮断時も exit 0

land 位置

tools/sougou-external-connectors/
  ├── external_core.py           # 既存 共通コア (v0.2.0)
  ├── sat_connector.py           # SAT 大蔵経
  ├── philosophy_connector.py    # PhilPapers + SEP
  ├── jp_academic_connector.py   # CiNii + J-STAGE
  └── rei-crossref-mcp/          # ★ NEW (STEP 2068)
      ├── README.md
      ├── rei_crossref/
      │   ├── __init__.py
      │   ├── core.py            # 純粋層 (MCP 依存なし、offline test 可能)
      │   └── server.py          # 薄い MCP 露出層 (fastmcp 4.x)
      └── tests/
          └── test_core.py       # 2 層 self-test

MCP server 起動 verify (STEP 2068 実測)

MCP SDK 2.0 で FastMCP は別 package (fastmcp) に split された。server.pyfrom fastmcp import FastMCP を使用。

pip install "mcp[cli]" fastmcp
python -m rei_crossref.server     # stdio

実測 environment (rei-aios-85 tab): mcp 2.0.0 + fastmcp 4.0.4 + Python 3.134 tool 全登録確認 + crossref_module_info end-to-end invoke で JSON {ok:true, module:{...}, rejects:{...}} 返却確認。

既知の限界 (honest scope)

装置設計の 3 原則 (embed)

  1. Reject は座標付き — 7 種の閉じた語彙 + where dict で「どこで・なぜ」を返す
  2. Self-test を被診断対象から切り離す — HTTP を fetch 関数として注入、偽 fetch で offline test 可能
  3. 正常系の fixture を必ず含める — 異常系だけだと「常に reject を返す実装」が満点を取る

関連 STEP