arxiv-agent-mcp
arXiv Research-Concept Companion
AI/ML学習コンパニオンエージェント(KSE Agentic Lab の課題)です。Obsidian ボールトのコンセプト要約ノートを読み、関連する arXiv の論文を探し、各論文をトピックへの関連性と経過年数で調整した被引用インパクトでスコアリングし、生き残った候補が前提としている確立済みの論文を見つけ、その結果をボールトに書き戻します。
既存MCPサーバー(Part A): Obsidian Local REST API MCP。
カスタムMCPサーバー(Part B):
custom_server/— FastMCPアプリ。公開されている arXiv API と OpenAlex API を扱う3つのツール(認証不要)。エージェント:
agent/— PydanticAI のAgent(OpenRouter をバックエンドとして使用)が、2つの MCP 接続をツールセットとして保持し、LangGraph ステートマシンがその調整を行う。
前提条件
Python 3.12+、
uv。OpenRouter の API キー。
Obsidian に Local REST API コミュニティプラグインがインストールされ、動作していること。また、それに接続する MCP サーバーがあること(任意の Obsidian Local REST API MCP 実装でよい — 起動コマンドは設定可能、以下参照)。
Related MCP server: arxiv-mcp
インストール
uv sync
cp .env.example .env.env を記入します。
変数 | 意味 |
| OpenRouter キー — エージェントと |
| モデルの slug(例: |
| Local REST API プラグインの認証情報。 |
| Obsidian MCP サーバーを起動するスペース区切り argv(例: |
| フィルタを通過するための最低関連性スコア(0–1)。デフォルト |
| インパクト判定を通過するための最低年間被引用数。デフォルト |
| この年数未満の論文はインパクト判定を免除。デフォルト |
実行
1つの uv プロジェクトを共有する2つの独立したプロセス:
# process 1 — the custom MCP server (arXiv + OpenAlex)
uv run python -m custom_server.server
# process 2 — the agent (connects to both MCP servers), driven by a free-text prompt
uv run python -m agent.graph "Find papers related to my 'Transformers Concept Note'"agent/graph.py は custom_server/server.py を self 自身の stdio サブプロセスとして起動します。したがって、プロセス2はプロセス1が既に起動している必要はありません — 上記の2つのコマンドは、各プロセスが独立に起動できることを示しているだけです。
プロンプトは文字どおりのノートタイトルではありません。エージェントの最初のステップ(parse_prompt)は、LLM 呼び出しを使ってプロンプトが参照する Obsidian ノートを特定します。もしそれを特定できない場合は、実行は直ちに止まり、Obsidian に触れることなく「情報が不十分です。プロンプトに Obsidian ノートやページ名が指定されていませんでした」と表示します。また、そのノートから十分なコンセプトキーワードが得られない場合(min_keywords 未満。デフォルトは2)、そのノートを読み終えたところで実行は止まり、arXiv を検索せずに同様の「情報が不十分です」というメッセージを表示します。
オフライン / リプレイモード
カスタムサーバーは3つの外部ネットワークAPI(arXiv、OpenAlex、OpenRouter)を呼び出します。CUSTOM_SERVER_OFFLINE=1 を設定すると、custom_server/fixtures/ に記録されたフィクスチャからツールを提供してきるため、ネットワークアクセスや OPENROUTER_API_KEY は不要です。ネットワークが不安定なデモ・審査や、素早い反復に役立ちます。
CUSTOM_SERVER_OFFLINE=1 uv run python -m custom_server.server対象範囲: search_arxiv_papers(記録済みの検索フィードが1つあり、どのクエリにもそれを返す — 下記の制限を参照)、および記録済みの2件の論文、GPT-3(2005.14165)と ResNet(1512.03385)に対する score_paper_relevance / find_foundational_citations。
既知の制限:
search_arxiv_papersはオフラインモードではクエリに依存しません。クエリテキストに関係なく常に同じ記録済みフィードを返します。score_paper_relevanceとfind_foundational_citationsは記録された2つの論文のみを認識します。記録されていないarxiv\_idはPaperNotFoundError(実際の OpenAlex で見つからない場合に発生するのと同じエラー)をスローします。また、score_paper_relevanceに渡された未答録の論文タイトルはFixtureNotFoundErrorをスローします — この2つは区別でき、黙って誤った回答を返すことはありません。
フィクスチャを再生成・拡張するには: uv run python -m custom_server.fixtures.record が記録済みのarXiv/OpenAlexレスポンス(どちらも公開・認証不要API)を再度取得し、custom_server/fixtures/ 内の JSON/XML ファイルを上書きします。新しい論文を追加するには、record.py に httpx.get の呼び出しを2つ追加し、relevance_scores.json にそれに対応するエントリを追加してください。実際の OpenRouter の raw chat-completion レスポンスを記録してもワイヤーフォーマットの脆さに見合わないため、relevance_scores.json は手書きです(実際の OpenRouter 出力ではありません)。構造化された {relevance, novelty, rationale} フィールドは、PydanticAI の FunctionModel を直接を通じて再生されます。
テスト
uv run pytest custom_server/tests agent/testsすべてのネットワーク呼び出し(arXiv、OpenAlex、OpenRouter)はモック化されています。テスト中に実ネットワーク通信は発生しません。
ツール契約(Part C)
search_arxiv_papers(カスタム)
目的 | |
目的 | 主要なデータソースツール: トピックに関する候補論文を arXiv で検索します。 |
モデル向け説明 | 「トピックに関する論文を arXiv で検索する。カテゴリと最低投稿日で任意に制限できる。 |
入力 |
|
出力 |
|
エラー条件 | 不正なカテゴリーコード、不正な |
副作用 | なし — |
例 |
|
score_paper_relevance(カスタム)
目的 | |
目的 | 評価ツール: 1つの候補論文のテーマへの適合度と、その被引用状況が年齢調整済みの基準を満たしているかを判定します。 |
モデル向け説明 | 論文がコンセプト要約に対してどの程度関連し、新規性があるかをスコアリングし、被引用インパクトが最低基準(年間被引用数、1年未満の論文は免除)を満たしているか確認する。 |
入力 | 指定入力: |
出力 |
|
エラー条件 |
|
副作用 | 読み取り専用: OpenAlex GET と OpenRouter chat-completion 呼び出しがそれぞれ1回ずつ。 |
例 |
|
find_foundational_citations (カスタム)
目的 | 引用グラフ解析:1つの論文が与えられたら、その引用元である参考文献を被引用数で並べ替え、その論文が拠り所とする確立済みの研究を浮き彫りにします。 |
モデル向けの説明 | 「1つの論文の arXiv ID が与えられたら、その論文が引用している中で最も被引用数の多い参考文献 — つまりその論文が支えている確立された先行研究成果 — を返します。読む論文を選んだ後にこれを使い、その背後にある背景文献を浮き彫りにしてください。参考文献がひとつも記録されていない論文は空リストを返します。これは正常な結果であり、エラーではありません。」 |
入力 |
|
出力 |
|
エラー条件 |
|
副作用 | 読み出し専用。OpenAlex の paper ルックアップ1回+OpenAlex の works バッチルックアップを1回以上実行(1リクエストあたり50 ID 刻みで処理)。 |
例 |
|
Obsidian Local REST API MCP (既存, Part A)
PydanticAI エージェントの自然言語ツール呼び出し(固定のラッパー関数ではありません)を利用し、フローの以下の操作で使用します:
参照解決 | Obsidian を呼び出す前に、 |
読み込み | エージェントは、 |
書き込み | エージェントは、 |
エラー条件 | プラグインの停止、API キーの無効、またはノートの欠落は、黙って空の結果としてではなく、MCP サーバーからの判別可能な tool call 失敗として表現されます。 |
設計の根拠
なぜ Obsidian なのか: この課題は、エージェントが読み取りと書き込みの両方を行える既存の MCP サーバーを必要としています。自分のコンセプトノートは「すでに自分が何を知っているか」を取り込む自然な入力であり、生き残った論文を書き戻すことで、vault 内のループを視覚的に閉じることができます。
なぜログイン必須のサイトではなく arXiv + OpenAlex なのか: 当初検討していた KSE schedule / Moodle などの情報元は、いずれも個人ログインが必要であり、この課題の public-API ルールで紛失となります。arXiv と OpenAlex は公開・認証不要で、「relevance + impact」というドメインを直接支えています。
なぜエンペディングではなく LLM で関連性を判断するのか: OpenRouter にはエンペディングのエンドポイントが存在しないため(ライブのモデルカタログで確認済み)、
score_paper_relevanceはベクター類似度の代わりに PydanticAI の構造化出力呼び出しを使います。これは、このプロジェクトがすでに必要とする唯一のモデル認証情報をそのまま再利用する方法です。なぜ
find_foundational_citationsが「OpenAlex で再検索」でではないのか: これは、特定の1本の論文の参考文献リストを取り上げて被引用影響でランク付けするもので、課題の例が用いる「制御された文法比較しきい値」と同種の物です。キーワード駆動のsearch_arxiv_papersとは、役割と処理が明確に分離されています。フィルタリングは、4つめのツールではなく素朴な Python であるwhy:
agent/graph.pyのfilter_candidates_nodeにある relevance-threshold とimpact_passのフィルタは、スコア済みデータに対する決定的な後処理であって、新しいドメインロジックではありません。ツールにしたとしても、ifの穴をひとつ回るだけです。トレードオフ / 制限: カスタムサーバーのオフライン/リプレイ モード(前述の「オフライン / リプレイモード」参照)は、記録済みの2つの論文と、クエリに依存しない棚エクスプレス検索に対応しており、無作為なクエリに対する汎用的な記録・リプレイなものではありません。
agent/自身による Obsidian 呼び出しと OpenRouter 呼び出しはこの影響を受けず、引き続きライブアクセスが必要です。影響・関連は.envの設定値であり、リクエストごとに実行時調整できるようなものではありません。
先延ばしリスト(フラグ付き・削除はしていません)
ハードコードされた閾値を
.envよりリッチな実行時設定として送付すること。
デモ / ディフェンス用チェックリスト
uv run python -m custom_server.serverが単体で起動し、素の MCP クライアントのlist_toolsに3つのツールすべてが表示される。uv run pytest custom_server/tests agent/tests— ネットワークをモック / スタブして、すべてグリーンになる。CUSTOM_SERVER_OFFLINE=1 uv run python -m custom_server.serverで起動し、ライブネットワーク・API キーなしで3つのツール呼び出しに応答する(「オフライン / リプレイモード」を参照)。デモ用の vault ノートにて概要(例: "attention mechanisms")付きのノートを用意し、タイトルを「Transformers Concept Note」などにする。
uv run python -m agent.graph "Find papers related to my 'Transformers Concept Note'"を実行 — 全体のライブ実行が: ノート参照を解決し、ノートを読み込み、arXiv を検索し、候補をスコア化し、フィルタリングし、基礎引用をさがし、"{note_title} — Related Papers"を vault に書き戻す。2つのMCP 接続が最終出力に寄与していることを示す: 書き戻した note が、arXiv/OpenAlex のデータ(カスタムサーバー)と、元のコンセプト ノートの内容(Obsidian)の両方を参照を含んでいる。
情報不足のデモ: ノート名を指定しないプロンプト(例:
"What's a transformer?")で実行して、Obsidian を呼び出すことなく「十分な情報がありません...」と停止することを示す。そのあと、ほとんど空の内容のノートで実行し、arXiv を呼び出す前にそのノートを読んで停止することを示す。障害表示デモ (Obsidian) — Local REST APIプラグインを停止する(または不正な
OBSIDIAN_API_KEYや存在しないノートタイトルを使う)ことで、黙って空の結果にではなく、判別可能なエラーを出す。障害失敗デモ (カスタムサーバー) — 無効なカテゴリで
search_arxiv_papers
Available Tools
3 toolsfind_foundational_citationsA
Given one paper's arXiv ID, return its most-cited references — the well-established prior work it builds on.
Use this after selecting a paper to read, to surface the background literature behind it. A paper with no recorded references returns an empty list — that is a normal result, not an error.
| Name | Required | Description | Default |
|---|---|---|---|
| arxiv_id | Yes | ||
| max_results | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does disclose one important behavioral fact: an empty list is normal, not an error. It also implies a read-only operation. Yet it does not explain truncation behavior related to max_results or what the output format contains, though an output schema is present.
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 with meaningful information: what the tool returns, when to use it, and an important normalization about empty results. No filler or repetition.
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 tells the agent what input is expected, when to invoke it, and how to interpret an empty result. Since an output schema exists, return-value details are covered. The main remaining gap is clarifying max_results, but the schema's default and name largely bridge that.
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 clarifies what arxiv_id represents (the paper's identifier), but it does not explain max_results, which limits the number of references returned. The name max_results is somewhat self-explanatory, and its default of 3 helps, but the description could have explicitly connected it to the 'most-cited' behavior.
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 states the action (return references) and resource (most-cited references for a given arXiv ID). It also conveys the purpose (surface well-established prior work), but it does not explicitly distinguish itself from sibling tools such as search_arxiv_papers or score_paper_relevance.
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 says to use the tool after selecting a paper to read, which gives a clear context. However, it does not mention when not to use it or point to alternative sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
score_paper_relevanceA
Score how relevant and novel a paper is to a concept summary, and check whether its citation impact clears a minimum bar (citations per year, exempting papers younger than one year).
Use this on each candidate from search_arxiv_papers to decide whether it belongs in a reading list. Raises if the paper has no OpenAlex record, or if the underlying relevance-scoring model call fails.
| Name | Required | Description | Default |
|---|---|---|---|
| paper | Yes | ||
| concept_summary | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the behavioral burden. It discloses two error conditions (missing OpenAlex record and underlying model failure) and explains the citation-impact filtering rule, including the one-year exemption. This goes well beyond the schema.
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?
Every sentence carries necessary content: the scoring criterion, the usage context, and the failure behavior. There is no filler or repetition.
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 two-parameter tool with an output schema and sibling context, the description covers its need: why to call it, what to pass, how it decides, and what to expect when it errors.
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?
Since schema description coverage is 0%, the description has to convey parameter meaning. It explains concept_summary as the reference for scoring and clarifies that paper is a candidate from search_arxiv_papers. It does not detail paper field internals, but those are inherited from that tool.
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 verb and resource: score a paper's relevance and novelty against a concept summary, and check its citation impact. This clearly distinguishes it from search_arxiv_papers (retrieval) and find_foundational_citations.
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 intended use: apply this tool to each candidate from search_arxiv_papers to decide reading-list membership. It does not explicitly name alternatives or exclusions, but the context is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_arxiv_papersA
Search arXiv for papers on a topic, optionally restricted to categories and a minimum submission date.
Use this to find candidate papers before evaluating them individually with score_paper_relevance. A valid query that matches nothing returns an empty list — that is a normal result, not an error.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| categories | No | ||
| since_date | No | ||
| max_results | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the behavioral burden. It usefully discloses that an empty result is a normal outcome, not an error. However, it adds little about other behaviors such as result ordering, matching semantics, rate limits, or external API behavior, beyond what is essentially implied by a 'Search' operation.
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, each earning their place: the first states the operation and optional filters, the second gives pipeline guidance, and the third normalizes an empty result. It is front-loaded and free of 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?
Given that an output schema exists, return values are covered. The missing context is input format guidance for categories and since_date and the behavior of max_results. The description is adequate for a basic search call but not fully self-sufficient for an agent invoking an external API it has no prior knowledge about.
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 has 0% description coverage, so the description must compensate. It maps 'query' to topic, 'categories' to category restrictions, and 'since_date' to a minimum submission date. However, it does not explain expected formats for categories or since_date, and 'max_results' is never addressed, even though its name and default make its role partially inferable.
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?
States a specific verb and resource: 'Search arXiv for papers on a topic.' It also names the optional scope (categories, minimum submission date) and differentiates from the sibling by framing this as the discovery step before score_paper_relevance.
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?
Explicitly instructs when to use it: 'Use this to find candidate papers before evaluating them individually with score_paper_relevance.' This gives a clear pipeline context. It does not explicitly mention when not to use it or how it relates to the other sibling, find_foundational_citations, so it stops short of a 5.
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.
3 tool updates
v0.1.0- First observed
find_foundational_citations - First observed
score_paper_relevance - First observed
search_arxiv_papers
TDQS
Scored across 3 tools
The three tools have clearly distinct roles: searching arXiv, scoring a candidate paper, and tracing foundational references. There is no meaningful overlap between discovery, evaluation, and citation expansion.
All tool names follow a clean verb_noun snake_case pattern: search_arxiv_papers, score_paper_relevance, find_foundational_citations. The naming style is predictable and signals the action clearly.
Three tools is a well-scoped size for a focused arXiv triage workflow. Each tool covers a necessary step without redundant or filler tools.
The set covers the core pipeline: find candidate papers, evaluate relevance and citation impact, then discover foundational references. Minor omissions like retrieving full paper metadata or listing available arXiv categories could be useful but do not create dead ends.
Maintenance
Related MCP Connectors
Academic research MCP server for paper search, citation checks, graphs, and deep research.
Driflyte MCP server which lets AI assistants query topic-specific knowledge from web and GitHub.
An MCP server for deep research or task groups
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceThis MCP server enables users to search for scientific papers on arXiv and retrieve detailed metadata for specific papers. It provides tools to perform search queries and fetch in-depth information using paper IDs.3Apache 2.0
- FlicenseAqualityDmaintenanceA streamlined MCP server that connects AI assistants to arXiv's vast collection of academic papers, enabling search, retrieval, and analysis of research papers.71-
- FlicenseNot gradedqualityDmaintenanceAn advanced scholarly research MCP server that enables AI assistants to discover, fetch, process, and manage academic papers across multiple sources like arXiv, PubMed, and Semantic Scholar, with capabilities for summarization, citation analysis, and concept relationship extraction.2-
- FlicenseNot gradedqualityCmaintenanceAn MCP server that enables AI assistants to search arXiv papers, retrieve metadata, and access PDFs.-