list_changesets
Retrieve and filter ServiceNow changesets by state, application, developer, or timeframe to monitor and manage system modifications.
Instructions
List changesets from ServiceNow
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| application | No | Filter by application | |
| developer | No | Filter by developer | |
| limit | No | Maximum number of records to return | |
| offset | No | Offset to start from | |
| query | No | Additional query string | |
| state | No | Filter by state | |
| timeframe | No | Filter by timeframe (recent, last_week, last_month) |
Implementation Reference
- The core handler function that implements the logic for listing changesets. It validates input parameters, constructs the appropriate ServiceNow Table API query for the sys_update_set table, makes the HTTP GET request, and returns the results or error.def list_changesets( auth_manager: AuthManager, server_config: ServerConfig, params: Union[Dict[str, Any], ListChangesetsParams], ) -> Dict[str, Any]: """ List changesets from ServiceNow. Args: auth_manager: The authentication manager. server_config: The server configuration. params: The parameters for listing changesets. Can be a dictionary or a ListChangesetsParams object. Returns: A list of changesets. """ # Unwrap and validate parameters result = _unwrap_and_validate_params(params, ListChangesetsParams) if not result["success"]: return result validated_params = result["params"] # Get the instance URL instance_url = _get_instance_url(auth_manager, server_config) if not instance_url: return { "success": False, "message": "Cannot find instance_url in either server_config or auth_manager", } # Get the headers headers = _get_headers(auth_manager, server_config) if not headers: return { "success": False, "message": "Cannot find get_headers method in either auth_manager or server_config", } # Build query parameters query_params = { "sysparm_limit": validated_params.limit, "sysparm_offset": validated_params.offset, } # Build sysparm_query query_parts = [] if validated_params.state: query_parts.append(f"state={validated_params.state}") if validated_params.application: query_parts.append(f"application={validated_params.application}") if validated_params.developer: query_parts.append(f"developer={validated_params.developer}") if validated_params.timeframe: if validated_params.timeframe == "recent": query_parts.append("sys_created_onONLast 7 days@javascript:gs.beginningOfLast7Days()@javascript:gs.endOfToday()") elif validated_params.timeframe == "last_week": query_parts.append("sys_created_onONLast week@javascript:gs.beginningOfLastWeek()@javascript:gs.endOfLastWeek()") elif validated_params.timeframe == "last_month": query_parts.append("sys_created_onONLast month@javascript:gs.beginningOfLastMonth()@javascript:gs.endOfLastMonth()") if validated_params.query: query_parts.append(validated_params.query) if query_parts: query_params["sysparm_query"] = "^".join(query_parts) # Make the API request url = f"{instance_url}/api/now/table/sys_update_set" try: response = requests.get(url, params=query_params, headers=headers) response.raise_for_status() result = response.json() return { "success": True, "changesets": result.get("result", []), "count": len(result.get("result", [])), } except requests.exceptions.RequestException as e: logger.error(f"Error listing changesets: {e}") return { "success": False, "message": f"Error listing changesets: {str(e)}", }
- Pydantic BaseModel defining the input schema for the list_changesets tool, including optional filters like limit, offset, state, application, developer, timeframe, and custom query.class ListChangesetsParams(BaseModel): """Parameters for listing changesets.""" limit: Optional[int] = Field(10, description="Maximum number of records to return") offset: Optional[int] = Field(0, description="Offset to start from") state: Optional[str] = Field(None, description="Filter by state") application: Optional[str] = Field(None, description="Filter by application") developer: Optional[str] = Field(None, description="Filter by developer") timeframe: Optional[str] = Field(None, description="Filter by timeframe (recent, last_week, last_month)") query: Optional[str] = Field(None, description="Additional query string")
- src/servicenow_mcp/utils/tool_utils.py:621-627 (registration)Tool registration entry in get_tool_definitions() function, mapping the tool name to its handler (list_changesets_tool), input schema model (ListChangesetsParams), return type hint, description, and serialization instruction. This dictionary is used by the MCP server to expose the tool and handle calls."list_changesets": ( list_changesets_tool, ListChangesetsParams, str, # Expects JSON string "List changesets from ServiceNow", "json", # Tool returns list/dict ),
- Helper function used by the handler to unwrap dictionary parameters into a Pydantic model instance, validate them, and check for required fields. Called at the start of list_changesets.def _unwrap_and_validate_params( params: Union[Dict[str, Any], BaseModel], model_class: Type[T], required_fields: Optional[List[str]] = None ) -> Dict[str, Any]: """ Unwrap and validate parameters. Args: params: The parameters to unwrap and validate. Can be a dictionary or a Pydantic model. model_class: The Pydantic model class to validate against. required_fields: List of fields that must be present. Returns: A dictionary with success status and validated parameters or error message. """ try: # Handle case where params is already a Pydantic model if isinstance(params, BaseModel): # If it's already the correct model class, use it directly if isinstance(params, model_class): model_instance = params # Otherwise, convert to dict and create new instance else: model_instance = model_class(**params.dict()) # Handle dictionary case else: # Create model instance model_instance = model_class(**params) # Check required fields if required_fields: missing_fields = [] for field in required_fields: if getattr(model_instance, field, None) is None: missing_fields.append(field) if missing_fields: return { "success": False, "message": f"Missing required fields: {', '.join(missing_fields)}", } return { "success": True, "params": model_instance, } except Exception as e: return { "success": False, "message": f"Invalid parameters: {str(e)}", }