Skip to content

Commit e743cf1

Browse files
committed
add instructions generation to toolset metadata
1 parent e6dd894 commit e743cf1

File tree

2 files changed

+129
-18
lines changed

2 files changed

+129
-18
lines changed

pkg/github/tools.go

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ var (
2828
Icon: "check-circle",
2929
}
3030
ToolsetMetadataContext = inventory.ToolsetMetadata{
31-
ID: "context",
32-
Description: "Tools that provide context about the current user and GitHub context you are operating in",
33-
Default: true,
34-
Icon: "person",
31+
ID: "context",
32+
Description: "Tools that provide context about the current user and GitHub context you are operating in",
33+
Default: true,
34+
Icon: "person",
35+
InstructionsFunc: generateContextToolsetInstructions,
3536
}
3637
ToolsetMetadataRepos = inventory.ToolsetMetadata{
3738
ID: "repos",
@@ -45,16 +46,18 @@ var (
4546
Icon: "git-branch",
4647
}
4748
ToolsetMetadataIssues = inventory.ToolsetMetadata{
48-
ID: "issues",
49-
Description: "GitHub Issues related tools",
50-
Default: true,
51-
Icon: "issue-opened",
49+
ID: "issues",
50+
Description: "GitHub Issues related tools",
51+
Default: true,
52+
Icon: "issue-opened",
53+
InstructionsFunc: generateIssuesToolsetInstructions,
5254
}
5355
ToolsetMetadataPullRequests = inventory.ToolsetMetadata{
54-
ID: "pull_requests",
55-
Description: "GitHub Pull Request related tools",
56-
Default: true,
57-
Icon: "git-pull-request",
56+
ID: "pull_requests",
57+
Description: "GitHub Pull Request related tools",
58+
Default: true,
59+
Icon: "git-pull-request",
60+
InstructionsFunc: generatePullRequestsToolsetInstructions,
5861
}
5962
ToolsetMetadataUsers = inventory.ToolsetMetadata{
6063
ID: "users",
@@ -93,9 +96,10 @@ var (
9396
Icon: "bell",
9497
}
9598
ToolsetMetadataDiscussions = inventory.ToolsetMetadata{
96-
ID: "discussions",
97-
Description: "GitHub Discussions related tools",
98-
Icon: "comment-discussion",
99+
ID: "discussions",
100+
Description: "GitHub Discussions related tools",
101+
Icon: "comment-discussion",
102+
InstructionsFunc: generateDiscussionsToolsetInstructions,
99103
}
100104
ToolsetMetadataGists = inventory.ToolsetMetadata{
101105
ID: "gists",
@@ -108,9 +112,10 @@ var (
108112
Icon: "shield",
109113
}
110114
ToolsetMetadataProjects = inventory.ToolsetMetadata{
111-
ID: "projects",
112-
Description: "GitHub Projects related tools",
113-
Icon: "project",
115+
ID: "projects",
116+
Description: "GitHub Projects related tools",
117+
Icon: "project",
118+
InstructionsFunc: generateProjectsToolsetInstructions,
114119
}
115120
ToolsetMetadataStargazers = inventory.ToolsetMetadata{
116121
ID: "stargazers",

pkg/github/toolset_instructions.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package github
2+
3+
import "github.com/github/github-mcp-server/pkg/inventory"
4+
5+
// Toolset instruction functions - these generate context-aware instructions for each toolset.
6+
// They are called during inventory build to generate server instructions.
7+
8+
func generateContextToolsetInstructions(_ *inventory.Inventory) string {
9+
return "Always call 'get_me' first to understand current user permissions and context."
10+
}
11+
12+
func generateIssuesToolsetInstructions(_ *inventory.Inventory) string {
13+
return `## Issues
14+
15+
Check 'list_issue_types' first for organizations to use proper issue types. Use 'search_issues' before creating new issues to avoid duplicates. Always set 'state_reason' when closing issues.`
16+
}
17+
18+
func generatePullRequestsToolsetInstructions(inv *inventory.Inventory) string {
19+
instructions := `## Pull Requests
20+
21+
PR review workflow: Always use 'pull_request_review_write' with method 'create' to create a pending review, then 'add_comment_to_pending_review' to add comments, and finally 'pull_request_review_write' with method 'submit_pending' to submit the review for complex reviews with line-specific comments.`
22+
23+
if inv.HasToolset("repos") {
24+
instructions += `
25+
26+
Before creating a pull request, search for pull request templates in the repository. Template files are called pull_request_template.md or they're located in '.github/PULL_REQUEST_TEMPLATE' directory. Use the template content to structure the PR description and then call create_pull_request tool.`
27+
}
28+
return instructions
29+
}
30+
31+
func generateDiscussionsToolsetInstructions(_ *inventory.Inventory) string {
32+
return `## Discussions
33+
34+
Use 'list_discussion_categories' to understand available categories before creating discussions. Filter by category for better organization.`
35+
}
36+
37+
func generateProjectsToolsetInstructions(_ *inventory.Inventory) string {
38+
return `## Projects
39+
40+
Workflow: 1) list_project_fields (get field IDs), 2) list_project_items (with pagination), 3) optional updates.
41+
42+
Field usage:
43+
- Call list_project_fields first to understand available fields and get IDs/types before filtering.
44+
- Use EXACT returned field names (case-insensitive match). Don't invent names or IDs.
45+
- Iteration synonyms (sprint/cycle) only if that field exists; map to the actual name (e.g. sprint:@current).
46+
- Only include filters for fields that exist and are relevant.
47+
48+
Pagination (mandatory):
49+
- Loop while pageInfo.hasNextPage=true using after=pageInfo.nextCursor.
50+
- Keep query, fields, per_page IDENTICAL on every page.
51+
- Use before=pageInfo.prevCursor only when explicitly navigating to a previous page.
52+
53+
Counting rules:
54+
- Count items array length after full pagination.
55+
- Never count field objects, content, or nested arrays as separate items.
56+
57+
Summary vs list:
58+
- Summaries ONLY if user uses verbs: analyze | summarize | summary | report | overview | insights.
59+
- Listing verbs (list/show/get/fetch/display/enumerate) → enumerate + total.
60+
61+
Self-check before returning:
62+
- Paginated fully
63+
- Correct IDs used
64+
- Field names valid
65+
- Summary only if requested.
66+
67+
Return COMPLETE data or state what's missing (e.g. pages skipped).
68+
69+
list_project_items query rules:
70+
Query string - For advanced filtering of project items using GitHub's project filtering syntax:
71+
72+
MUST reflect user intent; strongly prefer explicit content type if narrowed:
73+
- "open issues" → state:open is:issue
74+
- "merged PRs" → state:merged is:pr
75+
- "items updated this week" → updated:>@today-7d (omit type only if mixed desired)
76+
- "list all P1 priority items" → priority:p1 (omit state if user wants all, omit type if user specifies "items")
77+
- "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")
78+
- "all open issues I'm working on" → is:issue state:open assignee:@me
79+
80+
Query Construction Heuristics:
81+
a. Extract type nouns: issues → is:issue | PRs, Pulls, or Pull Requests → is:pr | tasks/tickets → is:issue (ask if ambiguity)
82+
b. Map temporal phrases: "this week" → updated:>@today-7d
83+
c. Map negations: "excluding wontfix" → -label:wontfix
84+
d. Map priority adjectives: "high/sev1/p1" → priority:high OR priority:p1 (choose based on field presence)
85+
e. When filtering by label, always use wildcard matching to account for cross-repository differences or emojis: (e.g. "bug 🐛" → label:*bug*)
86+
f. When filtering by milestone, always use wildcard matching to account for cross-repository differences: (e.g. "v1.0" → milestone:*v1.0*)
87+
88+
Syntax Essentials (items):
89+
AND: space-separated. (label:bug priority:high).
90+
OR: comma inside one qualifier (label:bug,critical).
91+
NOT: leading '-' (-label:wontfix).
92+
Hyphenate multi-word field names. (team-name:"Backend Team", story-points:>5).
93+
Quote multi-word values. (status:"In Review" team-name:"Backend Team").
94+
Ranges: points:1..3, updated:<@today-30d.
95+
Wildcards: title:*crash*, label:bug*.
96+
Assigned to User: assignee:@me | assignee:username | no:assignee
97+
98+
Common Qualifier Glossary (items):
99+
is:issue | is:pr | state:open|closed|merged | assignee:@me|username | label:NAME | status:VALUE |
100+
priority:p1|high | sprint-name:@current | team-name:"Backend Team" | parent-issue:"org/repo#123" |
101+
updated:>@today-7d | title:*text* | -label:wontfix | label:bug,critical | no:assignee | has:label
102+
103+
Never:
104+
- Infer field IDs; fetch via list_project_fields.
105+
- Drop 'fields' param on subsequent pages if field values are needed.`
106+
}

0 commit comments

Comments
 (0)