list_categories
Lists categories in a ServiceNow knowledge base, enabling filtering by active status, knowledge base ID, parent category, or search query for efficient navigation.
Instructions
List categories in a knowledge base
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Implementation Reference
- The handler function list_categories that implements the core logic: builds REST query to /table/kb_category, fetches data, transforms into dict with categories list including id, title, description, knowledge_base, parent_category, active status, timestamps.def list_categories( config: ServerConfig, auth_manager: AuthManager, params: ListCategoriesParams, ) -> Dict[str, Any]: """ List categories in a knowledge base. Args: config: Server configuration. auth_manager: Authentication manager. params: Parameters for listing categories. Returns: Dictionary with list of categories and metadata. """ api_url = f"{config.api_url}/table/kb_category" # Build query parameters query_params = { "sysparm_limit": params.limit, "sysparm_offset": params.offset, "sysparm_display_value": "all", } # Build query string query_parts = [] if params.knowledge_base: # Try different query format to ensure we match by sys_id value query_parts.append(f"kb_knowledge_base.sys_id={params.knowledge_base}") if params.parent_category: query_parts.append(f"parent.sys_id={params.parent_category}") if params.active is not None: query_parts.append(f"active={str(params.active).lower()}") if params.query: query_parts.append(f"labelLIKE{params.query}^ORdescriptionLIKE{params.query}") if query_parts: query_string = "^".join(query_parts) logger.debug(f"Constructed query string: {query_string}") query_params["sysparm_query"] = query_string # Log the query parameters for debugging logger.debug(f"Listing categories with query params: {query_params}") # Make request try: response = requests.get( api_url, params=query_params, headers=auth_manager.get_headers(), timeout=config.timeout, ) response.raise_for_status() # Get the JSON response json_response = response.json() # Safely extract the result if isinstance(json_response, dict) and "result" in json_response: result = json_response.get("result", []) else: logger.error("Unexpected response format: %s", json_response) return { "success": False, "message": "Unexpected response format", "categories": [], "count": 0, "limit": params.limit, "offset": params.offset, } # Transform the results categories = [] # Handle either string or list if isinstance(result, list): for category_item in result: if not isinstance(category_item, dict): logger.warning("Skipping non-dictionary category item: %s", category_item) continue # Safely extract values category_id = category_item.get("sys_id", "") title = category_item.get("label", "") description = category_item.get("description", "") # Extract knowledge base - handle both dictionary and string cases knowledge_base = "" kb_field = category_item.get("kb_knowledge_base") if isinstance(kb_field, dict): knowledge_base = kb_field.get("display_value", "") elif isinstance(kb_field, str): knowledge_base = kb_field # Also check if kb_knowledge_base is missing but there's a separate value field elif "kb_knowledge_base_value" in category_item: knowledge_base = category_item.get("kb_knowledge_base_value", "") elif "kb_knowledge_base.display_value" in category_item: knowledge_base = category_item.get("kb_knowledge_base.display_value", "") # Extract parent category - handle both dictionary and string cases parent = "" parent_field = category_item.get("parent") if isinstance(parent_field, dict): parent = parent_field.get("display_value", "") elif isinstance(parent_field, str): parent = parent_field # Also check alternative field names elif "parent_value" in category_item: parent = category_item.get("parent_value", "") elif "parent.display_value" in category_item: parent = category_item.get("parent.display_value", "") # Convert active to boolean - handle string or boolean types active_field = category_item.get("active") if isinstance(active_field, str): active = active_field.lower() == "true" elif isinstance(active_field, bool): active = active_field else: active = False created = category_item.get("sys_created_on", "") updated = category_item.get("sys_updated_on", "") categories.append({ "id": category_id, "title": title, "description": description, "knowledge_base": knowledge_base, "parent_category": parent, "active": active, "created": created, "updated": updated, }) # Log for debugging purposes logger.debug(f"Processed category: {title}, KB: {knowledge_base}, Parent: {parent}") else: logger.warning("Result is not a list: %s", result) return { "success": True, "message": f"Found {len(categories)} categories", "categories": categories, "count": len(categories), "limit": params.limit, "offset": params.offset, } except requests.RequestException as e: logger.error(f"Failed to list categories: {e}") return { "success": False, "message": f"Failed to list categories: {str(e)}", "categories": [], "count": 0, "limit": params.limit, "offset": params.offset, }
- Pydantic schema for input parameters to the list_categories tool, defining filters like knowledge_base, parent_category, pagination (limit/offset), active status, and search query.class ListCategoriesParams(BaseModel): """Parameters for listing categories in a knowledge base.""" knowledge_base: Optional[str] = Field(None, description="Filter by knowledge base ID") parent_category: Optional[str] = Field(None, description="Filter by parent category ID") limit: int = Field(10, description="Maximum number of categories to return") offset: int = Field(0, description="Offset for pagination") active: Optional[bool] = Field(None, description="Filter by active status") query: Optional[str] = Field(None, description="Search query for categories")
- src/servicenow_mcp/utils/tool_utils.py:776-782 (registration)Registration of the 'list_categories' tool in the central tool_definitions dictionary: maps name to (handler_impl, params_model alias, return_type, description, serialization_hint). The impl is aliased list_kb_categories_tool_impl passed from server.py."list_categories": ( list_kb_categories_tool_impl, # Use passed function ListKBCategoriesParams, Dict[str, Any], # Expects dict "List categories in a knowledge base", "raw_dict", # Tool returns raw dict ),
- src/servicenow_mcp/server.py:22-23 (registration)Import and alias of the list_categories handler as list_kb_categories_tool, passed to get_tool_definitions() for MCP server tool registry.list_categories as list_kb_categories_tool, )
- src/servicenow_mcp/tools/__init__.py:59-59 (registration)Re-export of list_categories function from knowledge_base.py in tools package __init__ for easy imports.list_categories,