search_studies
Search cancer studies by keyword in names or descriptions with pagination to explore genomic data and clinical information.
Instructions
Search for cancer studies by keyword in their name or description with pagination support.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| keyword | Yes | ||
| page_number | No | ||
| page_size | No | ||
| sort_by | No | ||
| direction | No | ASC | |
| limit | No |
Implementation Reference
- Core handler implementation for search_studies tool: validates inputs, fetches all studies from API, filters by keyword in name/description, applies sorting and pagination, returns structured response.@handle_api_errors("search studies") async def search_studies( self, keyword: str, page_number: int = 0, page_size: int = 50, sort_by: Optional[str] = None, direction: str = "ASC", limit: Optional[int] = None, ) -> Dict[str, Any]: """ Search for cancer studies by keyword in their name or description with pagination support. Args: keyword: Keyword to search for page_number: Page number to retrieve (0-based) page_size: Number of items per page sort_by: Field to sort by direction: Sort direction (ASC or DESC) limit: Maximum number of items to return across all pages (None for no limit) Returns: Dictionary containing list of studies and metadata """ # Input Validation validate_keyword(keyword) validate_page_params(page_number, page_size, limit) validate_sort_params(sort_by, direction) try: # Await the asynchronous API call all_studies = await self.api_client.make_api_request("studies") if not isinstance(all_studies, list): # Handle cases where API request might not return a list (e.g., error response) error_message = ( "Unexpected response from API when fetching all studies." ) if isinstance(all_studies, dict) and "error" in all_studies: error_message = all_studies["error"] return { "error": f"Failed to search studies for '{keyword}': {error_message}" } keyword_lower = keyword.lower() matching_studies = [ study for study in all_studies if keyword_lower in study.get("name", "").lower() or keyword_lower in study.get("description", "").lower() ] if sort_by: reverse = direction.upper() == "DESC" matching_studies.sort( key=lambda s: str(s.get(sort_by, "")), reverse=reverse ) total_count = len(matching_studies) start_idx = page_number * page_size end_idx = start_idx + page_size paginated_studies = matching_studies[start_idx:end_idx] if limit and limit > 0 and len(paginated_studies) > limit: paginated_studies = paginated_studies[:limit] has_more = end_idx < total_count return { "studies": paginated_studies, "pagination": { "page": page_number, "page_size": page_size if limit != 0 else total_count, # Adjust page_size if all were requested "total_found": total_count, "has_more": has_more if limit != 0 else False, # No more if all were requested }, } except httpx.HTTPStatusError as exc: return { "error": f"Failed to search studies for '{keyword}': API request failed with status {exc.response.status_code}" } except httpx.RequestError as exc: return { "error": f"Failed to search studies for '{keyword}': Network error - {str(exc)}" } except Exception as e: return { "error": f"Failed to search studies for '{keyword}': An unexpected error occurred - {str(e)}" }
- cbioportal_mcp/server.py:193-205 (handler)Top-level MCP tool handler for search_studies that delegates to the StudiesEndpoints instance.async def search_studies( self, keyword: str, page_number: int = 0, page_size: int = 50, sort_by: Optional[str] = None, direction: str = "ASC", limit: Optional[int] = None, ) -> Dict[str, Any]: """Search for cancer studies by keyword in their name or description with pagination support.""" return await self.studies.search_studies( keyword, page_number, page_size, sort_by, direction, limit )
- cbioportal_mcp/server.py:99-131 (registration)Registration of all MCP tools including 'search_studies' by dynamically adding server methods to the FastMCP instance.tool_methods = [ # Pagination utilities "paginate_results", "collect_all_results", # Studies endpoints "get_cancer_studies", "get_cancer_types", "search_studies", "get_study_details", "get_multiple_studies", # Genes endpoints "search_genes", "get_genes", "get_multiple_genes", "get_mutations_in_gene", # Samples endpoints "get_samples_in_study", "get_sample_list_id", # Molecular profiles endpoints "get_molecular_profiles", "get_clinical_data", "get_gene_panels_for_study", "get_gene_panel_details", ] for method_name in tool_methods: if hasattr(self, method_name): method = getattr(self, method_name) self.mcp.add_tool(method) logger.debug(f"Registered tool: {method_name}") else: logger.warning(f"Method {method_name} not found for tool registration")