Skip to content

Commit 57c65e7

Browse files
committed
pagination, prompt updates
1 parent 304f29a commit 57c65e7

File tree

6 files changed

+591
-247
lines changed

6 files changed

+591
-247
lines changed

README.md

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -830,24 +830,75 @@ Options are:
830830
- `project_number`: The project's number. (number, required)
831831

832832
- **list_project_fields** - List project fields
833+
- `after`: Forward pagination cursor. Use when the previous response's pageInfo.hasNextPage=true. Supply pageInfo.nextCursor as 'after' and immediately request the next page. LOOP UNTIL pageInfo.hasNextPage=false (don't stop early). Keep per_page identical for every page. (string, optional)
834+
- `before`: Backward pagination cursor (rare): supply to move to the preceding page using pageInfo.prevCursor. Not needed for normal forward iteration. (string, optional)
833835
- `owner`: If owner_type == user it is the handle for the GitHub user account. If owner_type == org it is the name of the organization. The name is not case sensitive. (string, required)
834836
- `owner_type`: Owner type (string, required)
835-
- `per_page`: Number of results per page (max 100, default: 30) (number, optional)
837+
- `per_page`: Results per page (max 50). Keep constant across paginated requests; changing mid-sequence can complicate page traversal. (number, optional)
836838
- `project_number`: The project's number. (number, required)
837839

838840
- **list_project_items** - List project items
839-
- `fields`: Specific list of field IDs to include in the response (e.g. ["102589", "985201", "169875"]). If not provided, only the title field is included. (string[], optional)
841+
- `after`: Forward pagination cursor. Use when the previous response's pageInfo.hasNextPage=true. Supply pageInfo.nextCursor as 'after' and immediately request the next page. LOOP UNTIL pageInfo.hasNextPage=false (don't stop early). Keep query, fields, and per_page identical for every page. (string, optional)
842+
- `before`: Backward pagination cursor (rare): supply to move to the preceding page using pageInfo.prevCursor. Not needed for normal forward iteration. (string, optional)
843+
- `fields`: Field IDs to include (e.g. ["102589", "985201"]). CRITICAL: Always provide to get field values. Without this, only titles returned. Get IDs from list_project_fields first. (string[], optional)
840844
- `owner`: If owner_type == user it is the handle for the GitHub user account. If owner_type == org it is the name of the organization. The name is not case sensitive. (string, required)
841845
- `owner_type`: Owner type (string, required)
842-
- `per_page`: Number of results per page (max 100, default: 30) (number, optional)
846+
- `per_page`: Results per page (max 50). Keep constant across paginated requests; changing mid-sequence can complicate page traversal. (number, optional)
843847
- `project_number`: The project's number. (number, required)
844-
- `query`: Search query to filter items (string, optional)
848+
- `query`: Query string - For advanced filtering of project items using GitHub's search syntax:
849+
850+
MUST reflect user intent; strongly prefer explicit content type if narrowed:
851+
- "open issues" → state:open is:issue
852+
- "merged PRs" → state:merged is:pr
853+
- "items updated this week" → updated:>@today-7d (omit type only if mixed desired)
854+
- "list all P1 priority items" → priority:p1 (omit state if user wants all, omit type if user speciifies "items")
855+
- "list all open P2 issues" → is:issue state:open priority:p2 (include state if user wants open or closed, include type if user speciifies "issues" or "PRs")
856+
- "all open issues I'm working on" → is:issue state:open assignee:@me
857+
Query Construction Heuristics:
858+
a. Extract type nouns: issues → is:issue | PRs, Pulls, or Pull Requests → is:pr | tasks/tickets → is:issue (ask if ambiguity)
859+
b. Map temporal phrases: "this week" → updated:>@today-7d
860+
c. Map negations: "excluding wontfix" → -label:wontfix
861+
d. Map priority adjectives: "high/sev1/p1" → priority:high OR priority:p1 (choose based on field presence)
862+
863+
Syntax Essentials (items):
864+
AND: space-separated. (label:bug priority:high).
865+
OR: comma inside one qualifier (label:bug,critical).
866+
NOT: leading '-' (-label:wontfix).
867+
Hyphenate multi-word field names. (team-name:"Backend Team", story-points:>5).
868+
Quote multi-word values. (status:"In Review" team-name:"Backend Team").
869+
Ranges: points:1..3, updated:<@today-30d.
870+
Wildcards: title:*crash*, label:bug*.
871+
Assigned to User: assignee:@me | assignee:username | no:assignee
872+
873+
Common Qualifier Glossary (items):
874+
is:issue | is:pr | state:open|closed|merged | assignee:@me|username | label:NAME | status:VALUE |
875+
priority:p1|high | sprint-name:@current | team-name:"Backend Team" | parent-issue:"org/repo#123" |
876+
updated:>@today-7d | title:*text* | -label:wontfix | label:bug,critical | no:assignee | has:label
877+
878+
Pagination Mandate:
879+
Do not analyze until ALL pages fetched (loop while pageInfo.hasNextPage=true). Always reuse identical query, fields, per_page.
880+
881+
Recovery Guidance:
882+
If user provides ambiguous request ("show project activity") → ask clarification OR return mixed set (omit is:issue/is:pr). If user mixes project + item qualifiers in one phrase → split: run list_projects for discovery, then list_project_items for detail.
883+
884+
Never:
885+
- Infer field IDs; fetch via list_project_fields.
886+
- Drop 'fields' param on subsequent pages if field values are needed. (string, optional)
845887

846888
- **list_projects** - List projects
889+
- `after`: Forward pagination cursor. Use when the previous response's pageInfo.hasNextPage=true. Supply pageInfo.nextCursor as 'after' and immediately request the next page. LOOP UNTIL pageInfo.hasNextPage=false (don't stop early). Keep query and per_page identical for every page. (string, optional)
890+
- `before`: Backward pagination cursor (rare): supply to move to the preceding page using pageInfo.prevCursor. Not needed for normal forward iteration. (string, optional)
847891
- `owner`: If owner_type == user it is the handle for the GitHub user account. If owner_type == org it is the name of the organization. The name is not case sensitive. (string, required)
848892
- `owner_type`: Owner type (string, required)
849-
- `per_page`: Number of results per page (max 100, default: 30) (number, optional)
850-
- `query`: Filter projects by a search query (matches title and description) (string, optional)
893+
- `per_page`: Results per page (max 50). Keep constant across paginated requests; changing mid-sequence can complicate page traversal. (number, optional)
894+
- `query`: Filter projects by a search query
895+
896+
Scope: title text + open/closed state.
897+
PERMITTED qualifiers: is:open, is:closed (state), simple title terms.
898+
FORBIDDEN: is:issue, is:pr, assignee:, label:, status:, sprint-name:, parent-issue:, team-name:, priority:, etc.
899+
Examples:
900+
- roadmap is:open
901+
- is:open feature planning (string, optional)
851902

852903
- **update_project_item** - Update project item
853904
- `item_id`: The unique identifier of the project item. This is not the issue or pull request ID. (number, required)

pkg/github/__toolsnaps__/list_project_fields.snap

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@
66
"description": "List Project fields for a user or org",
77
"inputSchema": {
88
"properties": {
9+
"after": {
10+
"description": "Forward pagination cursor. Use when the previous response's pageInfo.hasNextPage=true. Supply pageInfo.nextCursor as 'after' and immediately request the next page. LOOP UNTIL pageInfo.hasNextPage=false (don't stop early). Keep per_page identical for every page.",
11+
"type": "string"
12+
},
13+
"before": {
14+
"description": "Backward pagination cursor (rare): supply to move to the preceding page using pageInfo.prevCursor. Not needed for normal forward iteration.",
15+
"type": "string"
16+
},
917
"owner": {
1018
"description": "If owner_type == user it is the handle for the GitHub user account. If owner_type == org it is the name of the organization. The name is not case sensitive.",
1119
"type": "string"
@@ -19,7 +27,7 @@
1927
"type": "string"
2028
},
2129
"per_page": {
22-
"description": "Number of results per page (max 100, default: 30)",
30+
"description": "Results per page (max 50). Keep constant across paginated requests; changing mid-sequence can complicate page traversal.",
2331
"type": "number"
2432
},
2533
"project_number": {

pkg/github/__toolsnaps__/list_project_items.snap

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,19 @@
33
"title": "List project items",
44
"readOnlyHint": true
55
},
6-
"description": "List Project items for a user or org",
6+
"description": "GitHub Projects V2 - List Project Items with advanced filtering and field selection\n\nField usage:\n\n- Call list_project_fields first to get IDs/types.\n- Use EXACT returned field names (case-insensitive match). Don't invent names or IDs.\n- Iteration synonyms (sprint/cycle/iteration) only if that field exists; map to the actual name (e.g. sprint:@current).\n- Only include filters for fields that exist and are relevant.\n\nItem query syntax:\nAND = space | OR = comma (label:bug,critical) | NOT = prefix - ( -label:wontfix )\nQuote multi-word values: status:\"In Review\" team-name:\"Backend Team\"\nHyphenate multi-word field names (story-points).\nRanges: points:1..3 dates:2025-01-01..2025-12-31\nComparisons: updated:\u003e@today-7d priority:\u003e1 points:\u003c=10\nWildcards: title:*crash* label:bug*\nTemporal shortcuts: @today @today-7d @today-30d\nIteration shortcuts: @current @next @previous\n\nPagination (mandatory):\nLoop while pageInfo.hasNextPage=true using after=nextCursor. Keep query, fields, per_page IDENTICAL each page.\n\nFields parameter:\nInclude field IDs on EVERY paginated list_project_items call if you need values. Omit → title only.\n\nCounting rules:\n- Count items array length after full pagination.\n- If multi-page: collect all pages, dedupe by item.id (fallback node_id) before totals.\n- Never count field objects, content, or nested arrays as separate items.\n- item.id = project item ID (for updates/deletes). item.content.id = underlying issue/PR ID.\n\nSummary vs list:\n- Summaries ONLY if user uses verbs: analyze | summarize | summary | report | overview | insights.\n- Listing verbs (list/show/get/fetch/display/enumerate) → just enumerate + total.\n\nExamples:\nlist_projects: \"roadmap is:open\"\nlist_project_items: state:open is:issue sprint:@current priority:high updated:\u003e@today-7d\n\nSelf-check before returning:\n☑ Paginated fully ☑ Dedupe by id/node_id ☑ Correct IDs used ☑ Field names valid ☑ Summary only if requested.\n\nReturn COMPLETE data or state what's missing (e.g. pages skipped).",
77
"inputSchema": {
88
"properties": {
9+
"after": {
10+
"description": "Forward pagination cursor. Use when the previous response's pageInfo.hasNextPage=true. Supply pageInfo.nextCursor as 'after' and immediately request the next page. LOOP UNTIL pageInfo.hasNextPage=false (don't stop early). Keep query, fields, and per_page identical for every page.",
11+
"type": "string"
12+
},
13+
"before": {
14+
"description": "Backward pagination cursor (rare): supply to move to the preceding page using pageInfo.prevCursor. Not needed for normal forward iteration.",
15+
"type": "string"
16+
},
917
"fields": {
10-
"description": "Specific list of field IDs to include in the response (e.g. [\"102589\", \"985201\", \"169875\"]). If not provided, only the title field is included.",
18+
"description": "Field IDs to include (e.g. [\"102589\", \"985201\"]). CRITICAL: Always provide to get field values. Without this, only titles returned. Get IDs from list_project_fields first.",
1119
"items": {
1220
"type": "string"
1321
},
@@ -26,15 +34,15 @@
2634
"type": "string"
2735
},
2836
"per_page": {
29-
"description": "Number of results per page (max 100, default: 30)",
37+
"description": "Results per page (max 50). Keep constant across paginated requests; changing mid-sequence can complicate page traversal.",
3038
"type": "number"
3139
},
3240
"project_number": {
3341
"description": "The project's number.",
3442
"type": "number"
3543
},
3644
"query": {
37-
"description": "Search query to filter items",
45+
"description": "Query string - For advanced filtering of project items using GitHub's search syntax:\n\nMUST reflect user intent; strongly prefer explicit content type if narrowed:\n\t- \"open issues\" → state:open is:issue\n\t- \"merged PRs\" → state:merged is:pr\n\t- \"items updated this week\" → updated:\u003e@today-7d (omit type only if mixed desired)\n\t- \"list all P1 priority items\" → priority:p1 (omit state if user wants all, omit type if user speciifies \"items\")\n\t- \"list all open P2 issues\" → is:issue state:open priority:p2 (include state if user wants open or closed, include type if user speciifies \"issues\" or \"PRs\")\n\t- \"all open issues I'm working on\" → is:issue state:open assignee:@me\nQuery Construction Heuristics:\n\ta. Extract type nouns: issues → is:issue | PRs, Pulls, or Pull Requests → is:pr | tasks/tickets → is:issue (ask if ambiguity)\n\tb. Map temporal phrases: \"this week\" → updated:\u003e@today-7d\n\tc. Map negations: \"excluding wontfix\" → -label:wontfix\n\td. Map priority adjectives: \"high/sev1/p1\" → priority:high OR priority:p1 (choose based on field presence)\n\nSyntax Essentials (items):\n AND: space-separated. (label:bug priority:high).\n OR: comma inside one qualifier (label:bug,critical).\n NOT: leading '-' (-label:wontfix).\n Hyphenate multi-word field names. (team-name:\"Backend Team\", story-points:\u003e5).\n Quote multi-word values. (status:\"In Review\" team-name:\"Backend Team\").\n Ranges: points:1..3, updated:\u003c@today-30d.\n Wildcards: title:*crash*, label:bug*.\n\t Assigned to User: assignee:@me | assignee:username | no:assignee\n\nCommon Qualifier Glossary (items):\n is:issue | is:pr | state:open|closed|merged | assignee:@me|username | label:NAME | status:VALUE |\n priority:p1|high | sprint-name:@current | team-name:\"Backend Team\" | parent-issue:\"org/repo#123\" |\n updated:\u003e@today-7d | title:*text* | -label:wontfix | label:bug,critical | no:assignee | has:label\n\nPagination Mandate:\n Do not analyze until ALL pages fetched (loop while pageInfo.hasNextPage=true). Always reuse identical query, fields, per_page.\n\nRecovery Guidance:\n If user provides ambiguous request (\"show project activity\") → ask clarification OR return mixed set (omit is:issue/is:pr). If user mixes project + item qualifiers in one phrase → split: run list_projects for discovery, then list_project_items for detail.\n\nNever:\n - Infer field IDs; fetch via list_project_fields.\n - Drop 'fields' param on subsequent pages if field values are needed.",
3846
"type": "string"
3947
}
4048
},

pkg/github/__toolsnaps__/list_projects.snap

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,17 @@
33
"title": "List projects",
44
"readOnlyHint": true
55
},
6-
"description": "List Projects for a user or org",
6+
"description": "List Projects for a user or organization ",
77
"inputSchema": {
88
"properties": {
9+
"after": {
10+
"description": "Forward pagination cursor. Use when the previous response's pageInfo.hasNextPage=true. Supply pageInfo.nextCursor as 'after' and immediately request the next page. LOOP UNTIL pageInfo.hasNextPage=false (don't stop early). Keep query and per_page identical for every page.",
11+
"type": "string"
12+
},
13+
"before": {
14+
"description": "Backward pagination cursor (rare): supply to move to the preceding page using pageInfo.prevCursor. Not needed for normal forward iteration.",
15+
"type": "string"
16+
},
917
"owner": {
1018
"description": "If owner_type == user it is the handle for the GitHub user account. If owner_type == org it is the name of the organization. The name is not case sensitive.",
1119
"type": "string"
@@ -19,11 +27,11 @@
1927
"type": "string"
2028
},
2129
"per_page": {
22-
"description": "Number of results per page (max 100, default: 30)",
30+
"description": "Results per page (max 50). Keep constant across paginated requests; changing mid-sequence can complicate page traversal.",
2331
"type": "number"
2432
},
2533
"query": {
26-
"description": "Filter projects by a search query (matches title and description)",
34+
"description": "Filter projects by a search query\n\t\t\t\t\nScope: title text + open/closed state.\nPERMITTED qualifiers: is:open, is:closed (state), simple title terms.\nFORBIDDEN: is:issue, is:pr, assignee:, label:, status:, sprint-name:, parent-issue:, team-name:, priority:, etc.\nExamples:\n\t- roadmap is:open\n\t- is:open feature planning",
2735
"type": "string"
2836
}
2937
},

0 commit comments

Comments
 (0)