Skip to main content
Glama

Vaglio

MCP server per la ricerca accademica governata. Vagliare: separare il grano dalla pula. Trova, apre, legge — e non mente mai su quale delle tre è successa.

Nasce da un incidente misurato il 2026-07-28: nove agent di ricerca in parallelo hanno fatto scattare il rate-limit di OpenAlex per 18 ore (Retry-After: 64902) a metà di un workflow. Ogni agent si comportava bene da solo; insieme erano un attacco. Il backoff per-chiamata non protegge da questo, perché il budget appartiene alla flotta, non al chiamante.

Ricerca completa: ~/ricerche/topics/metodo-ricerca-accademica/pipeline-fonti-open-access/.

Cosa fa che gli altri non fanno

Il prior art esiste ed è buono — openags/paper-search-mcp (MIT, 20 fonti, backoff, catena OA-first) copre la meccanica delle fonti. Vaglio non la riscrive: aggiunge i tre organi che mancano.

Organo

Cosa fa

Governance

token bucket condiviso fra processi (fcntl.flock su stato JSON per host) + cooldown propagato: quando un agent prende un 429, tutti gli altri lo sanno subito invece di riscoprirlo uno per uno

Evidenza

read_depth è derivato dagli artefatti su disco, non dichiarato: full-text solo se il corpo è stato scaricato e pesa. Il tetto del tier è derivato dai metadata della fonte: una review narrativa non può portare un claim da RCT. Tier A su soli metadata viene rifiutato. Tier D è un rifiuto registrato, con motivazione obbligatoria

Inscrizione

il run diventa un record versionato in ~/ricerche, conforme allo schema dell'archivio, con sources popolato da ciò che è stato realmente aperto

Related MCP server: wikipedia-recent-changes-mcp

Il tier non si dichiara: si deriva

Europe PMC e PubMed pubblicano il tipo MeSH di ogni lavoro, e Crossref marca i preprint come posted-content. Sono dati della fonte, non giudizi — quindi il tetto di forza di un claim si legge, non si opina:

Il record dice

Classe

Tier massimo

Randomized Controlled Trial, Clinical Trial

primary-trial

A

Meta-Analysis, Systematic Review

synthesis

A

Review, Letter, Case Reports, Editorial

secondary

B

posted-content / arXiv

preprint (non peer-reviewed)

B

research-article senza altro

primary-study

nessun tetto

niente

unknown

nessun tetto

Su una ricerca reale (binaural beats anxiety, Europe PMC) la separazione è netta al primo colpo: un solo RCT ammette tier A, mentre una Letter, una Review e un Case Report si fermano a B. Chi volesse scrivere "tier A: i binaural beats riducono l'ansia" citando la review viene fermato dal costruttore, non da un revisore a valle.

Due precisazioni, perché il meccanismo sia onesto: il tetto non promuove mai nulla — un claim debole su un RCT resta debole; e quando la fonte non dichiara il tipo, non c'è tetto e il giudizio dell'agent vale come prima.

Le fonti, e il loro ruolo

I ruoli non sono intercambiabili — è questo che fa funzionare il failover.

Ruolo

Fonti

Nota

FIND

Crossref → OpenAlex → PubMed → OpenAIRE

Crossref è la spina dorsale: 3 req/s, polite-array

OPEN

Unpaywall

dal DOI alla copia open access legale

READ

arXiv, Europe PMC, CORE

arXiv per fisica/matematica/DSP; Europe PMC dà il full text XML senza chiave, ed è dove si leggono i metodi

Su 429 non si ritenta la stessa fonte: si cambia fonte per lo stesso scopo. Ritentare un host che ha risposto con 18 ore di Retry-After è tempo buttato.

Fuori per scelta: Sci-Hub (esposizione legale che un portfolio commerciale non può portare) e i riassuntori mediati da LLM (Elicit, Consensus, SciSpace: mettono un secondo grado di separazione fra claim e fonte primaria).

Tool

Tool

Cosa fa

vaglio_search

cerca con failover per ruolo; riporta quali fonti hanno rifiutato e perché

vaglio_read

scarica e archivia il corpo, rendendo verificabile la profondità

vaglio_status

vista di flotta: chi è utilizzabile, chi è in cooldown e per quante ore

vaglio_sources

catalogo fonti, ruoli, capacità di full text

vaglio_appraise

assegna un tier a un claim, sotto la disciplina che lo guarda

vaglio_inscribe

scrive il record in ~/ricerche e rigenera l'indice

Installazione

cd ~/mcp/vaglio-mcp
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest        # i falsificatori

Registrazione come server MCP:

claude mcp add vaglio -- ~/mcp/vaglio-mcp/.venv/bin/vaglio-mcp

Nessuna chiave, nessun account, nessuna dipendenza HTTP di terze parti: il trasporto è urllib di stdlib, di proposito — questo strato non può avere una dipendenza che decida di fare una richiesta scavalcando il throttle.

Falsificatori

I test sono i falsificatori pre-registrati nel record di ricerca, non un contorno:

  • F1 — il budget è condiviso: due istanze indipendenti (due processi) non ottengono rate token a testa; un 429 su una è visibile all'altra senza che abbia mai chiamato; un 429 senza Retry-After non vale mai zero.

  • F2 — la profondità non mente: file vuoto ≠ full-text; tier A su soli metadata è rifiutato; tier D senza motivazione è rifiutato; un run letto perlopiù ad abstract lo dichiara.

  • F3 — il failover cambia fonte: l'host bloccato è provato una volta sola, mai ritentato; se cadono tutte, il risultato vuoto si spiega invece di sembrare "nessun risultato".

  • F4 — l'inscrizione è valida: frontmatter conforme allo schema dell'archivio, slug in kebab-case, full text copiato in sources/.

  • F5 — il tetto derivato regge: le etichette reali delle API mappano alla classe giusta; una review rifiuta il tier A e accetta il B; un RCT ammette A; un preprint è segnalato come non peer-reviewed e limitato; il silenzio della fonte non declassa nulla; il tetto non promuove mai un claim debole.

Con una regola in più, di governo e non di codice: vaglio_inscribe rifiuta status: falsified. Dire in conversazione che qualcosa non regge è dovuto; inscriverlo nel record come verdetto chiuso è una decisione di chi possiede la ricerca, non dello strumento.

Usare i primitivi da soli

I due organi centrali sono agnostici rispetto alla ricerca accademica e si usano senza toccare l'MCP: servono a qualunque flotta di agent.

pip install "vaglio-mcp @ git+https://github.com/Alemusica/vaglio-mcp"

Governance — qualunque API con rate limit, condivisa fra processi:

from vaglio_mcp.core.throttle import Throttle, HostBlocked

t = Throttle()                       # stato condiviso in ~/.vaglio/throttle
try:
    t.acquire("api.example.com")     # attende il turno, nel budget della flotta
except HostBlocked as e:
    ...                              # l'host e fuori per e.seconds_left: cambia strada
t.report_rate_limited("api.example.com", retry_after=3600)   # lo dice a tutti

Evidenza — tier e profondita di lettura, per ricerca ma anche per due diligence, FTO, audit normativo:

from vaglio_mcp.core.evidence import Finding, Paper, Tier

Finding(claim="...", tier=Tier.A, paper=Paper(title="...", source="..."))
# TierDiscipline: tier A dichiarato su soli metadata viene rifiutato qui,
# non scoperto a valle.

Nessuno dei due importa l'altro, e nessuno dei due sa cosa sia un paper: il throttle conosce host e secondi, l'evidenza conosce claim e artefatti.

Stato

Versione 0.2.0.

Candidati all'estrazione verso magazzino (dichiarati, non ancora promossi — regola dei 3 consumatori): core/throttle.py come primitivo di governance riusabile da qualunque flotta di agent, e core/evidence.py come disciplina tier/profondità agnostica rispetto al dominio.

Available Tools

6 tools
vaglio_appraiseB

Attach an evidence tier to a claim, under the discipline that guards it.

Tier A requires at least the abstract to have been retrieved — asserting RCT-strength from a title alone is rejected here rather than caught later. Tier D is a RECORDED refusal: it demands refused_reason, so a rejected idea leaves a trace instead of vanishing.

Inputs: tier (required), claim (required), paper_title (required), doi, +5 more.

vaglio_inscribeA

Write the run into the ~/ricerche archive as a versioned, schema-valid record.

Closes the loop the archive exists for: research that stays in a transcript gets lost. Copies any stored full text into the record's sources/ and regenerates the index.

Will REFUSE status: falsified — declaring something dead in a durable artifact is the research owner's decision, not the tool's.

Inputs: body (required), title (required), topic (required), record_id (required), +7 more.

vaglio_readA

Retrieve and STORE the body of a work, so its depth becomes verifiable.

Tries the native readers first (arXiv PDF, Europe PMC full-text XML), then resolves the DOI through Unpaywall to a legal open-access copy. The stored file is the proof: read_depth reports full-text only when bytes exist on disk. Returns metadata-only depth without complaint when no OA copy exists — that is an honest outcome, not a failure.

Inputs: title (required), doi, pmcid, oa_url, +2 more.

vaglio_sourcesA

Catalogue of sources and what each one is actually good for.

Roles are not interchangeable: finders locate a DOI, the opener resolves it to a legal copy, readers give you the body. Picking by role is what makes failover work.

Inputs: no named parameters.

vaglio_statusA

Show the shared request budget: which hosts are usable, which are cooling down.

This is the fleet view. When a source shows blocked_hours, every agent in every process is blocked on it — switch source instead of waiting.

Inputs: no named parameters.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4/5.0

    Scored across 6 tools

    Disambiguation5/5

    Each tool has a clearly distinct purpose: vaglio_search finds works, vaglio_read retrieves full text, vaglio_status shows budget/blocked hosts, vaglio_sources catalogues sources, vaglio_appraise attaches evidence tiers, vaglio_inscribe archives runs. No ambiguity.

    Naming Consistency5/5

    All tool names follow a consistent 'vaglio_<verb>' pattern with lowercase and underscores. Verbs are descriptive and match the action (search, read, status, sources, appraise, inscribe).

    Tool Count5/5

    Six tools is well-scoped for the server's purpose of searching, reading, appraising, and archiving bibliographic works. Each tool earns its place without unnecessary overlap.

    Completeness5/5

    The tool set covers the full logical workflow: search, retrieve full text, check system status, list sources, appraise evidence, and archive results. No obvious gaps for the intended domain.

    Related MCP Connectors

    Related MCP Servers