# Give Your AI Agent a Scientist's Library. a Science MCP Server

> Source: <https://dev.to/valyuai/give-your-ai-agent-a-scientists-library-a-science-mcp-server-4pdb>
> Published: 2026-08-24 13:29:29+00:00

Most "research agent" demos are searching abstracts and calling it literature review. The abstract tells you a Phase 3 melanoma immunotherapy trial hit its endpoint. It does not tell you the imaging protocol used to assess tumour response that lives in the methods section, or a supplementary table, or a figure caption.

This walks through wiring a hosted science MCP server into your AI agent, scoping it to actual scientific collections, and running a controlled before-and-after test where exactly one variable changes.

Valyu is a search API built for AI agents:one endpoint over biomedical literature, clinical trial registries, patents, financial filings and the open web, returning full text and structured metadata with resolvable identifiers rather than a list of links to go click.

`mcp-remote`

.`query`

and `max_num_results`

and nothing else.`included_sources`

in the API, then check `result.source`

on every hit.`include_abstracts=True`

`result.doi`

— read it, don't prompt for it.`pip install valyu`

for the API examplesNo Node.js. The hosted server is remote HTTP.

The endpoint is:

```
https://mcp.valyu.ai/mcp?valyuApiKey=YOUR_API_KEY
```

Auth rides in the query string. You can cap spend per session by appending `&maxPrice=50`

.

**Claude Desktop / claude.ai** — go to [claude.ai/settings/connectors](https://claude.ai/settings/connectors) → Add custom connector → paste the URL.

Eleven tools, not one :

| Tool | Arguments | Use |
|---|---|---|
`valyu_search` |
`query` , `max_num_results` , `fast_mode`
|
Web search returning full page content |
`valyu_academic_search` |
`query` , `max_num_results`
|
Full text across arXiv, PubMed, bioRxiv, medRxiv |
`valyu_bio_search` |
`query` , `max_num_results`
|
PubMed, clinical trials, FDA labels, bioRxiv, medRxiv, ChEMBL, PubChem, DrugBank, Open Targets, NPI Registry, WHO ICD |
`valyu_patents` |
`query` , `max_num_results`
|
Patent documents — claims, abstracts, inventors, filings |
`valyu_contents` |
`urls` |
Extract content from up to 10 URLs |
`valyu_datasources` |
`category` |
Enumerate the 36+ datasets at runtime |

Plus `valyu_financial_search`

, `valyu_sec_search`

(adds `response_length`

), `valyu_company_research`

(`company`

, `sections`

), `valyu_economics_search`

and `valyu_datasources_categories`

.

*(API and SDK only — see the constraint above.)*

Sources are addressed two ways through `included_sources`

: **presets** (curated bundles) and **dataset IDs** (individual collections).

Presets: `academic`

, `finance`

, `patent`

, `health`

, `genomics`

, `chemistry`

, `physics`

, `legal`

, `politics`

, `transportation`

, `pulse`

, `cybersecurity`

, `environment`

, `automotive`

, `compliance`

, `medical`

.

**Watch the preset boundaries — this bites people.** `academic`

covers literature and preprints only:

| Dataset ID | Preset | Coverage |
|---|---|---|
`valyu/valyu-pubmed` |
academic | 37M+ open-access biomedical papers, monthly |
`valyu/valyu-arxiv` |
academic | Physics, CS, maths, quant finance, economics |
`valyu/valyu-biorxiv` |
academic | 250K+ life-sciences preprints |
`valyu/valyu-medrxiv` |
academic | 80K+ clinical/health preprints |
`valyu/valyu-chemrxiv` |
academic | 30K+ chemistry preprints |
`valyu/valyu-clinical-trials` |
health |
500K+ ClinicalTrials.gov studies, real-time |
`valyu/valyu-drug-labels` |
health |
150K+ FDA labels via DailyMed |
`valyu/valyu-patents` |
patent |
8M+ USPTO filings, full text and figures |
`valyu/valyu-patents-epo` |
patent |
4M+ European filings from 1978 |
`valyu/valyu-chembl` |
chemistry |
2.5M+ bioactive compounds |
`valyu/valyu-pubchem` |
chemistry |
100M+ compounds |
`valyu/valyu-open-targets` |
chemistry |
60K+ drug targets |

`valyu_bio_search`

additionally reaches DrugBank, the NPI Registry and WHO ICD codes, which aren't broken out as dataset IDs in the datasources guide.

Clinical trials are **not** in `academic`

. If you scope a trial question to the academic preset you will get papers *about* trials, not registry records. Use `health`

, or name `valyu/valyu-clinical-trials`

directly.

``` python
from valyu import Valyu

valyu = Valyu(api_key="YOUR_API_KEY")  # or set VALYU_API_KEY

response = valyu.search(
    "Phase 3 melanoma immunotherapy trials",
    search_type="proprietary",          # all | web | proprietary | news
    included_sources=["valyu/valyu-pubmed"],
    max_num_results=10,
)

for result in response.results:
    print(result.title)
    print(result.source)          # check this
    print(result.doi)
    print(result.content)
```

**Then check the results.** Every `SearchResult`

carries a `source`

field. After each search, confirm each result came from a collection you declared. If something arrives from elsewhere, treat the output as unscoped and rerun tighter. Filtering narrows the search; it is not a guarantee of exclusion.

Note `excluded_sources`

accepts dataset IDs and domains but **not** presets.

Here's the part worth running, with one honest caveat up front.

By default (`include_abstracts=False`

), PubMed search is restricted to **papers that have available full text**. Setting `include_abstracts=True`

**expands** the search to PubMed's complete abstract corpus and returns document-level abstracts.

So this is *not* a clean single-variable A/B. Two things change at once: the corpus gets bigger, and the returned granularity drops to abstract level. It's still the sharpest comparison the API gives you, but describe it accurately — you are comparing *full-text-only retrieval* against *broad abstract-level retrieval*, not "the same search with and without full text."

You want a detail that lives in the methods, a figure caption, or a supplement:

What imaging protocol did the trial use for tumour response assessment?

```
abstract_run = valyu.search(
    "Phase 3 melanoma immunotherapy tumour response assessment imaging protocol",
    search_type="proprietary",
    included_sources=["valyu/valyu-pubmed"],
    include_abstracts=True,      # widen to the full PubMed abstract corpus
    max_num_results=10,
)
```

**This has to run in Python, not through the MCP client.** No MCP tool accepts `include_abstracts`

— see the section above. Save the output verbatim. This is your baseline.

```
fulltext_run = valyu.search(
    "Phase 3 melanoma immunotherapy tumour response assessment imaging protocol",
    search_type="proprietary",
    included_sources=["valyu/valyu-pubmed"],
    include_abstracts=False,     # default — papers with available full text only
    max_num_results=10,
)
```

Identical query, identical source, identical result count. Save that too.

Put them side by side. Does the abstract-only answer contain the imaging protocol? Does the full-text one?

If full text surfaces evidence abstract-only missed, you have a controlled result — **for this query, this index, and this date.**

Things not to do with it:

Four things, or nobody can reproduce it: the exact call parameters, the full verbatim output, the source list, and the correction.

```
{
  "query": "<identical query string used in both runs>",
  "shared_params": {
    "search_type": "proprietary",
    "included_sources": ["valyu/valyu-pubmed"],
    "max_num_results": 10
  },
  "run_abstract_only": {
    "include_abstracts": true,
    "output": "<full output, verbatim>",
    "sources_returned": ["<result.source values>"]
  },
  "run_full_text": {
    "include_abstracts": false,
    "output": "<full output, verbatim>",
    "sources_returned": ["<result.source values>"]
  },
  "run_date": "<YYYY-MM-DD>",
  "correction": {
    "missed_by_abstract": "<what was missing>",
    "found_in_full_text": "<what full-text surfaced>",
    "source_doi": "<result.doi>",
    "location": "<methods / figure caption / supplement>"
  }
}
```

Record the date — PubMed syncs monthly and trials update in real time, so the same call will drift.

Every claim links to a resolvable identifier. This is the line between a science agent and a chatbot with a search tool.

| Source type | Identifier | Resolves at |
|---|---|---|
| Journal articles | DOI | `https://doi.org/<doi>` |
| Preprints (bioRxiv, medRxiv, ChemRxiv) | DOI | `https://doi.org/<doi>` |
| Clinical trials | NCT number | `https://clinicaltrials.gov/study/<nct>` |
| US patents | USPTO patent number | USPTO patent search portal |

You don't have to parse these out of prose — `SearchResult`

exposes `doi`

, `citation`

, `authors`

, `publication_date`

, `citation_count`

and `source`

as structured fields. Read them directly rather than asking the model to extract them.

Do not demand a DOI for everything. Trials and patents have their own registries, and a prompt that insists on DOIs produces fabricated ones.

```
For every factual claim, cite a resolvable identifier: a DOI for journal
articles, an NCT number for clinical trials, or a patent number for patents.
If the result has no identifier, give the URL and state that the claim is
unverified. Never construct an identifier that was not returned.
```

Three scoped searches, correct preset for each:

``` python
from valyu import Valyu

valyu = Valyu(api_key="YOUR_API_KEY")

# Literature — academic preset
lit = valyu.search(
    "PD-1 inhibitor combination therapy melanoma",
    search_type="proprietary",
    included_sources=["academic"],
)

# Clinical trials — registry records live in health, NOT academic
trials = valyu.search(
    "PD-1 inhibitor melanoma Phase 3",
    search_type="proprietary",
    included_sources=["valyu/valyu-clinical-trials"],
)

# Patents — USPTO full text and figures
patents = valyu.search(
    "PD-1 antibody immunotherapy",
    search_type="proprietary",
    included_sources=["valyu/valyu-patents"],
)
```

DOIs for the literature, NCT numbers for the trials, patent numbers for the patents.

Valyu's DeepResearch (`POST /v1/deepresearch/tasks`

) spans the same catalogue asynchronously. It *can* reach across domains in one task, but verify the returned sources match your intended scope before treating the output as complete.

**Source provenance** — read `result.source`

on every result. If it isn't a collection you declared, the run is unscoped.

**Identifier resolution** — verify the cited identifier actually resolves before presenting the claim. DOI at doi.org, NCT at clinicaltrials.gov, patent through USPTO. Doesn't resolve → unverified.

**Full-text availability** — PubMed full text is open access only, and `include_abstracts=True`

means you got abstracts *instead of* full text. Have the agent state which mode it ran in. An agent reasoning over an abstract as though it read the paper is the failure this whole post is about.

**Preprint status** — bioRxiv, medRxiv and ChemRxiv are not peer-reviewed. Label them as preprints, with server name and DOI, so the reader can judge evidence level.

**Citation entailment** — when the agent says a source supports a statement, confirm the passage is actually in the returned `content`

. If it cites a figure, confirm the figure came back.

**Missing assets** — figures, tables and supplements are not retrievable from every source. `valyu/valyu-patents`

is the one dataset documented as carrying full text and figures; don't assume that generalises to the preprint servers. If an asset isn't there, the agent says so rather than substituting.

Retrieval is not a redistribution licence. The [Valyu Acceptable Use Policy](https://www.valyu.ai/valyu-acceptable-use-policy) applies across all APIs, datasets, models and indexes. You must not:

**The contents endpoint is your responsibility.** Per the AUP: *"You — not Valyu — are the party responsible for ensuring that your use of the Contents endpoint in connection with any given URL is lawful and authorised."* Before submitting a URL, review the target's terms and acceptable use policy, and confirm automated extraction isn't prohibited by `robots.txt`

, `X-Robots-Tag`

headers or `<meta name="robots">`

directives.

In practice: the agent reads and reasons over retrieved content in-session and does not store it for redistribution. And retrieved research is not a substitute for professional medical advice, or for a human reading the primary source.

`included_sources`

set, with the right preset for the source type`max_num_results`

`include_abstracts`

differs between the two runs, and the writeup says the corpus widened too`result.source`

checked on every result`doi`

, NCT number or patent number`/v1/contents`

without checking terms and robots directives**How do I run the same question through both abstract-only and full-content workflows?**

In Python, not through MCP — no MCP tool exposes `include_abstracts`

. Issue the identical query twice against `valyu/valyu-pubmed`

, once with `include_abstracts=True`

and once with the default `False`

, keeping `search_type`

, `included_sources`

and `max_num_results`

fixed. Save both outputs verbatim.

**Can I restrict my Claude Desktop agent to just PubMed?**

No. MCP search tools accept only `query`

and `max_num_results`

. Your scope control is which tool the agent picks. For real source pinning, call the API directly.

**What makes a good test question?**

One where the decisive detail sits outside the abstract — imaging protocols, assay conditions, eligibility subtleties. "What imaging protocol did the Phase 3 melanoma immunotherapy trial use for tumour response assessment?" works because that lives in methods or a supplement.

**Why did my clinical trial search return papers instead of registry records?**

You almost certainly scoped to the `academic`

preset. Clinical trials live in `health`

— use `included_sources=["valyu/valyu-clinical-trials"]`

.

**How should the agent cite results without DOIs?**

NCT number for trials, patent number for patents. If none exists, the URL plus an explicit note that the claim is unverified. Read `result.doi`

rather than having the model extract it.
