|
| 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