diff --git a/src/Tools/core/create/iTopCreateTools.php b/src/Tools/core/create/iTopCreateTools.php index 1457ad9..8800a9b 100644 --- a/src/Tools/core/create/iTopCreateTools.php +++ b/src/Tools/core/create/iTopCreateTools.php @@ -52,4 +52,16 @@ public function createUserRequest(string $title, string $description, int $calle ['title' => $title, 'description' => $description, 'caller_id' => $callerId, 'org_id' => $orgId, 'impact' => $impact, 'urgency' => $urgency] ); } + + /** + * This tool creates an Incident in iTop + */ + #[McpTool(name: TOOL_PREFIX.'create-incident', annotations: new ToolAnnotations(null, false, true, false, false))] + public function createIncident(string $title, string $description, int $callerId, int $orgId, int $impact = 3, int $urgency = 4): string + { + $this->mcpLogger->info('[Tool called] create-incident'); + return $this->runToolFromTemplates('createIncident', 'Incident', + ['title' => $title, 'description' => $description, 'caller_id' => $callerId, 'org_id' => $orgId, 'impact' => $impact, 'urgency' => $urgency] + ); + } } \ No newline at end of file diff --git a/src/Tools/core/get/iTopGetTools.php b/src/Tools/core/get/iTopGetTools.php index e5133b1..a7a2e67 100644 --- a/src/Tools/core/get/iTopGetTools.php +++ b/src/Tools/core/get/iTopGetTools.php @@ -146,4 +146,29 @@ public function searchAnyObjectByOql(string $oql, int $limit = 20, int $page = 1 ] ); } + + /** + * This tool searches for existing Incidents in iTop based on: + * - the email of the caller + * - an optional list of statuses for the Incident. + * - an optional start date + * - if a start date is specified, the condition/operator: either 'greater_than' or 'less_than' + * @param string $caller_email The email of the caller + * @param string[] $statuses Optional, a list of status codes (multiple values will be combined with a OR condition). Call get-class-schema('Incident') to find the possible values for the status field. + * @param string $start_date Optional, the start date-time of the Incident (format as a MySQL DateTime (YYYY-MM-DD hh:ii:ss) + * @param string $condition Optional, the condiotnal operator for the start date: either 'greater_than" or 'less_than' + */ + #[McpTool(name: TOOL_PREFIX.'search-incident-by-caller-status-start-date', annotations: new ToolAnnotations(null, true, false, true, false))] + public function searchIncidentByCallerStatusStartDate(#[Schema(format: 'email')] string $caller_email, array $statuses = [], string $start_date = '', string $condition = 'greater_than'): string + { + $statuses = array_map(fn($status) => static::quoteString((string)$status), $statuses); + return $this->runToolFromTemplates('searchIncidentFromCallerStatusDate', 'Incident', + [ + 'caller_email' => static::quoteString($caller_email), + 'statuses' => count($statuses) > 0 ? "'".implode("','", $statuses)."'" : '', + 'start_date' => static::quoteString($start_date), + 'condition' => $condition === 'greater_than' ? '>=' : '<=', + ] + ); + } } \ No newline at end of file diff --git a/src/Tools/core/update/iTopUpdateTools.php b/src/Tools/core/update/iTopUpdateTools.php index 9f794e1..361fcd3 100644 --- a/src/Tools/core/update/iTopUpdateTools.php +++ b/src/Tools/core/update/iTopUpdateTools.php @@ -45,6 +45,29 @@ public function updateUserRequest(int $id, string $additionalLogEntryHtml, strin ); } + /** + * This tool updates an Incident in iTop by adding an entry to the log and optionally updating the title or the description + * @param int $id The identifier of the Incident to update + * @param string $additionalLogEntryHtml An new entry to add to the log of the Incident - NOTE the log entry MUST BE formatted in HTML + * @param string $title Specify the new title for the Incident (leave empty for no change) + * @param string $descriptionHtml Specify the new description for the Incident (leave empty for no change) - NOTE the descriptipon MUST BE formatted in HTML + */ + #[McpTool(name: TOOL_PREFIX.'update-incident', annotations: new ToolAnnotations(null, false, true, false, false))] + public function updateIncident(int $id, string $additionalLogEntryHtml, string $title = '', string $descriptionHtml = ''): string + { + $this->mcpLogger->info('[Tool called] update-incident'); + return $this->runToolFromTemplates('updateIncident', 'Anything', + [ + 'id' => $id, + 'title' => $title, + 'description' => $descriptionHtml, + 'log' => $additionalLogEntryHtml, + 'output_fields' => $this->datamodel->getListZlist('Incident'), + 'log_field' => 'public_log', + ] + ); + } + /** * This tool can update any object in iTop. * diff --git a/templates/Incident-output.toon.twig b/templates/Incident-output.toon.twig new file mode 100644 index 0000000..2a16e5b --- /dev/null +++ b/templates/Incident-output.toon.twig @@ -0,0 +1,12 @@ +{% if json.objects === null %} +Sorry, no such Incident exists in iTop. +{% else %} +{% for obj in json.objects %} +class Incident: + id,ref,title,status,caller_id_friendlyname,org_id_friendlyname,priority + +Incident { + {{obj.key}}, {{obj.fields.ref}}, "{{obj.fields.title|e('js')}}", {{obj.fields.status}}, "{{obj.fields.caller_id_friendlyname|e('js')}}" , "{{obj.fields.org_id_friendlyname|e('js')}}", {{obj.fields.priority}} +} +{% endfor %} +{% endif %} \ No newline at end of file diff --git a/templates/createIncident-input.json.twig b/templates/createIncident-input.json.twig new file mode 100644 index 0000000..ffaa326 --- /dev/null +++ b/templates/createIncident-input.json.twig @@ -0,0 +1,14 @@ +{ + "operation":"core/create", + "class":"Incident", + "output_fields": "ref,title,description,status,caller_id_friendlyname,org_id_friendlyname,priority", + "fields": { + "org_id": {{org_id}}, + "caller_id": {{caller_id}}, + "title": "{{title}}", + "description": "{{description}}", + "impact": {{impact}}, + "urgency": {{urgency}} + }, + "comment": "Created via the MCP server" +} \ No newline at end of file diff --git a/templates/searchIncidentFromCallerStatusDate-input.json.twig b/templates/searchIncidentFromCallerStatusDate-input.json.twig new file mode 100644 index 0000000..10a8f0e --- /dev/null +++ b/templates/searchIncidentFromCallerStatusDate-input.json.twig @@ -0,0 +1,6 @@ +{ + "operation":"core/get", + "class": "Incident", + "key": "SELECT Incident AS I JOIN Person AS P ON I.caller_id = P.id WHERE P.email='{{caller_email}}'{% if statuses !== ''%} AND I.status IN({{ statuses }}){% endif%}{% if start_date !== '' %} AND I.start_date {{ condition }} '{{start_date}}'{% endif%}", + "output_fields": "id,ref,title,status,caller_id_friendlyname,org_id_friendlyname,priority" +} \ No newline at end of file diff --git a/templates/updateIncident-input.json.twig b/templates/updateIncident-input.json.twig new file mode 100644 index 0000000..98b64d5 --- /dev/null +++ b/templates/updateIncident-input.json.twig @@ -0,0 +1,12 @@ +{ + "operation": "core/update", + "class": "Incident", + "key": {{id}}, + "fields": { +{% if title !== '' %} "title":"{{title}}",{% endif %} +{% if description !== '' %} "description":"{{description}}",{% endif %} + "{{ log_field }}":"{{ log }}" + }, + "output_fields": "{{output_fields}}", + "comment": "Updated via the MCP server" +} \ No newline at end of file