Skip to main content
Glama
javerthl

ServiceNow MCP Server

by javerthl

list_articles

Retrieve knowledge articles from ServiceNow with filtering options for knowledge base, category, search query, and workflow state to find relevant information.

Instructions

List knowledge articles

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
categoryNoFilter by category
knowledge_baseNoFilter by knowledge base
limitNoMaximum number of articles to return
offsetNoOffset for pagination
queryNoSearch query for articles
workflow_stateNoFilter by workflow state

Implementation Reference

  • The core handler function that executes the list_articles tool by querying the ServiceNow kb_knowledge table API with filters and returning formatted article list.
    def list_articles( config: ServerConfig, auth_manager: AuthManager, params: ListArticlesParams, ) -> Dict[str, Any]: """ List knowledge articles with filtering options. Args: config: Server configuration. auth_manager: Authentication manager. params: Parameters for listing articles. Returns: Dictionary with list of articles and metadata. """ api_url = f"{config.api_url}/table/kb_knowledge" # 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: query_parts.append(f"kb_knowledge_base.sys_id={params.knowledge_base}") if params.category: query_parts.append(f"kb_category.sys_id={params.category}") if params.workflow_state: query_parts.append(f"workflow_state={params.workflow_state}") if params.query: query_parts.append(f"short_descriptionLIKE{params.query}^ORtextLIKE{params.query}") if query_parts: query_string = "^".join(query_parts) logger.debug(f"Constructed article query string: {query_string}") query_params["sysparm_query"] = query_string # Log the query parameters for debugging logger.debug(f"Listing articles 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() logger.debug(f"Article listing raw response: {json_response}") # 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": f"Unexpected response format", "articles": [], "count": 0, "limit": params.limit, "offset": params.offset, } # Transform the results articles = [] # Handle either string or list if isinstance(result, list): for article_item in result: if not isinstance(article_item, dict): logger.warning("Skipping non-dictionary article item: %s", article_item) continue # Safely extract values article_id = article_item.get("sys_id", "") title = article_item.get("short_description", "") # Extract nested values safely knowledge_base = "" if isinstance(article_item.get("kb_knowledge_base"), dict): knowledge_base = article_item["kb_knowledge_base"].get("display_value", "") category = "" if isinstance(article_item.get("kb_category"), dict): category = article_item["kb_category"].get("display_value", "") workflow_state = "" if isinstance(article_item.get("workflow_state"), dict): workflow_state = article_item["workflow_state"].get("display_value", "") created = article_item.get("sys_created_on", "") updated = article_item.get("sys_updated_on", "") articles.append({ "id": article_id, "title": title, "knowledge_base": knowledge_base, "category": category, "workflow_state": workflow_state, "created": created, "updated": updated, }) else: logger.warning("Result is not a list: %s", result) return { "success": True, "message": f"Found {len(articles)} articles", "articles": articles, "count": len(articles), "limit": params.limit, "offset": params.offset, } except requests.RequestException as e: logger.error(f"Failed to list articles: {e}") return { "success": False, "message": f"Failed to list articles: {str(e)}", "articles": [], "count": 0, "limit": params.limit, "offset": params.offset, }
  • Pydantic BaseModel defining the input parameters (limit, offset, filters) for the list_articles tool.
    class ListArticlesParams(BaseModel): """Parameters for listing knowledge articles.""" limit: int = Field(10, description="Maximum number of articles to return") offset: int = Field(0, description="Offset for pagination") knowledge_base: Optional[str] = Field(None, description="Filter by knowledge base") category: Optional[str] = Field(None, description="Filter by category") query: Optional[str] = Field(None, description="Search query for articles") workflow_state: Optional[str] = Field(None, description="Filter by workflow state")
  • Registers the list_articles tool in the MCP tool definitions dictionary, linking the handler function, input schema, return type, description, and serialization method.
    "list_articles": ( list_articles_tool, ListArticlesParams, Dict[str, Any], # Expects dict "List knowledge articles", "raw_dict", # Tool returns raw dict ),
  • Includes list_articles in the __all__ export list for the tools module.
    "list_articles",
  • Imports the list_articles handler as list_articles_tool for use in tool registration.
    list_articles as list_articles_tool,

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/javerthl/servicenow-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server