mcpField
R
request-management

request-management

github.com/serac-labs其他7760 次安装9 周前更新
代码仓库

关于 request-management

用于管理 ServiceNow 服务请求的技能,覆盖从目录条目到履行的流程。内容包括请求记录、目录任务、变量和审批,并提供面向管理员与开发者的 ES5 示例。

主要功能

  1. 01创建请求和请求条目
  2. 02查询用户的未完成请求
  3. 03创建履行任务
  4. 04读取并验证条目变量
  5. 05检查请求审批状态

适用场景

  1. 01根据目录条目创建请求
  2. 02查看用户待处理的请求
  3. 03协调请求条目的任务完成
  4. 04在处理请求前验证输入

MCP 相关

介绍用于查询请求和请求条目、查找目录条目、测试脚本及创建目录条目的 ServiceNow MCP 工具。

安装

复制下面的命令,在终端中运行。

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

安装后在 Claude Code 中输入/request-management确认已加载。

详细介绍

ServiceNow 请求管理

请求管理用于处理服务请求,从目录项到完成交付。

请求层级

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

主要表

表用途
sc_request父请求记录
sc_req_item请求的项目(RITM)
sc_task履行任务
sc_item_option_mtom变量值
sc_cat_item目录项定义

请求项目(ES5)

以编程方式创建请求
// 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()
}
查询请求项目
// 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
}

履行任务(ES5)

创建目录任务
// 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 },
])
任务完成后自动关闭 RITM
// 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()
      }
    }
  }
}

变量管理(ES5)

访问 RITM 变量
// 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 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
}

请求审批(ES5)

检查审批状态
// 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 工具集成

可用工具
工具用途
snow_query_table查询请求和 RITM
snow_artifact_manage (action='find')查找目录项
snow_execute_script测试请求脚本
snow_create_catalog_item创建目录项
工作流示例
// 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",
})

最佳实践

  1. 清晰的描述 - 使用便于用户理解的简短描述
  2. 变量验证 - 处理前先验证
  3. 任务排序 - 按逻辑顺序安排履行任务
  4. SLA 跟踪 - 设置适当的到期日期
  5. 通知 - 及时告知请求者
  6. 审批规则 - 配置适当的审批规则
  7. 自动关闭 - 任务完成后关闭 RITM
  8. 仅限 ES5 - 不使用现代 JavaScript 语法

评论

支持 Markdown