Skip to main content
Glama
tbaraniuk

arxiv-agent-mcp

by tbaraniuk

arXiv Research-Concept Companion

Un agente de estudio-compañero de IA/ML (tarea de KSE Agentic Lab). Lee una nota de resumen de conceptos de tu bóveda de Obsidian, encuentra artículos relacionados de arXiv, puntúa cada uno según su relevancia temática e impacto de citas ajustado por edad, encuentra los artículos bien establecidos en los que se basa un candidato superviviente y escribe los hallazgos de vuelta en la bóveda.

  • Servidor MCP existente (Parte A): Obsidian Local REST API MCP.

  • Servidor MCP personalizado (Parte B): custom_server/ — aplicación FastMCP, 3 herramientas sobre las APIs públicas de arXiv y OpenAlex (sin autenticación).

  • Agente: agent/ — un Agent de PydanticAI (respaldado por OpenRouter) que mantiene ambas conexiones MCP como conjuntos de herramientas, orquestado por una máquina de estados de LangGraph.

Requisitos previos

  • Python 3.12+, uv.

  • Una clave de API de OpenRouter.

  • Obsidian con el plugin de la comunidad Local REST API instalado y en ejecución, y un servidor MCP que se comunique con él (cualquier implementación de MCP de Obsidian Local REST API — el comando de lanzamiento es configurable, ver más abajo).

Related MCP server: arxiv-mcp

Instalación

uv sync
cp .env.example .env

Rellena .env:

Variable

Significado

OPENROUTER_API_KEY

Clave de OpenRouter — utilizada por el agente y por score_paper_relevance.

OPENROUTER_MODEL

Slug del modelo, p. ej. openai/gpt-4o-mini.

OBSIDIAN_API_KEY / OBSIDIAN_BASE_URL

Credenciales del plugin Local REST API.

OBSIDIAN_MCP_COMMAND

argv separado por espacios para lanzar tu servidor MCP de Obsidian, p. ej. npx -y <obsidian-mcp-package>.

RELEVANCE_PASS_THRESHOLD

Puntuación mínima de relevancia (0–1) para superar el filtro. Por defecto 0.5.

CITATIONS_PER_YEAR_THRESHOLD

Citas mínimas por año para superar la comprobación de impacto. Por defecto 5.

NEW_PAPER_AGE_EXEMPT_YEARS

Los artículos más recientes que esta edad están exentos de la comprobación de impacto. Por defecto 1.

Ejecución

Dos procesos independientes, que comparten un proyecto uv:

# 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 lanza custom_server/server.py como subproceso stdio, por lo que el proceso 2 no necesita que el proceso 1 ya esté en ejecución — los dos comandos anteriores solo demuestran que cada uno se puede iniciar de forma independiente.

El prompt no es un título de nota literal — el primer paso del agente (parse_prompt) utiliza una llamada LLM para identificar a qué nota de Obsidian se refiere el prompt. Si no puede identificar una, la ejecución se detiene inmediatamente e imprime "Información insuficiente: no se nombró ninguna nota o página de Obsidian en el prompt." sin tocar Obsidian. Si la nota que encuentra no produce suficientes palabras clave de concepto (menos de min_keywords, por defecto 2), la ejecución se detiene después de leerla e imprime un mensaje similar de "información insuficiente" en lugar de buscar en arXiv.

Modo sin conexión / reproducción

El servidor personalizado llama a tres APIs de red en vivo (arXiv, OpenAlex, OpenRouter). Al establecer CUSTOM_SERVER_OFFLINE=1, sus herramientas se sirven desde fixtures grabados en custom_server/fixtures/ en su lugar — no se requiere acceso a la red ni OPENROUTER_API_KEY. Útil para una demo/defensa sin red fiable, o para iteración rápida.

CUSTOM_SERVER_OFFLINE=1 uv run python -m custom_server.server

Lo que está cubierto: search_arxiv_papers (un feed de búsqueda grabado, servido para cualquier consulta — ver limitación abajo), y score_paper_relevance / find_foundational_citations para dos artículos grabados, GPT-3 (2005.14165) y ResNet (1512.03385).

Limitaciones conocidas:

  • search_arxiv_papers es agnóstico a la consulta en modo sin conexión — siempre devuelve el mismo feed grabado independientemente del texto de la consulta.

  • score_paper_relevance y find_foundational_citations solo reconocen los dos artículos grabados anteriores. Un arxiv_id no grabado lanza PaperNotFoundError (el mismo error que produciría un fallo real de OpenAlex); un título de artículo no grabado pasado a score_paper_relevance lanza FixtureNotFoundError — distinguible, no una respuesta incorrecta silenciosa.

Para regenerar o ampliar los fixtures: uv run python -m custom_server.fixtures.record vuelve a obtener las respuestas grabadas de arXiv/OpenAlex (ambas APIs públicas, sin autenticación) y sobrescribe los archivos JSON/XML en custom_server/fixtures/. Para añadir un nuevo artículo, añade sus dos llamadas httpx.get a record.py y una entrada correspondiente a relevance_scores.json (escrita a mano — no es salida real de OpenRouter, ya que grabar su respuesta cruda de chat-completion no vale la pena por la fragilidad del formato de cable; los campos estructurados {relevance, novelty, rationale} se reproducen directamente a través de un FunctionModel de PydanticAI).

Pruebas

uv run pytest custom_server/tests agent/tests

Todas las llamadas de red (arXiv, OpenAlex, OpenRouter) están simuladas; no hay tráfico en vivo durante las pruebas.

Contratos de herramientas (Parte C)

search_arxiv_papers (personalizado)

Propósito

Herramienta principal de fuente de datos: busca en arXiv artículos candidatos sobre un tema.

Descripción para el modelo

"Busca en arXiv artículos sobre un tema, opcionalmente restringido a categorías y una fecha mínima de envío. Usa esto para encontrar artículos candidatos antes de evaluarlos individualmente con score_paper_relevance. Una consulta válida que no coincide con nada devuelve una lista vacía — eso es un resultado normal, no un error."

Entrada

query: str, categories: list[str] = [cs.LG, cs.AI, cs.CL, stat.ML], since_date: str | None (YYYY-MM-DD), max_results: int = 10 (1–50)

Salida

list[{arxiv_id, title, abstract, authors: list[str], published_date, categories: list[str]}]

Condiciones de error

ValueError en un código de categoría inválido, un since_date malformado, o max_results fuera de [1, 50] — lanzado antes de cualquier llamada de red. Un fallo HTTP ascendente lanza vía raise_for_status(). Cero coincidencias es una lista vacía válida, no un error.

Efectos secundarios

Ninguno — GET HTTP de solo lectura a export.arxiv.org.

Ejemplo

search_arxiv_papers(query="transformer attention", max_results=5) → 5 artículos candidatos con resúmenes.

score_paper_relevance (personalizado)

Propósito

Herramienta evaluativa: juzga el ajuste temático de un candidato y si su registro de citas supera un umbral ajustado por edad.

Descripción para el modelo

"Puntúa cuán relevante y novedoso es un artículo para un resumen de concepto, y comprueba si su impacto de citas supera un umbral mínimo (citas por año, eximiendo artículos de menos de un año). Usa esto en cada candidato de search_arxiv_papers para decidir si pertenece a una lista de lectura. Lanza un error si el artículo no tiene registro en OpenAlex, o si la llamada subyacente al modelo de puntuación de relevancia falla."

Entrada

concept_summary: str, paper: {arxiv_id, title, abstract}

Salida

{relevance: float, novelty: float, citation_count: int, publication_year: int, citations_per_year: float, impact_pass: bool, rationale: str}

Condiciones de error

PaperNotFoundError (de custom_server.openalex) si OpenAlex no tiene registro para el DOI de arXiv del artículo — distinto de un artículo encontrado pero sin citas, que es un citation_count: 0 válido. UnexpectedModelBehavior si la salida estructurada de la llamada a OpenRouter falla la validación de esquema después de reintentos.

Efectos secundarios

Solo lectura: una GET a OpenAlex, una llamada de chat-completion a OpenRouter.

Ejemplo

score_paper_relevance(concept_summary="attention mechanisms in NLP", paper={...}){relevance: 0.92, novelty: 0.6, citation_count: 84331, impact_pass: True, ...}

find_foundational_citations (personalizado)

Propósito

Análisis de grafo de citas: dado un artículo, ordena sus propias referencias por número de citas para destacar el trabajo consolidado sobre el que se basa. Se distingue de search_arxiv_papers — analiza la lista de referencias de un artículo específico, no una búsqueda por palabras clave.

Descripción orientada al modelo

"Dado el ID de arXiv de un artículo, devuelve sus referencias más citadas — el trabajo previo consolidado sobre el que se basa. Úsalo después de seleccionar un artículo para leer, para sacar a la luz la literatura de fondo que hay detrás. Un artículo sin referencias registradas devuelve una lista vacía — eso es un resultado normal, no un error."

Entrada

arxiv_id: str, max_results: int = 3 (1–3)

Salida

list[{openalex_id, title, cited_by_count, publication_year}], ordenada por cited_by_count descendente, los max_results principales

Condiciones de error

ValueError si max_results está fuera de [1, 3]. PaperNotFoundError si OpenAlex no tiene registro para el ID de arXiv. Un artículo con cero referencias devuelve [] — válido, no un error.

Efectos secundarios

Solo lectura: una consulta de artículo en OpenAlex + una o más consultas por lotes de obras de OpenAlex (divididas en bloques de 50 IDs por solicitud).

Ejemplo

find_foundational_citations(arxiv_id="2005.14165", max_results=3) → los 3 artículos más citados que referencia GPT-3.

Obsidian Local REST API MCP (existente, Parte A)

Se usa mediante las llamadas a herramientas en lenguaje natural del agente PydanticAI (no una función envoltorio fija) para dos operaciones en el flujo:

Resolución de referencias

Antes de cualquier llamada a Obsidian, parse_prompt pide al agente PydanticAI (razonamiento LLM simple, no una llamada MCP) que identifique el título de la nota implícito en la consulta de texto libre del usuario. Si no se puede identificar ninguno, el flujo se detiene con un estado de "información insuficiente" y nunca llama a Obsidian.

Lectura

Se pide al agente que lea la nota titulada note_title (de parse_prompt) y devuelva su contenido en texto plano — alimenta concept_text, la entrada para la extracción de palabras clave y la puntuación de relevancia.

Escritura

Se pide al agente que cree/sobrescriba una nota titulada "{note_title} — Related Papers" con el markdown producido por compose_note_content — el efecto observable que cierra el bucle entre ambos servidores MCP.

Condiciones de error

Plugin detenido, clave API inválida o una nota inexistente se manifiestan como un fallo distinguible de llamada a herramienta desde el servidor MCP, no como un resultado vacío silencioso.

Justificación del diseño

  • Por qué Obsidian: la tarea necesita un servidor MCP existente del que el agente tanto lea como escriba. Las notas de conceptos propias de un estudiante son una entrada natural de "lo que ya sé", y escribir los supervivientes de vuelta cierra el bucle visiblemente en la bóveda.

  • Por qué arXiv + OpenAlex en lugar de un sitio con muro de inicio de sesión: las fuentes consideradas originalmente (horario KSE/Moodle) requieren ambas inicio de sesión personal, lo que la regla de API pública de la tarea descarta. arXiv y OpenAlex son públicos, sin autenticación, y respaldan directamente el dominio de "relevancia + impacto".

  • Por qué la relevancia la juzga un LLM, no embeddings: OpenRouter no tiene endpoint de embeddings (verificado contra su catálogo de modelos en vivo), por lo que score_paper_relevance usa una llamada de salida estructurada de PydanticAI en lugar de similitud vectorial — reutilizando la única credencial de modelo que el proyecto ya necesita.

  • Por qué find_foundational_citations no es "buscar de nuevo con OpenAlex": toma la lista de referencias de un artículo específico y la ordena por impacto de citas, el mismo tipo de comparación de indicadores controlada que usan los ejemplos de la propia tarea — responsabilidad y procesamiento distintos de la búsqueda por palabras clave search_arxiv_papers.

  • El filtrado es Python simple, no una 4ª herramienta: el umbral de relevancia + filtro impact_pass en filter_candidates_node de agent/graph.py es post-procesamiento determinista sobre datos ya puntuados, no lógica de dominio nueva — una herramienta sería solo indirección alrededor de un if.

  • Compensaciones / limitaciones: el modo offline/replay del servidor personalizado (ver "Modo offline / replay" más arriba) cubre dos artículos registrados y una búsqueda de arXiv independiente de la consulta — no una grabación/reproducción general de consultas arbitrarias. Las llamadas propias de agent/ a Obsidian y OpenRouter no se ven afectadas por él y siguen requiriendo acceso en vivo. Los umbrales de impacto/relevancia son valores de .env, no ajustables en tiempo de ejecución por solicitud.

Diferido (marcado, no descartado)

  • Exponer los umbrales codificados como configuración de ejecución más rica más allá de .env.

Lista de verificación para demostración / defensa

  • uv run python -m custom_server.server se inicia de forma independiente; un cliente MCP crudo con list_tools muestra las 3 herramientas.

  • uv run pytest custom_server/tests agent/tests — todo en verde, red simulada.

  • CUSTOM_SERVER_OFFLINE=1 uv run python -m custom_server.server se inicia y sirve las 3 llamadas a herramientas sin red en vivo ni claves API requeridas (ver "Modo offline / replay").

  • Siembra una nota de demostración en la bóveda con un resumen de concepto (p. ej. "mecanismos de atención"), titulada p. ej. "Nota de concepto sobre Transformers".

  • uv run python -m agent.graph "Find papers related to my 'Transformers Concept Note'" — ejecución completa en vivo: resuelve la referencia de la nota, lee la nota, busca en arXiv, puntúa candidatos, filtra, encuentra citas fundacionales, escribe "<nota> — Related Papers" de vuelta en la bóveda.

  • Muestra ambas conexiones MCP alimentando la salida final: la nota de escritura cita tanto datos de arXiv/OpenAlex (servidor personalizado) como el contenido de la nota de concepto original (Obsidian).

  • Demostración de información insuficiente: ejecuta con una consulta que no nombre ninguna nota (p. ej. "What's a transformer?") — muestra que el agente se detiene e imprime "Not enough information..." sin llamar a Obsidian. Luego ejecuta contra una nota con contenido casi vacío — muestra que se detiene después de leer la nota, antes de llamar a arXiv.

  • Demostración de fallo, Obsidian: detén el plugin Local REST API (o usa una OBSIDIAN_API_KEY incorrecta / un título de nota inexistente) — muestra que el agente presenta un error distinguible, no un resultado vacío silencioso.

  • Demostración de fallo, servidor personalizado: llama a search_arxiv_papers con una categoría inválida, o a find_foundational_citations con un ID de arXiv ausente en OpenAlex — muestra ValueError / PaperNotFoundError respectivamente, distinto de un resultado vacío válido.

Install Server
A
license - permissive license
A
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    This 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.
    3
    Apache 2.0
  • F
    license
    A
    quality
    D
    maintenance
    A streamlined MCP server that connects AI assistants to arXiv's vast collection of academic papers, enabling search, retrieval, and analysis of research papers.
    7
    1
  • F
    license
    Not graded
    quality
    D
    maintenance
    An 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.
    1

View all related MCP servers

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

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/tbaraniuk/arxiv-agent-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server