list_work_items
List and search work items within a project or across the entire workspace. Filter by assignee, state, priority, labels, and more to find items matching your criteria.
Instructions
List work items in a project or search across the workspace.
When any filter parameter is provided (assignee_ids, state_ids, state_groups, priorities, label_ids, type_ids, cycle_ids, module_ids, is_archived, created_by_ids, or query), this uses the advanced search endpoint which supports powerful filtering. Otherwise it uses the standard list endpoint.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project_id | No | UUID of the project. Required when no filters are provided. Optional when using filters (omit for workspace-wide search). | |
| query | No | Free-form text search across work item name and description | |
| assignee_ids | No | List of user UUIDs to filter by assignee | |
| state_ids | No | List of state UUIDs to filter by state | |
| state_groups | No | List of state groups to filter by (backlog, unstarted, started, completed, cancelled) | |
| priorities | No | List of priority values to filter by (urgent, high, medium, low, none) | |
| label_ids | No | List of label UUIDs to filter by label | |
| type_ids | No | List of work item type UUIDs to filter by type | |
| cycle_ids | No | List of cycle UUIDs to filter by cycle | |
| module_ids | No | List of module UUIDs to filter by module | |
| is_archived | No | Filter by archived status (true/false) | |
| created_by_ids | No | List of user UUIDs to filter by creator | |
| workspace_search | No | When true, search across all projects in the workspace. Only used with filters. Defaults to false. | |
| limit | No | Maximum number of results (only used with filters, default 25) | |
| cursor | No | Pagination cursor for getting next set of results (list only) | |
| per_page | No | Number of results per page, 1-100 (list only) | |
| expand | No | Comma-separated list of related fields to expand in response (list only, e.g. "assignees,labels,state") | |
| fields | No | Comma-separated list of fields to include in response (list only) | |
| order_by | No | Field to order results by, prefix with '-' for descending (list only) | |
| external_id | No | External system identifier for filtering (list only) | |
| external_source | No | External system source name for filtering (list only) |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- plane_mcp/tools/work_items.py:68-177 (handler)The main handler function for the 'list_work_items' tool. It uses advanced search if filters/query are provided, otherwise falls back to the standard list endpoint.
def list_work_items( project_id: str | None = None, query: str | None = None, assignee_ids: list[str] | None = None, state_ids: list[str] | None = None, state_groups: list[str] | None = None, priorities: list[str] | None = None, label_ids: list[str] | None = None, type_ids: list[str] | None = None, cycle_ids: list[str] | None = None, module_ids: list[str] | None = None, is_archived: bool | None = None, created_by_ids: list[str] | None = None, workspace_search: bool = False, limit: int | None = None, cursor: str | None = None, per_page: int | None = None, expand: str | None = None, fields: str | None = None, order_by: str | None = None, external_id: str | None = None, external_source: str | None = None, ) -> list[WorkItem] | list[AdvancedSearchResult]: """ List work items in a project or search across the workspace. When any filter parameter is provided (assignee_ids, state_ids, state_groups, priorities, label_ids, type_ids, cycle_ids, module_ids, is_archived, created_by_ids, or query), this uses the advanced search endpoint which supports powerful filtering. Otherwise it uses the standard list endpoint. Args: project_id: UUID of the project. Required when no filters are provided. Optional when using filters (omit for workspace-wide search). query: Free-form text search across work item name and description assignee_ids: List of user UUIDs to filter by assignee state_ids: List of state UUIDs to filter by state state_groups: List of state groups to filter by (backlog, unstarted, started, completed, cancelled) priorities: List of priority values to filter by (urgent, high, medium, low, none) label_ids: List of label UUIDs to filter by label type_ids: List of work item type UUIDs to filter by type cycle_ids: List of cycle UUIDs to filter by cycle module_ids: List of module UUIDs to filter by module is_archived: Filter by archived status (true/false) created_by_ids: List of user UUIDs to filter by creator workspace_search: When true, search across all projects in the workspace. Only used with filters. Defaults to false. limit: Maximum number of results (only used with filters, default 25) cursor: Pagination cursor for getting next set of results (list only) per_page: Number of results per page, 1-100 (list only) expand: Comma-separated list of related fields to expand in response (list only, e.g. "assignees,labels,state") fields: Comma-separated list of fields to include in response (list only) order_by: Field to order results by, prefix with '-' for descending (list only) external_id: External system identifier for filtering (list only) external_source: External system source name for filtering (list only) Returns: List of WorkItem objects (unfiltered) or AdvancedSearchResult objects (filtered) """ client, workspace_slug = get_plane_client_context() filters = _build_advanced_search_filters( assignee_ids=assignee_ids, state_ids=state_ids, state_groups=state_groups, priorities=priorities, label_ids=label_ids, type_ids=type_ids, cycle_ids=cycle_ids, module_ids=module_ids, is_archived=is_archived, created_by_ids=created_by_ids, ) if filters is not None or query is not None: data = AdvancedSearchWorkItem( query=query, filters=filters, limit=limit, project_id=project_id, workspace_search=workspace_search or None, ) return client.work_items.advanced_search( workspace_slug=workspace_slug, data=data, ) if project_id is None: raise ValueError("project_id is required when no filters are provided") params = WorkItemQueryParams( cursor=cursor, per_page=per_page, expand=expand, fields=fields, order_by=order_by, external_id=external_id, external_source=external_source, ) response: PaginatedWorkItemResponse = client.work_items.list( workspace_slug=workspace_slug, project_id=project_id, params=params, ) return response.results - plane_mcp/tools/work_items.py:22-61 (helper)Helper function that builds AND filter conditions (assignee, state, priority, label, type, cycle, module, archived, created_by) used by list_work_items for advanced search.
def _build_advanced_search_filters( *, assignee_ids: list[str] | None = None, state_ids: list[str] | None = None, state_groups: list[str] | None = None, priorities: list[str] | None = None, label_ids: list[str] | None = None, type_ids: list[str] | None = None, cycle_ids: list[str] | None = None, module_ids: list[str] | None = None, is_archived: bool | None = None, created_by_ids: list[str] | None = None, ) -> dict[str, Any] | None: """Build an AND filter dict from flat filter params.""" conditions: list[dict[str, Any]] = [] if assignee_ids: conditions.append({"assignee_id__in": assignee_ids}) if state_ids: conditions.append({"state_id__in": state_ids}) if state_groups: conditions.append({"state_group__in": state_groups}) if priorities: conditions.append({"priority__in": priorities}) if label_ids: conditions.append({"label_id__in": label_ids}) if type_ids: conditions.append({"type_id__in": type_ids}) if cycle_ids: conditions.append({"cycle_id__in": cycle_ids}) if module_ids: conditions.append({"module_id__in": module_ids}) if is_archived is not None: conditions.append({"is_archived": is_archived}) if created_by_ids: conditions.append({"created_by_id__in": created_by_ids}) if not conditions: return None if len(conditions) == 1: return conditions[0] return {"and": conditions} - plane_mcp/tools/work_items.py:64-67 (registration)The @mcp.tool() decorator on line 67 registers 'list_work_items' as an MCP tool via FastMCP.
def register_work_item_tools(mcp: FastMCP) -> None: """Register all work item-related tools with the MCP server.""" @mcp.tool() - plane_mcp/tools/__init__.py:27-49 (registration)Top-level registration: register_tools() calls register_work_item_tools(mcp) which registers the list_work_items tool.
def register_tools(mcp: FastMCP) -> None: """Register all tools with the MCP server.""" register_project_tools(mcp) register_work_item_tools(mcp) register_work_item_activity_tools(mcp) register_work_item_comment_tools(mcp) register_work_item_link_tools(mcp) register_work_item_relation_tools(mcp) register_work_log_tools(mcp) register_cycle_tools(mcp) register_user_tools(mcp) register_module_tools(mcp) register_initiative_tools(mcp) register_intake_tools(mcp) register_label_tools(mcp) register_page_tools(mcp) register_work_item_property_tools(mcp) register_work_item_type_tools(mcp) register_state_tools(mcp) register_workspace_tools(mcp) register_epic_tools(mcp) register_milestone_tools(mcp) - plane_mcp/tools/work_items.py:68-90 (schema)The function signature defines the input schema (project_id, filter params, pagination, etc.) and return type (list[WorkItem] | list[AdvancedSearchResult]).
def list_work_items( project_id: str | None = None, query: str | None = None, assignee_ids: list[str] | None = None, state_ids: list[str] | None = None, state_groups: list[str] | None = None, priorities: list[str] | None = None, label_ids: list[str] | None = None, type_ids: list[str] | None = None, cycle_ids: list[str] | None = None, module_ids: list[str] | None = None, is_archived: bool | None = None, created_by_ids: list[str] | None = None, workspace_search: bool = False, limit: int | None = None, cursor: str | None = None, per_page: int | None = None, expand: str | None = None, fields: str | None = None, order_by: str | None = None, external_id: str | None = None, external_source: str | None = None, ) -> list[WorkItem] | list[AdvancedSearchResult]: