NIH RePORTER MCP Server
Allows finding PubMed publications linked to NIH-funded research projects, returning PMIDs that can be used with PubMed APIs for citation details.
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., "@NIH RePORTER MCP Serverfind recent R01 grants on cancer immunotherapy"
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.
NIH RePORTER MCP Server
An MCP server that wraps the NIH RePORTER API v2, enabling AI agents to search and analyze NIH-funded research projects and their linked publications. No API key required.
Tools
Tool | Description |
| Search for NIH research projects by text, PI, organization, funding, and more |
| Get full details for a specific project by application ID or project number |
| Find PubMed publications linked to NIH grants |
nih_search_projects
Search the NIH RePORTER database for federally funded research projects. Multiple criteria are combined with AND logic; within list parameters, values use OR logic.
Parameters:
text(string, optional): Free-text search across titles, abstracts, and termstext_operator("and" | "or", default "and"): How multi-word queries are combinedtext_fields("all" | "title" | "abstract" | "terms", default "all"): Which fields to searchpi_name(string, optional): PI name, e.g. "Smith, John" or "Smith"organization(string, optional): Organization name (partial match)activity_codes(list of string, optional): e.g. ["R01", "R21"]agencies(list of string, optional): NIH IC abbreviations, e.g. ["NCI", "NIMH"]fiscal_years(list of int, optional): e.g. [2024, 2025]funding_mechanism(list of string, optional): e.g. ["RP", "SB"]spending_categories(list of int, optional): RCDC category IDsstates(list of string, optional): US state abbreviationsaward_amount_min/award_amount_max(int, optional): Dollar rangeproject_start_after/project_start_before(string, optional): YYYY-MM-DDexclude_subprojects(bool, default true): Exclude subprojectsinclude_active_only(bool, default false): Only active projectsdetail_level("summary" | "full", default "summary"): Summary returns key fields; full includes abstractssort_by("relevance" | "date" | "amount", default "relevance"): Sort orderlimit(int, default 10, max 50): Results per pageoffset(int, default 0): Pagination offsetsearch_id(string, optional): Reuse a prior search for pagination
Example:
{
"text": "machine learning",
"agencies": ["NIGMS"],
"activity_codes": ["R01"],
"fiscal_years": [2025],
"limit": 5
}nih_get_project
Get full details for a specific NIH-funded project. Use after finding a project of interest via nih_search_projects.
Parameters:
appl_id(int, optional): Application ID, e.g. 10878415project_num(string, optional): Full project number, e.g. "5R01CA123456-03"
One of appl_id or project_num is required.
Example:
{"appl_id": 10878415}nih_find_publications
Find PubMed publications linked to NIH-funded projects. Returns PMIDs that can be used with PubMed APIs for full citation details.
Parameters:
core_project_nums(list of string, optional): e.g. ["R01CA123456"]. Supports wildcard*.appl_ids(list of int, optional): Application IDspmids(list of int, optional): PubMed IDs (reverse lookup: which grants funded this paper?)limit(int, default 50, max 500): Results per pageoffset(int, default 0): Pagination offset
At least one of the search parameters is required.
Example:
{"core_project_nums": ["R01CA123456"]}Related MCP server: NIH Reporter MCP Server
Quick Start
Local Development
make install
make run-local
# Test with cmcp (in another terminal)
cmcp ".venv/bin/python -m src.main" tools/listDeploy to OpenShift
make deploy PROJECT=my-projectClient Configuration
STDIO (local):
{
"mcpServers": {
"nih-reporter": {
"command": ".venv/bin/python",
"args": ["-m", "src.main"]
}
}
}HTTP (remote):
{
"mcpServers": {
"nih-reporter": {
"url": "https://<route>/mcp/"
}
}
}Development
Running Tests
make test
# Or directly
.venv/bin/pytest tests/ -v
# Single test file
.venv/bin/pytest tests/tools/test_nih_search_projects.py -vAdding Tools
Create a Python file in src/tools/ using the @mcp.tool decorator:
from typing import Annotated
from pydantic import Field
from fastmcp import Context
from fastmcp.exceptions import ToolError
from src.core.app import mcp
@mcp.tool(
annotations={"readOnlyHint": True, "openWorldHint": True},
timeout=30.0,
)
async def my_tool(
param: Annotated[str, Field(description="Parameter description")],
ctx: Context = None,
) -> dict:
"""Tool description for the LLM."""
return {"result": param}Generate scaffolds with:
fips-agents generate tool my_tool --description "Tool description" --async --with-contextProject Structure
src/
├── core/
│ ├── app.py # Shared FastMCP instance
│ ├── server.py # Server bootstrap (load + run)
│ ├── loaders.py # Dynamic component discovery
│ ├── auth.py # Optional JWT authentication
│ └── logging.py # Logging configuration
├── tools/
│ ├── nih_client.py # Shared HTTP client with rate limiting
│ ├── nih_search_projects.py # Project search tool
│ ├── nih_get_project.py # Project detail tool
│ └── nih_find_publications.py # Publication search tool
├── resources/ # (none currently)
├── prompts/ # (none currently)
└── middleware/ # (none currently)
tests/
└── tools/
├── test_nih_search_projects.py # 55 tests
├── test_nih_get_project.py # 8 tests
└── test_nih_find_publications.py # 9 testsDependencies
fastmcp >= 2.11.3 -- MCP server framework
httpx >= 0.28.0 -- Async HTTP client for NIH API calls
Environment Variables
Variable | Default | Purpose |
|
| Transport: |
|
| HTTP bind address |
|
| HTTP port |
|
| HTTP endpoint path |
|
| Logging level |
|
| Enable hot-reload for development |
|
| Server name in MCP responses |
NIH API Notes
No authentication required. The API is publicly accessible.
Rate limit: 1 request per second (enforced by the shared client).
Result limit: The API can return at most 15,000 records per search. The tool warns when this limit is hit.
Documentation: api.reporter.nih.gov
License
This project is licensed under the MIT License.
Available Tools
3 toolsnih_find_publicationsNih Find PublicationsARead-only
Find publications linked to NIH-funded projects.
Returns PubMed IDs (PMIDs) associated with grants. Search by core project number (e.g. 'R01CA123456', supports wildcard *), application ID, or PubMed ID. Use PMIDs with PubMed APIs for full citation details. Note: publication linkage may lag behind award dates.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum results to return. | |
| pmids | No | PubMed IDs — find which NIH grants funded a known publication. | |
| offset | No | Starting position for pagination. | |
| appl_ids | No | Application IDs to search for linked publications. | |
| core_project_nums | No | Core project numbers to search. Example: ['R01CA123456']. Supports wildcard * for partial matching. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so the safety profile is covered. The description adds genuinely useful domain behavior beyond the annotations: results are PMIDs only, and 'publication linkage may lag behind award dates' — a real caveat an agent should know before interpreting sparse results.
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 tight paragraphs, front-loaded with purpose, then return value and search keys, then the caveat. Every sentence carries information and nothing is padded.
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 5-parameter, all-optional search tool with a full output schema and read-only annotations, the description says everything needed: what it returns, the three search dimensions, the downstream handoff to PubMed, and the data-lag caveat. Return-value and pagination details are appropriately delegated to the schema.
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 100%, so the baseline is 3, but the description adds framing the schema lacks: the reverse-lookup purpose of pmids ('find which grants funded a known publication') and the worked example/wildcard note for core_project_nums. It enriches meaning rather than just restating fields.
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 ('Find publications linked to NIH-funded projects') and pins down the output (PubMed IDs/PMIDs). It is clearly distinguishable from the sibling tools nih_search_projects and nih_get_project, which operate on projects rather than publications.
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?
Explains the accepted search keys (core project number, application ID, or PubMed ID) and tells the agent to pass PMIDs on to PubMed APIs for citation details. It gives clear context for use but does not explicitly state when to prefer this tool over the sibling project tools or note exclusion conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nih_get_projectNih Get ProjectARead-only
Get full details for a specific NIH-funded project.
Use this after finding a project of interest via nih_search_projects. Accepts either an application ID (numeric, e.g. 10878415) or a full project number (e.g. '5R01CA123456-03'). Returns the complete record including abstract, all PIs, funding breakdown, and study section.
| Name | Required | Description | Default |
|---|---|---|---|
| appl_id | No | Application ID — unique numeric identifier for an NIH grant application. Example: 10878415 | |
| project_num | No | Full NIH project number. Example: '5R01CA123456-03'. Format: type + activity + IC + serial + year. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds useful behavioral context — it accepts either an appl_id or a project_num, and it enumerates the returned content (abstract, all PIs, funding breakdown, study section). It doesn't mention auth, rate limits, or error behavior, keeping it short of a 5.
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, front-loaded with the core purpose and then the routing guidance. No filler; every sentence carries a distinct fact.
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?
An output schema exists, so return values needn't be re-explained, yet the description still summarizes the payload. With annotations covering safety and 100% schema coverage, nothing an agent needs to invoke this correctly is missing.
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 100%, so both parameters are already fully documented in the schema with the same example values the description repeats. The description's 'accepts either' phrasing adds mild value by implying the two identifiers are alternatives, but otherwise the schema does the heavy lifting.
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 ('Get full details') and resource ('a specific NIH-funded project'), and clearly demarcates itself from the sibling search tool. An agent can tell it apart from nih_search_projects without opening the schema.
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 states the workflow condition: 'Use this after finding a project of interest via nih_search_projects,' naming the alternative and when to reach for it. This is exactly the retrieval-after-search routing guidance an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nih_search_projectsNih Search ProjectsARead-only
Search the NIH RePORTER database for federally funded research projects.
NIH RePORTER (Research Portfolio Online Reporting Tools) provides access to data on all research projects funded by the National Institutes of Health. This includes grants, contracts, and intramural projects across all 27 NIH institutes and centers.
Text search supports multi-word queries. With text_operator="and" (default), all words must appear in the searched fields. With "or", any word matching is sufficient. Wrap phrases in quotes for exact phrase matching within the text parameter.
Multiple criteria are combined with AND logic (e.g., text + agency narrows results to projects matching both). Within list parameters like agencies or activity_codes, values use OR logic.
Common activity codes: R01 - Research Project Grant (most common) R21 - Exploratory/Developmental Research R03 - Small Research Grant P01 - Program Project Grant U01 - Research Project Cooperative Agreement K01 - Mentored Research Scientist Career Development K08 - Mentored Clinical Scientist Career Development K23 - Mentored Patient-Oriented Research Career Development T32 - Institutional Training Grant F31 - Predoctoral Fellowship F32 - Postdoctoral Fellowship
Common agency abbreviations: NCI (Cancer), NIMH (Mental Health), NIGMS (General Medical Sciences), NIAID (Allergy/Infectious Diseases), NHLBI (Heart/Lung/Blood), NIA (Aging), NINDS (Neurological Disorders), NIDA (Drug Abuse), NICHD (Child Health), NIDDK (Diabetes/Digestive/Kidney)
| Name | Required | Description | Default |
|---|---|---|---|
| text | No | Free-text search across project titles, abstracts, and terms. Supports multi-word queries; word matching is controlled by text_operator. | |
| limit | No | Maximum number of results to return (1-50). | |
| offset | No | Starting index for pagination. Use with search_id to page through results. | |
| states | No | US state abbreviations for organization location. Example: ["CA", "MA", "NY"]. | |
| pi_name | No | Principal Investigator name. Use "Last, First" for exact matching or a single name for broad matching. Partial names are supported (implicitly wildcarded). | |
| sort_by | No | Sort order for results. 'relevance' ranks by text match quality (best with text searches), 'date' by project start date descending, 'amount' by award amount descending. | relevance |
| agencies | No | NIH institute/center abbreviations. Examples: NCI, NIMH, NIGMS, NIAID, NHLBI, NIA, NINDS, NIDA, NICHD, NIDDK, NEI, NIBIB, NIEHS, NHGRI, NCATS, FIC, NLM, NCCIH. | |
| search_id | No | Reuse a previous search_id to page through an existing result set without re-specifying criteria. Returned in every search response. | |
| text_fields | No | Which text fields to search. 'all' searches titles, abstracts, and terms. 'title', 'abstract', or 'terms' restricts to that single field. | all |
| detail_level | No | 'summary' returns key fields (title, PI, org, amount, dates). 'full' returns all available fields including abstracts. | summary |
| fiscal_years | No | Fiscal years to include. NIH fiscal year runs Oct 1 - Sep 30. Example: [2024, 2025]. | |
| organization | No | Research organization name (implicitly wildcarded). Example: "Johns" matches "Johns Hopkins University". | |
| text_operator | No | How multi-word text queries are combined. "and" requires all words to appear (default), "or" matches any word. | and |
| activity_codes | No | NIH activity codes to filter by. Common codes: R01 (Research Project), R21 (Exploratory), R03 (Small Grant), P01 (Program Project), U01 (Cooperative Agreement), K01/K08/K23 (Career Development), T32 (Training Grant), F31/F32 (Fellowship). | |
| award_amount_max | No | Maximum award amount in dollars. | |
| award_amount_min | No | Minimum award amount in dollars. | |
| funding_mechanism | No | Funding mechanism codes: RP (Research Projects), SB (SBIR/STTR), RC (Research Centers), OR (Other Research), TR (Training Individual), TI (Training Institutional), CO (Construction). | |
| exclude_subprojects | No | Exclude subprojects from results. Usually True to avoid duplicate counting of large program projects. | |
| include_active_only | No | When True, only return currently active projects. | |
| project_start_after | No | Filter to projects starting on or after this date. Format: YYYY-MM-DD. | |
| spending_categories | No | RCDC spending category IDs (OR logic). Common IDs: 132 (Cancer), 140 (Cardiovascular), 224 (Diabetes), 284 (HIV/AIDS), 338 (Infectious Diseases), 443 (Mental Health), 525 (Neurosciences), 4372 (Machine Learning/AI), 4531 (Data Science). | |
| project_start_before | No | Filter to projects starting on or before this date. Format: YYYY-MM-DD. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and openWorldHint=true, so the safety profile is already covered. The description adds useful behavioral context: AND/OR combination logic, exact phrase quoting, and that search_id enables paging without re-specifying criteria. It does not mention rate limits, result caps, or anything beyond the schema. With annotations carrying the safety burden, this is adequate but not rich.
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 opening is front-loaded and clear, but the large inline reference lists for activity codes and agencies are bulky and partially duplicate the schema descriptions (which already list common codes). It is informative but not tightly structured; the code lists could be seen as padding since the schema already covers many of them.
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 22-parameter read-only search tool with an output schema present, the description covers query semantics, value conventions, and paging via search_id. It is largely complete; the main gap is the absence of guidance on choosing between this tool and its siblings, but return values are covered by the output schema.
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 100%, so the baseline is 3. The description adds genuine value beyond the schema by supplying the common activity code and agency abbreviation reference tables, which help the agent construct valid values for those parameters. That elevates it above baseline.
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?
Clearly states a specific verb and resource: search the NIH RePORTER database for federally funded research projects. It provides rich scope detail (grants, contracts, intramural, 27 institutes). It does not, however, differentiate itself from the sibling nih_get_project or explain how it relates to it, so it falls short of a 5.
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?
The description explains query semantics (AND across criteria, OR within lists, text_operator behavior) which implicitly guides usage, but it never states when to use this search tool versus nih_get_project or nih_find_publications. No explicit when/when-not guidance or named alternatives are given.
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.4.0- First observed
nih_find_publications - First observed
nih_get_project - First observed
nih_search_projects
TDQS
Scored across 3 tools
The three tools have clearly distinct purposes: searching for projects, retrieving full project details, and finding linked publications. Each tool's description clarifies its specific role, leaving no ambiguity for an agent to choose the appropriate tool.
All tool names follow a consistent snake_case convention with a common 'nih_' prefix and verb_noun structure: nih_search_projects, nih_get_project, nih_find_publications. This pattern is predictable and easy to parse.
With only 3 tools, the set is minimal but well-scoped for the core read-only operations of the NIH RePORTER database. Each tool serves a distinct essential function without overlap or redundancy.
The tools cover the primary read operations: search, detail retrieval, and publication linkage. However, there is no support for listing related entities (e.g., all projects by a PI or organization) or exporting results, which could be useful but are not critical for the stated purpose.
Maintenance
Related MCP Connectors
NIH RePORTER MCP — every NIH-funded research project (free, no auth)
Search US grants + federal contracts (Grants.gov + SAM.gov) from any LLM.
Search 36M+ PubMed biomedical articles and ClinicalTrials.gov studies.
Search biomedical literature, get article details, find related articles, and explore MeSH terms
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables AI assistants to search and retrieve biomedical research articles from PubMed's database of over 35 million citations, including metadata, abstracts, MeSH terms, and full-text PDFs when available.11MIT
- FlicenseNot gradedqualityDmaintenanceProvides programmatic access to the NIH Reporter API for searching and retrieving detailed information on NIH-funded research projects, grants, and investigators. It enables AI assistants to query project abstracts, funding amounts, and organization details through natural language.-
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to search and retrieve EU research outputs including publications, datasets, software, and funded projects from OpenAIRE.3 npmMIT
- FlicenseNot gradedqualityDmaintenanceProvides tools to search and retrieve data from NIH's RePORTER grant database, enabling queries for project counts, summaries, and detailed award information.-