mcp-server-rt
OfficialServer Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| RT_URL | Yes | Base URL of your RT instance (e.g. https://rt.example.com) | |
| RT_TOKEN | Yes | RT authentication token |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {} |
| prompts | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| search_ticketsA | Search for tickets using RT's TicketSQL query language. TicketSQL has non-obvious syntax — consult get_ticketsql_grammar before writing any query involving Status, date conditions, custom fields, or special values. Key syntax notes: Status has meta-values Active and Inactive that match all active/inactive statuses across lifecycles (e.g. Status = 'Active' rather than Status = 'open'). Basic examples: "Queue = 'General' AND Owner = 'Nobody'", "Subject LIKE 'login'". A useful default field set is sent automatically, with Queue and Owner expanded to names, so pass fields or subfields only when the context calls for a different set. |
| get_ticketA | Get detailed information about a specific ticket by its ID |
| get_transactionA | Get the full details of a single transaction including decoded message content. Use this after get_ticket_history to read the actual text of a reply or comment. |
| get_ticket_historyA | Get the transaction history for a ticket. Returns a list of transactions (comments, replies, status changes, etc.). Most entries name the field changed in Field and carry its old and new values. Two kinds do not. An owner or watcher change (Type SetWatcher, AddWatcher or DelWatcher) puts a numeric user ID in OldValue and NewValue, and no tool here turns one into a name — describe the change without inventing one. A custom field change (Type CustomField) puts the field's numeric ID in Field rather than its name, which get_queue_fields maps back; its OldValue and NewValue hold the values as usual, while OldReference and NewReference are row IDs that nothing here resolves. |
| get_ticket_attachmentsA | List all attachments on a ticket (names, MIME types, sizes, IDs) |
| get_attachmentA | Retrieve a single attachment by ID. Text content is returned decoded; binary content is returned as MIME Base64. Use get_ticket_attachments or get_transaction to find attachment IDs. |
| save_attachmentA | Save an attachment to a local file. The MCP server writes the file directly, so this works on any platform. If path is a directory, the original filename is used. |
| get_queueA | Get details about a specific queue by ID or name |
| list_queuesB | List all available queues |
| get_ticketsql_grammarA | Returns the TicketSQL grammar reference for RT 6.0.3. Consult this before writing any TicketSQL query — especially for Status conditions, date/time fields, custom fields, and link fields where syntax is non-obvious. |
| get_current_userA | Get the RT user account associated with the configured auth token. Use this to determine who "I" or "me" refers to when the user asks to assign tickets to themselves, find their own tickets, etc. |
| lookup_userB | Search for RT users by name or email address |
| get_queue_fieldsA | Get custom fields (with types and allowed values) and lifecycle name for a queue. Returns three separate groups, because RT applies custom fields to three different things: CustomFields are set on tickets in the queue (this is what you want when creating or updating a ticket), QueueCustomFields are set on the queue itself and include the queue's CurrentValues (RTIR uses these for RTIR Constituency and RTIR default WHOIS server), and TransactionCustomFields are set on individual comments and replies. When the user asks what custom fields a queue has, report all three groups and say which is which. Each field carries a ContentFormat saying how its value is rendered: "html" (send markup; a bare newline shows nothing), "plain-text-multiline" (send plain text; newlines become line breaks), "plain-text" (shown exactly as typed), "wikitext" (wiki markup), "file" (an uploaded image or attachment rather than text), "date", or "datetime" (send local time; RT reads it in the user's timezone). Check it before writing a multi-line or formatted value. Every applied field is always listed. If RT permits seeing that a field is applied but not reading the field itself, the entry carries id, Name and a DetailsUnavailable message explaining why; a QueueCustomFields entry still carries its CurrentValues too. The field is still applied to the queue either way, and a field in CustomFields can still be set on a ticket. Tell the user which fields came back without details rather than reporting them as missing. |
| create_ticketA | Create a new ticket in RT |
| update_ticketA | Update an existing ticket. Pass each property to change as a top-level parameter (e.g. Due, Status, Owner) — do NOT use a nested "fields" object. Links are changed only with the Add/Delete fields below: a bare relation name such as RefersTo, Parent or Children is refused, because RT would treat it as the complete list for that relation and silently remove every other link of the type. |
| add_commentA | Add an internal comment to a ticket (not visible to the requestor) |
| add_replyA | Send a reply (correspondence) on a ticket, visible to the requestor |
| create_queueA | Create a new RT queue. Returns the new queue ID and URL. After creating, use manage_queue_watchers to set up Cc/AdminCc members, grant_rights to configure permissions, and create_custom_field + apply_custom_field to add custom fields. |
| update_queueA | Update an existing queue's settings (name, description, lifecycle, email addresses, etc.). To manage watchers (Cc, AdminCc), use manage_queue_watchers instead. Each field is applied independently and the call succeeds even when some of them fail, so check the returned messages for every change you asked for — see PARTIAL UPDATES. |
| manage_queue_watchersA | Set the members of a queue role (Cc, AdminCc, or a multi-value custom role). Pass the complete member list — it replaces existing members. Members can be usernames, email addresses, or user/group IDs. To add a group by name, prefix it with "group:" (e.g. "group:Facilities Managers"); a bare name is looked up as a user and fails. Only user-defined groups resolve this way — not system groups like Everyone, and not role groups. Single-value custom roles (like Owner) cannot have queue-level members. A member that cannot be resolved is skipped and reported in the returned messages while the call still succeeds, so confirm every member you passed was actually added — see PARTIAL UPDATES. |
| list_groupsA | List user-defined groups. Returns group names, descriptions, and IDs. Use this to check for existing groups before creating new ones. |
| get_groupA | Get details about a specific group by numeric ID |
| create_groupA | Create a new user-defined group. After creating, use add_group_members to add users and grant_rights to give the group permissions on queues. |
| list_group_membersA | List the members of a group. RT returns only an id and a type (user or group) per member — this collection ignores a fields parameter, so names cannot be requested. get_group returns the same membership already resolved: a user member carries its username as its id, a group member its numeric id. Use get_group when the user needs members named rather than listed as bare ids. |
| add_group_membersA | Add one or more users to a group. Members are specified by user ID. Use lookup_user to find user IDs by name or email. Adding a user who is already a member has no effect. |
| remove_group_memberB | Remove a user from a group |
| list_lifecyclesA | List all available lifecycles. Each lifecycle defines the statuses and transitions for tickets in queues that use it. |
| get_lifecycleA | Get a lifecycle's full configuration including statuses (initial, active, inactive), allowed transitions, default statuses, and which queues/catalogs use it. |
| create_lifecycleA | Create a new lifecycle. Optionally clone an existing one as a starting point. A lifecycle defines the statuses and transitions for tickets in queues that use it. After creating, use update_lifecycle to customize statuses and transitions. |
| update_lifecycleA | Update a lifecycle's configuration. Pass the full lifecycle definition including initial, active, inactive status arrays, transitions, rights, actions, and defaults. This REPLACES the stored configuration — any key you omit is dropped, including keys inherited from a create_lifecycle clone. RT fills in a missing defaults.on_create from the first initial status, and falls back to ModifyTicket — DeleteTicket for deleted — where rights are missing, but it does that in memory as it loads the config: neither key reappears in get_lifecycle, so one absent there is a working default rather than damage to repair. Omitted actions, colors, status_metadata and transition_metadata are simply lost. Cloning "default" inherits a full set of metadata, so omitting those two keys here silently strips the descriptions from every status. Use get_lifecycle first to get the current config, then modify and send the whole thing back. The lifecycle is validated before saving; any warning fails the update with a 400. |
| validate_lifecycleA | Check a lifecycle definition without saving it. Takes the same payload as update_lifecycle and reports whether RT would accept it, with a warning for each problem found (unknown statuses, malformed transitions or actions, and so on). Use this to dry-run a custom lifecycle before writing it, since update_lifecycle rejects the whole payload if anything is wrong. RT checks only the payload sent: it never reads the lifecycle the name refers to, which is why the name need not exist yet and why it does nothing but label the warnings. So send a complete definition rather than the part being changed — transitions on their own report every status in them as nonexistent, including statuses the named lifecycle already has. Read the current definition with get_lifecycle, change it, and validate the whole thing. |
| delete_lifecycleA | Delete a lifecycle. Fails if any queue or catalog still uses it — reassign those to another lifecycle first (get_lifecycle reports them under used_by). Useful for cleaning up a lifecycle created by mistake. |
| update_lifecycle_mapsA | Update the status mappings between this lifecycle and other lifecycles. Maps define how statuses translate when tickets move between queues with different lifecycles. Format: {"lifecycle_a -> lifecycle_b": {"status_in_a": "status_in_b", ...}} |
| get_available_rightsA | Get the rights that can be granted on a queue, custom field, group, class, catalog, or globally. Returns rights grouped by category, and which categories come back depends on the object: RT's own are General, Staff and Admin, and a group offers only some of them. A queue — and the global object — also carries a Status category, holding one right for each status transition a lifecycle reserves behind a named right, so that is where a custom sign-off right appears once a lifecycle defines it. Read the categories from the response rather than assuming a fixed set. |
| list_rightsA | List rights currently granted on a queue, custom field, group, class, catalog, or globally. Can filter by user or group. |
| grant_rightsA | Grant rights on a queue, custom field, group, class, catalog, or globally. Specify a single right with Right + (User or Group), or pass an array of grants for bulk operation. Returns 409 if a right is already granted. |
| revoke_rightA | Revoke a right from a user or group on a queue, custom field, group, class, catalog, or globally. The principal goes in the URL path here rather than a request body, and RT resolves a name there only for a user: a group has to be given as its numeric ID, and a group name answers 404 even though grant_rights resolves that same name. RT answers 404 for a right that was never granted too, so a group name passed here looks like nothing to revoke rather than a bad parameter. Use get_group or list_groups to get the ID. |
| search_custom_fieldsA | Search for existing custom fields. Use this before creating new ones to avoid duplicates. Search by Name, Type, LookupType, or any combination. Returns matching custom fields with their IDs, types, and descriptions. |
| create_custom_fieldA | Create a new custom field. After creating, use apply_custom_field to apply it to specific queues or globally. Use add_custom_field_value to add values to Select-type fields. |
| add_custom_field_valueA | Add one or more selectable values to a custom field (for Select, Autocomplete, etc. types). Pass a single value with Name, or multiple values with the Values array. |
| apply_custom_fieldA | Apply a custom field to a specific object or globally. The CF's LookupType determines what kind of object it can apply to (e.g. a ticket CF applies to queues). Use ObjectId 0 to apply globally. Note: applying globally removes all specific object applications. |
| remove_custom_field_applicationA | Remove a custom field from a specific object or remove its global application. Use ObjectId 0 to remove the global application. |
| list_custom_field_applicationsA | List which objects a custom field is currently applied to, including whether it is applied globally. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| create-queue | Interactive workflow consultant that helps RT admins design and create a new queue — discovers the workflow, recommends configuration, then executes the setup using RT tools. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/bestpractical/mcp-server-rt'
If you have feedback or need assistance with the MCP directory API, please join our Discord server