MCP Tools — Projects, Sprints, Kanban & Team

The project management surface lets your AI agent create and manage projects, plan sprints, drive a full kanban workflow (columns, cards, labels, checklists, assignees, dependencies, comments, time logs, file attachments, and artifacts), and manage your team. All tools are scoped to your authenticated client — no tool can read or write another tenant's data.

Authentication & scopes: See MCP Overview. Every tool is guarded by a scope. The required scope is listed for each tool below.


Projects#

projects_list#

List all projects for your account.

  • Scope: projects:read
  • Inputs:
NameTypeRequiredDescription
status"active" | "paused" | "completed" | "archived"NoFilter by project status. Omit to return all.
  • Example call:
{
  "tool": "projects_list",
  "arguments": { "status": "active" }
}
  • Example response:
[
  {
    "id": 12,
    "name": "Q3 Website Redesign",
    "description": "Full redesign of the marketing site",
    "status": "active",
    "dueDate": null,
    "clientId": 4,
    "createdBy": 7,
    "createdAt": "2026-05-01T10:00:00.000Z",
    "updatedAt": "2026-05-20T14:30:00.000Z"
  }
]
  • Errors:
CodeMessage
{ error: "projects:read" }Missing projects:read scope

projects_create#

Create a new project. Optionally clone columns, labels, and card templates from an existing project (cards are not copied).

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
namestringYesProject name (min 1 char)
descriptionstringNoOptional description
cloneFromProjectIdnumberNoProject id to seed columns, labels, and templates from
  • Example call:
{
  "tool": "projects_create",
  "arguments": {
    "name": "Q4 Campaign",
    "description": "Holiday campaign work",
    "cloneFromProjectId": 12
  }
}
  • Example response:
{
  "id": 15,
  "name": "Q4 Campaign",
  "description": "Holiday campaign work",
  "status": "active",
  "clientId": 4,
  "createdBy": 7,
  "createdAt": "2026-06-01T09:00:00.000Z",
  "updatedAt": "2026-06-01T09:00:00.000Z"
}
  • Errors:
CodeMessage
{ error: "projects:write" }Missing scope
{ error: "Source project not found in this account" }cloneFromProjectId does not belong to your client

projects_update#

Update a project's name, description, status, or due date.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
idnumberYesProject id
namestringNoNew name
descriptionstringNoNew description
status"active" | "paused" | "completed" | "archived"NoNew status
dueDatestringNoISO date string (e.g. "2026-09-30")
  • Example call:
{
  "tool": "projects_update",
  "arguments": { "id": 12, "status": "completed", "dueDate": "2026-08-31" }
}
  • Example response:
{
  "id": 12,
  "name": "Q3 Website Redesign",
  "status": "completed",
  "dueDate": "2026-08-31T00:00:00.000Z",
  "updatedAt": "2026-06-04T08:00:00.000Z"
}
  • Errors:
CodeMessage
{ error: "Not found" }Project id not found or not owned by your client

Project Members#

project_members_list#

List members and their roles for a project.

  • Scope: projects:read
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id

Roles are owner, editor, commenter, or viewer. Staff users (admin/employee) have implicit owner-equivalent access on every project regardless of membership rows.

  • Example call:
{ "tool": "project_members_list", "arguments": { "projectId": 12 } }
  • Example response:
[
  {
    "id": 3,
    "userId": 7,
    "role": "owner",
    "addedAt": "2026-05-01T10:00:00.000Z",
    "name": "Alice Smith",
    "email": "alice@example.com"
  }
]
  • Errors:
CodeMessage
{ error: "Project not found" }Project not found or not owned by your client

project_members_set#

Add a user to a project or update their role if already a member. Idempotent. Caller must be a project owner.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
userIdnumberYesUser id to add or update
role"owner" | "editor" | "commenter" | "viewer"YesRole to assign
  • Example call:
{
  "tool": "project_members_set",
  "arguments": { "projectId": 12, "userId": 9, "role": "editor" }
}
  • Example response:
{
  "id": 5,
  "projectId": 12,
  "userId": 9,
  "role": "editor",
  "addedBy": 7,
  "addedAt": "2026-06-04T08:00:00.000Z"
}
  • Errors:
CodeMessage
{ error: "Project not found" }Project not found
{ error: "Only project owners can manage members" }Caller is not a project owner
{ error: "Invalid role" }Role value not in allowed set

project_members_remove#

Remove a user from a project. Refuses to remove the last owner.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
userIdnumberYesUser id to remove
  • Example call:
{ "tool": "project_members_remove", "arguments": { "projectId": 12, "userId": 9 } }
  • Example response:
{ "ok": true }
  • Errors:
CodeMessage
{ error: "Project not found" }Project not found
{ error: "Only project owners can manage members" }Caller is not a project owner
{ error: "Member not found" }User is not a project member
{ error: "Cannot remove the sole owner; promote another member first" }Last owner guard

My Tasks#

my_tasks_list#

List kanban cards assigned to the authenticated user across all of your client's projects.

  • Scope: projects:read
  • Inputs:
NameTypeRequiredDescription
openOnlybooleanNoExclude cards in done columns. Defaults to true.
  • Example call:
{ "tool": "my_tasks_list", "arguments": { "openOnly": true } }
  • Example response:
[
  {
    "id": 88,
    "number": 14,
    "title": "Write landing page copy",
    "priority": "high",
    "dueDate": "2026-06-15T00:00:00.000Z",
    "projectId": 12,
    "projectName": "Q3 Website Redesign",
    "projectKey": "WEB",
    "columnId": 3,
    "columnName": "In Progress",
    "columnIsDone": false
  }
]

Project Artifacts#

Artifacts are polymorphic links from a project to other platform objects (websites, email campaigns, pitch decks, proposals, booking pages, surveys, posts, and brain notes).

projects_artifacts_list#

List all artifacts linked to a project.

  • Scope: projects:read
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
  • Example call:
{ "tool": "projects_artifacts_list", "arguments": { "projectId": 12 } }
  • Example response:
[
  {
    "id": 2,
    "projectId": 12,
    "artifactType": "website",
    "artifactId": 5,
    "displayTitle": "Marketing Site",
    "pinned": true,
    "createdBy": 7,
    "createdAt": "2026-06-01T10:00:00.000Z"
  }
]

Attach an artifact to a project. Supported artifactType values: website, email_campaign, pitch_deck, proposal, booking, survey, post, brain_note.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
artifactTypestringYesOne of the supported artifact type values above
artifactIdnumberYesId of the artifact to link
pinnedbooleanNoPin the artifact to the top of the list
  • Example call:
{
  "tool": "projects_artifact_link",
  "arguments": { "projectId": 12, "artifactType": "pitch_deck", "artifactId": 3, "pinned": false }
}
  • Example response:
{
  "id": 4,
  "projectId": 12,
  "artifactType": "pitch_deck",
  "artifactId": 3,
  "displayTitle": "Q3 Investor Deck",
  "pinned": false,
  "createdBy": 7,
  "createdAt": "2026-06-04T09:00:00.000Z"
}
  • Errors:
CodeMessage
{ error: "Project not found" }Project not found or wrong client
{ error: "Artifact not found or not owned by this client" }Artifact doesn't exist or belongs to another client

projects_artifact_toggle_pin#

Pin or unpin a linked project artifact.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
artifactDbIdnumberYesThe id of the project_artifacts link row (not the artifact's own id)
pinnedbooleanYesNew pinned state

Remove an artifact link from a project. The underlying artifact is not deleted.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
artifactDbIdnumberYesThe id of the project_artifacts link row
  • Example response:
{ "id": 4, "projectId": 12, "artifactType": "pitch_deck" }
  • Errors:
CodeMessage
{ error: "Artifact link not found" }Link row id not found on this project

Stage a suggested project-to-artifact link as a pending AI review item instead of writing it directly. The suggestion lands in the brain review queue for a human to approve, edit, or reject. Prefer this tool over projects_artifact_link when the suggestion came from automated analysis the user hasn't explicitly authorized.

  • Scope: projects:write + brain:write
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
artifactTypestringYesArtifact type (same enum as projects_artifact_link)
artifactIdnumberYesArtifact id
pinnedbooleanNoWhether to pin if approved
rationalestringNoExplanation for the reviewer
  • Example response:
{
  "id": 9,
  "clientId": 4,
  "proposedType": "project_artifact_link",
  "status": "pending",
  "proposedPayload": {
    "projectId": 12,
    "artifactType": "survey",
    "artifactId": 7,
    "pinned": false,
    "rationale": "Survey collects feedback for this project's launch."
  }
}

Sprints#

sprints_list#

List sprints on a project.

  • Scope: projects:read
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
status"planning" | "active" | "completed"NoFilter by sprint status
  • Example call:
{ "tool": "sprints_list", "arguments": { "projectId": 12, "status": "active" } }
  • Example response:
[
  {
    "id": 6,
    "projectId": 12,
    "name": "Sprint 4",
    "goal": "Ship the new nav and hero",
    "startDate": "2026-06-02T00:00:00.000Z",
    "endDate": "2026-06-13T00:00:00.000Z",
    "status": "active",
    "order": 3
  }
]
  • Errors:
CodeMessage
{ error: "Project not found" }Project not found or wrong client

sprints_create#

Add a sprint to a project. Appends to the end unless order is specified.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
namestringYesSprint name
goalstringNoSprint goal statement
startDatestringNoISO date
endDatestringNoISO date
status"planning" | "active" | "completed"NoDefaults to "planning"
ordernumberNoSort position; defaults to end
  • Example call:
{
  "tool": "sprints_create",
  "arguments": {
    "projectId": 12,
    "name": "Sprint 5",
    "goal": "Implement contact form and booking flow",
    "startDate": "2026-06-16",
    "endDate": "2026-06-27"
  }
}
  • Example response:
{
  "id": 7,
  "projectId": 12,
  "name": "Sprint 5",
  "goal": "Implement contact form and booking flow",
  "startDate": "2026-06-16T00:00:00.000Z",
  "endDate": "2026-06-27T00:00:00.000Z",
  "status": "planning",
  "order": 4
}

sprints_update#

Update a sprint's name, goal, dates, status, or order.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
idnumberYesSprint id
namestringNoNew name
goalstring | nullNoNew goal; pass null to clear
startDatestring | nullNoISO date; pass null to clear
endDatestring | nullNoISO date; pass null to clear
status"planning" | "active" | "completed"NoNew status
ordernumberNoNew sort position
  • Errors:
CodeMessage
{ error: "Sprint not found" }Sprint id not found or not owned by your client

sprints_delete#

Permanently delete a sprint. Cards currently assigned to the sprint have their sprintId cleared (they return to the sprint dock) rather than being deleted.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
idnumberYesSprint id
  • Example response:
{ "deleted": true, "id": 7 }
  • Errors:
CodeMessage
{ error: "Sprint not found" }Sprint not found or wrong client

Kanban Board & Columns#

kanban_list_board#

Get all columns and cards for a project. Card responses use a slim projection (description is excluded from the board view; fetch it when opening a card's detail drawer).

  • Scope: projects:read
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
  • Example call:
{ "tool": "kanban_list_board", "arguments": { "projectId": 12 } }
  • Example response:
{
  "columns": [
    { "id": 1, "projectId": 12, "name": "Backlog", "color": null, "order": 0, "isDone": false, "wipLimit": null },
    { "id": 2, "projectId": 12, "name": "In Progress", "color": "#3b82f6", "order": 1, "isDone": false, "wipLimit": 3 },
    { "id": 3, "projectId": 12, "name": "Done", "color": null, "order": 2, "isDone": true, "wipLimit": null }
  ],
  "cards": [
    {
      "id": 88,
      "columnId": 2,
      "projectId": 12,
      "number": 14,
      "title": "Write landing page copy",
      "dueDate": "2026-06-15T00:00:00.000Z",
      "priority": "high",
      "order": 0,
      "sprintId": 6,
      "storyPoints": 3,
      "cardType": "story",
      "workflowState": "in_progress"
    }
  ]
}
  • Errors:
CodeMessage
{ error: "Project not found" }Project not found or wrong client

kanban_create_column#

Add a column to a project's kanban board.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
namestringYesColumn name
colorstringNoHex color like #3b82f6
ordernumberNoSort position; defaults to end of board
  • Example response:
{ "id": 4, "projectId": 12, "name": "Review", "color": "#f59e0b", "order": 2, "isDone": false, "wipLimit": null }

kanban_update_column#

Rename, recolor, or reorder a column.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
idnumberYesColumn id
namestringNoNew name
colorstring | nullNoNew hex color; null to clear
ordernumberNoNew sort position
  • Errors:
CodeMessage
{ error: "Column not found" }Column not found
{ error: "Permission denied" }Column belongs to a project not owned by your client

kanban_delete_column#

Permanently delete a column and every card inside it (cascade).

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
idnumberYesColumn id
  • Example response:
{ "success": true, "id": 4 }

Kanban Cards#

kanban_create_card#

Add a card to a kanban column. Supports agile fields, sprint assignment, hierarchy, and card templates.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
columnIdnumberYesColumn id the card starts in
titlestringNo*Card title. Required unless fromTemplateId supplies a titlePattern
descriptionstringNoCard body/description
priority"low" | "medium" | "high" | "urgent"NoDefaults to "medium"
dueDatestringNoISO date string
sprintIdnumber | nullNoSprint to assign the card to on creation; omit or null to leave in the sprint dock
storyPointsinteger | nullNoStory point estimate
cardType"task" | "story" | "epic" | "bug" | "spike"NoDefaults to "task"
parentCardIdnumber | nullNoParent card for hierarchy (e.g. story under epic); must belong to the same project
workflowState"todo" | "in_progress" | "in_review" | "done" | "canceled"NoDefaults to "todo"
fromTemplateIdnumberNoSeed fields + checklist + labels from a card template; explicit args override template values

If a column has a WIP limit set and moving there would exceed it, the call is rejected.

  • Example call:
{
  "tool": "kanban_create_card",
  "arguments": {
    "projectId": 12,
    "columnId": 1,
    "title": "Set up analytics tracking",
    "priority": "medium",
    "cardType": "task",
    "storyPoints": 2,
    "sprintId": 6
  }
}
  • Example response:
{
  "id": 90,
  "projectId": 12,
  "columnId": 1,
  "number": 16,
  "title": "Set up analytics tracking",
  "priority": "medium",
  "cardType": "task",
  "storyPoints": 2,
  "sprintId": 6,
  "workflowState": "todo",
  "dueDate": null,
  "createdBy": 7,
  "createdAt": "2026-06-04T09:00:00.000Z"
}
  • Errors:
CodeMessage
{ error: "..." }Ownership assertion failure (project/column mismatch)
{ error: "Sprint not found in this project" }sprintId belongs to a different project
{ error: "Parent card not found in this project" }parentCardId belongs to a different project
{ error: "title is required (or pass fromTemplateId with a titlePattern)" }No title and no template
{ error: "...", code: "wip_limit", limit: N, currentCount: N }Column WIP limit exceeded
{ error: "Template not available" }fromTemplateId not found or wrong client

kanban_update_card#

Update card fields. Use kanban_move_card to change the column or position.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
idnumberYesCard id
titlestringNoNew title
descriptionstring | nullNoNew description; null to clear
priority"low" | "medium" | "high" | "urgent"NoNew priority
dueDatestring | nullNoISO date; null to clear
assignedTonumber | nullNoUser id to set as the single assignee; null to clear all assignees
sprintIdnumber | nullNoSprint id to assign; null to remove from sprint (returns to dock)
storyPointsinteger | nullNoNew story point estimate
cardType"task" | "story" | "epic" | "bug" | "spike"NoNew card type
parentCardIdnumber | nullNoNew parent card
workflowState"todo" | "in_progress" | "in_review" | "done" | "canceled"NoNew workflow state
  • Errors:
CodeMessage
{ error: "Card not found" }Card id not found
{ error: "Permission denied" }Card belongs to a project not owned by your client
{ error: "Sprint not found in this project" }sprintId doesn't belong to this card's project

kanban_move_card#

Move a card to a different column and/or position. Respects WIP limits on the destination column.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
columnIdnumberYesTarget column id
ordernumberNoPosition within the column; defaults to 0
  • Example call:
{ "tool": "kanban_move_card", "arguments": { "cardId": 88, "columnId": 3, "order": 0 } }
  • Errors:
CodeMessage
{ error: "Card not found" }Card id not found
{ error: "Permission denied" }Project not owned by your client
{ error: "...", code: "wip_limit", limit: N, currentCount: N }Destination WIP limit exceeded

kanban_delete_card#

Permanently delete a kanban card.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
idnumberYesCard id
  • Example response:
{ "success": true, "id": 88 }

Kanban Labels#

kanban_labels_list#

List all labels defined on a project.

  • Scope: projects:read
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
  • Example response:
[
  { "id": 1, "projectId": 12, "name": "bug", "color": "#ef4444" },
  { "id": 2, "projectId": 12, "name": "design", "color": "#6366f1" }
]

kanban_labels_create#

Create a label on a project. Color must be a 6-digit hex; defaults to indigo (#6366f1).

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
namestringYesLabel name (max 50 chars)
colorstringNoHex color; defaults to #6366f1

kanban_labels_update#

Rename or recolor a label.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
idnumberYesLabel id
namestringNoNew name (max 50 chars)
colorstringNoNew hex color
  • Errors:
CodeMessage
{ error: "Label not found" }Label not found or belongs to another client's project

kanban_labels_delete#

Delete a label. Removes it from all cards automatically.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
idnumberYesLabel id
  • Example response:
{ "deleted": true, "id": 1 }

kanban_card_attach_label#

Add a project label to a card.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
labelIdnumberYesLabel id (must belong to the same project as the card)
  • Example response:
{ "attached": true }
  • Errors:
CodeMessage
{ error: "Card not found" }Card not found or wrong client
{ error: "Label not in this project" }Label belongs to a different project

kanban_card_detach_label#

Remove a label from a card.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
labelIdnumberYesLabel id
  • Example response:
{ "detached": true }

Kanban Checklists#

kanban_checklist_list#

List checklist items for a card.

  • Scope: projects:read
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
  • Example response:
[
  { "id": 1, "cardId": 88, "text": "Write copy", "completed": false, "completedAt": null, "order": 0 },
  { "id": 2, "cardId": 88, "text": "Get approval", "completed": true, "completedAt": "2026-06-03T14:00:00.000Z", "order": 1 }
]

kanban_checklist_add#

Append a checklist item to a card.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
textstringYesItem text (max 500 chars)

kanban_checklist_update#

Rename, toggle complete, or reorder a checklist item.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
idnumberYesChecklist item id
textstringNoNew text (max 500 chars)
completedbooleanNoMark complete or incomplete
ordernumberNoNew sort position
  • Errors:
CodeMessage
{ error: "Checklist item not found" }Item not found or belongs to another client's card

kanban_checklist_delete#

Permanently remove a checklist item.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
idnumberYesChecklist item id
  • Example response:
{ "deleted": true, "id": 1 }

Kanban Assignees#

kanban_card_assignees_list#

Return all users assigned to a card.

  • Scope: projects:read
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
  • Example response:
[
  { "id": 7, "name": "Alice Smith", "email": "alice@example.com" }
]

kanban_card_assign#

Add a user as a card assignee. Also automatically adds them as a watcher.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
userIdnumberYesUser id to assign
  • Example response:
{ "assigned": true }

kanban_card_unassign#

Remove a user from a card.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
userIdnumberYesUser id to remove
  • Example response:
{ "unassigned": true }

Kanban Dependencies#

kanban_card_dependencies_list#

Return the blockers (cards blocking this one) and blocking (cards this one blocks) for a card.

  • Scope: projects:read
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
  • Example response:
{
  "blockers": [{ "id": 75, "number": 8, "title": "Set up CI pipeline" }],
  "blocking": []
}

kanban_card_add_blocker#

Mark this card as blocked by another card in the same project.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesThe card being blocked
blockerCardIdnumberYesThe card doing the blocking
  • Example response:
{ "added": true }
  • Errors:
CodeMessage
{ error: "A card cannot block itself" }Self-reference
{ error: "Blocker must be in the same project" }Cross-project dependency not allowed
{ error: "Reciprocal dependency would create a cycle" }Direct cycle detected

kanban_card_remove_blocker#

Remove a blocker dependency from a card.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
blockerCardIdnumberYesBlocker card id to remove
  • Example response:
{ "removed": true }

Kanban Comments & Time Logs#

kanban_card_list_comments#

List comments on a kanban card.

  • Scope: projects:read
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
  • Example response:
[
  {
    "id": 5,
    "cardId": 88,
    "userId": 7,
    "body": "Copy is ready for review @9",
    "mentions": [9],
    "createdAt": "2026-06-03T15:00:00.000Z"
  }
]

kanban_card_add_comment#

Add a comment to a kanban card. Supports @mentions as an array of user ids.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
bodystringYesComment text
mentionsnumber[]NoArray of user ids mentioned

kanban_card_log_time#

Log minutes worked on a card.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
minutesintegerYesMinutes worked (min 1)
notestringNoOptional note about the work
loggedAtstringNoISO datetime; defaults to now
  • Example response:
{
  "id": 3,
  "cardId": 88,
  "userId": 7,
  "minutes": 90,
  "note": "Initial draft",
  "loggedAt": "2026-06-04T09:00:00.000Z"
}

Kanban File Attachments#

kanban_card_attach_file_from_url#

Download a remote file (HTTP/HTTPS, 25 MB maximum) and attach it to a kanban card. The file is stored in S3 using the same pipeline as media uploads.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
urlstringYesPublic HTTP or HTTPS URL of the file to download
filenamestringNoOverride filename; defaults to the URL basename
  • Example call:
{
  "tool": "kanban_card_attach_file_from_url",
  "arguments": {
    "cardId": 88,
    "url": "https://example.com/brief.pdf",
    "filename": "project-brief.pdf"
  }
}
  • Example response:
{
  "id": 2,
  "cardId": 88,
  "originalName": "project-brief.pdf",
  "mimeType": "application/pdf",
  "fileSize": 204800,
  "url": "https://cdn.example.com/uploads/abc123-project-brief.pdf"
}
  • Errors:
CodeMessage
{ error: "URL rejected: ..." }SSRF guard blocked the URL
{ error: "Refusing to follow redirects on remote upload (SSRF guard)." }Redirect on the remote URL
{ error: "Fetch failed: ..." }Network error fetching the URL
{ error: "Fetch returned N" }Remote server returned a non-2xx status
{ error: "File too large (N bytes)." }File exceeds 25 MB

Kanban Card Artifacts#

Card artifacts link platform objects to individual cards (same types as project artifacts plus project, but not brain_note).

Supported artifactType values: website, email_campaign, pitch_deck, proposal, booking, survey, project, post.

kanban_card_artifacts_list#

List all artifacts linked to a card.

  • Scope: projects:read
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id

Attach an artifact to a kanban card.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
artifactTypestringYesArtifact type (see list above)
artifactIdnumberYesArtifact id
pinnedbooleanNoPin to the top
  • Errors:
CodeMessage
{ error: "Card not found" }Card not found or wrong client
{ error: "Artifact not found or not owned by this client" }Artifact doesn't exist or belongs to another client

kanban_card_artifact_toggle_pin#

Update the pinned flag on a linked card artifact.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
artifactDbIdnumberYesid of the kanban_card_artifacts link row
pinnedbooleanYesNew pinned state

Remove an artifact link from a card. The underlying artifact is not deleted.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
cardIdnumberYesCard id
artifactDbIdnumberYesid of the link row
  • Errors:
CodeMessage
{ error: "Artifact link not found" }Link row not found on this card

Card Templates#

kanban_card_templates_list#

List card templates available to a project — both project-scoped and client-wide templates.

  • Scope: projects:read
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
  • Example response:
[
  {
    "id": 1,
    "clientId": 4,
    "projectId": null,
    "name": "Standard Bug Report",
    "description": "Use for all bug tickets",
    "payload": {
      "titlePattern": "Bug: ",
      "cardType": "bug",
      "priority": "high",
      "checklist": [
        { "text": "Reproduce the issue", "order": 0 },
        { "text": "Identify root cause", "order": 1 }
      ]
    }
  }
]

kanban_card_templates_create#

Create a reusable card template. Set clientWide: true to make it available across every project in your account.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject context for ownership; ignored if clientWide is true
namestringYesTemplate name (max 100 chars)
descriptionstringNoTemplate description (max 5000 chars)
clientWidebooleanNoMake available to all projects
payloadobjectYesTemplate fields (see below)

payload fields:

FieldTypeDescription
titlePatternstringDefault title; {{date}} is replaced with the creation date in recurring tasks
descriptionstringDefault card description
cardType"task" | "story" | "epic" | "bug" | "spike"Default card type
priority"low" | "medium" | "high" | "urgent"Default priority
storyPointsintegerDefault story point estimate
workflowState"todo" | "in_progress" | "in_review" | "done" | "canceled"Default workflow state
labelIdsnumber[]Label ids to attach on creation
checklist{ text: string, order?: number }[]Default checklist items

kanban_card_templates_delete#

Permanently delete a card template. This action is irreversible.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
idnumberYesTemplate id
  • Example response:
{ "ok": true }
  • Errors:
CodeMessage
{ error: "Template not found" }Template not found or belongs to another client

Sprint Planner#

kanban_propose_sprint#

Generate a greedy sprint-packing proposal for a project's backlog. This is a read-only planning tool — commit the chosen assignments by calling kanban_update_card with the target sprintId for each recommended card.

The planner packs cards from the prioritized backlog (sprintId = null, ordered by sprintOrder then order) up to the point cap, respecting unfinished blockers, and returns four buckets: recommended, skipped, blocked, and unsized.

  • Scope: projects:read
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
targetPointsinteger | nullNoHard point cap. If null, defaults to 1.1× recent average velocity
velocityWindowintegerNoNumber of recent completed sprints to average for the velocity baseline. Default 6, min 1, max 20
requireCardIdsnumber[]NoCard ids already pinned for the sprint; these bypass capacity and blocker gates
  • Example call:
{
  "tool": "kanban_propose_sprint",
  "arguments": {
    "projectId": 12,
    "targetPoints": 20,
    "velocityWindow": 4,
    "requireCardIds": [88]
  }
}
  • Example response:
{
  "recommended": [
    { "id": 88, "number": 14, "title": "Write landing page copy", "storyPoints": 3 },
    { "id": 91, "number": 17, "title": "Implement booking form", "storyPoints": 5 }
  ],
  "skipped": [],
  "blocked": [{ "id": 92, "number": 18, "title": "Deploy to staging", "blockerCardIds": [91] }],
  "unsized": [{ "id": 93, "number": 19, "title": "Team retro doc" }],
  "velocityBaseline": 18,
  "velocityWindowSprints": 4,
  "backlogTotal": 10
}

Recurring Tasks#

kanban_recurrences_list#

List card recurrence rules for a project — both active and paused — sorted by next fire time.

  • Scope: projects:read
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id

kanban_recurrences_create#

Configure a recurring card-creation rule. {{date}} in titlePattern is replaced with the firing date (YYYY-MM-DD) at each run. You must supply either templateId or titlePattern.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
projectIdnumberYesProject id
columnIdnumberYesColumn where new cards are created
cadence"daily" | "weekly" | "monthly"YesRecurrence frequency
dayOfWeekintegerNo0 (Sun) – 6 (Sat); used when cadence is "weekly"
dayOfMonthintegerNo1 – 28; used when cadence is "monthly"
hourUtcintegerNoHour (UTC, 0–23) to fire; defaults to 9
templateIdnumberNoCard template to apply on each fire
titlePatternstringNoCard title pattern (can include {{date}}); required if templateId not provided
descriptionstringNoDefault card description (max 5000 chars)
  • Errors:
CodeMessage
{ error: "Either templateId or titlePattern is required" }Neither supplied

kanban_recurrences_delete#

Permanently delete a recurring task rule. Future card generation stops immediately.

  • Scope: projects:write
  • Inputs:
NameTypeRequiredDescription
idnumberYesRecurrence rule id
  • Example response:
{ "ok": true }
  • Errors:
CodeMessage
{ error: "Recurrence not found" }Rule not found or belongs to another client

Team & Client#

team_list_members#

List users with access to this client account. Returns each user's name, email, and role.

  • Scope: team:read

  • Inputs: None

  • Example call:

{ "tool": "team_list_members", "arguments": {} }
  • Example response:
[
  {
    "memberId": 1,
    "role": "owner",
    "userId": 7,
    "name": "Alice Smith",
    "email": "alice@example.com",
    "joinedAt": "2026-01-15T10:00:00.000Z"
  }
]

team_invite#

Invite a user to this client by email. If the email is unknown, a new user account is created with a generated temporary password (returned once in the response — store it and deliver it to the user). If the email already exists, the user is linked as a member without a password change. Only the account owner can invite members.

  • Scope: team:write
  • Inputs:
NameTypeRequiredDescription
namestringYesNew user's display name
emailstringYesEmail address to invite

New members are always given the member role; use team_update_role to promote them.

  • Example call:
{
  "tool": "team_invite",
  "arguments": { "name": "Bob Jones", "email": "bob@example.com" }
}
  • Example response (new user):
{
  "member": { "id": 6, "clientId": 4, "userId": 11, "role": "member" },
  "user": { "id": 11, "name": "Bob Jones", "email": "bob@example.com" },
  "isNewUser": true,
  "tempPassword": "a3f2b9c1d7e0"
}
  • Example response (existing user):
{
  "member": { "id": 6, "clientId": 4, "userId": 11, "role": "member" },
  "user": { "id": 11, "name": "Bob Jones", "email": "bob@example.com" },
  "isNewUser": false,
  "tempPassword": null
}
  • Errors:
CodeMessage
{ error: "Only the account owner can invite members" }Caller is not the account owner
{ error: "User is already a team member" }Email already linked to this client

team_update_role#

Change a team member's client role.

  • Scope: team:write
  • Inputs:
NameTypeRequiredDescription
memberIdnumberYesThe client_members.id (from team_list_members)
role"owner" | "admin" | "member" | "viewer"YesNew role

Note: there is no server-side guard preventing you from demoting the last owner. Be careful.

  • Example response:
{ "id": 1, "clientId": 4, "userId": 7, "role": "admin" }
  • Errors:
CodeMessage
{ error: "Member not found" }memberId not found on this client

team_remove_member#

Remove a user's access to this client account. Does not delete the user account itself.

  • Scope: team:write
  • Inputs:
NameTypeRequiredDescription
memberIdnumberYesThe client_members.id to remove
  • Example response:
{ "success": true, "memberId": 6 }
  • Errors:
CodeMessage
{ error: "Member not found" }memberId not found on this client

client_get#

Return the full client record (company name, phone, website, address, email prefix, notes).

  • Scope: team:read

  • Inputs: None

  • Example response:

{
  "id": 4,
  "company": "Acme Corp",
  "phone": "+1-555-0100",
  "website": "https://acme.example.com",
  "address": "123 Main St, Springfield",
  "notes": "VIP client",
  "emailPrefix": "acme"
}

client_update#

Update the authenticated client's profile. You cannot change email or Stripe customer id via MCP.

  • Scope: team:write
  • Inputs:
NameTypeRequiredDescription
companystring | nullNoCompany name
phonestring | nullNoPhone number
websitestring | nullNoPublic website URL
addressstring | nullNoMailing address
notesstring | nullNoInternal notes