Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 40 additions & 37 deletions .github/aw/github-mcp-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**Source**: [github/github-mcp-server](https://github.com/github/github-mcp-server/tree/main/pkg/github)
**Mapping File**: [pkg/workflow/data/github_toolsets_permissions.json](https://github.com/github/gh-aw/blob/main/pkg/workflow/data/github_toolsets_permissions.json)
**Last Updated**: 2026-05-24
**Last Updated**: 2026-08-02

## Overview

Expand Down Expand Up @@ -66,23 +66,23 @@ When the GitHub tool is configured, gh-aw injects a separate `<github-context>`
| Toolset | When to Enable |
|---------|---------------|
| `actions` | Workflow introspection, triggering runs |
| `code_quality` | Code quality finding lookups |
| `code_security` | Code scanning alert management |
| `copilot` | Copilot assignment, PR creation, and review requests |
| `copilot_spaces` | GitHub Copilot Spaces (remote mode only) |
| `dependabot` | Dependency vulnerability management |
| `discussions` | Community discussion workflows |
| `experiments` | Dynamic toolset management |
| `gists` | Gist creation and management |
| `git` | Git API operations (tree, refs) |
| `github_support_docs_search` | GitHub support documentation search (remote mode only) |
| `labels` | Label management automation |
| `notifications` | Notification processing agents |
| `orgs` | Organization-level security advisories |
| `orgs` | Organization search operations |
| `projects` | GitHub Projects automation (requires PAT) |
| `search` | Cross-repository search operations |
| `secret_protection` | Secret scanning alert management |
| `security_advisories` | Advisory database queries |
| `stargazers` | Star/unstar repository operations |
| `users` | (currently empty — no tools registered) |
| `users` | User search operations |

## Tools by Toolset

Expand All @@ -97,6 +97,26 @@ When the GitHub tool is configured, gh-aw injects a separate `<github-context>`

---

### code_quality
**Description**: Code quality findings

| Tool | Purpose | Key Parameters |
|------|---------|----------------|
| `get_code_quality_finding` | Get details of a specific code quality finding | `owner`, `repo`, `alert_number` |

---

### copilot
**Description**: GitHub Copilot assignment, review, and coding agent tools

| Tool | Purpose | Key Parameters |
|------|---------|----------------|
| `assign_copilot_to_issue` | Assign GitHub Copilot to an issue | `owner`, `repo`, `issue_number` |
| `create_pull_request_with_copilot` | Ask Copilot to create a pull request | `owner`, `repo`, `issue_number` |
| `request_copilot_review` | Request a Copilot review on a pull request | `owner`, `repo`, `pullNumber` |

---

### copilot_spaces
**Description**: GitHub Copilot Spaces (remote-only)

Expand Down Expand Up @@ -129,8 +149,16 @@ When the GitHub tool is configured, gh-aw injects a separate `<github-context>`
| `list_releases` | List all releases for a repository | `owner`, `repo`, `page`, `per_page` |
| `list_repository_collaborators` | List collaborators of a repository | `owner`, `repo`, `affiliation`, `page`, `per_page` |
| `list_tags` | List tags in a repository | `owner`, `repo`, `page`, `per_page` |
| `search_code` | Search code across repositories | `query`, `page`, `per_page` |
| `search_commits` | Search commits across GitHub | `query`, `page`, `per_page` |
| `search_repositories` | Search for repositories | `query`, `page`, `per_page` |
| `push_files` | Push multiple files in a single commit | `owner`, `repo`, `branch`, `files`, `message` |

> **`search_repositories` known limitation — `repo:` qualifier is ignored**: The `repo:owner/name` qualifier has no effect in `search_repositories` queries. Instead of scoping results to the named repository, the API ranks by star count and may return a completely unrelated high-star repository as the top hit (e.g. querying `repo:github/gh-aw` may return `github/gitignore`). **Do not use `repo:` with `search_repositories`.**
>
> - To check whether a specific repository exists or to fetch its metadata, use `get_file_contents` (with explicit `owner` and `repo`) or any other `repos`-toolset call that takes `owner`/`repo` directly.
> - To discover repositories in a scope, use supported qualifiers such as `org:`, `user:`, `topic:`, `language:`, or `stars:`.

---

### git
Expand Down Expand Up @@ -166,6 +194,8 @@ When the GitHub tool is configured, gh-aw injects a separate `<github-context>`
| `list_issue_types` | List available issue types for a repository | `owner`, `repo` |
| `list_issues` | List issues in a repository | `owner`, `repo`, `state`, `labels`, `page` |
| `search_issues` | Search issues across GitHub | `query`, `page`, `per_page` |
| `semantic_issue_similarity_search` | Find GitHub issues semantically similar to a given issue | `owner`, `repo`, `issue_number` |
| `semantic_issues_search` | Search issues using natural language queries | `query`, `owner`, `repo` |
| `sub_issue_write` | Create or manage sub-issues | `owner`, `repo`, `issue_number` |

---
Expand Down Expand Up @@ -234,17 +264,6 @@ When calling `list_code_scanning_alerts` in workflow prompts/templates, always b

---

### experiments
**Description**: Experimental features — dynamic toolset management

| Tool | Purpose | Key Parameters |
|------|---------|----------------|
| `enable_toolset` | Dynamically enable a toolset | `toolset` |
| `get_toolset_tools` | Get tools available in a specific toolset | `toolset` |
| `list_available_toolsets` | List all available toolsets | — |

---

### gists
**Description**: Gist operations

Expand Down Expand Up @@ -287,7 +306,7 @@ When calling `list_code_scanning_alerts` in workflow prompts/templates, always b

| Tool | Purpose | Key Parameters |
|------|---------|----------------|
| `list_org_repository_security_advisories` | List security advisories for all repos in an org | `org`, `state` |
| `search_orgs` | Search GitHub organizations | `query`, `page`, `per_page` |

---

Expand All @@ -302,25 +321,6 @@ When calling `list_code_scanning_alerts` in workflow prompts/templates, always b

---

### search
**Description**: Advanced search across GitHub

| Tool | Purpose | Key Parameters |
|------|---------|----------------|
| `search_code` | Search code across repositories | `query`, `page`, `per_page` |
| `search_orgs` | Search GitHub organizations | `query`, `page`, `per_page` |
| `search_repositories` | Search for repositories | `query`, `page`, `per_page` |
| `search_users` | Search GitHub users | `query`, `page`, `per_page` |
| `semantic_issue_similarity_search` | Find GitHub issues semantically similar to a given issue | `owner`, `repo`, `issue_number` |
| `semantic_issues_search` | Search issues using natural language queries | `query`, `owner`, `repo` |

> **`search_repositories` known limitation — `repo:` qualifier is ignored**: The `repo:owner/name` qualifier has no effect in `search_repositories` queries. Instead of scoping results to the named repository, the API ranks by star count and may return a completely unrelated high-star repository as the top hit (e.g. querying `repo:github/gh-aw` may return `github/gitignore`). **Do not use `repo:` with `search_repositories`.**
>
> - To check whether a specific repository exists or to fetch its metadata, use `get_file_contents` (with explicit `owner` and `repo`) or any other `repos`-toolset call that takes `owner`/`repo` directly.
> - To discover repositories in a scope, use supported qualifiers such as `org:`, `user:`, `topic:`, `language:`, or `stars:`.

---

### secret_protection
**Description**: Secret scanning

Expand All @@ -340,6 +340,7 @@ When calling `list_code_scanning_alerts` in workflow prompts/templates, always b
| `check_dependency_vulnerabilities` | Check dependencies against known vulnerabilities in the GitHub Advisory Database | `owner`, `repo`, `dependencies` |
| `get_global_security_advisory` | Get a specific global security advisory | `ghsa_id` |
| `list_global_security_advisories` | List advisories from the GitHub Advisory Database | `type`, `severity`, `ecosystem` |
| `list_org_repository_security_advisories` | List security advisories for all repos in an org | `org`, `state` |
| `list_repository_security_advisories` | List security advisories for a specific repository | `owner`, `repo`, `state` |

---
Expand All @@ -358,7 +359,9 @@ When calling `list_code_scanning_alerts` in workflow prompts/templates, always b
### users
**Description**: User information

> **Note**: No tools are currently registered in the `users` toolset. User search is available via the `search` toolset (`search_users`).
| Tool | Purpose | Key Parameters |
|------|---------|----------------|
| `search_users` | Search GitHub users | `query`, `page`, `per_page` |

---

Expand Down
13 changes: 10 additions & 3 deletions pkg/workflow/data/github_tool_to_toolset.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"get_file_blame": "repos",
"get_file_contents": "repos",
"search_code": "repos",
"search_repositories": "repos",
"list_commits": "repos",
"get_commit": "repos",
"get_latest_release": "repos",
Expand All @@ -24,6 +25,8 @@
"create_issue": "issues",
"update_issue": "issues",
"search_issues": "issues",
"semantic_issue_similarity_search": "issues",
"semantic_issues_search": "issues",
"add_reaction": "issues",
"create_issue_comment": "issues",

Expand All @@ -48,7 +51,10 @@
"get_code_scanning_alert": "code_security",
"create_code_scanning_alert": "code_security",

"get_code_quality_finding": "code_quality",

"assign_copilot_to_issue": "copilot",
"create_pull_request_with_copilot": "copilot",
"request_copilot_review": "copilot",

"list_dependabot_alerts": "dependabot",
Expand Down Expand Up @@ -81,10 +87,11 @@

"list_secret_scanning_alerts": "secret_protection",
"get_secret_scanning_alert": "secret_protection",
"run_secret_scanning": "secret_protection",

"check_dependency_vulnerabilities": "security_advisories",

"get_user": "users",
"list_users": "users",

"search_repositories": "search",
"search_users": "search"
"search_users": "users"
}
24 changes: 19 additions & 5 deletions pkg/workflow/data/github_toolsets_permissions.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"version": "2.3",
"description": "GitHub MCP server toolsets and their required permissions (synced to github/github-mcp-server main: search toolset removed and search tools redistributed to repos/orgs/users, experiments toolset removed, semantic search + check_dependency_vulnerabilities + run_secret_scanning removed upstream, list_org_repository_security_advisories moved orgs->security_advisories, get_label dual-registered in issues, create_pull_request_with_copilot added)",
"version": "2.4",
"description": "GitHub MCP server toolsets and their required permissions (synced to github/github-mcp-server main: restored semantic search, advisory, and secret scanning tools; search tools remain redistributed to repos/orgs/users/issues; experiments toolset removed; list_org_repository_security_advisories moved orgs->security_advisories; get_label dual-registered in issues; create_pull_request_with_copilot added)",
"toolsets": {
"actions": {
"description": "GitHub Actions workflows",
Expand Down Expand Up @@ -72,7 +72,21 @@
"description": "Issue management (get_label is also registered here alongside labels)",
"read_permissions": ["issues"],
"write_permissions": ["issues"],
"tools": ["add_issue_comment", "get_label", "issue_dependency_read", "issue_dependency_write", "issue_read", "issue_write", "list_issue_fields", "list_issue_types", "list_issues", "search_issues", "sub_issue_write"]
"tools": [
"add_issue_comment",
"get_label",
"issue_dependency_read",
"issue_dependency_write",
"issue_read",
"issue_write",
"list_issue_fields",
"list_issue_types",
"list_issues",
"search_issues",
"semantic_issue_similarity_search",
"semantic_issues_search",
"sub_issue_write"
]
},
"labels": {
"description": "Label management",
Expand Down Expand Up @@ -146,13 +160,13 @@
"description": "Secret scanning",
"read_permissions": ["security-events"],
"write_permissions": [],
"tools": ["get_secret_scanning_alert", "list_secret_scanning_alerts"]
"tools": ["get_secret_scanning_alert", "list_secret_scanning_alerts", "run_secret_scanning"]
},
"security_advisories": {
"description": "Security advisories",
"read_permissions": ["security-events"],
"write_permissions": ["security-events"],
"tools": ["get_global_security_advisory", "list_global_security_advisories", "list_org_repository_security_advisories", "list_repository_security_advisories"]
"tools": ["check_dependency_vulnerabilities", "get_global_security_advisory", "list_global_security_advisories", "list_org_repository_security_advisories", "list_repository_security_advisories"]
},
"stargazers": {
"description": "Repository stars",
Expand Down
62 changes: 35 additions & 27 deletions pkg/workflow/github_tool_to_toolset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,9 @@ func TestValidateGitHubToolsAgainstToolsets(t *testing.T) {
errorContains: []string{"labels", "list_label"},
},
{
name: "Search toolset",
allowedTools: []string{"search_repositories", "search_users"},
enabledToolsets: []string{"search"},
name: "Redistributed search tools",
allowedTools: []string{"search_repositories", "search_users", "semantic_issues_search"},
enabledToolsets: []string{"repos", "users", "issues"},
expectError: false,
},
}
Expand Down Expand Up @@ -291,8 +291,8 @@ func TestGitHubToolToToolsetMap_Completeness(t *testing.T) {
// Verify that the map contains entries for all expected tool categories
expectedToolsets := []string{
"context", "repos", "issues", "pull_requests", "actions",
"code_security", "discussions", "gists", "labels",
"notifications", "orgs", "users", "search", "secret_protection",
"code_quality", "code_security", "copilot", "discussions", "gists", "labels",
"notifications", "orgs", "users", "secret_protection", "security_advisories",
}

foundToolsets := make(map[string]bool)
Expand All @@ -319,28 +319,36 @@ func TestGitHubToolToToolsetMap_IncludesDefaultGitHubTools(t *testing.T) {
func TestGitHubToolToToolsetMap_ConsistencyWithDocumentation(t *testing.T) {
// Sample of tools that should be in the map based on documentation
expectedMappings := map[string]string{
"get_me": "context",
"get_repository": "repos",
"get_file_contents": "repos",
"list_issues": "issues",
"create_issue": "issues",
"issue_dependency_read": "issues",
"issue_dependency_write": "issues",
"pull_request_read": "pull_requests",
"search_pull_requests": "pull_requests",
"actions_list": "actions",
"actions_get": "actions",
"actions_run_trigger": "actions",
"list_code_scanning_alerts": "code_security",
"create_discussion": "discussions",
"create_gist": "gists",
"get_label": "labels",
"list_label": "labels",
"list_notifications": "notifications",
"get_organization": "orgs",
"get_user": "users",
"search_repositories": "search",
"list_secret_scanning_alerts": "secret_protection",
"get_me": "context",
"get_repository": "repos",
"get_file_contents": "repos",
"list_issues": "issues",
"create_issue": "issues",
"issue_dependency_read": "issues",
"issue_dependency_write": "issues",
"pull_request_read": "pull_requests",
"search_pull_requests": "pull_requests",
"actions_list": "actions",
"actions_get": "actions",
"actions_run_trigger": "actions",
"get_code_quality_finding": "code_quality",
"create_pull_request_with_copilot": "copilot",
"list_code_scanning_alerts": "code_security",
"create_discussion": "discussions",
"create_gist": "gists",
"get_label": "labels",
"list_label": "labels",
"list_notifications": "notifications",
"get_organization": "orgs",
"search_orgs": "orgs",
"get_user": "users",
"search_users": "users",
"search_repositories": "repos",
"semantic_issue_similarity_search": "issues",
"semantic_issues_search": "issues",
"check_dependency_vulnerabilities": "security_advisories",
"list_secret_scanning_alerts": "secret_protection",
"run_secret_scanning": "secret_protection",
}

toolToToolsetMap := loadGitHubToolToToolsetMap(t)
Expand Down
44 changes: 43 additions & 1 deletion pkg/workflow/permissions_validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ func TestToolsetPermissionsMapping(t *testing.T) {
// Verify that all toolsets are properly defined
expectedToolsets := []string{
"context", "repos", "issues", "pull_requests", "actions",
"code_security", "dependabot", "discussions",
"code_quality", "code_security", "copilot", "dependabot", "discussions",
"gists", "labels", "notifications", "orgs", "projects",
"secret_protection", "security_advisories", "stargazers",
"users",
Expand All @@ -345,6 +345,48 @@ func TestToolsetPermissionsMapping(t *testing.T) {
}
}

func TestToolsetPermissionsMapping_RestoredGitHubMCPTools(t *testing.T) {
toolsetPermissionsMap := getToolsetPermissionsMap()

tests := []struct {
toolset string
tools []string
}{
{
toolset: "issues",
tools: []string{"semantic_issue_similarity_search", "semantic_issues_search"},
},
{
toolset: "secret_protection",
tools: []string{"run_secret_scanning"},
},
{
toolset: "security_advisories",
tools: []string{"check_dependency_vulnerabilities"},
},
}

for _, tt := range tests {
t.Run(tt.toolset, func(t *testing.T) {
permissions, exists := toolsetPermissionsMap[tt.toolset]
if !exists {
t.Fatalf("Toolset %q not defined in toolsetPermissionsMap", tt.toolset)
}

tools := make(map[string]struct{}, len(permissions.Tools))
for _, tool := range permissions.Tools {
tools[tool] = struct{}{}
}

for _, tool := range tt.tools {
if _, ok := tools[tool]; !ok {
t.Errorf("Expected tool %q in toolset %q", tool, tt.toolset)
}
}
})
}
}

func TestValidatePermissions_ComplexScenarios(t *testing.T) {
tests := []struct {
name string
Expand Down