freshservice-mcp 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.js +23 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -207,6 +207,8 @@ Freshservice Changes use numeric values for their standard fields:
|
|
|
207
207
|
|
|
208
208
|
`associate_tickets_to_change` uses the association shape documented by Freshservice's Ticket API. The default relationship, `change_initiated_by_ticket`, means the ticket initiated the Change. Use `association_type: "change_initiating_ticket"` when the Change initiated the ticket. `change_id` is placed in the documented nested `display_id` field.
|
|
209
209
|
|
|
210
|
+
Because the association is applied as a ticket update, Freshservice validates the whole ticket — so on an instance where `description` is a mandatory field, a ticket with an empty description would otherwise be rejected with a 400. The tool handles this transparently: it retries once with a minimal placeholder description, and only for tickets that genuinely have none. Existing descriptions are never overwritten.
|
|
211
|
+
|
|
210
212
|
## Local Development
|
|
211
213
|
|
|
212
214
|
```bash
|
package/dist/index.js
CHANGED
|
@@ -11180,12 +11180,29 @@ async function updateChange(config2, changeId, payload) {
|
|
|
11180
11180
|
async function associateTicketsToChange(config2, changeDisplayId, ticketIds, associationType = "change_initiated_by_ticket") {
|
|
11181
11181
|
return Promise.all(
|
|
11182
11182
|
ticketIds.map(
|
|
11183
|
-
(ticketId) =>
|
|
11184
|
-
[associationType]: { display_id: changeDisplayId }
|
|
11185
|
-
})
|
|
11183
|
+
(ticketId) => associateOneTicket(config2, ticketId, changeDisplayId, associationType)
|
|
11186
11184
|
)
|
|
11187
11185
|
);
|
|
11188
11186
|
}
|
|
11187
|
+
function isBlankDescriptionError(error2) {
|
|
11188
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
11189
|
+
return message.includes("400") && message.includes('"field":"description"') && message.toLowerCase().includes("blank");
|
|
11190
|
+
}
|
|
11191
|
+
async function associateOneTicket(config2, ticketId, changeDisplayId, associationType) {
|
|
11192
|
+
const association = { [associationType]: { display_id: changeDisplayId } };
|
|
11193
|
+
try {
|
|
11194
|
+
return await updateTicket(config2, ticketId, association);
|
|
11195
|
+
} catch (error2) {
|
|
11196
|
+
if (!isBlankDescriptionError(error2)) throw error2;
|
|
11197
|
+
const existing = await getTicket(config2, ticketId);
|
|
11198
|
+
const currentDescription = existing.description_text?.trim() || stripHtml(existing.description ?? "");
|
|
11199
|
+
if (currentDescription) throw error2;
|
|
11200
|
+
return updateTicket(config2, ticketId, {
|
|
11201
|
+
...association,
|
|
11202
|
+
description: BLANK_DESCRIPTION_PLACEHOLDER
|
|
11203
|
+
});
|
|
11204
|
+
}
|
|
11205
|
+
}
|
|
11189
11206
|
async function addChangeNote(config2, changeId, payload) {
|
|
11190
11207
|
const data = await fsPost(
|
|
11191
11208
|
config2,
|
|
@@ -11206,10 +11223,11 @@ async function listAgents(config2, options = {}) {
|
|
|
11206
11223
|
const data = await fsGet(config2, "agents", params);
|
|
11207
11224
|
return data.agents ?? [];
|
|
11208
11225
|
}
|
|
11209
|
-
var DEFAULT_STATUS_MAP, PRIORITY_MAP, CHANGE_PRIORITY_MAP, CHANGE_STATUS_MAP, CHANGE_TYPE_MAP, CHANGE_IMPACT_MAP, CHANGE_RISK_MAP;
|
|
11226
|
+
var BLANK_DESCRIPTION_PLACEHOLDER, DEFAULT_STATUS_MAP, PRIORITY_MAP, CHANGE_PRIORITY_MAP, CHANGE_STATUS_MAP, CHANGE_TYPE_MAP, CHANGE_IMPACT_MAP, CHANGE_RISK_MAP;
|
|
11210
11227
|
var init_freshservice_client = __esm({
|
|
11211
11228
|
"src/freshservice-client.ts"() {
|
|
11212
11229
|
"use strict";
|
|
11230
|
+
BLANK_DESCRIPTION_PLACEHOLDER = ".";
|
|
11213
11231
|
DEFAULT_STATUS_MAP = {
|
|
11214
11232
|
2: "Open",
|
|
11215
11233
|
3: "Pending",
|
|
@@ -21857,7 +21875,7 @@ ${JSON.stringify(normalizeChange(change), null, 2)}`
|
|
|
21857
21875
|
"associate_tickets_to_change",
|
|
21858
21876
|
{
|
|
21859
21877
|
title: "Associate Tickets to Change",
|
|
21860
|
-
description: "Associate existing tickets with a Change by updating each ticket using Freshservice's documented Change association object.",
|
|
21878
|
+
description: "Associate existing tickets with a Change by updating each ticket using Freshservice's documented Change association object. A ticket whose description is empty on an instance where description is mandatory is retried once with a minimal placeholder description so the association still lands; existing descriptions are never overwritten.",
|
|
21861
21879
|
inputSchema: external_exports.object({
|
|
21862
21880
|
change_id: external_exports.number().int().positive().describe(
|
|
21863
21881
|
"Change display ID (Freshservice requires display_id in the association body)"
|