MCP Tools Reference
Complete reference for all tools, resources, and slash commands (prompts) exposed by the Alloy MCP server. For setup instructions, see the MCP Guide.
Table of Contents
- Tools vs Slash Commands
- Tools Overview
- Connectivity —
ping,whoami - Tickets —
create_ticket,get_ticket,search_tickets,update_ticket,transition_ticket,batch_transition,batch_update_tickets,assign_ticket,get_my_tickets,delete_ticket - Comments —
add_comment,list_comments,update_comment,delete_comment - Label Management —
create_label,list_labels,add_ticket_label,remove_ticket_label,get_label,update_label,delete_label - Tag Management —
set_tags,get_tags,delete_tag,search_by_tag - Project Management —
create_project,list_projects,get_project,update_project,delete_project - Sprint Lifecycle —
create_sprint,list_sprints,update_sprint,start_sprint,complete_sprint,get_sprint_burndown,get_sprint,delete_sprint - Team Management —
create_team,list_teams,delete_team - Workflow Management —
create_workflow,list_workflows,update_workflow,get_workflow,delete_workflow - Projects & Sprints —
get_project_summary - Organization & Access —
list_members,create_invite,list_invites,add_project_member,remove_project_member,list_project_members,create_api_key,list_api_keys,delete_api_key - Activity —
get_ticket_activity - Time Tracking —
log_time,get_time_entry,update_time_entry,delete_time_entry,list_time_entries - Finance & Reporting —
get_time_report,get_capitalization_report,submit_time_entry,approve_time_entry,get_capitalization_export - Data Export & Import —
export_data,import_data - Resources
- Enums Reference
- Pagination
- Slash Commands (Prompts)
- Error Handling
Tools vs Slash Commands
The Alloy MCP server exposes two types of capabilities:
- Tools are functions the AI assistant calls on your behalf (e.g.,
create_ticket,search_tickets). You don’t invoke them directly — the assistant decides when to use them based on your request. - Slash commands (MCP prompts) are pre-built workflows you invoke explicitly by typing a command like
/alloy:standup. They provide the assistant with structured instructions to accomplish a multi-step task using one or more tools. Think of them as recipes that orchestrate several tool calls into a coherent workflow.
Tools Overview
The Alloy MCP server exposes 69 tools organized into fourteen categories:
| Category | Tools |
|---|---|
| Connectivity | ping, whoami |
| Tickets | create_ticket, get_ticket, search_tickets, update_ticket, transition_ticket, batch_transition, batch_update_tickets, assign_ticket, get_my_tickets, delete_ticket |
| Comments | add_comment, list_comments, update_comment, delete_comment |
| Label Management | create_label, list_labels, add_ticket_label, remove_ticket_label, get_label, update_label, delete_label |
| Tag Management | set_tags, get_tags, delete_tag, search_by_tag |
| Project Management | create_project, list_projects, get_project, update_project, delete_project |
| Sprint Lifecycle | create_sprint, list_sprints, update_sprint, start_sprint, complete_sprint, get_sprint_burndown, get_sprint, delete_sprint |
| Team Management | create_team, list_teams, delete_team |
| Workflow Management | create_workflow, list_workflows, update_workflow, get_workflow, delete_workflow |
| Projects & Sprints | get_project_summary |
| Organization & Access | list_members, create_invite, list_invites, add_project_member, remove_project_member, list_project_members, create_api_key, list_api_keys, delete_api_key |
| Activity | get_ticket_activity |
| Time Tracking | log_time, get_time_entry, update_time_entry, delete_time_entry, list_time_entries |
| Finance & Reporting | get_time_report, get_capitalization_report, submit_time_entry, approve_time_entry, get_capitalization_export |
Connectivity
ping
Check connectivity to the Alloy API.
Parameters: None
Example prompt:
Check the Alloy connection
Expected response:
Alloy MCP connected to http://localhost:3000 as alice@example.com (org 550e8400-e29b-41d4-a716-446655440000)
whoami
Get the current authenticated user’s identity.
Parameters: None
Example prompt:
Who am I logged in as?
Expected response:
{
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"org_id": "660e8400-e29b-41d4-a716-446655440000",
"email": "alice@example.com",
"role": "Admin"
}
Tickets
create_ticket
Create a new ticket in a project. Returns the created ticket with its auto-assigned ticket number.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
project_id | string | yes | UUID of the project |
title | string | yes | Ticket title (1–500 characters) |
description | string | no | Ticket description (markdown supported) |
status | string | no | Initial status (defaults to Backlog). Values are defined by the project’s workflow; see Status Values |
priority | string | no | Priority level (defaults to None) |
assignee_id | string | no | UUID of the user to assign |
See Status Values and Priority Values for reference values.
Example prompt:
Create a ticket in project 550e8400-… titled “Fix login timeout” with priority High
Expected response:
{
"id": "770e8400-e29b-41d4-a716-446655440000",
"ticket_number": 42,
"project_id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Fix login timeout",
"description": null,
"status": "Backlog",
"priority": "High",
"assignee_id": null,
"reporter_id": "660e8400-e29b-41d4-a716-446655440000",
"created_at": "2026-03-29T10:00:00Z",
"updated_at": "2026-03-29T10:00:00Z"
}
get_ticket
Get a ticket by its UUID. Returns full ticket details including status, priority, and assignee.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
ticket_id | string | yes | UUID of the ticket |
Example prompt:
Get the details for ticket 770e8400-…
Expected response:
{
"id": "770e8400-e29b-41d4-a716-446655440000",
"ticket_number": 42,
"project_id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Fix login timeout",
"description": "Users experience a 30s timeout on the login page.",
"status": "InProgress",
"priority": "High",
"assignee_id": "660e8400-e29b-41d4-a716-446655440000",
"reporter_id": "660e8400-e29b-41d4-a716-446655440000",
"created_at": "2026-03-29T10:00:00Z",
"updated_at": "2026-03-29T11:30:00Z"
}
search_tickets
Search tickets in a project. Supports filtering by status, priority, and assignee. Returns paginated results.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
project_id | string | yes | UUID of the project |
status | string | no | Filter by status (workflow-defined; see Status Values) |
priority | string | no | Filter by priority |
assignee_id | string | no | Filter by assignee UUID |
limit | integer | no | Max results per page (1–100, default 50) |
cursor | string | no | Pagination cursor from previous response |
See Pagination for details on cursor-based paging.
Example prompt:
Search for all high-priority in-progress tickets in project 550e8400-…
Expected response:
{
"data": [
{
"id": "770e8400-...",
"ticket_number": 42,
"title": "Fix login timeout",
"status": "InProgress",
"priority": "High",
"assignee_id": "660e8400-..."
}
],
"next_cursor": null,
"has_more": false
}
update_ticket
Update a ticket’s fields. Only provided fields are changed; omitted fields remain untouched.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
ticket_id | string | yes | UUID of the ticket |
title | string | no | New title (1–500 characters) |
description | string | no | New description (markdown supported, or null to clear) |
status | string | no | New status (workflow-defined; see Status Values) |
priority | string | no | New priority |
assignee_id | string | no | UUID of user to assign, or null to unassign |
Example prompt:
Update ticket 770e8400-… to set priority to Urgent and add a description
Expected response:
{
"id": "770e8400-e29b-41d4-a716-446655440000",
"ticket_number": 42,
"title": "Fix login timeout",
"description": "Critical path blocker for v2.0 release.",
"status": "InProgress",
"priority": "Urgent",
"assignee_id": "660e8400-...",
"updated_at": "2026-03-29T12:00:00Z"
}
transition_ticket
Transition a ticket to a new status. Validates against the project’s workflow rules. On error, returns the list of available transitions from the current status.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
ticket_id | string | yes | UUID of the ticket |
to_status | string | yes | Target status — must be a valid transition in the project’s workflow (e.g., InProgress, InReview, Done in the default workflow) |
Example prompt:
Move ticket 770e8400-… to InReview
Expected response (success):
{
"id": "770e8400-...",
"status": "InReview",
"updated_at": "2026-03-29T14:00:00Z"
}
Expected response (invalid transition):
Transition failed: Cannot transition from Backlog to Done. Current status: Backlog. Available transitions: [Todo, Cancelled]
batch_transition
Transition multiple tickets to the same status in one call. Each ticket is validated individually against its project workflow. Returns per-ticket results: succeeded and failed arrays. Useful for sprint completion (move all to Done).
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
ticket_ids | string[] | yes | Array of ticket UUIDs to transition |
to_status | string | yes | Target status for all tickets |
Example prompt:
Move tickets 770e8400-… and 880e9500-… to Done
Expected response:
{
"succeeded": [
{"id": "770e8400-...", "status": "Done"},
{"id": "880e9500-...", "status": "Done"}
],
"failed": []
}
batch_update_tickets
Update multiple tickets at once with the same field values. Pass ticket_ids and any combination of fields to update: status, priority, assignee_id, sprint_id, title, description. Returns the count of updated tickets.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
ticket_ids | string[] | yes | Array of ticket UUIDs to update |
title | string | no | New title for all tickets (1–500 characters) |
description | string | no | New description (markdown supported, or null to clear) |
status | string | no | New status for all tickets |
priority | string | no | New priority: None, Low, Medium, High, Urgent |
assignee_id | string | no | UUID of user to assign, or null to unassign |
sprint_id | string | no | UUID of sprint to assign, or null to unassign |
Example prompt:
Set priority to High on tickets 770e8400-… and 880e9500-…
Expected response:
{
"updated": 2
}
assign_ticket
Assign a ticket to a user by UUID, or unassign by omitting assignee_id. A convenience wrapper around ticket update.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
ticket_id | string | yes | UUID of the ticket |
assignee_id | string | no | UUID of user to assign to, or omit to unassign |
Example prompt:
Assign ticket 770e8400-… to user 660e8400-…
Expected response:
{
"id": "770e8400-...",
"assignee_id": "660e8400-...",
"updated_at": "2026-03-29T14:30:00Z"
}
get_my_tickets
Get all tickets assigned to the current authenticated user in a project. Returns paginated results.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
project_id | string | yes | UUID of the project |
status | string | no | Filter by status (workflow-defined; see Status Values) |
limit | integer | no | Max results per page (1–100, default 50) |
cursor | string | no | Pagination cursor from previous response |
Example prompt:
Show me my tickets in project 550e8400-…
Expected response:
{
"data": [
{
"id": "770e8400-...",
"ticket_number": 42,
"title": "Fix login timeout",
"status": "InProgress",
"priority": "High"
}
],
"next_cursor": null,
"has_more": false
}
delete_ticket
Delete a ticket by its UUID. Returns 204 No Content on success. Fails with 409 Conflict if the ticket has comments — use cascade=true to force deletion. Use dry_run=true with cascade to preview what would be deleted.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
ticket_id | string | yes | UUID of the ticket to delete |
cascade | boolean | no | Force-delete the ticket and all its comments (default false) |
dry_run | boolean | no | Preview what would be deleted without actually deleting (requires cascade=true) |
Example prompt:
Delete ticket 770e8400-…
Expected response:
deleted successfully.
Comments
add_comment
Add a comment to a ticket. The comment author is set to the authenticated user. Supports threaded replies via parent_comment_id.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
ticket_id | string | yes | UUID of the ticket |
body | string | yes | Comment body (markdown supported) |
parent_comment_id | string | no | UUID of parent comment for threaded replies |
Example prompt:
Add a comment to ticket 770e8400-… saying “Reproduced on staging, investigating now”
Expected response:
{
"id": "880e8400-...",
"ticket_id": "770e8400-...",
"author_id": "660e8400-...",
"body": "Reproduced on staging, investigating now",
"parent_comment_id": null,
"created_at": "2026-03-29T15:00:00Z"
}
list_comments
List comments on a ticket. Returns paginated results ordered by creation time.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
ticket_id | string | yes | UUID of the ticket |
limit | integer | no | Max results per page (1–100, default 20) |
cursor | string | no | Pagination cursor from previous response |
Example prompt:
Show comments on ticket 770e8400-…
Expected response:
{
"data": [
{
"id": "880e8400-...",
"author_id": "660e8400-...",
"body": "Reproduced on staging, investigating now",
"parent_comment_id": null,
"created_at": "2026-03-29T15:00:00Z"
}
],
"next_cursor": null,
"has_more": false
}
update_comment
Update a comment. Only the comment author or an Admin can edit a comment.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
comment_id | string | yes | UUID of the comment to update |
body | string | yes | New comment body text (markdown supported) |
Example prompt:
Update comment 880e8400-… to say “Actually this is a duplicate of #45”
Expected response:
{
"id": "880e8400-...",
"ticket_id": "770e8400-...",
"author_id": "660e8400-...",
"body": "Actually this is a duplicate of #45",
"parent_comment_id": null,
"created_at": "...",
"updated_at": "..."
}
delete_comment
Delete a comment. Only the comment author or an Admin can delete a comment. Returns 204 No Content on success.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
comment_id | string | yes | UUID of the comment to delete |
Example prompt:
Delete comment 880e8400-…
Expected response:
deleted successfully.
Label Management
create_label
Create a new label in the current organization. Labels are org-scoped and can be assigned to tickets across projects.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
name | string | yes | The label name (e.g. “bug”, “feature”, “urgent”) |
color | string | yes | Hex color code (e.g. “#FF5733”). Must be 4–7 characters |
Example prompt:
Create a “bug” label with red color #FF5733
Expected response:
{
"id": "...",
"org_id": "...",
"name": "bug",
"color": "#FF5733",
"created_at": "...",
"updated_at": "..."
}
list_labels
List all labels in the current organization.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | no | Maximum results to return (1–100). Defaults to 20 |
cursor | string | no | Cursor for pagination from a previous response |
Example prompt:
List all labels in the organization
Expected response:
{
"data": [
{
"id": "...",
"org_id": "...",
"name": "bug",
"color": "#FF5733",
"created_at": "...",
"updated_at": "..."
}
],
"has_more": false
}
add_ticket_label
Add a label to a ticket. The label must already exist in the organization. A ticket can have multiple labels.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
ticket_id | string | yes | UUID of the ticket to add the label to |
label_id | string | yes | UUID of the label to add |
Example prompt:
Add the “bug” label to ticket 550e8400-e29b-41d4-a716-446655440000
Expected response:
{
"id": "...",
"org_id": "...",
"name": "bug",
"color": "#FF5733",
"created_at": "...",
"updated_at": "..."
}
remove_ticket_label
Remove a label from a ticket. Does not delete the label itself, only removes the association.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
ticket_id | string | yes | UUID of the ticket to remove the label from |
label_id | string | yes | UUID of the label to remove |
Example prompt:
Remove the “bug” label from ticket 550e8400-e29b-41d4-a716-446655440000
Expected response:
deleted successfully.
get_label
Get a single label by its UUID. Returns the label’s name, color, and timestamps.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
label_id | string | yes | UUID of the label |
Example prompt:
Get label details for label abc123-…
Expected response:
{
"id": "...",
"org_id": "...",
"name": "bug",
"color": "#FF5733",
"created_at": "...",
"updated_at": "..."
}
update_label
Update a label. Only provided fields are changed.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
label_id | string | yes | UUID of the label to update |
name | string | no | New label name |
color | string | no | New hex color code |
Example prompt:
Rename label abc123-… to “critical” and change color to #FF0000
Expected response:
{
"id": "...",
"org_id": "...",
"name": "critical",
"color": "#FF0000",
"created_at": "...",
"updated_at": "..."
}
delete_label
Delete a label by its UUID. Returns 204 No Content on success. Fails with 409 Conflict if the label is still attached to tickets — use cascade=true to force deletion.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
label_id | string | yes | UUID of the label to delete |
cascade | boolean | no | Force-delete the label even if attached to tickets (default false) |
Example prompt:
Delete label abc123-…
Expected response:
deleted successfully.
Tag Management
set_tags
Set one or more key–value tags on an entity. Supported entity types: project, ticket, user, team, time_entry. If a tag key already exists on the entity its value is updated (upsert). Returns all tags currently set on the entity.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
entity_type | string | yes | The entity type to tag. One of: project, ticket, user, team, time_entry |
entity_id | string | yes | UUID of the entity to tag |
tags | array | yes | Array of {key, value} objects. Existing keys are updated |
Example prompt:
Tag ticket 770e8400-… with environment=production and team=platform
{
"entity_type": "ticket",
"entity_id": "770e8400-...",
"tags": [
{"key": "environment", "value": "production"},
{"key": "team", "value": "platform"}
]
}
Expected response:
{
"data": [
{
"id": "...",
"org_id": "...",
"entity_type": "ticket",
"entity_id": "770e8400-...",
"key": "environment",
"value": "production",
"created_at": "...",
"updated_at": "..."
},
{
"id": "...",
"org_id": "...",
"entity_type": "ticket",
"entity_id": "770e8400-...",
"key": "team",
"value": "platform",
"created_at": "...",
"updated_at": "..."
}
]
}
get_tags
Get all tags currently set on an entity. Supported entity types: project, ticket, user, team, time_entry.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
entity_type | string | yes | The entity type. One of: project, ticket, user, team, time_entry |
entity_id | string | yes | UUID of the entity to get tags for |
Example prompt:
Get all tags for project abc12345-…
Expected response:
{
"data": [
{
"id": "...",
"org_id": "...",
"entity_type": "project",
"entity_id": "abc12345-...",
"key": "cost_center",
"value": "eng-001",
"created_at": "...",
"updated_at": "..."
}
]
}
delete_tag
Delete a tag by key from an entity. Supported entity types: project, ticket, user, team, time_entry. Removes only the specified tag key; other tags on the entity are unchanged.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
entity_type | string | yes | The entity type. One of: project, ticket, user, team, time_entry |
entity_id | string | yes | UUID of the entity to delete a tag from |
tag_key | string | yes | The tag key to delete |
Example prompt:
Delete the “environment” tag from user 550e8400-…
Expected response:
deleted successfully.
search_by_tag
Search for entities with a specific tag key–value pair. Returns paginated entity IDs and types that match.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
key | string | yes | The tag key to search for (e.g. “environment”) |
value | string | yes | The tag value to search for (e.g. “production”) |
limit | integer | no | Maximum results to return (1–100, default 20) |
cursor | string | no | Cursor for pagination from a previous response |
Example prompt:
Find all entities tagged environment=production
Expected response:
{
"data": [
{
"id": "...",
"org_id": "...",
"entity_type": "ticket",
"entity_id": "...",
"key": "environment",
"value": "production",
"created_at": "...",
"updated_at": "..."
},
{
"id": "...",
"org_id": "...",
"entity_type": "project",
"entity_id": "...",
"key": "environment",
"value": "production",
"created_at": "...",
"updated_at": "..."
}
],
"has_more": false,
"next_cursor": null
}
Project Management
create_project
Create a new project in the current organization. Returns the full project object with its auto-generated UUID.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
key | string | yes | Unique short key for the project (1–10 characters, e.g. ALLOY) |
name | string | yes | Project name (1–255 characters) |
description | string | no | Project description |
team_id | string | no | UUID of the team that owns this project |
budget_cents | integer | no | Budget amount in cents (e.g. 100000 = $1,000.00) |
budget_period | string | no | Budget period: Monthly, Quarterly, Yearly, or Fixed |
Example prompt:
Create a project with key “ROCKET” named “Rocket Launch” with description “Space exploration project”
Expected response:
{
"id": "990e8400-e29b-41d4-a716-446655440000",
"org_id": "660e8400-...",
"team_id": null,
"workflow_id": null,
"key": "ROCKET",
"name": "Rocket Launch",
"description": "Space exploration project",
"ticket_counter": 0,
"capitalization_type": null,
"development_phase": null,
"cost_center_id": null,
"amortization_months": null,
"budget_cents": null,
"budget_period": null,
"created_at": "2026-03-30T10:00:00Z",
"updated_at": "2026-03-30T10:00:00Z"
}
list_projects
List all projects in the current organization. Returns paginated results.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | no | Max results per page (1–100, default 20) |
cursor | string | no | Pagination cursor from previous response |
See Pagination for details on cursor-based paging.
Example prompt:
List all projects
Expected response:
{
"items": [
{
"id": "990e8400-...",
"org_id": "660e8400-...",
"key": "ROCKET",
"name": "Rocket Launch",
"description": "Space exploration project",
"ticket_counter": 0,
"created_at": "2026-03-30T10:00:00Z",
"updated_at": "2026-03-30T10:00:00Z"
}
],
"next_cursor": null,
"has_more": false
}
get_project
Get a single project by its UUID. Returns full project details including key, name, description, team, and budget info.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
project_id | string | yes | UUID of the project |
Example prompt:
Get project 990e8400-…
Expected response:
{
"id": "990e8400-e29b-41d4-a716-446655440000",
"org_id": "660e8400-...",
"team_id": null,
"workflow_id": null,
"key": "ROCKET",
"name": "Rocket Launch",
"description": "Space exploration project",
"ticket_counter": 5,
"capitalization_type": null,
"development_phase": null,
"cost_center_id": null,
"amortization_months": null,
"budget_cents": null,
"budget_period": null,
"created_at": "2026-03-30T10:00:00Z",
"updated_at": "2026-03-30T11:00:00Z"
}
update_project
Update a project’s fields. Only provided fields are changed; omitted fields remain untouched. Pass null to clear optional fields.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
project_id | string | yes | UUID of the project to update |
name | string | no | New project name (1–255 characters) |
description | string | null | no | New description, or null to clear |
team_id | string | null | no | UUID of team that owns this project, or null to clear |
budget_cents | integer | null | no | Budget in cents (e.g. 100000 = $1,000.00), or null to clear |
budget_period | string | null | no | Monthly, Quarterly, Yearly, Fixed, or null to clear |
capitalization_type | string | null | no | CapEx or OpEx, or null to clear |
development_phase | string | null | no | Planning, Development, Maintenance, Sunset, or null to clear |
cost_center_id | string | null | no | Cost center ID string, or null to clear |
amortization_months | integer | null | no | Amortization period in months, or null to clear |
Example prompt:
Rename project 990e8400-… to “Rocket Launch v2” and set budget to $5,000 monthly
Expected response:
{
"id": "990e8400-e29b-41d4-a716-446655440000",
"org_id": "660e8400-...",
"team_id": null,
"workflow_id": null,
"key": "ROCKET",
"name": "Rocket Launch v2",
"description": "Space exploration project",
"ticket_counter": 5,
"capitalization_type": null,
"development_phase": null,
"cost_center_id": null,
"amortization_months": null,
"budget_cents": 500000,
"budget_period": "Monthly",
"created_at": "2026-03-30T10:00:00Z",
"updated_at": "2026-03-30T12:00:00Z"
}
delete_project
Delete a project by ID. By default, fails with dependency info if the project has tickets or sprints. Use cascade mode to delete all dependents, or dry-run to preview.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
project_id | string | yes | UUID of the project to delete |
cascade | boolean | no | If true, delete all dependent tickets, sprints, and comments (default false) |
dry_run | boolean | no | If true (with cascade), preview what would be deleted without actually deleting (default false) |
Example prompt:
Delete project 990e8400-… and all its tickets
Expected response (success with cascade):
Deleted project 990e8400-... and all dependents
Expected response (blocked, no cascade):
{
"error": {
"code": "conflict",
"message": "Cannot delete project: has dependents",
"details": {
"project_id": "990e8400-...",
"dependents": {
"tickets": 5,
"sprints": 2,
"comments": 12
}
}
}
}
Expected response (cascade dry-run):
{
"project_id": "990e8400-...",
"dependents": {
"tickets": 5,
"sprints": 2,
"comments": 12
}
}
Sprint Lifecycle
create_sprint
Create a new sprint in a project. Requires a name, start date, and end date.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
project_id | string | yes | UUID of the project |
name | string | yes | Sprint name (e.g. “Sprint 1”) |
goal | string | no | Sprint goal describing what the team aims to accomplish |
start_date | string | yes | Start date in YYYY-MM-DD format |
end_date | string | yes | End date in YYYY-MM-DD format |
Example prompt:
Create a two-week sprint starting March 30 in project 550e8400-…
Expected response:
{
"id": "...",
"project_id": "550e8400-...",
"name": "Sprint 1",
"goal": "Complete onboarding flow",
"start_date": "2026-03-30",
"end_date": "2026-04-13",
"status": "Planned",
"created_at": "...",
"updated_at": "..."
}
list_sprints
List sprints for a project. Returns paginated results with sprint details.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
project_id | string | yes | UUID of the project |
limit | integer | no | Maximum results to return (1–100, default 20) |
cursor | string | no | Cursor from a previous response for pagination |
Example prompt:
List sprints for project 550e8400-…
Expected response:
{
"data": [
{
"id": "...",
"project_id": "550e8400-...",
"name": "Sprint 1",
"goal": "Complete onboarding flow",
"start_date": "2026-03-30",
"end_date": "2026-04-13",
"status": "Active",
"created_at": "...",
"updated_at": "..."
}
],
"next_cursor": null
}
update_sprint
Update a sprint’s details. All fields are optional — only provided fields are changed.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
sprint_id | string | yes | UUID of the sprint to update |
name | string | no | New sprint name |
goal | string | no | New sprint goal (or null to clear) |
start_date | string | no | New start date in YYYY-MM-DD format |
end_date | string | no | New end date in YYYY-MM-DD format |
Example prompt:
Rename sprint abc123 to “Sprint 2 - API Polish” and update the goal
Expected response:
{
"id": "...",
"project_id": "...",
"name": "Sprint 2 - API Polish",
"goal": "Polish all API endpoints",
"start_date": "2026-03-30",
"end_date": "2026-04-13",
"status": "Planned",
"created_at": "...",
"updated_at": "..."
}
start_sprint
Start a sprint by transitioning its status from Planned to Active. Fails if the sprint is not in Planned status.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
sprint_id | string | yes | UUID of the sprint to start |
Example prompt:
Start sprint abc123
Expected response:
{
"id": "...",
"project_id": "...",
"name": "Sprint 1",
"goal": "...",
"start_date": "2026-03-30",
"end_date": "2026-04-13",
"status": "Active",
"created_at": "...",
"updated_at": "..."
}
complete_sprint
Complete a sprint by transitioning its status from Active to Completed. Fails if the sprint is not in Active status.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
sprint_id | string | yes | UUID of the sprint to complete |
Example prompt:
Complete sprint abc123
Expected response:
{
"id": "...",
"project_id": "...",
"name": "Sprint 1",
"goal": "...",
"start_date": "2026-03-30",
"end_date": "2026-04-13",
"status": "Completed",
"created_at": "...",
"updated_at": "..."
}
get_sprint_burndown
Get burndown chart data for a sprint. Returns daily data points showing total, completed, and remaining story points or ticket counts over the sprint duration.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
sprint_id | string | yes | UUID of the sprint |
Example prompt:
Show me the burndown for sprint 990e8400-…
Expected response:
{
"sprint_id": "990e8400-...",
"data_points": [
{ "date": "2026-03-24", "total": 20, "completed": 0, "remaining": 20 },
{ "date": "2026-03-25", "total": 20, "completed": 3, "remaining": 17 },
{ "date": "2026-03-26", "total": 20, "completed": 7, "remaining": 13 }
]
}
get_sprint
Get a single sprint by its UUID. Returns sprint details including name, goal, start/end dates, and status.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
sprint_id | string | yes | UUID of the sprint |
Example prompt:
Get details for sprint 990e8400-…
Expected response:
{
"id": "990e8400-...",
"project_id": "550e8400-...",
"name": "Sprint 1",
"goal": "Complete onboarding flow",
"start_date": "2026-03-30",
"end_date": "2026-04-13",
"status": "Active",
"created_at": "...",
"updated_at": "..."
}
delete_sprint
Delete a sprint by its UUID. Returns 204 No Content on success. Fails with 409 Conflict if the sprint has tickets — use cascade=true to force deletion. Use dry_run=true with cascade to preview what would be deleted.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
sprint_id | string | yes | UUID of the sprint to delete |
cascade | boolean | no | Force-delete the sprint and unlink its tickets (default false) |
dry_run | boolean | no | Preview what would be deleted without actually deleting (requires cascade=true) |
Example prompt:
Delete sprint 990e8400-…
Expected response:
deleted successfully.
Team Management
create_team
Create a new team in the current organization. Teams group users and can own projects.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
name | string | yes | Team name |
description | string | no | Team description |
Example prompt:
Create a team called “Backend” with description “Backend engineering team”
Expected response:
{
"id": "...",
"org_id": "...",
"name": "Backend",
"description": "Backend engineering team",
"created_at": "...",
"updated_at": "..."
}
list_teams
List all teams in the current organization. Returns team name, description, and timestamps.
Parameters:
None.
Example prompt:
List all teams
Expected response:
{
"data": [
{
"id": "...",
"org_id": "...",
"name": "Backend",
"description": "Backend engineering team",
"created_at": "...",
"updated_at": "..."
}
],
"has_more": false,
"next_cursor": null
}
delete_team
Delete a team by its UUID. Returns 204 No Content on success. Fails with 409 Conflict if the team has members or projects — use cascade=true to force deletion. Use dry_run=true with cascade to preview what would be deleted.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
team_id | string | yes | UUID of the team to delete |
cascade | boolean | no | Force-delete the team and remove all associations (default false) |
dry_run | boolean | no | Preview what would be deleted without actually deleting (requires cascade=true) |
Example prompt:
Delete team abc123-…
Expected response:
deleted successfully.
Workflow Management
create_workflow
Create a new workflow in the current organization. A workflow defines custom statuses, allowed transitions between statuses, and an enforcement mode.
Enforcement Modes:
| Mode | Description |
|---|---|
none | Transitions are not enforced — tickets can move to any status freely (default) |
warn | Invalid transitions are allowed but produce a warning in the response |
strict | Only transitions defined in the workflow are allowed — invalid transitions are rejected with an error |
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | The workflow name (e.g. “Default”, “Bug Triage”) |
statuses | array | Yes | List of status objects, each with name (string) and category (“todo”, “in_progress”, or “done”) |
transitions | array | Yes | List of transition objects, each with from (string) and to (string) status names |
enforcement | string | No | Enforcement mode: “none” (default), “warn”, or “strict” |
Example prompt:
Create a workflow called “Bug Triage” with statuses Open (todo), Investigating (in_progress), and Fixed (done), with transitions from Open to Investigating and from Investigating to Fixed, enforcement set to warn
Expected response:
{
"id": "...",
"org_id": "...",
"name": "Bug Triage",
"statuses": [
{"name": "Open", "category": "todo"},
{"name": "Investigating", "category": "in_progress"},
{"name": "Fixed", "category": "done"}
],
"transitions": [
{"from": "Open", "to": "Investigating"},
{"from": "Investigating", "to": "Fixed"}
],
"enforcement": "warn",
"created_at": "...",
"updated_at": "..."
}
list_workflows
List all workflows in the current organization. Returns paginated results.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | No | Maximum number of results (1–100, default 20) |
cursor | string | No | Cursor from a previous next_cursor for pagination |
Example prompt:
List all workflows in the org
Expected response:
{
"data": [
{
"id": "...",
"org_id": "...",
"name": "Default",
"statuses": [
{"name": "Open", "category": "todo"},
{"name": "Done", "category": "done"}
],
"transitions": [
{"from": "Open", "to": "Done"}
],
"enforcement": "none",
"created_at": "...",
"updated_at": "..."
}
],
"has_more": false,
"next_cursor": null
}
update_workflow
Update an existing workflow’s fields. Only provided fields are changed.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
workflow_id | string | Yes | The UUID of the workflow to update |
name | string | No | New name for the workflow |
statuses | array | No | New list of statuses (replaces all existing) |
transitions | array | No | New list of transitions (replaces all existing) |
enforcement | string | No | New enforcement mode: “none”, “warn”, or “strict” |
Example prompt:
Update workflow wf-uuid-1 to use strict enforcement
Expected response:
{
"id": "...",
"org_id": "...",
"name": "Bug Triage",
"statuses": [
{"name": "Open", "category": "todo"},
{"name": "Investigating", "category": "in_progress"},
{"name": "Fixed", "category": "done"}
],
"transitions": [
{"from": "Open", "to": "Investigating"},
{"from": "Investigating", "to": "Fixed"}
],
"enforcement": "strict",
"created_at": "...",
"updated_at": "..."
}
get_workflow
Get a workflow by its UUID. Returns the workflow with name, statuses, transitions, and enforcement mode.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
workflow_id | string | yes | UUID of the workflow |
Example prompt:
Get workflow details for wf-uuid-1
Expected response:
{
"id": "...",
"org_id": "...",
"name": "Bug Triage",
"statuses": [
{"name": "Open", "category": "todo"},
{"name": "Investigating", "category": "in_progress"},
{"name": "Fixed", "category": "done"}
],
"transitions": [
{"from": "Open", "to": "Investigating"},
{"from": "Investigating", "to": "Fixed"}
],
"enforcement": "warn",
"created_at": "...",
"updated_at": "..."
}
delete_workflow
Delete a workflow by its UUID. Returns 204 No Content on success. Requires admin role.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
workflow_id | string | yes | UUID of the workflow to delete |
Example prompt:
Delete workflow wf-uuid-1
Expected response:
deleted successfully.
Projects & Sprints
get_project_summary
Get a comprehensive project summary. Aggregates multiple API calls into a single response: project details, ticket counts by status, and active/planned sprints.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
project_id | string | yes | UUID of the project |
Example prompt:
Give me a summary of project 550e8400-…
Expected response:
{
"project": {
"id": "550e8400-...",
"name": "Alloy Core",
"key": "ALLOY",
"description": "Headless project management platform"
},
"ticket_summary": {
"total": 24,
"by_status": {
"Backlog": 8,
"Todo": 5,
"InProgress": 4,
"InReview": 3,
"Done": 4
},
"has_more": false
},
"sprints": [
{
"id": "990e8400-...",
"name": "Sprint 3",
"status": "Active",
"start_date": "2026-03-24",
"end_date": "2026-04-07"
}
]
}
Organization & Access
This section covers tools for managing organization members, invitations, project membership, and API keys. These tools require appropriate permissions — see Role Values and API Key Scopes for details.
list_members
List all members of the current organization. Returns each member’s user ID, display name, email, role, and join date.
Parameters: None
Example prompt:
Who are the members of this organization?
Expected response:
{
"items": [
{
"user_id": "...",
"display_name": "Alice Smith",
"email": "alice@example.com",
"role": "Owner",
"joined_at": "2026-01-01T00:00:00Z"
},
{
"user_id": "...",
"display_name": "Bob Jones",
"email": "bob@example.com",
"role": "Member",
"joined_at": "2026-02-01T00:00:00Z"
}
]
}
create_invite
Create an invite for someone to join the current organization. Returns an invite code and link. Optionally specify the invitee’s email and their role. See Role Values for valid roles.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
email | string | no | Email address of the person to invite (omit for a generic invite link) |
role | string | no | Role to assign: Owner, Admin, Member, Reporter, or Viewer. Defaults to Member |
Example prompt:
Invite alice@example.com as an Admin
Expected response:
{
"id": "...",
"invite_code": "ABC123xyz789",
"invite_link": "/register?invite=ABC123xyz789",
"email": "alice@example.com",
"role": "Admin",
"expires_at": "2026-04-06T10:00:00Z"
}
list_invites
List all pending invites for the current organization. Returns each invite’s ID, email, role, invite code, expiry, and status.
Parameters: None
Example prompt:
Show me all pending invites
Expected response:
[
{
"id": "...",
"org_id": "...",
"email": "pending@example.com",
"invite_code": "CODE1",
"role": "Member",
"created_by": "...",
"expires_at": "2026-04-06T10:00:00Z",
"accepted_at": null,
"revoked_at": null,
"created_at": "2026-03-30T10:00:00Z"
}
]
add_project_member
Add a user to a project as a member. Requires the user’s UUID and the project’s UUID.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
project_id | string | yes | UUID of the project |
user_id | string | yes | UUID of the user to add |
Example prompt:
Add user abc123 to project def456
Expected response:
{
"project_id": "...",
"user_id": "...",
"created_at": "..."
}
remove_project_member
Remove a user from a project.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
project_id | string | yes | UUID of the project |
user_id | string | yes | UUID of the user to remove |
Example prompt:
Remove user abc123 from project def456
Expected response:
The tool returns a confirmation: "deleted successfully."
list_project_members
List all members of a project.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
project_id | string | yes | UUID of the project |
Example prompt:
List members of project def456
Expected response:
[
{
"project_id": "...",
"user_id": "...",
"created_at": "..."
}
]
create_api_key
Create a new API key for the current user. Returns the full key value (only shown once). Optionally specify scopes and project restrictions. See API Key Scopes for valid scope values.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
name | string | yes | Human-readable name for the key (1–255 characters) |
scopes | array of strings | no | Permissions: read, write, admin. Defaults to ["read", "write"] |
project_ids | array of strings | no | UUIDs of projects to restrict the key to |
Example prompt:
Create an API key called “CI Pipeline” with read and write scopes
Expected response:
{
"id": "...",
"name": "CI Pipeline",
"key": "alloy_live_abc123...",
"key_prefix": "alloy_live_abc",
"scopes": ["read", "write"],
"project_ids": [],
"created_at": "2026-03-30T12:00:00Z",
"expires_at": null
}
list_api_keys
List all API keys belonging to the current user. Returns key metadata (prefix only, not the full key).
Parameters: None
Example prompt:
Show my API keys
Expected response:
[
{
"id": "...",
"name": "CI Pipeline",
"key_prefix": "alloy_live_abc",
"scopes": ["read", "write"],
"project_ids": [],
"created_at": "2026-03-30T12:00:00Z",
"last_used_at": "2026-03-30T14:00:00Z",
"expires_at": null
}
]
delete_api_key
Delete an API key by its UUID. Only the key’s owner can delete it.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
id | string | yes | UUID of the API key to delete |
Example prompt:
Delete API key abc12345-…
Expected response:
The tool returns a confirmation: "deleted successfully."
Activity
get_ticket_activity
Get the activity feed for a ticket. Returns a chronological stream of comments and changes (status transitions, field updates, etc.) with actor, action, and timestamp. Supports cursor-based pagination.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
ticket_id | string | yes | UUID of the ticket |
limit | integer | no | Max results per page (1–100, default 20) |
cursor | string | no | Pagination cursor from previous response |
Example prompt:
Show activity on ticket abc-123-def
Expected response:
{
"items": [
{
"type": "change",
"actor": "...",
"timestamp": "2026-03-30T12:00:00Z",
"payload": {
"audit_log_id": "...",
"action": "update",
"entity_type": "ticket",
"changes": [
{ "field": "status", "old": "Backlog", "new": "InProgress" }
]
}
},
{
"type": "comment",
"actor": "...",
"timestamp": "2026-03-30T11:00:00Z",
"payload": {
"comment_id": "...",
"body": "Started working on this",
"parent_comment_id": null
}
}
],
"next_cursor": null,
"has_more": false
}
Time Tracking
log_time
Log time spent working on a ticket. Creates a time entry with the specified duration, date, and activity type.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
ticket_id | string | yes | UUID of the ticket |
project_id | string | yes | UUID of the project |
date | string | yes | Date the work was done (YYYY-MM-DD) |
duration_minutes | integer | yes | Duration of work in minutes |
activity_type | string | yes | One of the 13 activity types (see below) |
description | string | no | Description of the work done |
Activity types (all 13):
| Activity Type | Description |
|---|---|
Coding | Writing or modifying application code |
Testing | Writing or running tests |
CodeReview | Reviewing pull requests and code |
Design | UI/UX design work |
Architecture | System design and architecture decisions |
PM | Project management tasks |
Requirements | Gathering and documenting requirements |
Training | Learning, onboarding, or training activities |
Maintenance | Infrastructure and dependency maintenance |
BugFixing | Investigating and fixing bugs |
Documentation | Writing or updating documentation |
Deployment | Deploying, releasing, or CI/CD work |
Meetings | Meetings, standups, and ceremonies |
Example prompt:
Log 90 minutes of Coding on ticket 770e8400-… in project 550e8400-… for today
Expected response:
{
"id": "aa0e8400-...",
"user_id": "660e8400-...",
"ticket_id": "770e8400-...",
"project_id": "550e8400-...",
"date": "2026-03-29",
"duration_minutes": 90,
"activity_type": "Coding",
"description": null,
"status": "Draft",
"created_at": "2026-03-29T16:00:00Z"
}
get_time_entry
Get a time entry by its UUID. Returns the time entry with date, duration, activity type, status, and associated ticket/project info.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
time_entry_id | string | yes | UUID of the time entry |
Example prompt:
Get time entry aa0e8400-…
Expected response:
{
"id": "aa0e8400-...",
"user_id": "660e8400-...",
"ticket_id": "770e8400-...",
"project_id": "550e8400-...",
"date": "2026-03-29",
"duration_minutes": 90,
"activity_type": "Coding",
"description": null,
"status": "Draft",
"created_at": "..."
}
update_time_entry
Update a draft time entry. Only draft entries can be updated. Only provided fields are changed.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
time_entry_id | string | yes | UUID of the time entry to update |
date | string | no | New date (YYYY-MM-DD) |
duration_minutes | integer | no | New duration in minutes |
description | string | no | New description |
activity_type | string | no | New activity type |
Example prompt:
Update time entry aa0e8400-… to 120 minutes and change activity to CodeReview
Expected response:
{
"id": "aa0e8400-...",
"user_id": "660e8400-...",
"ticket_id": "770e8400-...",
"project_id": "550e8400-...",
"date": "2026-03-29",
"duration_minutes": 120,
"activity_type": "CodeReview",
"description": null,
"status": "Draft",
"created_at": "..."
}
delete_time_entry
Delete a draft time entry by its UUID. Only draft entries can be deleted. Returns 204 No Content on success.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
time_entry_id | string | yes | UUID of the time entry to delete |
Example prompt:
Delete time entry aa0e8400-…
Expected response:
deleted successfully.
list_time_entries
List time entries for a specific ticket. Returns paginated results with time entry details.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
ticket_id | string | yes | UUID of the ticket |
limit | integer | no | Max results per page (1–100, default 20) |
cursor | string | no | Pagination cursor from previous response |
Example prompt:
List time entries for ticket 770e8400-…
Expected response:
{
"data": [
{
"id": "aa0e8400-...",
"user_id": "660e8400-...",
"date": "2026-03-29",
"duration_minutes": 90,
"activity_type": "Coding",
"description": null,
"status": "Draft"
}
],
"next_cursor": null,
"has_more": false
}
Finance & Reporting
get_time_report
Get time entries for a user. Returns paginated time entries showing logged hours, activity types, and approval status.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
user_id | string | no | UUID of the user (defaults to authenticated user) |
limit | integer | no | Max results per page (1–100, default 50) |
cursor | string | no | Pagination cursor from previous response |
Example prompt:
Show my recent time entries
Expected response:
{
"data": [
{
"id": "aa0e8400-...",
"ticket_id": "770e8400-...",
"date": "2026-03-29",
"duration_minutes": 90,
"activity_type": "Coding",
"description": null,
"status": "Draft"
}
],
"next_cursor": null,
"has_more": false
}
get_capitalization_report
Get capitalization report for a given period. Returns per-project capitalization breakdown with activity types, hours, and amounts. Supports grouping by team or user, filtering by team/user/cost-center/activity-type/tag, and including budget utilization data.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
period | string | yes | Period in YYYY-MM format (e.g. “2026-03”) |
group_by | string | no | Group results by “team” or “user” |
team_id | string | no | Filter by team UUID |
user_id | string | no | Filter by user UUID |
cost_center_id | string | no | Filter by cost center ID |
activity_type | string | no | Filter by activity type (e.g. “Coding”, “Design”) |
tag | string | no | Comma-separated tag filters in key:value format |
include_users | boolean | no | Include per-user breakdown within each project |
include_budget | boolean | no | Include budget utilization data |
Example prompt:
Show me the capitalization report for March 2026
Expected response:
{
"period": "2026-03",
"projects": [
{
"project_id": "...",
"project_key": "ALY",
"project_name": "Alloy",
"capitalization_type": "Capex",
"development_phase": "AppDevelopment",
"cost_center_id": "CC-100",
"total_hours": 160.0,
"total_amount_cents": 2400000,
"breakdown": [
{ "activity_type": "Coding", "hours": 120.0, "amount_cents": 1800000 },
{ "activity_type": "Design", "hours": 40.0, "amount_cents": 600000 }
]
}
]
}
Grouping with group_by:
Use group_by=team to aggregate capitalization data by team, or group_by=user for per-person breakdown:
Show capitalization report for March 2026 grouped by team
Parameters: period=2026-03, group_by=team
Show capitalization report for March 2026 grouped by user
Parameters: period=2026-03, group_by=user
Including budget with include_budget:
Set include_budget=true to include budget utilization and ROI data for each project. The response adds budget_cents, budget_used_cents, budget_remaining_cents, and roi_percent fields:
Show capitalization with budget data for March 2026
Parameters: period=2026-03, include_budget=true
Example response with budget fields:
{
"period": "2026-03",
"projects": [
{
"project_id": "...",
"project_key": "ALY",
"project_name": "Alloy",
"capitalization_type": "Capex",
"development_phase": "AppDevelopment",
"cost_center_id": "CC-100",
"total_hours": 160.0,
"total_amount_cents": 2400000,
"breakdown": [
{ "activity_type": "Coding", "hours": 120.0, "amount_cents": 1800000 },
{ "activity_type": "Design", "hours": 40.0, "amount_cents": 600000 }
],
"budget_cents": 5000000,
"budget_used_cents": 2400000,
"budget_remaining_cents": 2600000,
"roi_percent": 48.0
}
]
}
submit_time_entry
Submit a draft time entry for approval. Changes the entry status from Draft to Submitted. Only the author of the time entry can submit it.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
time_entry_id | string | yes | UUID of the time entry to submit |
Example prompt:
Submit my time entry te-1 for approval
Expected response:
{
"id": "aa0e8400-...",
"ticket_id": "770e8400-...",
"date": "2026-03-29",
"duration_minutes": 90,
"activity_type": "Coding",
"status": "Submitted",
"approved_by": null,
"approved_at": null
}
approve_time_entry
Approve a submitted time entry. Changes the entry status from Submitted to Approved. Records who approved it and when. Requires admin role.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
time_entry_id | string | yes | UUID of the time entry to approve |
Example prompt:
Approve time entry te-2
Expected response:
{
"id": "bb0e8400-...",
"ticket_id": "770e8400-...",
"date": "2026-03-29",
"duration_minutes": 120,
"activity_type": "Testing",
"status": "Approved",
"approved_by": "550e8400-...",
"approved_at": "2026-03-30T09:00:00Z"
}
get_capitalization_export
Export capitalization report as CSV for a given period. Returns CSV text with columns: Period, Project, ProjectKey, Employee, Department, CostCenter, Hours, ActivityType, Phase, CapExOpEx, LoadedRate, Amount, Team, Tags, BudgetCents, SpentCents, Utilization. Supports filtering by team, user, cost center, activity type, and tags.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
period | string | yes | Period in YYYY-MM format (e.g. “2026-03”) |
team_id | string | no | Filter by team UUID |
cost_center_id | string | no | Filter by cost center ID |
activity_type | string | no | Filter by activity type (e.g. “Coding”) |
tag | string | no | Comma-separated tag filters in key:value format |
Example prompt:
Export the capitalization report for March 2026 as CSV
Expected response:
Period,Project,ProjectKey,Employee,Department,CostCenter,Hours,ActivityType,Phase,CapExOpEx,LoadedRate,Amount,Team,Tags,BudgetCents,SpentCents,Utilization
2026-03,Alloy,ALY,Jane Doe,Engineering,CC-100,120.0,Coding,AppDevelopment,Capex,15000,1800000,Backend,env:prod,5000000,2400000,48.0
Data Export & Import
export_data
Export complete project data as portable JSON or SQLite. All relationships use human-readable keys (emails, project keys, label names) instead of UUIDs.
| Parameter | Type | Required | Description |
|---|---|---|---|
org_id | string | yes | Organization UUID |
project | string | no | Project key to filter (e.g. PROJ) |
format | string | no | Export format: json (default) or sqlite |
Returns: Complete AlloyExport JSON (default), or a downloadable SQLite database file when format=sqlite.
Export everything
{
"org_id": "...",
"project": null
}
Response:
{
"version": 1,
"source": "alloy",
"exported_at": "...",
"projects": ["..."],
"labels": ["..."],
"workflows": ["..."],
"users": ["..."]
}
Export a single project
{
"project": "PROJ"
}
import_data
Import data into the current organization from an Alloy JSON export (as produced by export_data). Creates users, workflows, labels, projects, sprints, tickets, comments, and time entries, preserving all relationships. Users and workflows are resolved by email/name to avoid duplicates.
| Parameter | Type | Required | Description |
|---|---|---|---|
data | object | yes | The full Alloy export JSON object. Must contain version, source, exported_at, projects, labels, workflows, and users fields. |
Returns: Summary of what was created.
Import a full export
{
"data": {
"version": 1,
"source": "alloy",
"exported_at": "2026-03-31T12:00:00Z",
"projects": [],
"labels": [],
"workflows": [],
"users": []
}
}
Response:
{
"status": "ok",
"summary": {
"users_created": 0,
"workflows_created": 0,
"labels_created": 0,
"projects_created": 0,
"sprints_created": 0,
"tickets_created": 0,
"comments_created": 0,
"time_entries_created": 0
}
}
Resources
Resources provide read-only access to Alloy data via URI patterns. MCP clients can browse resources without invoking tools.
Static Resources
| URI | Name | Description |
|---|---|---|
alloy://projects | projects | List all projects in the organization |
alloy://user/{current_user_id}/assigned | my-assigned-tickets | Tickets assigned to the current authenticated user |
Resource Templates
| URI Pattern | Name | Description |
|---|---|---|
alloy://project/{key} | project | Get a project by its key (e.g., PROJ) |
alloy://ticket/{id} | ticket | Get a ticket by its UUID |
alloy://sprint/{id}/board | sprint-board | Board view for a sprint — tickets grouped by status |
alloy://user/{id}/assigned | user-assigned-tickets | Tickets assigned to a specific user |
All resources return application/json.
Enums Reference
Status Values
Status values are defined by each project’s workflow and may vary between projects. The values below are the defaults provided by the built-in workflow. Your project may have different or additional statuses depending on its workflow configuration.
Default workflow statuses (examples):
| Value | Description |
|---|---|
Backlog | Not yet scheduled for work |
Todo | Scheduled but not started |
InProgress | Actively being worked on |
InReview | Work complete, awaiting review |
Done | Completed and accepted |
Cancelled | Cancelled, will not be done |
Tip: Use
transition_ticketto discover available transitions from a ticket’s current status. If you attempt an invalid transition, the error response lists the valid target statuses for that ticket’s workflow.
Priority Values
Ticket urgency levels used in create, update, and search operations.
| Value | Description |
|---|---|
None | No priority set (default) |
Low | Low urgency |
Medium | Normal urgency |
High | Important, address soon |
Urgent | Critical, address immediately |
Role Values
Organization roles control what a user can do. Roles are hierarchical — each role includes all permissions of the roles below it.
| Value | Privilege Level | Description |
|---|---|---|
Owner | 50 | Full control: billing, org deletion, and all admin capabilities |
Admin | 40 | Manage members, invites, projects, and settings |
Member | 30 | Create and manage tickets, sprints, and project content |
Reporter | 20 | Create tickets and comments, but cannot manage projects or members |
Viewer | 10 | Read-only access to all organization data |
Roles are used in create_invite (to set the invitee’s role) and returned by list_members and whoami.
API Key Scopes
API key scopes control what operations a key can perform. Multiple scopes can be combined. Keys default to ["read", "write"] if no scopes are specified.
| Scope | Description |
|---|---|
read | Read-only access: list and get operations (tickets, projects, members, etc.) |
write | Create and update operations: create tickets, log time, add comments, etc. |
admin | Administrative operations: manage members, invites, org settings |
Scopes are specified when calling create_api_key and returned by list_api_keys. Keys can optionally be restricted to specific projects via project_ids.
Key prefix convention: Production keys are prefixed alloy_live_, test keys are prefixed alloy_test_.
Sprint Status Values
| Value | Description |
|---|---|
Planned | Sprint has not started |
Active | Sprint is currently in progress |
Completed | Sprint has ended |
Time Entry Status Values
Approval lifecycle for time entries.
| Value | Description |
|---|---|
Draft | Entry created, not yet submitted |
Submitted | Submitted for approval |
Approved | Approved by a manager |
Rejected | Rejected, needs correction |
Pagination
All list endpoints use cursor-based pagination. The response includes:
| Field | Type | Description |
|---|---|---|
data | array | Array of result items |
next_cursor | string or null | Cursor to pass for the next page, or null if no more results |
has_more | boolean | true if additional results exist beyond this page |
Usage: Pass the next_cursor value as the cursor parameter in your next request to fetch the next page. Continue until has_more is false or next_cursor is null.
Example — paginating through tickets:
- First request:
search_ticketswithproject_idandlimit: 10 - Response includes
"next_cursor": "eyJ...","has_more": true - Next request: same parameters plus
cursor: "eyJ..." - Continue until
has_moreisfalse
Slash Commands (Prompts)
The Alloy MCP server provides 15 slash commands — pre-built workflows that guide the assistant through multi-step tasks. Invoke them by typing the command in your AI client (e.g., Claude Code).
| Command | Description |
|---|---|
/alloy:assign | Assign a ticket to a team member |
/alloy:comment | Add a comment to a ticket |
/alloy:create-ticket | Interactively gather fields and create a new ticket |
/alloy:invite | Invite a user to the organization |
/alloy:log-work | Interactively log time spent on a ticket |
/alloy:move | Move a ticket to a new workflow status |
/alloy:my-work | Fetch and summarize your assigned tickets by status |
/alloy:new-project | Create a new Alloy project |
/alloy:ping | Check server connectivity and authentication status |
/alloy:plan-sprint | Guide sprint planning with backlog review and capacity |
/alloy:project-summary | High-level overview of all projects and their health |
/alloy:report | Generate a project status report for a given period |
/alloy:search | Search for tickets by text, status, priority, or assignee |
/alloy:sprint-status | Review active sprint progress and burndown trends |
/alloy:standup | Generate a daily standup: yesterday, today, blockers |
/alloy:assign
Assigns a ticket to a team member. Guides the assistant through identifying the ticket and the assignee, then assigns it via the assign_ticket tool.
Optional arguments:
| Argument | Description |
|---|---|
ticket | Ticket number to assign (e.g., PROJ-42) — skips asking for it |
user | Team member name or email to assign to — skips asking for it |
Behavior:
- If both ticket and user are provided, looks up the user via
list_membersand assigns immediately withassign_ticket - If only ticket is provided, fetches ticket details with
get_ticketand asks who to assign it to - If only user is provided, asks which ticket to assign (can search via
search_tickets) - If neither is provided, asks for both interactively
- Confirms the assignment showing ticket number, title, and assignee
Tools used: assign_ticket, get_ticket, search_tickets, list_members
/alloy:comment
Adds a comment to a ticket. Guides the assistant through identifying the ticket and composing the comment, then posts it via the add_comment tool.
Optional arguments:
| Argument | Description |
|---|---|
ticket | Ticket number to comment on (e.g., PROJ-42) — skips asking for it |
Behavior:
- If ticket is provided, fetches ticket details with
get_ticketfor context, then asks for the comment text - If no ticket is provided, asks the user to identify the ticket first (can search via
search_tickets) - Posts the comment via
add_comment - Confirms the comment was added
Tools used: add_comment, get_ticket, search_tickets
/alloy:create-ticket
Guides you through creating a new ticket by gathering required and optional fields, then calling the create_ticket tool.
Optional arguments:
| Argument | Description |
|---|---|
project_key | Pre-fill the project key (e.g., PROJ) — skips asking for it |
title | Pre-fill the ticket title — skips asking for it |
Behavior:
- Asks for the project key and title (unless pre-filled via arguments)
- Asks about optional fields: description, priority, ticket type, assignee, labels, sprint
- Calls
create_ticketwith all gathered fields - Shows the created ticket number and URL
Tools used: create_ticket
/alloy:invite
Invites a user to the Alloy organization. Guides the assistant through collecting the email address and role, then creates the invite via the create_invite tool.
Optional arguments:
| Argument | Description |
|---|---|
email | Email address of the person to invite |
role | Role to assign: admin, member, or viewer |
Behavior:
- If both email and role are provided, calls
create_inviteimmediately - If only email is provided, asks which role to assign (explains the three options)
- If only role is provided, asks for the email address
- If neither is provided, asks for both interactively
- Confirms the invitation was sent
Tools used: create_invite
/alloy:log-work
Interactively guides you through logging time spent on a ticket.
Arguments: None
Behavior:
- Asks which ticket you worked on — uses
search_ticketsto find it if you provide a number or description - Asks for duration (accepts natural language like “2 hours”, “90 minutes”), date (defaults to today), activity type, and optional description
- Activity types: Coding, Testing, CodeReview, Design, Architecture, PM, Requirements, Training, Maintenance, BugFixing, Documentation, Deployment, Meetings
- Confirms all details before logging
- Calls
log_timewith the collected parameters - Offers to log more time on the same or a different ticket
Supports natural language shortcuts — e.g., “3 hours on PROJ-42 doing code review” extracts all fields automatically.
Tools used: search_tickets, log_time
/alloy:move
Moves a ticket to a new workflow status by guiding you through identifying the ticket and target status, then calling transition_ticket.
Optional arguments:
| Argument | Description |
|---|---|
ticket | Ticket number to move (e.g., PROJ-42) — skips asking for it |
status | Target status (e.g., In Progress, Done) — skips asking for it |
Behavior:
- If ticket and status are both provided, calls
transition_ticketimmediately - If only ticket is provided, fetches current status with
get_ticketand asks for target status - If only status is provided, asks which ticket to move (can search via
search_tickets) - If neither is provided, asks for both ticket and status interactively
- Confirms the transition showing ticket number, title, previous status, and new status
Tools used: transition_ticket, get_ticket, search_tickets
/alloy:my-work
Fetches all tickets assigned to you and presents them grouped by status with actionable highlights.
Arguments: None
Behavior:
- Calls
get_my_ticketsto fetch your assigned tickets - Groups results by status: In Progress, Open/To Do, In Review, Blocked, Done (recent)
- Highlights actionable items: high-priority tickets not yet started, stale tickets (no updates in 7+ days), tickets missing estimates or descriptions
- Ends with a summary: total count, in-progress count, items needing attention
Tools used: get_my_tickets
/alloy:new-project
Creates a new Alloy project. Guides the assistant through collecting the project name and key, then creates it via the create_project tool.
Optional arguments:
| Argument | Description |
|---|---|
name | Name for the new project (e.g., My App) |
key | Short project key (e.g., MYAPP) — uppercase letters, used in ticket IDs |
Behavior:
- If both name and key are provided, calls
create_projectimmediately - If only name is provided, suggests an uppercase key derived from the name and asks for confirmation
- If only key is provided, asks for the project name
- If neither is provided, asks for the project name first, then suggests a key
- Confirms the project was created with its name, key, and URL
Tools used: create_project
/alloy:ping
Checks connectivity to the Alloy MCP server and reports authentication status.
Arguments: None
Behavior:
- Calls the
pingtool to verify server connectivity - Reports which server you are connected to, your authenticated user, and your organisation
- If the ping fails, suggests checking API URL, API key, and network connectivity
Tools used: ping
/alloy:plan-sprint
Guides you through planning an upcoming sprint with backlog review, capacity estimation, and scope selection.
Arguments: None
Behavior:
- Calls
get_project_summaryfor current project and sprint state - Calls
search_ticketsto find backlog items (Open/To Do, not in a sprint) and carryover tickets - Reviews backlog sorted by priority (Critical → Low)
- Asks about team capacity (developers, sprint length)
- Recommends tickets to include based on priority, estimates, and capacity
- Flags dependencies and suggests a balanced mix of features, bugs, and tech debt
- Summarizes proposed sprint plan: goal, selected tickets, effort vs capacity, risks
Tools used: get_project_summary, search_tickets
/alloy:project-summary
Provides a high-level overview of all projects including ticket breakdowns, sprint progress, and items needing attention.
Arguments: None
Behavior:
- Calls
get_project_summaryto fetch all active projects - Presents each project: name, key, ticket breakdown (open vs closed, by priority), sprint status (progress %, days remaining), recent activity
- Highlights items needing attention: projects with no active sprint, sprints ending within 2 days, high ratio of Critical/High open tickets, stale tickets (14+ days)
- Ends with 2–3 actionable recommendations
Tools used: get_project_summary
/alloy:report
Generates a project status report. Aggregates data from project summaries, sprint burndowns, time tracking, and capitalization into a structured report.
Optional arguments:
| Argument | Description |
|---|---|
period | Report period in YYYY-MM format (e.g., 2026-03) or natural language (e.g., this week) |
Behavior:
- If period is provided, gathers data immediately from
get_project_summary,get_sprint_burndown,get_time_report, andget_capitalization_report - If no period is provided, asks the user to specify the reporting period first
- Structures the report into sections: Executive Summary, Sprint Progress, Time & Effort, Key Metrics, and Action Items
Tools used: get_project_summary, get_sprint_burndown, get_time_report, get_capitalization_report
/alloy:search
Searches for tickets by text, status, priority, assignee, labels, or project.
Optional arguments:
| Argument | Description |
|---|---|
query | Search query text (e.g., auth bug, high priority) — searches immediately |
Behavior:
- If query is provided, calls
search_ticketsimmediately with the query - If no query, asks what the user is looking for (text, status, priority, assignee, labels, project)
- Presents results in a tabular format: ticket number, title, status, priority, assignee
Tools used: search_tickets
/alloy:sprint-status
Reviews the status of all active sprints across projects, including burndown analysis and risk assessment.
Arguments: None
Behavior:
- Calls
get_project_summaryto identify active projects and sprints - Calls
get_sprint_burndownfor each active sprint to get progress metrics - Summarizes each sprint: name, date range, completed vs total points, burndown trend, tickets by status, at-risk items
- Provides an overall assessment with recommended actions (re-scope, reassign, escalate)
Tools used: get_project_summary, get_sprint_burndown
/alloy:standup
Generates a 3-part daily standup summary based on your assigned tickets and recent activity.
Arguments: None
Behavior:
- Calls
get_my_ticketsto fetch your assigned tickets - Yesterday: Identifies tickets recently moved to Done or In Review, or with activity in the last 24 hours
- Today: Lists In Progress or high-priority Open tickets as planned focus
- Blockers: Flags blocked tickets, stale tickets (no updates in 3+ days while In Progress), or unresolved dependencies
Output is kept under 15 lines for quick reading.
Tools used: get_my_tickets
Error Handling
When a tool call fails, the MCP server returns an error with a descriptive message.
Common Error Patterns
| Error | Cause | Resolution |
|---|---|---|
Failed to connect to Alloy API: ... | API server unreachable | Verify ALLOY_API_URL and that the server is running |
Permission denied: ... | Insufficient permissions | Check your API key scopes and org role |
Not found | Invalid UUID or deleted resource | Verify the ID exists using a search or list tool |
Transition failed: ... | Invalid workflow transition | Check the error message for available transitions from the current status |
Validation error: ... | Invalid input (e.g., title too long) | Fix the input according to the parameter constraints |
Error Response Format
Tool errors are returned as MCP error objects:
{
"code": -32603,
"message": "Not found: Ticket with id 770e8400-... does not exist"
}
The transition_ticket tool provides enhanced error messages that include the current status and list of valid transitions when a transition fails.