list_changesets
Retrieve and filter changesets from ServiceNow with options to limit results, apply offsets, and filter by state, application, developer, or timeframe.
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 for the 'list_changesets' tool. It validates parameters, constructs a query for the ServiceNow sys_update_set table API, makes the HTTP request, and returns the list of changesets.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/parameters for the list_changesets tool, used for validation.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:575-581 (registration)MCP tool registration entry in get_tool_definitions() function. Maps the tool name to its handler, input schema (ListChangesetsParams), description, and serialization hints. Used by the MCP server to expose the tool."list_changesets": ( list_changesets_tool, ListChangesetsParams, str, # Expects JSON string "List changesets from ServiceNow", "json", # Tool returns list/dict ),
- Helper function used by list_changesets (and other tools) to validate and unwrap input parameters against the Pydantic schema.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)}", }