search_combined
Search NIH-funded research projects and their related publications in a single query using filters like fiscal years, PI names, organization, funding type, and award amounts.
Instructions
Search for NIH projects and their related publications in a single query
Args:
fiscal_years: Comma-separated list of fiscal years (e.g., "2022,2023")
pi_names: Comma-separated list of PI names
organization: Name of the organization
org_state: Two-letter state code (e.g., "CA", "NY")
funding_mechanism: Type of funding (e.g., "R01", "F32", "K99")
ic_code: Institute or Center code (e.g., "NCI", "NIMH")
min_amount: Minimum award amount
max_amount: Maximum award amount
covid_response: COVID-19 response category
include_publications: Whether to include related publications
publication_years: Comma-separated list of publication years
limit: Maximum number of results to return (default: 10, max: 50)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| fiscal_years | No | ||
| pi_names | No | ||
| organization | No | ||
| org_state | No | ||
| funding_mechanism | No | ||
| ic_code | No | ||
| min_amount | No | ||
| max_amount | No | ||
| covid_response | No | ||
| include_publications | No | ||
| publication_years | No | ||
| limit | No |
Implementation Reference
- mcp-nih-reporter.py:549-691 (handler)The handler function for the 'search_combined' tool, registered via @mcp.tool(). It constructs criteria for NIH RePORTER API to search projects, optionally fetches related publications, and formats results in markdown.@mcp.tool() async def search_combined( # Project search parameters fiscal_years: Optional[str] = None, pi_names: Optional[str] = None, organization: Optional[str] = None, org_state: Optional[str] = None, funding_mechanism: Optional[str] = None, ic_code: Optional[str] = None, min_amount: Optional[float] = None, max_amount: Optional[float] = None, covid_response: Optional[str] = None, # Publication parameters include_publications: Optional[bool] = True, publication_years: Optional[str] = None, # General parameters limit: Optional[int] = 10 ) -> str: """ Search for NIH projects and their related publications in a single query Args: fiscal_years: Comma-separated list of fiscal years (e.g., "2022,2023") pi_names: Comma-separated list of PI names organization: Name of the organization org_state: Two-letter state code (e.g., "CA", "NY") funding_mechanism: Type of funding (e.g., "R01", "F32", "K99") ic_code: Institute or Center code (e.g., "NCI", "NIMH") min_amount: Minimum award amount max_amount: Maximum award amount covid_response: COVID-19 response category include_publications: Whether to include related publications publication_years: Comma-separated list of publication years limit: Maximum number of results to return (default: 10, max: 50) """ try: logger.info(f"Combined search request received with parameters: {locals()}") # First, search for projects project_criteria = {} if fiscal_years: try: # Handle escaped quotes and clean the input string years_str = fiscal_years.replace('\\"', '').replace('"', '').strip() years = [int(year.strip()) for year in years_str.split(",") if year.strip()] if not years: raise ValueError("No valid years found after parsing") project_criteria["fiscal_years"] = years except ValueError as e: logger.error(f"Invalid fiscal years format: {fiscal_years}, error: {str(e)}") return f"Error: Invalid fiscal years format. Please provide comma-separated years (e.g., 2020,2021)" if pi_names: try: # Handle escaped quotes and clean the input string names_str = pi_names.replace('\\"', '').replace('"', '').strip() names = [name.strip() for name in names_str.split(",") if name.strip()] if not names: raise ValueError("No valid names found after parsing") project_criteria["pi_names"] = [{"any_name": name} for name in names] except Exception as e: logger.error(f"Invalid PI names format: {pi_names}, error: {str(e)}") return f"Error: Invalid PI names format. Please provide comma-separated names" if organization: project_criteria["org_names"] = [organization] if org_state: project_criteria["org_states"] = [org_state.upper()] if funding_mechanism: project_criteria["funding_mechanism"] = funding_mechanism.strip().strip('"').strip("'") if ic_code: project_criteria["agency_ic_admin"] = ic_code.strip().strip('"').strip("'").upper() if min_amount is not None or max_amount is not None: project_criteria["award_amount_range"] = { "min_amount": min_amount if min_amount is not None else 0, "max_amount": max_amount if max_amount is not None else float('inf') } if covid_response: project_criteria["covid_response"] = [covid_response] project_criteria["limit"] = min(max(1, limit), 50) logger.info(f"Searching for projects with criteria: {json.dumps(project_criteria, indent=2)}") project_results = await api_client.get_projects(project_criteria) # If we want publications, get them for each project if include_publications: project_nums = [] for project in project_results.get("results", []): if project.get("project_num"): project_nums.append(project["project_num"]) if project_nums: logger.info(f"Found project numbers for publication search: {project_nums}") pub_criteria = { "criteria": { "core_project_nums": project_nums }, "limit": 100 # Get more publications since they're related } # Only add publication years if explicitly specified by the user if publication_years: try: years_str = publication_years.strip().strip('"').strip("'") years = [int(year.strip()) for year in years_str.split(",")] pub_criteria["criteria"]["publication_years"] = years logger.info(f"Filtering publications by years: {years}") except ValueError as e: logger.error(f"Invalid publication years format: {publication_years}") return f"Error: Invalid publication years format. Please provide comma-separated years without quotes (e.g., 2020,2021)" logger.info(f"Searching for publications with criteria: {json.dumps(pub_criteria, indent=2)}") pub_results = await api_client.get_publications(pub_criteria) # Add publications to each project pub_by_project = {} for pub in pub_results.get("results", []): proj_num = pub.get("core_project_num") if proj_num: if proj_num not in pub_by_project: pub_by_project[proj_num] = [] pub_by_project[proj_num].append(pub) for project in project_results.get("results", []): proj_num = project.get("project_num") if proj_num in pub_by_project: project["related_publications"] = pub_by_project[proj_num] return api_client.format_project_results(project_results, include_publications=include_publications) except Exception as e: logger.error(f"Combined search failed: {str(e)}", exc_info=True) return f"Combined search failed: {str(e)}\nPlease check the logs for more details."