Skip to content

Commit e903346

Browse files
tmelliottjrCopilot
andauthored
projects: serialization & pagination updates (#1390)
* pagination, serialization updates * projects: add server instructions (#1393) * add server instructions * Update instructions.go --------- Co-authored-by: Copilot <[email protected]>
1 parent 3d6ce68 commit e903346

File tree

8 files changed

+332
-293
lines changed

8 files changed

+332
-293
lines changed

README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -844,24 +844,30 @@ Options are:
844844
- `project_number`: The project's number. (number, required)
845845

846846
- **list_project_fields** - List project fields
847+
- `after`: Forward pagination cursor from previous pageInfo.nextCursor. (string, optional)
848+
- `before`: Backward pagination cursor from previous pageInfo.prevCursor (rare). (string, optional)
847849
- `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)
848850
- `owner_type`: Owner type (string, required)
849-
- `per_page`: Number of results per page (max 100, default: 30) (number, optional)
851+
- `per_page`: Results per page (max 50) (number, optional)
850852
- `project_number`: The project's number. (number, required)
851853

852854
- **list_project_items** - List project items
853-
- `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)
855+
- `after`: Forward pagination cursor from previous pageInfo.nextCursor. (string, optional)
856+
- `before`: Backward pagination cursor from previous pageInfo.prevCursor (rare). (string, optional)
857+
- `fields`: Field IDs to include (e.g. ["102589", "985201"]). CRITICAL: Always provide to get field values. Without this, only titles returned. (string[], optional)
854858
- `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)
855859
- `owner_type`: Owner type (string, required)
856-
- `per_page`: Number of results per page (max 100, default: 30) (number, optional)
860+
- `per_page`: Results per page (max 50) (number, optional)
857861
- `project_number`: The project's number. (number, required)
858-
- `query`: Search query to filter items (string, optional)
862+
- `query`: Query string for advanced filtering of project items using GitHub's project filtering syntax. (string, optional)
859863

860864
- **list_projects** - List projects
865+
- `after`: Forward pagination cursor from previous pageInfo.nextCursor. (string, optional)
866+
- `before`: Backward pagination cursor from previous pageInfo.prevCursor (rare). (string, optional)
861867
- `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)
862868
- `owner_type`: Owner type (string, required)
863-
- `per_page`: Number of results per page (max 100, default: 30) (number, optional)
864-
- `query`: Filter projects by a search query (matches title and description) (string, optional)
869+
- `per_page`: Results per page (max 50) (number, optional)
870+
- `query`: Filter projects by title text and open/closed state; permitted qualifiers: is:open, is:closed; examples: "roadmap is:open", "is:open feature planning". (string, optional)
865871

866872
- **update_project_item** - Update project item
867873
- `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 from previous pageInfo.nextCursor.",
11+
"type": "string"
12+
},
13+
"before": {
14+
"description": "Backward pagination cursor from previous pageInfo.prevCursor (rare).",
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)",
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": "Search project items with advanced filtering",
77
"inputSchema": {
88
"properties": {
9+
"after": {
10+
"description": "Forward pagination cursor from previous pageInfo.nextCursor.",
11+
"type": "string"
12+
},
13+
"before": {
14+
"description": "Backward pagination cursor from previous pageInfo.prevCursor (rare).",
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.",
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)",
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 project filtering syntax.",
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 from previous pageInfo.nextCursor.",
11+
"type": "string"
12+
},
13+
"before": {
14+
"description": "Backward pagination cursor from previous pageInfo.prevCursor (rare).",
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)",
2331
"type": "number"
2432
},
2533
"query": {
26-
"description": "Filter projects by a search query (matches title and description)",
34+
"description": "Filter projects by title text and open/closed state; permitted qualifiers: is:open, is:closed; examples: \"roadmap is:open\", \"is:open feature planning\".",
2735
"type": "string"
2836
}
2937
},

pkg/github/instructions.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,75 @@ Check 'list_issue_types' first for organizations to use proper issue types. Use
6262
return `## Discussions
6363
6464
Use 'list_discussion_categories' to understand available categories before creating discussions. Filter by category for better organization.`
65+
case "projects":
66+
return `## Projects
67+
68+
Workflow: 1) list_project_fields (get field IDs), 2) list_project_items (with pagination), 3) optional updates.
69+
70+
Field usage:
71+
- Call list_project_fields first to understand available fields and get IDs/types before filtering.
72+
- Use EXACT returned field names (case-insensitive match). Don't invent names or IDs.
73+
- Iteration synonyms (sprint/cycle) only if that field exists; map to the actual name (e.g. sprint:@current).
74+
- Only include filters for fields that exist and are relevant.
75+
76+
Pagination (mandatory):
77+
- Loop while pageInfo.hasNextPage=true using after=pageInfo.nextCursor.
78+
- Keep query, fields, per_page IDENTICAL on every page.
79+
- Use before=pageInfo.prevCursor only when explicitly navigating to a previous page.
80+
81+
Counting rules:
82+
- Count items array length after full pagination.
83+
- Never count field objects, content, or nested arrays as separate items.
84+
85+
Summary vs list:
86+
- Summaries ONLY if user uses verbs: analyze | summarize | summary | report | overview | insights.
87+
- Listing verbs (list/show/get/fetch/display/enumerate) → enumerate + total.
88+
89+
Self-check before returning:
90+
- Paginated fully
91+
- Correct IDs used
92+
- Field names valid
93+
- Summary only if requested.
94+
95+
Return COMPLETE data or state what's missing (e.g. pages skipped).
96+
97+
list_project_items query rules:
98+
Query string - For advanced filtering of project items using GitHub's project filtering syntax:
99+
100+
MUST reflect user intent; strongly prefer explicit content type if narrowed:
101+
- "open issues" → state:open is:issue
102+
- "merged PRs" → state:merged is:pr
103+
- "items updated this week" → updated:>@today-7d (omit type only if mixed desired)
104+
- "list all P1 priority items" → priority:p1 (omit state if user wants all, omit type if user specifies "items")
105+
- "list all open P2 issues" → is:issue state:open priority:p2 (include state if user wants open or closed, include type if user specifies "issues" or "PRs")
106+
- "all open issues I'm working on" → is:issue state:open assignee:@me
107+
108+
Query Construction Heuristics:
109+
a. Extract type nouns: issues → is:issue | PRs, Pulls, or Pull Requests → is:pr | tasks/tickets → is:issue (ask if ambiguity)
110+
b. Map temporal phrases: "this week" → updated:>@today-7d
111+
c. Map negations: "excluding wontfix" → -label:wontfix
112+
d. Map priority adjectives: "high/sev1/p1" → priority:high OR priority:p1 (choose based on field presence)
113+
e. When filtering by label, always use wildcard matching to account for cross-repository differences or emojis: (e.g. "bug 🐛" → label:*bug*)
114+
f. When filtering by milestone, always use wildcard matching to account for cross-repository differences: (e.g. "v1.0" → milestone:*v1.0*)
115+
116+
Syntax Essentials (items):
117+
AND: space-separated. (label:bug priority:high).
118+
OR: comma inside one qualifier (label:bug,critical).
119+
NOT: leading '-' (-label:wontfix).
120+
Hyphenate multi-word field names. (team-name:"Backend Team", story-points:>5).
121+
Quote multi-word values. (status:"In Review" team-name:"Backend Team").
122+
Ranges: points:1..3, updated:<@today-30d.
123+
Wildcards: title:*crash*, label:bug*.
124+
Assigned to User: assignee:@me | assignee:username | no:assignee
125+
126+
Common Qualifier Glossary (items):
127+
is:issue | is:pr | state:open|closed|merged | assignee:@me|username | label:NAME | status:VALUE |
128+
priority:p1|high | sprint-name:@current | team-name:"Backend Team" | parent-issue:"org/repo#123" |
129+
updated:>@today-7d | title:*text* | -label:wontfix | label:bug,critical | no:assignee | has:label
130+
131+
Never:
132+
- Infer field IDs; fetch via list_project_fields.
133+
- Drop 'fields' param on subsequent pages if field values are needed.`
65134
default:
66135
return ""
67136
}

0 commit comments

Comments
 (0)