mcpField
R
request-management

request-management

github.com/serac-labsOther7760 installsUpdated 9w ago
Repository

About request-management

A ServiceNow skill for handling service requests from catalog selection through fulfillment. It covers request records, catalog tasks, variables, and approvals with ES5 examples for developers and administrators.

Key features

  1. 01Create requests and request items
  2. 02Query users' open requests
  3. 03Create fulfillment tasks
  4. 04Read and validate item variables
  5. 05Check request approval status

Use cases

  1. 01Create a request from a catalog item
  2. 02Review a user's pending requests
  3. 03Coordinate task completion for a request item
  4. 04Validate inputs before request processing

MCP support

Documents ServiceNow MCP tools for querying requests and request items, finding catalog items, testing scripts, and creating catalog items.

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/serac-labs/serac --skill request-management

After installing, type/request-managementin Claude Code to confirm it loaded.

Details

From the project README

Request Management for ServiceNow

Request Management handles service requests from catalog items through fulfillment.

Request Hierarchy

Request (sc_request)
    ├── Request Item (sc_req_item) - RITM
    │   ├── Catalog Tasks (sc_task)
    │   └── Variables (sc_item_option_mtom)
    └── Request Item
        └── Catalog Tasks

Key Tables

TablePurpose
sc_requestParent request record
sc_req_itemRequested items (RITM)
sc_taskFulfillment tasks
sc_item_option_mtomVariable values
sc_cat_itemCatalog item definitions

Request Items (ES5)

Create Request Programmatically
// Create request and RITM (ES5 ONLY!)
function createServiceRequest(catalogItemName, requestedFor, variables) {
  // Get catalog item
  var catItem = new GlideRecord("sc_cat_item")
  if (!catItem.get("name", catalogItemName)) {
    gs.error("Catalog item not found: " + catalogItemName)
    return null
  }

  // Create request
  var request = new GlideRecord("sc_request")
  request.initialize()
  request.setValue("requested_for", requestedFor)
  request.setValue("opened_by", gs.getUserID())
  request.setValue("description", "Request for " + catalogItemName)
  var requestSysId = request.insert()

  // Create RITM
  var ritm = new GlideRecord("sc_req_item")
  ritm.initialize()
  ritm.setValue("request", requestSysId)
  ritm.setValue("cat_item", catItem.getUniqueValue())
  ritm.setValue("requested_for", requestedFor)
  ritm.setValue("quantity", 1)

  var ritmSysId = ritm.insert()

  // Set variables
  if (variables) {
    setRITMVariables(ritmSysId, variables)
  }

  return {
    request: request.getValue("number"),
    ritm: ritm.getValue("number"),
    request_sys_id: requestSysId,
    ritm_sys_id: ritmSysId,
  }
}

function setRITMVariables(ritmSysId, variables) {
  var ritm = new GlideRecord("sc_req_item")
  if (!ritm.get(ritmSysId)) return

  for (var varName in variables) {
    if (variables.hasOwnProperty(varName)) {
      ritm.variables[varName] = variables[varName]
    }
  }
  ritm.update()
}
Query Request Items
// Get user's open requests (ES5 ONLY!)
function getUserRequests(userSysId, includeCompleted) {
  var requests = []

  var ritm = new GlideRecord("sc_req_item")
  ritm.addQuery("requested_for", userSysId)

  if (!includeCompleted) {
    ritm.addQuery("state", "!=", "3") // Not Closed Complete
    ritm.addQuery("state", "!=", "4") // Not Closed Incomplete
  }

  ritm.orderByDesc("sys_created_on")
  ritm.query()

  while (ritm.next()) {
    requests.push({
      sys_id: ritm.getUniqueValue(),
      number: ritm.getValue("number"),
      short_description: ritm.getValue("short_description"),
      cat_item: ritm.cat_item.getDisplayValue(),
      state: ritm.state.getDisplayValue(),
      stage: ritm.stage.getDisplayValue(),
      opened_at: ritm.getValue("sys_created_on"),
      due_date: ritm.getValue("due_date"),
    })
  }

  return requests
}

Fulfillment Tasks (ES5)

Create Catalog Tasks
// Create fulfillment tasks for RITM (ES5 ONLY!)
function createFulfillmentTasks(ritmSysId, taskDefinitions) {
  var ritm = new GlideRecord("sc_req_item")
  if (!ritm.get(ritmSysId)) {
    return []
  }

  var createdTasks = []

  for (var i = 0; i < taskDefinitions.length; i++) {
    var taskDef = taskDefinitions[i]

    var task = new GlideRecord("sc_task")
    task.initialize()
    task.setValue("request_item", ritmSysId)
    task.setValue("request", ritm.getValue("request"))
    task.setValue("short_description", taskDef.description)
    task.setValue("assignment_group", taskDef.assignmentGroup)
    task.setValue("order", (i + 1) * 100)

    // Calculate due date if specified
    if (taskDef.daysToComplete) {
      var dueDate = new GlideDateTime()
      dueDate.addDaysLocalTime(taskDef.daysToComplete)
      task.setValue("due_date", dueDate)
    }

    var taskSysId = task.insert()
    createdTasks.push({
      sys_id: taskSysId,
      number: task.getValue("number"),
    })
  }

  return createdTasks
}

// Example usage
var tasks = createFulfillmentTasks(ritmSysId, [
  { description: "Verify request details", assignmentGroup: "Service Desk", daysToComplete: 1 },
  { description: "Provision access", assignmentGroup: "IAM Team", daysToComplete: 2 },
  { description: "Notify user", assignmentGroup: "Service Desk", daysToComplete: 1 },
])
Auto-close RITM on Task Completion
// Business Rule: after, update, sc_task (ES5 ONLY!)
;(function executeRule(current, previous) {
  // Check if task was just closed
  if (current.state.changesTo("3") || current.state.changesTo("4")) {
    checkAndCloseRITM(current.getValue("request_item"))
  }
})(current, previous)

function checkAndCloseRITM(ritmSysId) {
  // Check if all tasks are complete
  var openTasks = new GlideAggregate("sc_task")
  openTasks.addQuery("request_item", ritmSysId)
  openTasks.addQuery("state", "NOT IN", "3,4,7") // Not closed or cancelled
  openTasks.addAggregate("COUNT")
  openTasks.query()

  if (openTasks.next()) {
    var count = parseInt(openTasks.getAggregate("COUNT"), 10)
    if (count === 0) {
      // All tasks complete, close RITM
      var ritm = new GlideRecord("sc_req_item")
      if (ritm.get(ritmSysId)) {
        ritm.state = 3 // Closed Complete
        ritm.update()
      }
    }
  }
}

Variable Management (ES5)

Access RITM Variables
// Get variable values from RITM (ES5 ONLY!)
function getRITMVariables(ritmSysId) {
  var variables = {}

  var ritm = new GlideRecord("sc_req_item")
  if (!ritm.get(ritmSysId)) {
    return variables
  }

  // Get all variable values
  var varValue = new GlideRecord("sc_item_option_mtom")
  varValue.addQuery("request_item", ritmSysId)
  varValue.query()

  while (varValue.next()) {
    var varName = varValue.sc_item_option.item_option_new.name.toString()
    var value = varValue.getValue("sc_item_option")

    // Get display value for reference fields
    var varDef = varValue.sc_item_option.item_option_new.getRefRecord()
    if (varDef.getValue("type") === "8") {
      // Reference
      var refRecord = new GlideRecord(varDef.getValue("reference"))
      if (refRecord.get(value)) {
        variables[varName] = {
          value: value,
          display_value: refRecord.getDisplayValue(),
        }
      }
    } else {
      variables[varName] = {
        value: value,
        display_value: varValue.sc_item_option.getDisplayValue(),
      }
    }
  }

  return variables
}
Validate Variables
// Validate RITM variables (ES5 ONLY!)
function validateRITMVariables(ritmSysId) {
  var errors = []

  var ritm = new GlideRecord("sc_req_item")
  if (!ritm.get(ritmSysId)) {
    return ["RITM not found"]
  }

  // Get catalog item variable definitions
  var catItem = ritm.cat_item.getRefRecord()

  var varDef = new GlideRecord("item_option_new")
  varDef.addQuery("cat_item", catItem.getUniqueValue())
  varDef.addQuery("mandatory", true)
  varDef.query()

  while (varDef.next()) {
    var varName = varDef.getValue("name")
    var varValue = ritm.variables[varName]

    if (!varValue || varValue.toString() === "") {
      errors.push("Missing required variable: " + varDef.getValue("question_text"))
    }
  }

  return errors
}

Request Approvals (ES5)

Check Approval Status
// Get approval status for request (ES5 ONLY!)
function getRequestApprovalStatus(requestSysId) {
  var approvals = []

  var approval = new GlideRecord("sysapproval_approver")
  approval.addQuery("sysapproval", requestSysId)
  approval.query()

  while (approval.next()) {
    approvals.push({
      approver: approval.approver.getDisplayValue(),
      state: approval.state.getDisplayValue(),
      comments: approval.getValue("comments"),
      sys_updated_on: approval.getValue("sys_updated_on"),
    })
  }

  // Determine overall status
  var pending = 0
  var approved = 0
  var rejected = 0

  for (var i = 0; i < approvals.length; i++) {
    var state = approvals[i].state
    if (state === "Requested") pending++
    else if (state === "Approved") approved++
    else if (state === "Rejected") rejected++
  }

  return {
    approvals: approvals,
    summary: {
      pending: pending,
      approved: approved,
      rejected: rejected,
      overall: rejected > 0 ? "Rejected" : pending > 0 ? "Pending" : "Approved",
    },
  }
}

MCP Tool Integration

Available Tools
ToolPurpose
snow_query_tableQuery requests and RITMs
snow_artifact_manage (action='find')Find catalog items
snow_execute_scriptTest request scripts
snow_create_catalog_itemCreate catalog items
Example Workflow
// 1. Query open requests
await snow_query_table({
  table: "sc_req_item",
  query: "state!=3^state!=4^requested_for=javascript:gs.getUserID()",
  fields: "number,short_description,cat_item,state,stage",
})

// 2. Get request details
await snow_execute_script({
  script: `
        var vars = getRITMVariables('ritm_sys_id');
        gs.info(JSON.stringify(vars));
    `,
})

// 3. Check approvals
await snow_query_table({
  table: "sysapproval_approver",
  query: "sysapproval=request_sys_id",
  fields: "approver,state,comments",
})

Best Practices

  1. Clear Descriptions - User-friendly short descriptions
  2. Variable Validation - Validate before processing
  3. Task Ordering - Logical fulfillment sequence
  4. SLA Tracking - Set appropriate due dates
  5. Notifications - Keep requesters informed
  6. Approval Rules - Configure appropriate approvals
  7. Auto-closure - Close RITMs when tasks complete
  8. ES5 Only - No modern JavaScript syntax

Comments

Markdown supported