-
Notifications
You must be signed in to change notification settings - Fork 28
feat: implement unified search_events tool with natural language queries #375
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: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
✅ All tests successful. No failed tests found. Additional details and impacted files@@ Coverage Diff @@
## main #375 +/- ##
==========================================
+ Coverage 62.65% 62.94% +0.28%
==========================================
Files 77 78 +1
Lines 6879 7491 +612
Branches 620 666 +46
==========================================
+ Hits 4310 4715 +405
- Misses 2569 2776 +207
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Turning into a large patch as I'm trying to clean up evals in addition as I had to expand them.. |
- Fix update-issue.eval.ts: remove unnecessary find_organizations call when issueUrl provided - Fix prompts.ts: correct template literal interpolation for search_events example - Fix package.json: replace hardcoded vitest path with portable command - Fix ToolPredictionScorer: better handle "org/project" format and team assignment description - Update tool descriptions to accurately reflect capabilities All critical functionality bugs resolved, 38/41 tests now passing. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
….4.0 - Changed all test data from 'expectedTools' to 'expected' field name - Fixed ToolPredictionScorer to follow expected sequences exactly - All 41 tests now passing with perfect scores - Resolved discrepancy between tests expecting/not expecting discovery calls The vitest-evals 0.4.0 requires 'expected' field name for test expectations. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Removed legacy TaskRunner (all tests use SimpleTaskRunner) - Removed unused scoring functions: Factuality, ToolUsage, SearchEventsScorer - Removed detectTool, detectToolWithConfidence, getRelatedTools - Removed TOOL_PATTERNS and all related pattern matching code - Removed captureToolCalls option (always returns TaskResult format) - Simplified TaskRunner options handling Reduced file from 908 lines to 150 lines (83% reduction) while maintaining all functionality. All 41 tests still pass. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Replace \S+ with [^\s]+ in regular expressions to prevent catastrophic backtracking. This addresses the polynomial regular expression security issue flagged in PR review.
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.
Pull Request Overview
This PR introduces a unified search_events
tool to replace find_errors
and find_transactions
, updates dependencies (including vitest-evals
to 0.4.0), and modernizes testing to use tool-call focused evals.
- Add new
search_events
tool with natural language query support - Remove old
find_errors
andfind_transactions
exports - Upgrade to
vitest-evals
0.4.0 and switch toToolPredictionScorer
Reviewed Changes
Copilot reviewed 53 out of 54 changed files in this pull request and generated 1 comment.
File | Description |
---|---|
pnpm-workspace.yaml | Added date-fns and bumped vitest-evals to 0.4.0 |
packages/mcp-server/src/tools/search-events.ts | Implemented new search_events tool |
packages/mcp-server/src/tools/search-events.test.ts | Added tests for search_events |
packages/mcp-server/src/tools/index.ts | Swapped out find_errors /find_transactions for search_events |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (3)
packages/mcp-server/src/tools/search-events.ts:173
- The rules string contains a stray '+-' prefix. Remove the leading '+' so each item starts with a single '-' for proper list formatting.
- Use level field for severity (error, warning, info, debug)
packages/mcp-server/src/tools/search-events.ts:188
- The rules string for logs has an extra '+' before the dash. Remove the '+' so the list marker is just '-'.
- Use severity field for log levels (fatal, error, warning, info, debug, trace)
packages/mcp-server/src/tools/search-events.ts:178
- In the examples string, remove the leading '+' before the '-' so the example list renders correctly.
- "unhandled errors in production" → error.handled:false AND environment:production
.default(false) | ||
.describe("Include explanation of how the query was translated"), | ||
}, | ||
async handler(params, context: ServerContext) { |
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.
[nitpick] The handler
function spans hundreds of lines and mixes prompt construction, API interaction, and output formatting. Consider extracting parts into smaller helper functions to improve readability and maintainability.
Copilot uses AI. Check for mistakes.
- Extract formatErrorResults() for error-specific formatting (35 lines) - Extract formatLogResults() for log-specific formatting (68 lines) - Extract formatSpanResults() for span-specific formatting (36 lines) - Extract buildSystemPrompt() for AI prompt construction - Extract getProjectId() for project slug to ID conversion Reduces handler from ~320 lines to ~80 lines, improving readability and maintainability without changing functionality.
Instead of fetching all projects with listProjects() and filtering client-side, we now use a dedicated getProject() method that fetches a single project by slug or ID. This is more efficient and reduces API load. - Added getProject() method to SentryApiService - Updated search-events to use getProject() instead of listProjects() - Updated tests to mock the single project endpoint - Maintains the requirement that search API needs numeric project IDs 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
const searchTerms = cleanQuery | ||
.replace(/\w+\.\w+:[^\s]+/g, "") // Remove field.subfield:value pairs |
Check failure
Code scanning / CodeQL
Polynomial regular expression used on uncontrolled data High
regular expression
library input
This
regular expression
library input
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.
Bug: Misleading Parameter Name Causes API Confusion
The searchEvents
method's projectSlug
parameter is misleadingly named, as it expects a numeric project ID (as a string) rather than a project slug. While current callers correctly pass stringified project IDs, this naming mismatch creates a confusing API interface that could lead to incorrect usage and future bugs if developers attempt to pass actual project slugs.
packages/mcp-server/src/api-client/client.ts#L1369-L1424
sentry-mcp/packages/mcp-server/src/api-client/client.ts
Lines 1369 to 1424 in 903600d
/** | |
* Searches for events in Sentry using a general query. | |
* This method is used by the search_events tool for semantic search. | |
*/ | |
async searchEvents( | |
{ | |
organizationSlug, | |
query, | |
fields, | |
limit = 10, | |
projectSlug, | |
dataset = "spans", | |
statsPeriod, | |
sort = "-timestamp", | |
}: { | |
organizationSlug: string; | |
query: string; | |
fields: string[]; | |
limit?: number; | |
projectSlug?: string; | |
dataset?: "spans" | "errors" | "ourlogs"; | |
statsPeriod?: string; | |
sort?: string; | |
}, | |
opts?: RequestOptions, | |
) { | |
const queryParams = new URLSearchParams(); | |
queryParams.set("per_page", limit.toString()); | |
queryParams.set("query", query); | |
queryParams.set("referrer", "sentry-mcp"); | |
queryParams.set("dataset", dataset); | |
if (statsPeriod) { | |
queryParams.set("statsPeriod", statsPeriod); | |
} | |
queryParams.set("sort", sort); | |
// Add project filter if specified | |
if (projectSlug) { | |
queryParams.set("project", projectSlug); | |
} | |
// Add dataset-specific parameters | |
if (dataset === "spans") { | |
queryParams.set("allowAggregateConditions", "0"); | |
queryParams.set("useRpc", "1"); | |
} | |
// Add each field as a separate parameter | |
for (const field of fields) { | |
queryParams.append("field", field); | |
} | |
const apiUrl = `/organizations/${organizationSlug}/events/?${queryParams.toString()}`; | |
return await this.requestJSON(apiUrl, undefined, opts); | |
} |
Was this report helpful? Give feedback by reacting with 👍 or 👎
Summary
This PR implements a unified
search_events
tool that replaces the separatefind_errors
andfind_transactions
tools, providing a more flexible and powerful way to search Sentry data using natural language queries. Additionally, this PR modernizes the entire evaluation system to use vitest-evals 0.4.0 with tool-call focused testing.Key Changes
New
search_events
ToolTool Consolidation
find_errors
andfind_transactions
from tool exportsfind_errors_in_file
prompt to use the newsearch_events
toolEvaluation System Overhaul
Dependencies
@ai-sdk/openai
for natural language query processingExamples
This change improves both the user experience by allowing more intuitive, natural language queries and the development experience with a modernized, more realistic evaluation system.