@mgsoftwarebv/mcp-server-bridge 3.5.4 → 3.5.5
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/dist/index.js +116 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -105991,6 +105991,22 @@ var TOOLS = [
|
|
|
105991
105991
|
required: ["ticketId"]
|
|
105992
105992
|
}
|
|
105993
105993
|
},
|
|
105994
|
+
{
|
|
105995
|
+
name: "delete-ticket-attachment",
|
|
105996
|
+
description: "Safely remove a ticket or comment attachment by id. Validates provider/team access and that the attachment belongs to the requested ticket. Hard-deletes the DB row and vault file, and logs ticket activity with the filename. Find attachment ids via get-ticket-by-id.",
|
|
105997
|
+
inputSchema: {
|
|
105998
|
+
type: "object",
|
|
105999
|
+
properties: {
|
|
106000
|
+
teamId: teamIdProp,
|
|
106001
|
+
ticketId: ticketIdentifierProp,
|
|
106002
|
+
attachmentId: {
|
|
106003
|
+
type: "string",
|
|
106004
|
+
description: "Attachment ID from get-ticket-by-id (ticket or comment attachment)."
|
|
106005
|
+
}
|
|
106006
|
+
},
|
|
106007
|
+
required: ["ticketId", "attachmentId"]
|
|
106008
|
+
}
|
|
106009
|
+
},
|
|
105994
106010
|
{
|
|
105995
106011
|
name: "get-customers",
|
|
105996
106012
|
description: "Get customers with optional search. Each result includes its ID (UUID), name, email, website, phone, status, archived flag, and created date. Archived customers are hidden by default; pass status 'archived' or 'all' to include them.",
|
|
@@ -120639,6 +120655,36 @@ function validateAttachmentBuffer(buffer2, mimeType) {
|
|
|
120639
120655
|
return null;
|
|
120640
120656
|
}
|
|
120641
120657
|
|
|
120658
|
+
// src/tools/ticket-attachment-delete-util.ts
|
|
120659
|
+
function validateDeleteAttachmentInput(attachmentId) {
|
|
120660
|
+
if (!attachmentId?.trim()) {
|
|
120661
|
+
return "missing_attachment_id";
|
|
120662
|
+
}
|
|
120663
|
+
return null;
|
|
120664
|
+
}
|
|
120665
|
+
function validateAttachmentBelongsToTicket(attachmentTicketId, requestedTicketId) {
|
|
120666
|
+
return attachmentTicketId === requestedTicketId;
|
|
120667
|
+
}
|
|
120668
|
+
function buildDeleteAttachmentResult(input) {
|
|
120669
|
+
return {
|
|
120670
|
+
deleted: true,
|
|
120671
|
+
attachmentId: input.attachmentId,
|
|
120672
|
+
ticketId: input.ticketId,
|
|
120673
|
+
fileName: input.fileName,
|
|
120674
|
+
source: input.source
|
|
120675
|
+
};
|
|
120676
|
+
}
|
|
120677
|
+
function formatDeleteAttachmentRefusal(reason, context2) {
|
|
120678
|
+
switch (reason) {
|
|
120679
|
+
case "missing_attachment_id":
|
|
120680
|
+
return "attachmentId is required. Use get-ticket-by-id to list attachment ids.";
|
|
120681
|
+
case "attachment_not_found":
|
|
120682
|
+
return `Attachment not found: ${context2.attachmentId}. Use get-ticket-by-id on ${context2.ticketNumber} to list valid attachment ids.`;
|
|
120683
|
+
case "wrong_ticket":
|
|
120684
|
+
return `Attachment ${context2.attachmentId} (${context2.fileName ?? "unknown file"}) belongs to ticket ${context2.actualTicketId}, not ${context2.ticketNumber}. Pass the correct ticketId or choose an attachment id from that ticket.`;
|
|
120685
|
+
}
|
|
120686
|
+
}
|
|
120687
|
+
|
|
120642
120688
|
// src/tools/ticket-attachments.ts
|
|
120643
120689
|
function textResponse5(text3) {
|
|
120644
120690
|
return { content: [{ type: "text", text: text3 }] };
|
|
@@ -120785,6 +120831,72 @@ Download URL (valid 1 hour):
|
|
|
120785
120831
|
${url3}` : "")
|
|
120786
120832
|
);
|
|
120787
120833
|
}
|
|
120834
|
+
async function handleDeleteTicketAttachment(input) {
|
|
120835
|
+
const ctx = getAuthContext() ?? authContext;
|
|
120836
|
+
if (!ctx) {
|
|
120837
|
+
return textResponse5("Error: Not authenticated.");
|
|
120838
|
+
}
|
|
120839
|
+
const inputError = validateDeleteAttachmentInput(input.attachmentId);
|
|
120840
|
+
if (inputError) {
|
|
120841
|
+
return textResponse5(formatDeleteAttachmentRefusal(inputError, { ticketNumber: input.ticketId }));
|
|
120842
|
+
}
|
|
120843
|
+
const access = await loadAccessibleTicket(input.teamId, input.ticketId);
|
|
120844
|
+
if (!access.ok) return access.response;
|
|
120845
|
+
const ticket = access.ticket;
|
|
120846
|
+
const attachment = await findAttachment(input.attachmentId);
|
|
120847
|
+
if (!attachment) {
|
|
120848
|
+
return textResponse5(
|
|
120849
|
+
formatDeleteAttachmentRefusal("attachment_not_found", {
|
|
120850
|
+
attachmentId: input.attachmentId,
|
|
120851
|
+
ticketNumber: ticket.ticketNumber
|
|
120852
|
+
})
|
|
120853
|
+
);
|
|
120854
|
+
}
|
|
120855
|
+
if (!validateAttachmentBelongsToTicket(attachment.ticketId, ticket.id)) {
|
|
120856
|
+
return textResponse5(
|
|
120857
|
+
formatDeleteAttachmentRefusal("wrong_ticket", {
|
|
120858
|
+
attachmentId: input.attachmentId,
|
|
120859
|
+
ticketNumber: ticket.ticketNumber,
|
|
120860
|
+
fileName: attachment.fileName,
|
|
120861
|
+
actualTicketId: attachment.ticketId
|
|
120862
|
+
})
|
|
120863
|
+
);
|
|
120864
|
+
}
|
|
120865
|
+
const table = attachment.source === "ticket" ? schema_exports.ticketAttachments : schema_exports.ticketCommentAttachments;
|
|
120866
|
+
const [deletedRow] = await db.delete(table).where(eq(table.id, input.attachmentId)).returning({ id: table.id });
|
|
120867
|
+
if (!deletedRow) {
|
|
120868
|
+
return textResponse5(
|
|
120869
|
+
`Failed to delete attachment ${input.attachmentId}. It may have been removed already.`
|
|
120870
|
+
);
|
|
120871
|
+
}
|
|
120872
|
+
try {
|
|
120873
|
+
await storage.remove({
|
|
120874
|
+
bucket: "vault",
|
|
120875
|
+
paths: [attachment.storageKey]
|
|
120876
|
+
});
|
|
120877
|
+
} catch {
|
|
120878
|
+
}
|
|
120879
|
+
await db.insert(schema_exports.ticketActivity).values({
|
|
120880
|
+
ticketId: ticket.id,
|
|
120881
|
+
teamId: ticket.teamId,
|
|
120882
|
+
userId: ctx.userId,
|
|
120883
|
+
activityType: "attachment_removed",
|
|
120884
|
+
metadata: {
|
|
120885
|
+
attachmentId: input.attachmentId,
|
|
120886
|
+
fileName: attachment.fileName,
|
|
120887
|
+
source: attachment.source,
|
|
120888
|
+
removedBy: "mcp"
|
|
120889
|
+
}
|
|
120890
|
+
});
|
|
120891
|
+
await db.update(schema_exports.tickets).set({ updatedAt: sql`NOW()`, updatedBy: ctx.userId }).where(eq(schema_exports.tickets.id, ticket.id));
|
|
120892
|
+
const result = buildDeleteAttachmentResult({
|
|
120893
|
+
attachmentId: input.attachmentId,
|
|
120894
|
+
ticketId: ticket.id,
|
|
120895
|
+
fileName: attachment.fileName,
|
|
120896
|
+
source: attachment.source
|
|
120897
|
+
});
|
|
120898
|
+
return textResponse5(JSON.stringify(result, null, 2));
|
|
120899
|
+
}
|
|
120788
120900
|
|
|
120789
120901
|
// src/tools/tiptap-text.ts
|
|
120790
120902
|
function renderNode(node) {
|
|
@@ -122861,6 +122973,10 @@ function createMcpServer() {
|
|
|
122861
122973
|
return await handleUploadTicketAttachment(
|
|
122862
122974
|
asToolArgs(toolArgs)
|
|
122863
122975
|
);
|
|
122976
|
+
case "delete-ticket-attachment":
|
|
122977
|
+
return await handleDeleteTicketAttachment(
|
|
122978
|
+
asToolArgs(toolArgs)
|
|
122979
|
+
);
|
|
122864
122980
|
case "get-customers":
|
|
122865
122981
|
return await handleGetCustomers(asToolArgs(toolArgs));
|
|
122866
122982
|
case "create-customer":
|