Trengo MCP by usefulapi

Work tickets and messages, look up contacts and teams, pull reports, and reply, assign or close.

Should I use this

Quality & Safety

A
Description quality
96%
Schema completeness
95%
Naming quality
79%
Poisoning risk
100%
Permission match
100%
Protocol compliance
100%

Findings (2)

  • LOWTool 'trengo_assign_ticket' description lacks action verbin trengo_assign_ticket
  • LOWTool 'trengo_get_ticket_details_report' name length outside 3-30 rangein trengo_get_ticket_details_report

Based on automated analysis of tool definitions and protocol compliance.

Context Cost

~5,110Tokens (tool definitions)
~1.7 KBTypical response size
Significant attention impact (3.99% of 128k context)

This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.

Install

One-Click Install

Add this to your `claude_desktop_config.json` file:

{
  "mcpServers": {
    "trengo": {
      "url": "https://trengo.usefulapi.io/mcp"
    }
  }
}

Remote endpoints

https://trengo.usefulapi.io/mcpstreamable-http

What it can do

Tool inventory

Tools (24)

🟢 Read-only🟡 Write🔴 Delete⚪ Unknown
🟢trengo_list_tickets(status, contact_id, users, channels, labels, ...)

List tickets (conversations) visible to the token's user, newest activity first, with channel and latest message. Filter by status, contact, assignee, channel, label, last message direction or update time. Trengo: GET /tickets.

Input Schema

{
  "type": "object",
  "properties": {
    "status": {
      "description": "Only tickets in this status. INVALID = spam.",
      "type": "string",
      "enum": [
        "OPEN",
        "ASSIGNED",
        "CLOSED",
        "INVALID"
      ]
    },
    "contact_id": {
      "description": "Only tickets of this contact.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "users": {
      "description": "Only these assigned user ids.",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    },
    "channels": {
      "description": "Only these channel ids.",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    },
    "labels": {
      "description": "Only these label ids.",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    },
    "last_message_type": {
      "description": "Only tickets whose last message was INBOUND or OUTBOUND.",
      "type": "string",
      "enum": [
        "INBOUND",
        "OUTBOUND"
      ]
    },
    "sort": {
      "description": "By last message time: -date newest first (default), date oldest first.",
      "type": "string",
      "enum": [
        "-date",
        "date"
      ]
    },
    "updated_at_gt": {
      "description": "Only tickets updated after this date-time.",
      "type": "string"
    },
    "page": {
      "description": "Page number (1-based). Omit for the first page.",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢trengo_list_ticket_messages(ticket_id, page)

List the messages of one ticket — inbound, outbound and internal notes — with the contact or agent behind each. Trengo: GET /tickets/{ticket_id}/messages.

Input Schema

{
  "type": "object",
  "properties": {
    "ticket_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The ticket id."
    },
    "page": {
      "description": "Page number (1-based). Omit for the first page.",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "ticket_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢trengo_get_email_message(ticket_id, message_id)

Fetch the full email behind one message of a ticket: original HTML body, from, to, subject and Message-ID. The message must be an email message. Trengo: GET /tickets/{ticket_id}/full_email_messages/{message_id}.

Input Schema

{
  "type": "object",
  "properties": {
    "ticket_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The ticket id."
    },
    "message_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The message id."
    }
  },
  "required": [
    "ticket_id",
    "message_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢trengo_list_contacts(term, include_last_interaction, page)

List contacts, or search them by name, email or phone number. Trengo: GET /contacts.

Input Schema

{
  "type": "object",
  "properties": {
    "term": {
      "description": "Search term, matched on email, phone number and name.",
      "type": "string"
    },
    "include_last_interaction": {
      "description": "Also return each contact's last interaction.",
      "type": "boolean"
    },
    "page": {
      "description": "Page number (1-based). Omit for the first page.",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢trengo_get_contact(contact_id, include_notes)

Fetch one contact with name, email, phone and custom field data, optionally with notes. Trengo: GET /contacts/{id}.

Input Schema

{
  "type": "object",
  "properties": {
    "contact_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The contact id."
    },
    "include_notes": {
      "description": "Also return the contact's notes.",
      "type": "boolean"
    }
  },
  "required": [
    "contact_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢trengo_list_contact_groups(page)

List the contact groups in the account — use their ids with trengo_update_contact. Trengo: GET /contact_groups.

Input Schema

{
  "type": "object",
  "properties": {
    "page": {
      "description": "Page number (1-based). Omit for the first page.",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢trengo_list_users(sort, page)

List the agents (users) in the Trengo account — use their ids to assign tickets or filter. Trengo: GET /users.

Input Schema

{
  "type": "object",
  "properties": {
    "sort": {
      "description": "Sort column (default id).",
      "type": "string",
      "enum": [
        "id",
        "first_name",
        "last_name",
        "created_at"
      ]
    },
    "page": {
      "description": "Page number (1-based). Omit for the first page.",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢trengo_list_teams(page)

List the teams in the account — use their ids to assign tickets to a team. Trengo: GET /teams.

Input Schema

{
  "type": "object",
  "properties": {
    "page": {
      "description": "Page number (1-based). Omit for the first page.",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢trengo_list_labels(page)

List the ticket labels (tags) in the account, for filtering tickets and reports. Trengo: GET /labels.

Input Schema

{
  "type": "object",
  "properties": {
    "page": {
      "description": "Page number (1-based). Omit for the first page.",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢trengo_list_ticket_results(page)

List the ticket results (closing outcomes, e.g. 'Resolved', 'Sale') that can be applied when closing a ticket. Trengo: GET /ticket_results.

Input Schema

{
  "type": "object",
  "properties": {
    "page": {
      "description": "Page number (1-based). Omit for the first page.",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢trengo_list_custom_fields(page)

List the custom fields defined for tickets, contacts and profiles. Trengo: GET /custom_fields.

Input Schema

{
  "type": "object",
  "properties": {
    "page": {
      "description": "Page number (1-based). Omit for the first page.",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢trengo_list_quick_replies(type)

List the saved quick replies (canned responses), optionally only the messaging or email ones — useful for drafting consistent answers. Trengo: GET /quick_replies.

Input Schema

{
  "type": "object",
  "properties": {
    "type": {
      "description": "Only quick replies of this type.",
      "type": "string",
      "enum": [
        "MESSAGING",
        "EMAIL"
      ]
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢trengo_get_reporting_metrics(metrics, start_date, end_date, team_ids, channel_ids, ...)

Aggregate support metrics over a period: new, created, assigned, closed and reopened tickets, average first response time and average total resolution time (seconds). Filter by team, channel, label or direction. Trengo: GET /reporting/metrics.

Input Schema

{
  "type": "object",
  "properties": {
    "metrics": {
      "minItems": 1,
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "new_tickets",
          "assigned_tickets",
          "average_total_resolution_time",
          "average_first_response_time",
          "created_tickets",
          "closed_tickets",
          "reopened_tickets"
        ]
      },
      "description": "Which metrics to return."
    },
    "start_date": {
      "description": "Period start as ISO 8601, e.g. 2026-09-01T00:00:00+00:00. Give it together with its pair.",
      "type": "string"
    },
    "end_date": {
      "description": "Period end as ISO 8601, e.g. 2026-09-01T00:00:00+00:00. Give it together with its pair.",
      "type": "string"
    },
    "team_ids": {
      "description": "Only these team ids.",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    },
    "channel_ids": {
      "description": "Only these channel ids.",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    },
    "label_ids": {
      "description": "Only these label ids.",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    },
    "direction": {
      "description": "Only INBOUND or OUTBOUND conversations.",
      "type": "string",
      "enum": [
        "INBOUND",
        "OUTBOUND"
      ]
    }
  },
  "required": [
    "metrics"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢trengo_get_agent_performance(start_date, end_date, team_ids, channel_ids, label_ids, ...)

Per-agent performance over a period: messages sent, notes, tickets assigned and closed, average first response and resolution times (with and without business hours). Trengo: GET /reporting/agent_performance.

Input Schema

{
  "type": "object",
  "properties": {
    "start_date": {
      "description": "Period start as ISO 8601, e.g. 2026-09-01T00:00:00+00:00. Give it together with its pair.",
      "type": "string"
    },
    "end_date": {
      "description": "Period end as ISO 8601, e.g. 2026-09-01T00:00:00+00:00. Give it together with its pair.",
      "type": "string"
    },
    "team_ids": {
      "description": "Only these team ids.",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    },
    "channel_ids": {
      "description": "Only these channel ids.",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    },
    "label_ids": {
      "description": "Only these label ids.",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    },
    "user_ids": {
      "description": "Only these user ids.",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    },
    "page": {
      "description": "Page number (1-based). Omit for the first page.",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢trengo_get_ticket_details_report(statuses, team_ids, channel_ids, label_ids, direction, ...)

Per-ticket reporting rows: status, assignee, labels, first reply, first resolution and total resolution times (with and without business hours). Filter by team, channel, label, direction, status and created/closed/assigned date ranges; sort by a timing metric. For large accounts page with start_after_ticket_id instead of page. Trengo: GET /reporting/details/ticket.

Input Schema

{
  "type": "object",
  "properties": {
    "statuses": {
      "description": "Only tickets in these statuses.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "OPEN",
          "ASSIGNED",
          "CLOSED",
          "INVALID"
        ]
      }
    },
    "team_ids": {
      "description": "Only these team ids.",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    },
    "channel_ids": {
      "description": "Only these channel ids.",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    },
    "label_ids": {
      "description": "Only these label ids.",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    },
    "direction": {
      "description": "Only INBOUND or OUTBOUND conversations.",
      "type": "string",
      "enum": [
        "INBOUND",
        "OUTBOUND"
      ]
    },
    "created_start_date": {
      "description": "Created-from as ISO 8601, e.g. 2026-09-01T00:00:00+00:00. Give it together with its pair.",
      "type": "string"
    },
    "created_end_date": {
      "description": "Created-until as ISO 8601, e.g. 2026-09-01T00:00:00+00:00. Give it together with its pair.",
      "type": "string"
    },
    "closed_start_date": {
      "description": "Closed-from as ISO 8601, e.g. 2026-09-01T00:00:00+00:00. Give it together with its pair.",
      "type": "string"
    },
    "closed_end_date": {
      "description": "Closed-until as ISO 8601, e.g. 2026-09-01T00:00:00+00:00. Give it together with its pair.",
      "type": "string"
    },
    "assigned_start_date": {
      "description": "Assigned-from as ISO 8601, e.g. 2026-09-01T00:00:00+00:00. Give it together with its pair.",
      "type": "string"
    },
    "assigned_end_date": {
      "description": "Assigned-until as ISO 8601, e.g. 2026-09-01T00:00:00+00:00. Give it together with its pair.",
      "type": "string"
    },
    "sort_by": {
      "description": "Sort column.",
      "type": "string",
      "enum": [
        "first_resolution_time_opening_hours",
        "first_resolution_time",
        "first_response_time_opening_hours",
        "first_response_time",
        "total_resolution_time_opening_hours",
        "total_resolution_time",
        "created_at",
        "assigned_at",
        "closed_at"
      ]
    },
    "sort_order": {
      "description": "Sort direction.",
      "type": "string",
      "enum": [
        "asc",
        "desc"
      ]
    },
    "start_after_ticket_id": {
      "description": "Keyset cursor: return tickets after this ticket id (replaces page for huge accounts).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "page": {
      "description": "Page number (1-based). Omit for the first page.",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴trengo_create_ticket(channel_id, contact_id, subject)

Open a new ticket for an existing contact on a channel. Nothing is sent to the customer until you post a message with trengo_send_ticket_message. Trengo: POST /tickets.

Input Schema

{
  "type": "object",
  "properties": {
    "channel_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The channel id."
    },
    "contact_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The contact id."
    },
    "subject": {
      "description": "Optional subject.",
      "type": "string"
    }
  },
  "required": [
    "channel_id",
    "contact_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴trengo_assign_ticket(ticket_id, type, user_id, team_id, note)

Assign a ticket to a user or a team, with an optional assignment note. Reversible by reassigning. Trengo: POST /tickets/{ticket_id}/assign.

Input Schema

{
  "type": "object",
  "properties": {
    "ticket_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The ticket id."
    },
    "type": {
      "type": "string",
      "enum": [
        "user",
        "team"
      ],
      "description": "Assign to a user or to a team."
    },
    "user_id": {
      "description": "The user id — required when type is user.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "team_id": {
      "description": "The team id — required when type is team.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "note": {
      "description": "Optional assignment note.",
      "type": "string"
    }
  },
  "required": [
    "ticket_id",
    "type"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴trengo_close_ticket(ticket_id, ticket_result_id)

Close a ticket, optionally applying a ticket result (see trengo_list_ticket_results). Reversible with trengo_reopen_ticket. Trengo: POST /tickets/{ticket_id}/close.

Input Schema

{
  "type": "object",
  "properties": {
    "ticket_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The ticket id."
    },
    "ticket_result_id": {
      "description": "Optional ticket result to apply.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "ticket_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴trengo_reopen_ticket(ticket_id)

Reopen a closed ticket. Trengo: POST /tickets/{ticket_id}/reopen.

Input Schema

{
  "type": "object",
  "properties": {
    "ticket_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The ticket id."
    }
  },
  "required": [
    "ticket_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴trengo_send_ticket_message(ticket_id, message, internal_note, subject, attachment_ids)

Post a message on a ticket. With internal_note=true it is an internal note visible only to agents. OTHERWISE IT IS DELIVERED TO THE CUSTOMER on the ticket's channel (email, WhatsApp, chat...) and cannot be recalled — confirm the text first. Trengo: POST /tickets/{ticket_id}/messages.

Input Schema

{
  "type": "object",
  "properties": {
    "ticket_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The ticket id."
    },
    "message": {
      "type": "string",
      "minLength": 1,
      "description": "The message. May contain HTML when the channel is email."
    },
    "internal_note": {
      "description": "true = internal note for agents only; false/omitted = sent to the customer.",
      "type": "boolean"
    },
    "subject": {
      "description": "Email channels only. Trengo prefixes it with 'Re:' when replying.",
      "type": "string"
    },
    "attachment_ids": {
      "description": "Email channels only: ids of previously uploaded attachments.",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    }
  },
  "required": [
    "ticket_id",
    "message"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴trengo_create_contact(channel_id, identifier, name)

Create a contact on a channel. The identifier is the contact's address on that channel: an email address for email channels, a phone number for WhatsApp/SMS/voice. Trengo: POST /channels/{channel_id}/contacts.

Input Schema

{
  "type": "object",
  "properties": {
    "channel_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The channel id."
    },
    "identifier": {
      "type": "string",
      "minLength": 1,
      "description": "Email address or phone number, depending on the channel."
    },
    "name": {
      "description": "The contact's full name.",
      "type": "string"
    }
  },
  "required": [
    "channel_id",
    "identifier"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴trengo_update_contact(contact_id, name, contact_group_ids)

Rename a contact and/or set the contact groups it belongs to. contact_group_ids REPLACES the contact's groups. Trengo: PUT /contacts/{id}.

Input Schema

{
  "type": "object",
  "properties": {
    "contact_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The contact id."
    },
    "name": {
      "description": "The contact's new name.",
      "type": "string"
    },
    "contact_group_ids": {
      "description": "The full set of contact group ids (replaces the current groups).",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    }
  },
  "required": [
    "contact_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴trengo_create_board_card(board_id, stage_id, name, description)

Create a card (e.g. a deal or task) in a stage of a Trengo board. The board id is in the board's URL in Trengo. Trengo: POST /boards/{boardId}/cards.

Input Schema

{
  "type": "object",
  "properties": {
    "board_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The board id."
    },
    "stage_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The stage id."
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "description": "The card's name."
    },
    "description": {
      "description": "The card's description.",
      "type": "string"
    }
  },
  "required": [
    "board_id",
    "stage_id",
    "name"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴trengo_update_board_card(board_id, card_id, name, stage_id, user_ids, ...)

Partially update a board card: rename it, move it to another stage, or set its users (owners) and contacts (leads). user_ids / contact_ids replace the current sets. Trengo: PUT /boards/{boardId}/cards/{cardId}.

Input Schema

{
  "type": "object",
  "properties": {
    "board_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The board id."
    },
    "card_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "The card id."
    },
    "name": {
      "description": "The card's new name.",
      "type": "string"
    },
    "stage_id": {
      "description": "Move the card to this stage.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "user_ids": {
      "description": "Trengo user ids on the card, e.g. deal owners (replaces the set).",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    },
    "contact_ids": {
      "description": "Trengo contact ids on the card, e.g. leads (replaces the set).",
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      }
    }
  },
  "required": [
    "board_id",
    "card_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}

Community

Rate this Server

Evidence

Recent observations

verifiedversion not recorded24 tools
verifiedversion not recorded24 tools