-
Notifications
You must be signed in to change notification settings - Fork 24
feat: add search issues tools #37
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
WalkthroughAdds a new search_issues tool and registers it in the server initialization. The tool builds a query from provided parameters and issues a GET request to Plane’s issues search endpoint using the workspace slug from an environment variable, returning pretty-printed JSON as text content. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor U as Client
participant S as MCP Server
participant T as search_issues Tool
participant API as Plane API
U->>S: invoke tool "search_issues"(search, limit?, project_id?, workspace_search?)
S->>T: execute
T->>T: Build URLSearchParams (search, limit?, project_id?, workspace_search?)
T->>API: GET /workspaces/{PLANE_WORKSPACE_SLUG}/issues/search/?query
API-->>T: JSON response
T-->>S: Pretty-printed JSON (text)
S-->>U: content: [{ type: "text", text }]
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal). Please share your feedback with us on this Discord post. 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: 2
🧹 Nitpick comments (2)
src/tools/search-issues.ts (2)
8-10
: Polish tool description for clarity.Minor grammar tweak improves readability.
- "Use this to search issues by text query. This requests project_id as uuid parameter. If you have a readable identifier for project, you can use the get_projects tool to get the project_id from it", + "Search issues by text query. The project_id parameter is a UUID. If you have a readable project identifier, use the get_projects tool to resolve its project_id.",
11-15
: Tighten input validation (UUID, non-empty search, integer/positive limit, boolean coercion).Prevents silent drops (e.g., limit=0), empty searches, and invalid IDs.
- limit: z.number().describe("The number of issues to return").optional(), - project_id: z.string().describe("The uuid identifier of the project to search issues for").optional(), - search: z.string().describe("The search query"), - workspace_search: z.boolean().describe("Whether to search across all projects in the workspace").optional(), + limit: z.coerce.number().int().min(1).describe("Max issues to return (positive integer)").optional(), + project_id: z.string().uuid().describe("The UUID of the project to search within").optional(), + search: z.string().trim().min(1).describe("The search query (non-empty)"), + workspace_search: z.coerce.boolean().describe("Whether to search across all projects in the workspace").optional(),
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/tools/index.ts
(2 hunks)src/tools/search-issues.ts
(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/tools/index.ts (1)
src/tools/search-issues.ts (1)
registerSearchIssueTools
(6-38)
src/tools/search-issues.ts (1)
src/common/request-helper.ts (1)
makePlaneRequest
(3-36)
🔇 Additional comments (3)
src/tools/index.ts (2)
10-10
: Import looks correct and consistent with ESM .js extension.
19-19
: Registration order LGTM — "search_issues" is registered only once.
Single registration found at src/tools/search-issues.ts:7-8 (server.tool("search_issues", ...)).src/tools/search-issues.ts (1)
11-22
: Confirm mutual-exclusivity of project_id vs workspace_search (or enforce XOR)Repo tool currently sends both params (src/tools/search-issues.ts:11–22). Plane docs list standard issue endpoints but do not document an /issues/search endpoint, and there is a GH feature request for a search API — confirm the server semantics and either validate/reject when both project_id and workspace_search are provided or document which param wins when both are present. (docs.plane.so)
if (limit) queryParams.set("limit", limit.toString()); | ||
if (project_id) queryParams.set("project_id", project_id); | ||
if (workspace_search) queryParams.set("workspace_search", workspace_search.toString()); | ||
if (search) queryParams.set("search", search); |
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.
🛠️ Refactor suggestion
Don’t gate on truthiness; include false/0 and avoid dropping valid values.
Using truthy checks drops limit=0 and workspace_search=false. Prefer explicit undefined checks and always send the required search param.
- if (limit) queryParams.set("limit", limit.toString());
+ if (limit !== undefined) queryParams.set("limit", String(limit));
if (project_id) queryParams.set("project_id", project_id);
- if (workspace_search) queryParams.set("workspace_search", workspace_search.toString());
- if (search) queryParams.set("search", search);
+ if (workspace_search !== undefined) queryParams.set("workspace_search", String(workspace_search));
+ queryParams.set("search", search);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
if (limit) queryParams.set("limit", limit.toString()); | |
if (project_id) queryParams.set("project_id", project_id); | |
if (workspace_search) queryParams.set("workspace_search", workspace_search.toString()); | |
if (search) queryParams.set("search", search); | |
if (limit !== undefined) queryParams.set("limit", String(limit)); | |
if (project_id) queryParams.set("project_id", project_id); | |
if (workspace_search !== undefined) queryParams.set("workspace_search", String(workspace_search)); | |
queryParams.set("search", search); |
🤖 Prompt for AI Agents
In src/tools/search-issues.ts around lines 19 to 22, the current truthy checks
drop valid falsy values like limit=0 and workspace_search=false and may omit the
required search param; change the guards to explicit undefined/null checks
(e.g., check for !== undefined && !== null) so limit and workspace_search are
set even when falsy, and always set the search query parameter (without gating
on truthiness) to ensure it is sent.
const response = await makePlaneRequest( | ||
"GET", | ||
`workspaces/${process.env.PLANE_WORKSPACE_SLUG}/issues/search/?${queryParams.toString()}` | ||
); |
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.
Guard missing workspace slug and URL-encode it.
Without PLANE_WORKSPACE_SLUG this hits workspaces/undefined/…, yielding confusing failures. Also encode the slug for safety.
- const response = await makePlaneRequest(
- "GET",
- `workspaces/${process.env.PLANE_WORKSPACE_SLUG}/issues/search/?${queryParams.toString()}`
- );
+ const slug = process.env.PLANE_WORKSPACE_SLUG;
+ if (!slug) {
+ throw new Error("Environment variable PLANE_WORKSPACE_SLUG is required for search_issues.");
+ }
+ const path = `workspaces/${encodeURIComponent(slug)}/issues/search/?${queryParams.toString()}`;
+ const response = await makePlaneRequest("GET", path);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const response = await makePlaneRequest( | |
"GET", | |
`workspaces/${process.env.PLANE_WORKSPACE_SLUG}/issues/search/?${queryParams.toString()}` | |
); | |
const slug = process.env.PLANE_WORKSPACE_SLUG; | |
if (!slug) { | |
throw new Error("Environment variable PLANE_WORKSPACE_SLUG is required for search_issues."); | |
} | |
const path = `workspaces/${encodeURIComponent(slug)}/issues/search/?${queryParams.toString()}`; | |
const response = await makePlaneRequest("GET", path); |
🤖 Prompt for AI Agents
In src/tools/search-issues.ts around lines 24 to 27, the code uses
process.env.PLANE_WORKSPACE_SLUG directly when building the request path which
can produce confusing failures if the env var is missing and is unsafe for
special characters; add a guard that checks for the presence of
PLANE_WORKSPACE_SLUG and either throw a clear Error or return a rejected promise
if it's undefined/empty, and use
encodeURIComponent(process.env.PLANE_WORKSPACE_SLUG) when interpolating the slug
into the URL so the workspace slug is URL-encoded.
In the example provided (pasted below), the endpoint did not include
When I follow the example implementation and test the workspace wide issue search, I get a 404 error.
However, I find that using project_id in the path param correctly returns issues.
Is |
@sarahyun02 looks like you missed Example curl
|
Description
search_issues
tool insrc/tools/search-issues.ts
src/tools/index.ts
to register the new toolUsage
The tool can be used to search issues by text query.
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Chores