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構文は使用しません

コメント