-
Notifications
You must be signed in to change notification settings - Fork 0
Reduce MCP list endpoint context #40
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: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -70,6 +70,18 @@ const SQLITE_BUSY = 5; | |||||||||||||||||
| const SQLITE_BUSY_SNAPSHOT = 517; // SQLITE_BUSY | (2 << 8) | ||||||||||||||||||
| const SQLITE_LOCKED = 6; | ||||||||||||||||||
|
|
||||||||||||||||||
| const STORY_FIELD_SETS: Record<FieldSet, string[]> = { | ||||||||||||||||||
| minimal: ["id", "title", "status", "epic_id"], | ||||||||||||||||||
| standard: ["id", "title", "status", "epic_id", "description", "created_at", "updated_at"], | ||||||||||||||||||
| full: ["id", "epic_id", "title", "description", "status", "created_at", "updated_at"], | ||||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
| const EPIC_FIELD_SETS: Record<FieldSet, string[]> = { | ||||||||||||||||||
| minimal: ["id", "title", "status", "priority"], | ||||||||||||||||||
| standard: ["id", "project_id", "title", "description", "priority", "status", "created_at", "updated_at"], | ||||||||||||||||||
| full: ["id", "project_id", "title", "description", "priority", "status", "created_at", "updated_at"], | ||||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
| /** | ||||||||||||||||||
| * Typed error for database lock contention that is recoverable by the user. | ||||||||||||||||||
| * Thrown when node:sqlite reports SQLITE_BUSY or SQLITE_BUSY_SNAPSHOT. | ||||||||||||||||||
|
|
@@ -301,7 +313,7 @@ export class TaskDatabase { | |||||||||||||||||
| * Get tasks with optional filtering | ||||||||||||||||||
| */ | ||||||||||||||||||
| getTasks(opts: GetTasksOptions = {}): Task[] { | ||||||||||||||||||
| const { status, epic_id, priority, story_status, epic_status, limit = 50, fields = "minimal" } = opts; | ||||||||||||||||||
| const { status, epic_id, priority, story_status, epic_status, limit = 10, offset = 0, fields = "minimal", search } = opts; | ||||||||||||||||||
|
|
||||||||||||||||||
|
Comment on lines
315
to
317
|
||||||||||||||||||
| // Build SELECT clause based on fields parameter | ||||||||||||||||||
| const fieldSet = FIELD_SETS[fields] || FIELD_SETS.minimal; | ||||||||||||||||||
|
|
@@ -339,10 +351,15 @@ export class TaskDatabase { | |||||||||||||||||
| params.push(epic_status); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| if (search) { | ||||||||||||||||||
| conditions.push("LOWER(t.title) LIKE LOWER(?)"); | ||||||||||||||||||
| params.push(`%${search}%`); | ||||||||||||||||||
|
Comment on lines
+355
to
+356
|
||||||||||||||||||
| conditions.push("LOWER(t.title) LIKE LOWER(?)"); | |
| params.push(`%${search}%`); | |
| conditions.push("INSTR(LOWER(t.title), LOWER(?)) > 0"); | |
| params.push(search); |
Copilot
AI
Apr 27, 2026
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.
Same LIKE-wildcard issue as getTasks(): getStories search is documented as a substring match, but '%' and '_' in user input will act as wildcards. Escaping LIKE wildcards (or using a literal substring function) would make behavior match the tool description.
Copilot
AI
Apr 27, 2026
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.
Same LIKE-wildcard issue as getTasks()/getStories(): getEpics search currently treats '%' and '_' in user input as wildcards, which can surprise callers expecting a literal substring search. Escaping LIKE wildcards (or using a literal substring function) would align behavior with the API description.
| conditions.push("LOWER(title) LIKE LOWER(?)"); | |
| params.push(`%${search}%`); | |
| const escapedSearch = search | |
| .replace(/\\/g, "\\\\") | |
| .replace(/%/g, "\\%") | |
| .replace(/_/g, "\\_"); | |
| conditions.push("LOWER(title) LIKE LOWER(?) ESCAPE '\\'"); | |
| params.push(`%${escapedSearch}%`); |
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.
STORY_FIELD_SETS and EPIC_FIELD_SETS currently make "standard" and "full" effectively identical (story differs only by column order; epic is identical). This makes the
fieldsparameter misleading and harder to evolve. Consider makingstandardomit some heavier/less-needed fields (e.g., timestamps/project_id) sofullis meaningfully larger, or documenting thatstandard==fullfor these tables.