-
Notifications
You must be signed in to change notification settings - Fork 51
feat: add PLANE_TOOLS env var to filter tool groups #57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: canary
Are you sure you want to change the base?
Conversation
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. 📝 WalkthroughWalkthroughAdds an environment-driven tool registration system: a public immutable Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Env as Environment (PLANE_TOOLS)
participant Registrar as register_tools()
participant Registry as TOOL_GROUPS (mapping)
participant ToolFn as Tool registration functions
Env->>Registrar: read PLANE_TOOLS
Registrar->>Registry: evaluate entries (include / exclude / default)
alt inclusion mode (explicit list)
Registrar->>Registry: select included groups
else exclusion mode (leading '!')
Registrar->>Registry: remove excluded groups
else default (unset/empty)
Registrar->>Registry: select all groups
end
loop for each selected group
Registrar->>ToolFn: call registration function
ToolFn-->>Registrar: registration complete (or log warning)
end
Registrar-->>Env: finished
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
plane_mcp/tools/__init__.py (2)
17-27: Consider making TOOL_GROUPS immutable.Since
TOOL_GROUPSis a new public export, consider making it immutable to prevent unintended modifications by external code. This ensures the tool registry remains stable.🔎 Proposed fix using MappingProxyType
+from types import MappingProxyType + from fastmcp import FastMCP from plane_mcp.tools.cycles import register_cycle_tools# Map of tool group names to their registration functions -TOOL_GROUPS: dict[str, Callable[[FastMCP], None]] = { +_TOOL_GROUPS: dict[str, Callable[[FastMCP], None]] = { "projects": register_project_tools, "work_items": register_work_item_tools, "cycles": register_cycle_tools, "users": register_user_tools, "modules": register_module_tools, "initiatives": register_initiative_tools, "intake": register_intake_tools, "work_item_properties": register_work_item_property_tools, } + +TOOL_GROUPS = MappingProxyType(_TOOL_GROUPS)
52-58: Consider validating group names to catch typos.Invalid group names in
PLANE_TOOLSare silently ignored, which could lead to confusion if users misspell a group name. Consider adding validation to warn users about unrecognized groups.🔎 Proposed enhancement with validation
def register_tools(mcp: FastMCP) -> None: """Register tools with the MCP server based on PLANE_TOOLS configuration. The PLANE_TOOLS environment variable controls which tool groups are registered: - Not set or empty: Register all tools (default) - Comma-separated list: Register only specified groups Example: PLANE_TOOLS=projects,work_items,users - Exclusion mode (prefix with !): Register all except specified groups Example: PLANE_TOOLS=!cycles,!modules,!initiatives Available tool groups: projects, work_items, cycles, users, modules, initiatives, intake, work_item_properties """ tools_config = os.getenv("PLANE_TOOLS", "").strip() if not tools_config: # Default: register all tools enabled_groups = set(TOOL_GROUPS.keys()) elif tools_config.startswith("!"): # Exclusion mode: start with all, remove specified groups excluded = {t.strip().lstrip("!") for t in tools_config.split(",")} + # Validate excluded group names + invalid = excluded - set(TOOL_GROUPS.keys()) - {""} + if invalid: + import logging + logging.warning(f"Unknown tool groups in PLANE_TOOLS will be ignored: {', '.join(invalid)}") enabled_groups = set(TOOL_GROUPS.keys()) - excluded else: # Inclusion mode: only register specified groups enabled_groups = {t.strip() for t in tools_config.split(",")} + # Validate included group names + invalid = enabled_groups - set(TOOL_GROUPS.keys()) - {""} + if invalid: + import logging + logging.warning(f"Unknown tool groups in PLANE_TOOLS will be ignored: {', '.join(invalid)}") for name, register_fn in TOOL_GROUPS.items(): if name in enabled_groups: register_fn(mcp)
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
plane_mcp/tools/__init__.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Cursor Bugbot
🔇 Additional comments (2)
plane_mcp/tools/__init__.py (2)
3-4: LGTM!The imports are correctly added to support environment variable access and type hints for the new filtering logic.
30-58: Well-structured implementation!The environment variable parsing logic correctly handles all documented use cases:
- Default mode (empty) registers all tools
- Inclusion mode registers only specified groups
- Exclusion mode registers all except specified groups
The logic properly handles whitespace, trailing commas, and empty strings. The docstring provides clear examples for users.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR is being reviewed by Cursor Bugbot
Details
Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
9b19501 to
12eafa4
Compare
Allows users to reduce context usage by enabling only needed tool groups. Usage: - PLANE_TOOLS=projects,work_items,users (inclusion mode) - PLANE_TOOLS=!cycles,!modules,!initiatives (exclusion mode) Available groups: projects, work_items, cycles, users, modules, initiatives, intake, work_item_properties 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
12eafa4 to
a1bfdc0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
plane_mcp/tools/__init__.py (2)
19-30: LGTM!The pattern of using a private
_TOOL_GROUPSdict with a public immutableTOOL_GROUPSproxy is excellent for preventing accidental modifications. The mapping is clean and well-structured.Optional: Add explicit type annotation for clarity
Adding an explicit type annotation would improve code documentation:
} -TOOL_GROUPS = MappingProxyType(_TOOL_GROUPS) +TOOL_GROUPS: MappingProxyType[str, Callable[[FastMCP], None]] = MappingProxyType(_TOOL_GROUPS)
60-63: Consider clarifying the warning message.The warning message "Unprefixed items in exclusion mode will be ignored" could be misinterpreted. Users might think these groups won't be registered at all, when actually they will be registered (because they're not excluded).
Suggested improvement for clarity
logging.warning( - f"Unprefixed items in exclusion mode will be ignored: {unprefixed_str}. " + f"Unprefixed items in exclusion mode will not be excluded (groups will still be registered): {unprefixed_str}. " f"Did you mean: {suggested}?" )
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
plane_mcp/tools/__init__.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Cursor Bugbot
🔇 Additional comments (3)
plane_mcp/tools/__init__.py (3)
3-6: LGTM!The new imports are appropriate and necessary for the environment-based configuration and immutable tool groups mapping.
34-45: LGTM!The docstring is comprehensive and provides clear examples for each mode. The listing of available tool groups is particularly helpful for users.
71-83: LGTM!The inclusion mode parsing and registration loop are correctly implemented. Empty strings from malformed input (trailing/double commas) are silently ignored, which is reasonable behavior. The validation warnings will help users catch typos in group names.
| # Exclusion mode: start with all, remove specified groups | ||
| # Only items prefixed with ! are excluded | ||
| items = [t.strip() for t in tools_config.split(",")] | ||
| excluded = {t[1:] for t in items if t.startswith("!")} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whitespace after ! prefix not stripped in exclusion
In exclusion mode, when extracting group names with t[1:], whitespace after the ! prefix is preserved. If a user writes PLANE_TOOLS="! cycles" (with a space after !), the excluded set contains " cycles" (with leading space), which doesn't match "cycles" in TOOL_GROUPS. This causes the exclusion to silently fail—all groups remain enabled. A warning is logged about unknown groups, but the behavior is unexpected compared to inclusion mode which properly strips each item.
Summary
Adds environment variable-based filtering to reduce MCP tool token usage by enabling only needed tool groups.
Usage
Inclusion mode - only register specified groups:
Exclusion mode - register all except specified groups:
Default (no env var): All tools registered (backwards compatible)
Available tool groups
projects(9 tools)work_items(6 tools)cycles(12 tools)users(1 tool)modules(11 tools)initiatives(5 tools)intake(5 tools)work_item_properties(5 tools)Use case
LLM-based MCP clients have limited context windows. Each tool definition consumes tokens (~600-1500 per tool). Users who don't need all features can exclude unused tool groups to free up context for actual conversation.
Example: Excluding cycles, modules, and initiatives reduces tool count from 55 to 27, saving ~18k tokens.
Note
Introduces environment-controlled tool registration to reduce loaded MCP tools.
PLANE_TOOLSenv var supports inclusion (projects,work_items,...), exclusion (!cycles,!modules,...), and default (all) modesregister_toolsto register only enabled groups; iteratesTOOL_GROUPSand applies selection logicTOOL_GROUPSmapping for group→registration functionWritten by Cursor Bugbot for commit a1bfdc0. This will update automatically on new commits. Configure here.
Summary by CodeRabbit
New Features
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.