Skip to content

feat(tower): retrieve_work_item_by_identifier — UUID lookup by 'PROJECT-N'#21

Merged
volodchenkov merged 1 commit into
mainfrom
feat/retrieve-work-item-by-identifier
May 18, 2026
Merged

feat(tower): retrieve_work_item_by_identifier — UUID lookup by 'PROJECT-N'#21
volodchenkov merged 1 commit into
mainfrom
feat/retrieve-work-item-by-identifier

Conversation

@volodchenkov

@volodchenkov volodchenkov commented May 18, 2026

Copy link
Copy Markdown
Owner

Summary

  • New MCP tool mcp__plane-tower__retrieve_work_item_by_identifier — resolves a human-readable identifier (<PROJECT_IDENTIFIER>-<N>, e.g. COINEX-72) to its full work-item record with UUID.
  • Counterpart to pickup_issue for interactive use when the operator has only the canonical identifier (from a Plane browse URL or comment) and no UUID. SDLC-pipeline agents continue to use pickup_issue — they receive UUIDs via the spawn prompt.
  • Underlying PlaneClient.retrieve_issue_by_sequence_id walks list_issues and short-circuits on first match, since Plane v1 silently ignores ?sequence_id= as a query filter (same category as ?parent=).
  • Workspace auto-resolves via project_identifier registry when the prefix is registered; can be overridden via explicit workspace= arg.

Motivation

Interactive users (operators in chat, ad-hoc tower calls) routinely have only the COINEX-72-style identifier, never the UUID — Plane's /browse/ URL doesn't even expose UUID. Until this PR, the only path was list_sub_issues(root_uuid) which itself needs a UUID, or a raw REST call outside MCP.

Test plan

  • tests/test_plane_client.py::test_retrieve_issue_by_sequence_id_finds_match — short-circuit on match
  • tests/test_plane_client.py::test_retrieve_issue_by_sequence_id_returns_none_when_missing — None on absent sequence
  • tests/test_mcp_tower.py::test_retrieve_work_item_by_identifier_happy_path — full resolve via prefix
  • tests/test_mcp_tower.py::test_retrieve_work_item_by_identifier_case_insensitivetest-42 accepted
  • tests/test_mcp_tower.py::test_retrieve_work_item_by_identifier_malformed_raises — strict shape contract
  • tests/test_mcp_tower.py::test_retrieve_work_item_by_identifier_not_found_raises — clear error
  • Full suite: 206 passed
  • ruff check + ruff format clean

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added ability to retrieve work items using human-readable identifiers (e.g., PROJECT-123 format, case-insensitive)
    • Implemented issue lookup by sequence ID within a project
  • Tests

    • Added comprehensive test coverage for identifier resolution and error handling

Review Change Stack

…CT-N'

Counterpart to pickup_issue for interactive use when the operator has only
the canonical identifier (e.g. from a Plane browse URL or comment reference)
and no UUID. SDLC-pipeline agents continue to use pickup_issue — they
receive UUIDs in the spawn prompt.

Identifier parsing is strict (^[A-Z][A-Z0-9]*-\d+$, case-insensitive),
workspace auto-resolves via project_identifier when registered.
Underlying PlaneClient.retrieve_issue_by_sequence_id walks list_issues and
short-circuits on first match, since Plane v1 silently ignores
?sequence_id= as a query filter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 18, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e69bfc8c-172d-4fef-8efe-cb831132fe9b

📥 Commits

Reviewing files that changed from the base of the PR and between bb1f689 and 5a78797.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • src/plane_conductor/mcp_tower.py
  • src/plane_conductor/plane_client.py
  • tests/test_mcp_tower.py
  • tests/test_plane_client.py

Walkthrough

This PR adds an identifier-based work item lookup system. PlaneClient gains a retrieve_issue_by_sequence_id helper that searches paginated issue lists, and a new MCP tool retrieve_work_item_by_identifier validates human-readable PROJECT-N identifiers and routes them to the correct workspace before retrieval. Comprehensive tests and changelog documentation are included.

Changes

Work item identifier lookup

Layer / File(s) Summary
PlaneClient sequence ID lookup helper
src/plane_conductor/plane_client.py, tests/test_plane_client.py
PlaneClient.retrieve_issue_by_sequence_id iterates list_issues results and returns the first issue matching the provided sequence_id, or None when no match is found. Tests verify successful match retrieval and None return on missing sequences.
MCP tool for identifier-based resolution
src/plane_conductor/mcp_tower.py, tests/test_mcp_tower.py
New retrieve_work_item_by_identifier MCP tool validates identifiers in PROJECT_IDENTIFIER-N format, resolves workspace context (explicit or via registered project identifier), calls PlaneClient.retrieve_issue_by_sequence_id, and returns the formatted issue with canonical identifier. Raises ValueError for malformed or missing identifiers. Tests cover valid resolution, case-insensitive input, malformed formats, and not-found sequences.
Feature documentation
CHANGELOG.md
Changelog entries document the new PlaneClient.retrieve_issue_by_sequence_id and retrieve_work_item_by_identifier capabilities under Unreleased → Added.

Sequence Diagram

sequenceDiagram
  participant Caller
  participant MCPTool as retrieve_work_item_by_identifier
  participant PlaneClient
  participant PlaneAPI as Plane API
  Caller->>MCPTool: identifier, optional workspace
  MCPTool->>MCPTool: validate format against _IDENTIFIER_RE
  MCPTool->>MCPTool: parse project_identifier and sequence_id
  MCPTool->>MCPTool: resolve workspace (explicit or via registry)
  MCPTool->>PlaneClient: retrieve_issue_by_sequence_id(project_id, sequence_id)
  PlaneClient->>PlaneAPI: list_issues(project_id)
  PlaneAPI-->>PlaneClient: issues array
  PlaneClient->>PlaneClient: iterate and find first matching sequence_id
  PlaneClient-->>MCPTool: issue record or None
  alt issue found
    MCPTool->>MCPTool: format response with canonical identifier
    MCPTool-->>Caller: issue dict with identifier field
  else issue not found
    MCPTool-->>Caller: ValueError: not found
  end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • volodchenkov/plane-conductor#17: Removes get_issue_by_sequence_id/list_issues re-discovery logic that this PR reintroduces as a new retrieve_issue_by_sequence_id method to support identifier-based lookup.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature: adding a new MCP tool retrieve_work_item_by_identifier that performs UUID lookup via human-readable PROJECT-N identifiers, which is the central change across all modified files.
Docstring Coverage ✅ Passed Docstring coverage is 92.86% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/retrieve-work-item-by-identifier

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@volodchenkov volodchenkov merged commit 5d62d94 into main May 18, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant