Skip to main content
Glama
echelon-ai-labs

ServiceNow MCP Server

list_articles

Retrieve knowledge articles from ServiceNow based on filters like category, knowledge base, or workflow state. Supports pagination and search queries for precise results.

Instructions

List knowledge articles

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
paramsYes

Implementation Reference

  • The core handler function for the 'list_articles' tool. It queries the ServiceNow 'kb_knowledge' table API with pagination and filters (knowledge_base, category, workflow_state, query), processes the response, and returns a structured list of articles.
    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 schema defining the input parameters 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")
  • Tool registration in the central tool_definitions dictionary, mapping 'list_articles' to its handler, schema, description, and serialization method.
    "list_articles": (
        list_articles_tool,
        ListArticlesParams,
        Dict[str, Any],  # Expects dict
        "List knowledge articles",
        "raw_dict",  # Tool returns raw dict
  • Import of the list_articles function into the tools package __init__, exposing it for use.
    from servicenow_mcp.tools.knowledge_base import (
        create_article,
        create_category,
        create_knowledge_base,
        get_article,
        list_articles,
        list_knowledge_bases,
        publish_article,
        update_article,
        list_categories,
    )
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure but offers minimal insight. It implies a read-only operation by using 'list', but doesn't clarify aspects like pagination behavior, rate limits, authentication needs, or what happens if no articles match filters. The description lacks details on return format, error conditions, or any constraints beyond the basic action.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise with just three words, which could be seen as efficient but results in under-specification. It's front-loaded but lacks necessary detail, making it more sparse than appropriately brief. While not verbose, it doesn't earn its place by adding value beyond the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness1/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (6 parameters with no schema description coverage, no annotations, no output schema), the description is completely inadequate. It doesn't explain what 'list' returns, how filters work, pagination behavior, or any operational context. For a tool with multiple filtering options and no structured guidance, this description leaves critical gaps for an AI agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description provides no information about parameters, while the schema has 0% description coverage (parameters are documented but schema-level description is absent). With 6 parameters (category, knowledge_base, limit, offset, query, workflow_state) all undocumented in the description, the agent lacks context on how these filters interact or their practical use. The description fails to compensate for the schema gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose2/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'List knowledge articles' is a tautology that merely restates the tool name 'list_articles' with minimal elaboration. It specifies the resource (knowledge articles) but lacks a clear verb beyond 'list' and doesn't differentiate from sibling tools like 'get_article' or 'list_categories'. The purpose is vague about what 'list' entails operationally.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines1/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention sibling tools like 'get_article' for retrieving a single article or 'list_categories' for different resources, nor does it specify any prerequisites, contexts, or exclusions for usage. This leaves the agent without direction on tool selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

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/echelon-ai-labs/servicenow-mcp'

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