Skip to content

Commit 7fae283

Browse files
authored
Merge branch 'main' into add-remote-mcp-to-registry
2 parents 10f4dd0 + e903346 commit 7fae283

File tree

11 files changed

+337
-297
lines changed

11 files changed

+337
-297
lines changed

.github/workflows/docker-publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ jobs:
7070
# https://github.com/docker/metadata-action
7171
- name: Extract Docker metadata
7272
id: meta
73-
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
73+
uses: docker/metadata-action@318604b99e75e41977312d83839a89be02ca4893 # v5.9.0
7474
with:
7575
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
7676
tags: |

README.md

Lines changed: 13 additions & 7 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)
@@ -1218,7 +1224,7 @@ Possible options:
12181224

12191225
## Dynamic Tool Discovery
12201226

1221-
**Note**: This feature is currently in beta and may not be available in all environments. Please test it out and let us know if you encounter any issues.
1227+
**Note**: This feature is currently in beta and is not available in the Remote GitHub MCP Server. Please test it out and let us know if you encounter any issues.
12221228

12231229
Instead of starting with all tools enabled, you can turn on dynamic toolset discovery. Dynamic toolsets allow the MCP host to list and enable toolsets in response to a user prompt. This should help to avoid situations where the model gets confused by the sheer number of tools available.
12241230

docs/remote-server.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ The Remote GitHub MCP server has optional headers equivalent to the Local server
5757

5858
- `X-MCP-Toolsets`: Comma-separated list of toolsets to enable. E.g. "repos,issues".
5959
- Equivalent to `GITHUB_TOOLSETS` env var for Local server.
60-
- If the list is empty, default toolsets will be used. If a bad toolset is provided, the server will fail to start and emit a 400 bad request status. Whitespace is ignored.
60+
- If the list is empty, default toolsets will be used. Invalid or unknown toolsets are silently ignored without error and will not prevent the server from starting. Whitespace is ignored.
6161
- `X-MCP-Readonly`: Enables only "read" tools.
6262
- Equivalent to `GITHUB_READ_ONLY` env var for Local server.
6363
- If this header is empty, "false", "f", "no", "n", "0", or "off" (ignoring whitespace and case), it will be interpreted as false. All other values are interpreted as true.

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)