radar-papers-mcp
This MCP server lets you query locally stored recent papers from PubMed/medRxiv and generate structured summaries using a local LLM.
Search recent papers (
buscar_papers_novos): find papers from monitored topics published/entered in the last N days (1–365), with pagination and filtering by topic name.Get paper summaries (
resumir_paper): given a paper key (DOI or source ID), returns a structured summary (problem, method, main finding, relevance) generated from the abstract by a local LLM.Handle unavailable summaries: if a paper has no abstract or the LLM is offline, it returns an explicit
indisponivelstatus with an explanation instead of inventing content.Cached results: summaries are cached, so the same paper is not summarized twice.
Browse metadata: each paper result includes title, source, URL, authors, DOI, publication/entry dates, and whether an abstract is available.
Monitors PubMed for research papers matching configurable topics, retrieves paper metadata and abstracts via the E-utilities API, and stores results locally with deduplication by DOI.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@radar-papers-mcpbusque e resuma papers novos sobre multicalibração dos últimos 7 dias"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
radar-papers-mcp
Servidor MCP que monitora PubMed e medRxiv por tópicos de pesquisa configuráveis e resume os papers com um LLM local. Guarda o resultado numa base local, deduplicado por DOI.
Sobre o que esta ferramenta faz e não faz
O resumo sai do abstract, não do texto completo. Ele serve para triagem: decidir se vale abrir o paper. Não substitui a leitura.
O resumo é gerado por LLM e pode errar. Confira os números no abstract original, o link vem em toda resposta.
A cobertura depende das suas queries. O que não casa com a query configurada simplesmente não aparece; ausência de resultado não significa ausência de literatura.
Requisitos
O quê | Versão | Para quê |
Python | 3.12+ | runtime |
recente | dependências e venv | |
Um LLM local com API OpenAI-compatible | - | resumo dos papers |
Chave da NCBI (opcional) | - | eleva o rate limit de 3 para 10 req/s |
Related MCP server: kavi-research-assistant-mcp
Instalação
git clone https://github.com/fabianofilho/radar-papers-mcp.git
cd radar-papers-mcp
uv sync
cp .env.example .envConfiguração
Variável | Padrão | Observação |
|
| llama.cpp. Ollama: |
|
| llama.cpp e LM Studio aceitam qualquer nome |
| vazio | |
|
| base local |
|
| tópicos monitorados |
Os tópicos ficam em config/topicos.yaml. Cada um tem duas configurações, porque as
fontes funcionam de forma diferente:
topicos:
- nome: multicalibração
pubmed: multicalibration[All Fields] # sintaxe das E-utilities
medrxiv: # palavras simples, filtradas localmente
- multicalibration
- multi-calibrationuv run papers-cli topicos
uv run papers-cli sync --dias 30
uv run papers-cli buscar "multicalibração"
uv run papers-cli resumir "10.1016/j.exemplo.2026.100217"Sync agendado
O servidor MCP só lê a base; quem a alimenta é papers-cli sync. O agendamento oficial é
um timer systemd de usuário, versionado em deploy/: roda todo dia às 04:10,
com atraso aleatório de até 30 minutos (para várias máquinas não baterem nas APIs públicas
no mesmo minuto) e Persistent=true (se a máquina estava desligada, roda ao ligar).
As units supõem o repositório em ~/radar-papers-mcp e o uv em ~/.local/bin/uv. Se for
diferente, ajuste WorkingDirectory e ExecStart antes de instalar.
cp deploy/radar-papers-sync.service deploy/radar-papers-sync.timer \
deploy/radar-papers-sync-falha.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now radar-papers-sync.timer
systemctl --user list-timers radar-papers-sync.timer # próxima execução
journalctl --user -u radar-papers-sync.service # log dos syncsFalha não passa em silêncio: se o PubMed (em qualquer tópico) ou o medRxiv falhar,
papers-cli sync grava o que as outras fontes trouxeram, lista as falhas no stderr e sai
com código 1. O systemd marca a unit como failed e o OnFailure roda
radar-papers-sync-falha.service, que grava uma linha com prioridade err no journal e,
se houver notify-send, mostra uma notificação. Para ser avisado por outro canal, troque
o ExecStart dessa unit. Para ver falhas recentes:
systemctl --user status radar-papers-sync.service
journalctl --user -t radar-papers-sync -p errSem o timer, rode papers-cli sync à mão ou pelo agendador que preferir; o servidor não
agenda nada sozinho.
Atualizando uma base criada antes do schema 2
A versão atual decide o que é "novo" pela data de entrada na fonte (coluna
data_entrada). Uma base antiga é migrada sozinha na primeira conexão de escrita (o
próximo sync, por exemplo). Na migração, a data de entrada do PubMed é aproximada pelo
dia da última coleta; para gravar a data Entrez real dos papers que já estavam na base,
rode uma vez:
uv run papers-cli corrigir-datasLigando ao Claude Code
claude mcp add radar-papers --scope user \
-e DUCKDB_PATH=/caminho/para/radar-papers-mcp/data/papers.duckdb \
-e TOPICOS_PATH=/caminho/para/radar-papers-mcp/config/topicos.yaml \
-e QWEN_ENDPOINT=http://127.0.0.1:8080/v1 \
-e QWEN_MODEL=local-model \
-- uv --directory /caminho/para/radar-papers-mcp run radar-papers-mcpUso
buscar_papers_novos(topico="", dias=7, limite=50)
Papers que entraram no PubMed ou no medRxiv nos últimos dias, lidos da base local, com
a chave para usar no resumo e o link original.
"Novo" é pela data de entrada na fonte (
data_entrada: Entrez no PubMed, postagem no medRxiv), não pela data da edição da revista (data_publicacao, só para exibição). A edição pode estar meses antes ou depois da entrada, e muitas revistas informam só o ano ou o mês.topicoé o nome de um tópico configurado. Caixa e acento não importam, e basta um trecho com palavras inteiras do nome (fairness,calibracao). A comparação é por palavra inteira:calibraçãonão trazmulticalibração. Se o pedido não corresponder a um único tópico, a resposta vem vazia com a lista dos tópicos válidos emaviso.diasvai de 1 a 365 elimitede 1 a 200. Os mais recentes vêm primeiro.totalconta todos os papers do período, mesmo os que ficaram além dolimite; nesse casoavisodiz quantos foram omitidos.
resumir_paper(paper_id: str)
{
"chave": "pubmed:42761253",
"titulo": "Mortality risk ranking after medical emergency team review...",
"url": "https://pubmed.ncbi.nlm.nih.gov/42761253/",
"origem": "llm",
"resumo": {
"problema": "Validação externa e redesenvolvimento de modelos preditivos de mortalidade após revisão da equipe de emergência.",
"metodo": "Coorte multicêntrica em quatro hospitais, 1.937 adultos.",
"achado_principal": "O modelo original discriminou bem (AUC 0,80) mas com estimativas variáveis entre hospitais; o novo modelo chegou a AUC 0,84 com menos variáveis.",
"relevancia": "Mostra que a discriminação pode ser robusta mesmo quando a calibração absoluta varia entre instituições."
},
"aviso": "O resumo é gerado por LLM local a partir do abstract, não do texto completo. Sempre confira no link original antes de citar."
}O conteúdo do resumo é de um retorno real (a chave acima é ilustrativa). O resumo fica
cacheado: o mesmo paper não é resumido duas vezes. Sem abstract, ou com o LLM fora do ar,
resumo vem nulo, origem vem indisponivel e aviso explica o motivo.
As duas fontes
Fonte | API | Limite |
PubMed | E-utilities ( | 3 req/s sem chave, 10 com chave |
medRxiv |
| sem busca por termo; paginado de 100 em 100 |
O sync pagina as duas fontes até o fim: o PubMed até o count do esearch (teto de 1000
IDs por tópico) e o medRxiv até o total da janela (teto de 100 páginas, 10 mil preprints).
Se um teto for atingido, o log do sync registra um aviso com o total da fonte.
O rate limit da NCBI é aplicado de verdade, a primeira tentativa de teste deste projeto
recebeu {"error": "API rate limit exceeded"}. O fetcher espaça as requisições conforme a
chave configurada.
O medRxiv não aceita busca por termo: a API é consultada uma vez por janela e o filtro por tópico é local, sobre título e abstract.
Deduplicação por DOI
O mesmo paper casa com mais de um tópico, e um preprint do medRxiv pode sair depois num periódico indexado no PubMed com o mesmo DOI. A chave é o DOI (ou o id da fonte quando não há DOI), e um paper já conhecido ganha o novo tópico na lista em vez de virar uma segunda linha.
Limitações conhecidas
Sem abstract, não há resumo. Um paper sem abstract devolve erro explícito em vez de um resumo gerado a partir do título. Resumir texto vazio produz exatamente o tipo de invenção plausível que torna a ferramenta inútil para pesquisa.
A janela do medRxiv custa caro. Uma semana do medRxiv tem por volta de mil preprints, e
o sync baixa todos para filtrar localmente (cerca de 10 requisições). Um backfill largo
(sync --dias 90) baixa muito mais; acima de 10 mil preprints na janela, o que passar do
teto fica de fora e o log avisa.
O filtro do medRxiv privilegia a cobertura, não a precisão. Um preprint casa com o
tópico quando qualquer termo da lista aparece como trecho do título ou do abstract. Isso é
intencional, para não perder preprint relevante, mas traz ruído: no tópico de calibração
aparecem preprints que falam de calibrar um instrumento ou um modelo econômico, sem relação
com modelo clínico. A triagem fica com você (ou com o resumir_paper, cujo campo
relevancia diz quando o paper só tangencia o tópico). Para reduzir o ruído, use termos
mais específicos no YAML.
A query do PubMed é sua responsabilidade. Uma query mal formada devolve zero sem erro.
Teste no PubMed antes de colocar no YAML, na prática,
buscas muito específicas devolvem pouquíssimo (multicalibration retorna ~14 resultados
em toda a base).
O resumo não é verificado contra o abstract. Diferente do projeto de protocolos, aqui
não há conferência de citação literal: o campo achado_principal pode conter um número
que o modelo interpretou errado.
Só PubMed e medRxiv. Sem arXiv, bioRxiv, Scopus ou Web of Science.
Privacidade
Sai da máquina: requisições ao PubMed (NCBI) e ao medRxiv. Se você configurar uma chave da NCBI, ela vai junto nas requisições, é o funcionamento normal da API.
Não sai: seus tópicos de pesquisa ficam no arquivo local; as queries vão às APIs como qualquer busca.
O abstract vai para o seu LLM no resumo.
Sem telemetria, sem analytics.
Contribuindo
Veja CONTRIBUTING.md. PubMed e medRxiv são serviços públicos: não rode sincronização em loop nem contorne o limitador de taxa.
Licença e atribuição
MIT: este projeto é agregação de literatura e metadados abertos, sem contato com regulação, conduta clínica ou dado de paciente.
Construído no contexto do IA.med.
Available Tools
2 toolsbuscar_papers_novosA
Papers que entraram no PubMed ou no medRxiv nos últimos dias, por tópico monitorado.
Consulta a base local, alimentada pelo sync (papers-cli sync, em geral agendado por um timer diário). "Novo" é pela data de entrada na fonte (Entrez no PubMed, postagem no medRxiv), não pela data da edição da revista. Cada resultado traz a chave para usar em resumir_paper e o link original. 'total' conta todos os papers do período; se passar de 'limite', o aviso diz.
Args: topico: nome de um tópico configurado; vazio devolve todos. Caixa e acento não importam, e basta um trecho com palavras inteiras do nome ("fairness"). Se não corresponder a um único tópico, a resposta traz a lista dos tópicos válidos no aviso. dias: tamanho da janela, de 1 a 365, a contar de hoje. limite: máximo de resultados devolvidos, de 1 a 200. Os mais recentes vêm primeiro.
| Name | Required | Description | Default |
|---|---|---|---|
| dias | No | ||
| limite | No | ||
| topico | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| dias | Yes | |
| aviso | No | |
| total | Yes | Quantos papers o período tem, mesmo além do limite |
| topico | Yes | |
| resultados | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does so thoroughly: it defines 'new' by source entry date, explains the local database sync, specifies that results include the key and link, describes the total/warning behavior when exceeding the limit, and details topic-matching nuances such as case/accent insensitivity and ambiguous-topic handling.
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 well structured: a one-sentence summary, followed by behavioral context, then a clear Args list. It is front-loaded with the essential purpose and contains 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 read/search tool with an output schema, the description covers everything needed to invoke it correctly: source, freshness definition, parameter semantics, output content, warnings, and the link to the sibling tool. Very little is left to guesswork.
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. The Args block fully documents all three parameters: topico's matching and failure behavior, dias' 1-365 window counted from today, and limite's 1-200 cap with newest-first ordering. This is substantial value beyond the bare schema.
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 tool as a search/lookup operation for papers newly entered in PubMed or medRxiv, scoped by monitored topic. It also differentiates from the only sibling, resumir_paper, by stating each result carries the key to use in that summarization tool.
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 gives clear context for use: consult a local database fed by a scheduled sync, filter by topic, time window, and result limit, and then use the resulting key with resumir_paper. It does not explicitly list when-not-to-use or alternative conditions, but the workflow context is unambiguous enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resumir_paperA
Resumo estruturado de um paper: problema, método, achado e relevância.
O resumo vem do abstract, não do texto completo, e é gerado pelo LLM local. Fica cacheado: o mesmo paper não é resumido duas vezes. Sem abstract, ou com o LLM fora do ar, resumo vem nulo, origem vem "indisponivel" e o aviso diz o motivo, em vez de um resumo inventado.
Args: paper_id: a chave devolvida por buscar_papers_novos (o DOI, em geral).
| Name | Required | Description | Default |
|---|---|---|---|
| paper_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | |
| aviso | No | |
| chave | Yes | |
| origem | Yes | llm, cache ou indisponivel |
| resumo | No | |
| titulo | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden — and it delivers. It discloses that the summary comes from the abstract (not full text), that it is generated by the local LLM, that results are cached (same paper never summarized twice), and precisely how failures behave: null summary, origin 'indisponivel', and a warning explaining the reason instead of fabricating content. This is exemplary edge-case disclosure.
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?
Compact and well-structured: purpose sentence first, then behavioral constraints, then the single argument. Every sentence earns its place — the caching, fallback, and source details are all high-value. No filler or repetition of the schema.
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?
Complete for a single-parameter tool. An output schema exists, so return values need not be spelled out in the description. The description covers purpose, input provenance, caching, and failure modes. The only minor gap is that it doesn't explicitly enumerate the output schema fields, but that is the output schema's job.
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 — and it does. It explains paper_id as the key returned by buscar_papers_novos (usually the DOI), giving both the provenance and format of the value. For a single-parameter tool this is sufficient; a slight gap is not spelling out the expected DOI format explicitly, but the source reference covers it.
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+resource: a structured summary (problema, método, achado, relevância) of a paper. It clearly distinguishes from the sibling buscar_papers_novos (search vs. summarize), and even references that tool as the source of the input key, so an agent cannot confuse the two.
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?
Usage context is implied rather than stated. The Args section references 'a chave devolvida por buscar_papers_novos', which implies the correct workflow (call search first, then summarize). However, it never explicitly says 'use this after buscar_papers_novos' or gives a when-not-to-use condition beyond the abstract/LLM fallback, so the guidance is implicit.
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.
1 tool update
- Changed
buscar_papers_novos4 fields changed- added
Input schema / properties / limiteAdded value: +{ + "default": 50, + "title": "Limite", + "type": "integer" +} - added
Output schema / $defs / PaperEncontrado / properties / data_entradaAdded value: +{ + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Data em que o paper entrou na fonte; é a que define 'novo'", + "title": "Data Entrada" +} - added
Output schema / $defs / PaperEncontrado / properties / data_publicacao / descriptionAdded value: +"Data da edição da revista (ou da postagem do preprint)" - added
Output schema / properties / total / descriptionAdded value: +"Quantos papers o período tem, mesmo além do limite"
2 tool updates
v0.1.0- First observed
buscar_papers_novos - First observed
resumir_paper
TDQS
Scored across 2 tools
The two tools have clearly distinct purposes: one retrieves recent paper lists, the other generates a structured summary of a single paper. No overlap or ambiguity in their roles.
Both tool names follow a consistent verb_noun pattern in Portuguese: buscar_papers_novos and resumir_paper. Naming style is uniform, lowercase with underscores.
With only two tools, the set is minimal but fits a narrow, focused purpose (monitor new papers and summarize them). It stays on the thin side but does not feel inadequate for that bounded scope.
The core workflow of finding new papers and getting summaries is fully supported. Minor gaps exist (e.g., no tool to fetch a single paper's raw metadata by ID), but agents can complete the primary loop without dead ends.
Maintenance
Related MCP Connectors
Search PubMed/Europe PMC, fetch articles and full text (PMC/EPMC/Unpaywall), citations, MeSH terms.
Extract papers from ArXiv — titles, abstracts, authors, categories & PDF links. Monitor new AI, phys
Search arXiv/Semantic Scholar/OpenAlex + medical evidence (PubMed/Europe PMC) + LaTeX/PDF tools.
Extract structured data points from research papers and other documents with an LLM.
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP server pulling academic publications (arXiv, PubMed, HF Daily Papers), trending code (GitHub, HF Hub), and medical-device regulatory data (FDA 510(k), recalls) into newspaper-style briefings. Per-category round-robin, weighted configuration, sandbox-safe Python launcher.166MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI to save, organize, search, and synthesize research materials using a local vector database with support for both OpenAI and Ollama backends.1MIT
- AlicenseAqualityCmaintenanceProvides structured PubMed literature data for LLM agents, supporting search, caching, and open-access full-text downloads via the MCP protocol.533 npm11Apache 2.0
- FlicenseNot gradedqualityBmaintenanceEnables local research workflows (paper discovery, relevance scoring, digests) and homelab monitoring (Prometheus, logs) through an MCP server, using local LLM inference via Ollama with no cloud dependencies.-