Skip to content

feat: add project membership management tools#180

Open
davgordo wants to merge 1 commit into
makeplane:mainfrom
davgordo:feat/member-management-upstream
Open

feat: add project membership management tools#180
davgordo wants to merge 1 commit into
makeplane:mainfrom
davgordo:feat/member-management-upstream

Conversation

@davgordo

@davgordo davgordo commented Jul 16, 2026

Copy link
Copy Markdown

Description

Adds project membership mutation tools for administrative automation:

  • add_project_members adds one or more existing workspace users to a project with Guest, Member, or Admin roles.
  • update_project_member changes a project membership record's role when the caller has a project-membership record UUID.
  • remove_project_member deactivates a project membership when the caller has a project-membership record UUID.

Verified identifier contract:

  • Plane's public project-member listing returns user-shaped records. Each listed id is the workspace-user UUID.
  • The public listing does not expose the project-membership record UUID for existing memberships.
  • The public mutation endpoints return project-membership records. In those responses, id is the project-membership record UUID and member is the workspace-user UUID.
  • update_project_member and remove_project_member therefore accept the membership id returned by add_project_members or another public mutation response; they do not claim that get_project_members can discover arbitrary existing membership IDs.

This uses a small adapter around the SDK resource's lower-level HTTP methods because plane-sdk==0.2.19 exposes project member listing but not public mutation helpers.

Type of Change

  • Bug fix
  • Feature
  • Improvement
  • Code refactoring
  • Performance improvements
  • Documentation update

Test Scenarios

Unit tests cover:

  • current filters and pagination on get_project_members
  • verified identifier meanings for listing versus mutation responses
  • membership ID returned by add being usable for update
  • single-member and multi-member additions
  • empty input and duplicate input rejection before API calls
  • valid role values 5, 15, and 20
  • invalid role rejection before API calls
  • active duplicate member validation error propagation
  • inactive membership re-add/reactivation validation error propagation
  • update endpoint and payload
  • removal endpoint and HTTP 204/None return behavior
  • permission and validation error propagation
  • FastMCP registration, input schema, and output schema

Commands run:

  • .venv/bin/ruff format plane_mcp/ tests/
  • .venv/bin/ruff check plane_mcp/tools/projects.py tests/test_project_memberships.py
  • .venv/bin/pytest tests/test_project_memberships.py -v
  • .venv/bin/python -m compileall plane_mcp
  • git diff --check

References

Addresses #175

Summary by CodeRabbit

  • New Features

    • Added tools to add, update, and remove project members.
    • Supports bulk member additions with role assignment.
    • Added validation for supported roles, duplicate members, and empty requests.
    • Clarified project-member identifiers returned when viewing members.
  • Documentation

    • Updated the available tools documentation to include project-member management.
  • Tests

    • Added coverage for member management, validation, permissions, pagination, and tool schemas.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Project membership management now supports adding members, updating roles, and removing memberships through MCP tools, with role/input validation, REST integration, clarified member identifiers, documentation updates, and end-to-end coverage.

Changes

Project Membership Management

Layer / File(s) Summary
Membership models and REST bridge
plane_mcp/tools/projects.py, tests/test_project_memberships.py
Adds project role types, mutation response models, REST create/update/delete methods, and deterministic fake-client fixtures.
Membership tool lifecycle
plane_mcp/tools/projects.py, tests/test_project_memberships.py, tests/test_integration.py, README.md
Registers add, update, and remove tools; clarifies workspace-user versus membership IDs; and updates tool availability, schemas, and lifecycle tests.
Validation and error behavior
plane_mcp/tools/projects.py, tests/test_project_memberships.py
Validates roles, non-empty input, and duplicate members while preserving API validation, uniqueness, and permission errors.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MCPTool
  participant ProjectMembershipAPI
  participant PlaneRESTAPI
  MCPTool->>ProjectMembershipAPI: Create, update, or delete membership
  ProjectMembershipAPI->>PlaneRESTAPI: Send membership REST request
  PlaneRESTAPI-->>ProjectMembershipAPI: Return membership response or error
  ProjectMembershipAPI-->>MCPTool: Return mutation result
Loading

Possibly related issues

  • makeplane/plane-mcp-server#175 — Directly covers the requested project membership add, update/reactivate, and remove operations.

Suggested reviewers: akhil-vamshi-konam

🚥 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 clearly summarizes the main change: adding project membership management tools.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
plane_mcp/tools/projects.py (3)

386-388: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Refactor the list endpoint to omit pagination metadata.

Based on learnings, list endpoints in plane_mcp/tools should return only the list of items (response.results) and omit the full pagination metadata from the initial response. Since you are modifying the docstring here, consider updating the tool's signature and return statement to return just the results list to conform with this pattern.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plane_mcp/tools/projects.py` around lines 386 - 388, Update the
project-member listing tool’s signature and docstring to describe a list of
member items rather than paginated response metadata, and change its return
statement to return only response.results. Preserve the existing member
retrieval behavior and field mappings.

Source: Learnings


429-434: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Optimize duplicate member detection.

Using list.count() inside a set comprehension results in $O(N^2)$ time complexity. While members is likely small, using a set to track seen elements is more efficient and idiomatic.

♻️ Proposed refactor
-        member_ids = [member.member for member in members]
-        duplicate_member_ids = {member_id for member_id in member_ids if member_ids.count(member_id) > 1}
+        seen = set()
+        duplicate_member_ids = {member.member for member in members if member.member in seen or seen.add(member.member)}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plane_mcp/tools/projects.py` around lines 429 - 434, Update duplicate
detection in the member validation block to use a single-pass seen-set approach,
collecting repeated member IDs without calling list.count() for each item.
Preserve the existing sorted duplicate_list formatting and ValueError message.

440-448: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Consider documenting partial failure behavior during bulk addition.

Because these API calls are executed sequentially, if an error occurs mid-loop (e.g., the second member addition fails), the function will raise an exception. Any successfully created memberships prior to the failure will remain in Plane, but their generated ids will not be returned to the client. The caller will have to filter out the already-added members before retrying to avoid active duplicate errors.

If bulk atomicity is not supported by the underlying API, consider noting this partial-failure behavior in the docstring.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plane_mcp/tools/projects.py` around lines 440 - 448, Document in the
enclosing bulk membership-addition function’s docstring that calls execute
sequentially and may partially succeed: an exception can leave earlier
memberships created while their generated IDs are not returned, requiring
callers to exclude them before retrying.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@plane_mcp/tools/projects.py`:
- Around line 386-388: Update the project-member listing tool’s signature and
docstring to describe a list of member items rather than paginated response
metadata, and change its return statement to return only response.results.
Preserve the existing member retrieval behavior and field mappings.
- Around line 429-434: Update duplicate detection in the member validation block
to use a single-pass seen-set approach, collecting repeated member IDs without
calling list.count() for each item. Preserve the existing sorted duplicate_list
formatting and ValueError message.
- Around line 440-448: Document in the enclosing bulk membership-addition
function’s docstring that calls execute sequentially and may partially succeed:
an exception can leave earlier memberships created while their generated IDs are
not returned, requiring callers to exclude them before retrying.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1eac21b8-4790-4808-b97f-8ad332bf0f8c

📥 Commits

Reviewing files that changed from the base of the PR and between b0fb136 and f788a5d.

📒 Files selected for processing (4)
  • README.md
  • plane_mcp/tools/projects.py
  • tests/test_integration.py
  • tests/test_project_memberships.py

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