diff --git a/.github/aw/github-mcp-server.md b/.github/aw/github-mcp-server.md new file mode 100644 index 00000000000..8bef2c837f0 --- /dev/null +++ b/.github/aw/github-mcp-server.md @@ -0,0 +1,381 @@ +# GitHub MCP Server Instructions + +**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-03-01 + +## Overview + +The GitHub MCP server provides tools to interact with GitHub APIs through the Model Context Protocol (MCP). It operates in two modes: + +- **Remote mode**: Connects to GitHub's hosted MCP endpoint (`https://api.githubcopilot.com/mcp/`) +- **Local mode**: Runs `gh mcp` (GitHub CLI) as a local subprocess + +### Authentication + +**Remote mode**: Uses a Bearer token in the Authorization header: +``` +Authorization: Bearer +``` + +**Read-only mode**: Add the `X-MCP-Readonly: true` header to restrict to read operations only: +``` +X-MCP-Readonly: true +``` + +**Local mode**: Uses the GitHub CLI's existing authentication (`gh auth login`). + +## Configuration + +### In Agentic Workflows + +```yaml +tools: + github: + mode: "remote" # or "local" + toolsets: [default] # or specific toolsets + # Optional: GitHub App authentication + app-id: ${{ vars.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} +``` + +### Toolset Options + +- `[default]` — Recommended defaults: `context`, `repos`, `issues`, `pull_requests` +- `[all]` — Enable all toolsets +- Specific toolsets: `[repos, issues, pull_requests, discussions]` +- Extend defaults: `[default, discussions, actions]` + +## Recommended Default Toolsets + +The following toolsets are recommended as defaults for typical agentic workflows: + +| Toolset | Rationale | +|---------|-----------| +| `context` | Identity and team awareness (`get_me`, `get_teams`) — essential for any GitHub-aware agent | +| `repos` | Core repository operations (read files, list commits/branches) — most workflows need file access | +| `issues` | Issue management (read, comment, create) — common in CI/CD and automation workflows | +| `pull_requests` | PR operations (read, create, review) — critical for code review and merge automation | + +**Enable explicitly when needed** (not in defaults): + +| Toolset | When to Enable | +|---------|---------------| +| `actions` | Workflow introspection, triggering runs | +| `code_security` | Code scanning alert management | +| `dependabot` | Dependency vulnerability management | +| `discussions` | Community discussion workflows | +| `experiments` | Dynamic toolset management | +| `gists` | Gist creation and management | +| `labels` | Label management automation | +| `notifications` | Notification processing agents | +| `orgs` | Organization-level security advisories | +| `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) | + +## Tools by Toolset + +### context +**Description**: GitHub context and environment (current user, teams) +**Source**: [`pkg/github/context_tools.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/context_tools.go) + +| Tool | Purpose | Key Parameters | +|------|---------|----------------| +| `get_me` | Get details of the authenticated user | — | +| `get_team_members` | List members of a GitHub team | `org`, `team_slug` | +| `get_teams` | List teams the authenticated user belongs to | `org` | + +--- + +### repos +**Description**: Repository operations +**Source**: [`pkg/github/repositories.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/repositories.go) + +| Tool | Purpose | Key Parameters | +|------|---------|----------------| +| `create_branch` | Create a new branch | `owner`, `repo`, `branch`, `from_branch` | +| `create_or_update_file` | Create or update a file in a repository | `owner`, `repo`, `path`, `content`, `message`, `branch` | +| `create_repository` | Create a new GitHub repository | `name`, `description`, `private`, `auto_init` | +| `delete_file` | Delete a file from a repository | `owner`, `repo`, `path`, `message`, `sha`, `branch` | +| `fork_repository` | Fork a repository | `owner`, `repo`, `organization` | +| `get_commit` | Get details of a specific commit | `owner`, `repo`, `sha` | +| `get_file_contents` | Read file or directory contents | `owner`, `repo`, `path`, `ref` | +| `get_latest_release` | Get the latest release for a repository | `owner`, `repo` | +| `get_release_by_tag` | Get a release by its tag name | `owner`, `repo`, `tag` | +| `get_tag` | Get details of a specific tag | `owner`, `repo`, `tag` | +| `list_branches` | List branches in a repository | `owner`, `repo`, `page`, `per_page` | +| `list_commits` | List commits in a repository | `owner`, `repo`, `sha`, `path`, `page` | +| `list_releases` | List all releases for a repository | `owner`, `repo`, `page`, `per_page` | +| `list_tags` | List tags in a repository | `owner`, `repo`, `page`, `per_page` | +| `push_files` | Push multiple files in a single commit | `owner`, `repo`, `branch`, `files`, `message` | + +--- + +### issues +**Description**: Issue management +**Source**: [`pkg/github/issues.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/issues.go) + +| Tool | Purpose | Key Parameters | +|------|---------|----------------| +| `add_issue_comment` | Add a comment to an issue | `owner`, `repo`, `issue_number`, `body` | +| `issue_read` | Read issue details and comments | `owner`, `repo`, `issue_number` | +| `issue_write` | Create or update an issue | `owner`, `repo`, `title`, `body`, `labels`, `assignees` | +| `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` | +| `sub_issue_write` | Create or manage sub-issues | `owner`, `repo`, `issue_number` | + +--- + +### pull_requests +**Description**: Pull request operations +**Source**: [`pkg/github/pullrequests.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/pullrequests.go) + +| Tool | Purpose | Key Parameters | +|------|---------|----------------| +| `add_comment_to_pending_review` | Add a comment to a pending PR review | `owner`, `repo`, `pull_number`, `review_id` | +| `add_reply_to_pull_request_comment` | Reply to a PR review comment | `owner`, `repo`, `pull_number`, `comment_id`, `body` | +| `create_pull_request` | Create a new pull request | `owner`, `repo`, `title`, `body`, `head`, `base` | +| `list_pull_requests` | List pull requests in a repository | `owner`, `repo`, `state`, `head`, `base` | +| `merge_pull_request` | Merge a pull request | `owner`, `repo`, `pull_number`, `merge_method` | +| `pull_request_read` | Read PR details, reviews, and comments | `owner`, `repo`, `pull_number` | +| `pull_request_review_write` | Create or submit a PR review | `owner`, `repo`, `pull_number`, `event`, `body` | +| `search_pull_requests` | Search pull requests across GitHub | `query`, `page`, `per_page` | +| `update_pull_request` | Update PR title, body, or state | `owner`, `repo`, `pull_number`, `title`, `body` | +| `update_pull_request_branch` | Update PR branch with latest base | `owner`, `repo`, `pull_number` | + +--- + +### actions +**Description**: GitHub Actions workflows +**Source**: [`pkg/github/actions.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/actions.go) + +| Tool | Purpose | Key Parameters | +|------|---------|----------------| +| `actions_get` | Get details of a specific workflow run | `owner`, `repo`, `run_id` | +| `actions_list` | List GitHub Actions workflows and runs | `owner`, `repo`, `workflow_id` | +| `actions_run_trigger` | Trigger a workflow run | `owner`, `repo`, `workflow_id`, `ref`, `inputs` | +| `get_job_logs` | Download logs for a specific workflow job | `owner`, `repo`, `job_id` | + +--- + +### code_security +**Description**: Code scanning alerts +**Source**: [`pkg/github/code_scanning.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/code_scanning.go) + +| Tool | Purpose | Key Parameters | +|------|---------|----------------| +| `get_code_scanning_alert` | Get details of a specific code scanning alert | `owner`, `repo`, `alert_number` | +| `list_code_scanning_alerts` | List code scanning alerts for a repository | `owner`, `repo`, `state`, `severity` | + +--- + +### dependabot +**Description**: Dependabot alerts +**Source**: [`pkg/github/dependabot.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/dependabot.go) + +| Tool | Purpose | Key Parameters | +|------|---------|----------------| +| `get_dependabot_alert` | Get details of a specific Dependabot alert | `owner`, `repo`, `alert_number` | +| `list_dependabot_alerts` | List Dependabot alerts for a repository | `owner`, `repo`, `state`, `severity` | + +--- + +### discussions +**Description**: GitHub Discussions +**Source**: [`pkg/github/discussions.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/discussions.go) + +| Tool | Purpose | Key Parameters | +|------|---------|----------------| +| `get_discussion` | Get details of a specific discussion | `owner`, `repo`, `discussion_number` | +| `get_discussion_comments` | Get comments for a specific discussion | `owner`, `repo`, `discussion_number` | +| `list_discussion_categories` | List discussion categories for a repository | `owner`, `repo` | +| `list_discussions` | List discussions in a repository | `owner`, `repo`, `category_id` | + +--- + +### experiments +**Description**: Experimental features — dynamic toolset management +**Source**: [`pkg/github/dynamic_tools.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/dynamic_tools.go) + +| 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 +**Source**: [`pkg/github/gists.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/gists.go) + +| Tool | Purpose | Key Parameters | +|------|---------|----------------| +| `create_gist` | Create a new gist | `description`, `files`, `public` | +| `get_gist` | Get a specific gist by ID | `gist_id` | +| `list_gists` | List gists for a user | `username`, `page`, `per_page` | +| `update_gist` | Update an existing gist | `gist_id`, `description`, `files` | + +--- + +### labels +**Description**: Label management +**Source**: [`pkg/github/labels.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/labels.go) + +| Tool | Purpose | Key Parameters | +|------|---------|----------------| +| `get_label` | Get details of a specific label | `owner`, `repo`, `name` | +| `label_write` | Create or update a label | `owner`, `repo`, `name`, `color`, `description` | +| `list_label` | List labels in a repository | `owner`, `repo`, `page`, `per_page` | + +--- + +### notifications +**Description**: Notification management +**Source**: [`pkg/github/notifications.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/notifications.go) + +| Tool | Purpose | Key Parameters | +|------|---------|----------------| +| `dismiss_notification` | Dismiss a specific notification | `notification_id` | +| `get_notification_details` | Get details of a specific notification | `notification_id` | +| `list_notifications` | List user notifications | `all`, `participating`, `page` | +| `manage_notification_subscription` | Manage notification subscription for a thread | `thread_id`, `subscribed` | +| `manage_repository_notification_subscription` | Manage notifications for a repository | `owner`, `repo`, `subscribed` | +| `mark_all_notifications_read` | Mark all notifications as read | `last_read_at` | + +--- + +### orgs +**Description**: Organization operations +**Source**: [`pkg/github/security_advisories.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/security_advisories.go) (for `list_org_repository_security_advisories`) + +| Tool | Purpose | Key Parameters | +|------|---------|----------------| +| `list_org_repository_security_advisories` | List security advisories for all repos in an org | `org`, `state` | + +--- + +### projects +**Description**: GitHub Projects (requires PAT — not supported by GITHUB_TOKEN) +**Source**: [`pkg/github/projects.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/projects.go) + +| Tool | Purpose | Key Parameters | +|------|---------|----------------| +| `projects_get` | Get details of a specific project | `owner`, `project_number` | +| `projects_list` | List GitHub Projects for a user or organization | `owner`, `per_page` | +| `projects_write` | Create or update project items/fields | `owner`, `project_number` | + +--- + +### search +**Description**: Advanced search across GitHub +**Source**: [`pkg/github/search.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/search.go) + +| 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` | + +--- + +### secret_protection +**Description**: Secret scanning +**Source**: [`pkg/github/secret_scanning.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/secret_scanning.go) + +| Tool | Purpose | Key Parameters | +|------|---------|----------------| +| `get_secret_scanning_alert` | Get details of a specific secret scanning alert | `owner`, `repo`, `alert_number` | +| `list_secret_scanning_alerts` | List secret scanning alerts for a repository | `owner`, `repo`, `state` | + +--- + +### security_advisories +**Description**: Security advisories +**Source**: [`pkg/github/security_advisories.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/security_advisories.go) + +| Tool | Purpose | Key Parameters | +|------|---------|----------------| +| `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_repository_security_advisories` | List security advisories for a specific repository | `owner`, `repo`, `state` | + +--- + +### stargazers +**Description**: Repository stars +**Source**: [`pkg/github/repositories.go`](https://github.com/github/github-mcp-server/blob/main/pkg/github/repositories.go) + +| Tool | Purpose | Key Parameters | +|------|---------|----------------| +| `list_starred_repositories` | List repositories starred by a user | `username`, `page`, `per_page` | +| `star_repository` | Star a repository | `owner`, `repo` | +| `unstar_repository` | Unstar a repository | `owner`, `repo` | + +--- + +### users +**Description**: User information +**Source**: N/A (currently no tools registered) + +> **Note**: No tools are currently registered in the `users` toolset. User search is available via the `search` toolset (`search_users`). + +--- + +## Best Practices + +### Toolset Selection + +1. **Start with defaults** (`context`, `repos`, `issues`, `pull_requests`) for most workflows +2. **Add toolsets incrementally** based on actual needs rather than enabling `all` +3. **Security toolsets** (`code_security`, `dependabot`, `secret_protection`, `security_advisories`) require `security-events` permission +4. **Write operations** require appropriate GitHub token permissions (see `write_permissions` in the JSON mapping) +5. **Projects toolset** requires a PAT (Personal Access Token) — `GITHUB_TOKEN` lacks the required `project` scope + +### Permission Requirements + +Most toolsets work with the default `GITHUB_TOKEN` in GitHub Actions. Exceptions: + +- `projects` — Requires a PAT with `project` scope +- `security_advisories` (write) — Requires `security-events: write` permission +- `actions` (write for `actions_run_trigger`) — Requires `actions: write` permission + +### Token Scopes for Remote Mode + +When using remote mode with a PAT: +- Basic read: `repo` scope +- Issues/PRs write: `repo` scope (covers everything) +- Projects: `project` scope +- Gists: `gist` scope +- Notifications: `notifications` scope + +## Tool Count Summary + +| Toolset | Tool Count | +|---------|-----------| +| actions | 4 | +| code_security | 2 | +| context | 3 | +| dependabot | 2 | +| discussions | 4 | +| experiments | 3 | +| gists | 4 | +| issues | 7 | +| labels | 3 | +| notifications | 6 | +| orgs | 1 | +| projects | 3 | +| pull_requests | 10 | +| repos | 15 | +| search | 4 | +| secret_protection | 2 | +| security_advisories | 3 | +| stargazers | 3 | +| users | 0 | +| **Total** | **79** | diff --git a/.github/workflows/github-mcp-tools-report.md b/.github/workflows/github-mcp-tools-report.md index 3a16516aaa3..14510797b0b 100644 --- a/.github/workflows/github-mcp-tools-report.md +++ b/.github/workflows/github-mcp-tools-report.md @@ -190,7 +190,7 @@ Create a detailed markdown report with the following structure: - **Toolset Categories**: [NUMBER] - **Report Date**: [DATE] - **Source**: [pkg/workflow/data/github_toolsets_permissions.json](https://github.com/github/gh-aw/blob/main/pkg/workflow/data/github_toolsets_permissions.json) -- **Instructions File**: [.github/instructions/github-mcp-server.instructions.md](https://github.com/github/gh-aw/blob/main/.github/instructions/github-mcp-server.instructions.md) +- **Instructions File**: [.github/aw/github-mcp-server.md](https://github.com/github/gh-aw/blob/main/.github/aw/github-mcp-server.md) - **Changes Since Last Report**: [If previous data exists, show changes summary] - **New Tools**: [NUMBER] - **Removed Tools**: [NUMBER] @@ -348,7 +348,7 @@ tools: - **Categorization**: Based on GitHub API domains and functionality - **Documentation**: Derived from tool names, descriptions, and usage patterns - **JSON Mapping**: [pkg/workflow/data/github_toolsets_permissions.json](https://github.com/github/gh-aw/blob/main/pkg/workflow/data/github_toolsets_permissions.json) -- **Instructions**: [.github/instructions/github-mcp-server.instructions.md](https://github.com/github/gh-aw/blob/main/.github/instructions/github-mcp-server.instructions.md) +- **Instructions**: [.github/aw/github-mcp-server.md](https://github.com/github/gh-aw/blob/main/.github/aw/github-mcp-server.md) - **MCP Server Source**: [github/github-mcp-server](https://github.com/github/github-mcp-server/tree/main/pkg/github) ``` @@ -387,7 +387,7 @@ A successful report: - ✅ **Creates pull request** with updated JSON mapping if changes were made - ✅ Compares with previous run and identifies changes (new/removed/moved tools) - ✅ Saves current tools list to cache for next run -- ✅ **Creates/updates `.github/instructions/github-mcp-server.instructions.md`** with comprehensive documentation +- ✅ **Creates/updates `.github/aw/github-mcp-server.md`** with comprehensive documentation - ✅ **Identifies and documents recommended default toolsets** with rationale - ✅ **Updates default toolsets** in documentation files (github-agentic-workflows.md) - ✅ Organizes tools by their appropriate toolset categories @@ -425,7 +425,7 @@ Your output MUST: 8. Save the current tools list to `/tmp/gh-aw/cache-memory/github-mcp-tools.json` for the next run - Use a structured JSON format with tool names, toolsets, and descriptions - Include timestamp and metadata -9. **Update `.github/instructions/github-mcp-server.instructions.md`** with comprehensive documentation: +9. **Update `.github/aw/github-mcp-server.md`** with comprehensive documentation: - Document all available tools organized by toolset - Include tool descriptions, parameters, and usage examples - Provide configuration reference for remote vs local mode @@ -507,7 +507,7 @@ Begin your tool discovery now. Follow these steps: - Evaluate the current defaults: `context`, `repos`, `issues`, `pull_requests`, `users` - Determine if these defaults should be updated based on actual tool availability and usage patterns - Document your rationale for the recommended defaults -10. **Create comprehensive documentation file**: Create/update `.github/instructions/github-mcp-server.instructions.md` with: +10. **Create comprehensive documentation file**: Create/update `.github/aw/github-mcp-server.md` with: - Overview of GitHub MCP server (remote vs local mode) - Complete list of available tools organized by toolset - Tool descriptions, parameters, and return values diff --git a/pkg/workflow/data/github_toolsets_permissions.json b/pkg/workflow/data/github_toolsets_permissions.json index ecc634a2282..9ddfe925f18 100644 --- a/pkg/workflow/data/github_toolsets_permissions.json +++ b/pkg/workflow/data/github_toolsets_permissions.json @@ -1,36 +1,12 @@ { - "version": "2.0", - "description": "GitHub MCP server toolsets and their required permissions (updated to match actual MCP server capabilities)", + "version": "2.1", + "description": "GitHub MCP server toolsets and their required permissions (updated to match actual MCP server source code in github/github-mcp-server)", "toolsets": { - "context": { - "description": "GitHub Actions context and environment", - "read_permissions": [], - "write_permissions": [], - "tools": ["get_copilot_space", "github_support_docs_search", "list_copilot_spaces"] - }, - "repos": { - "description": "Repository operations", - "read_permissions": ["contents"], - "write_permissions": ["contents"], - "tools": ["get_commit", "get_file_contents", "get_latest_release", "get_release_by_tag", "get_repository_tree", "get_tag", "list_branches", "list_commits", "list_releases", "list_tags"] - }, - "issues": { - "description": "Issue management", - "read_permissions": ["issues"], - "write_permissions": ["issues"], - "tools": ["issue_read", "list_issue_types", "list_issues", "search_issues"] - }, - "pull_requests": { - "description": "Pull request operations", - "read_permissions": ["pull-requests"], - "write_permissions": ["pull-requests"], - "tools": ["list_pull_requests", "pull_request_read", "search_pull_requests"] - }, "actions": { "description": "GitHub Actions workflows", "read_permissions": ["actions"], - "write_permissions": [], - "tools": ["actions_get", "actions_list", "get_job_logs"] + "write_permissions": ["actions"], + "tools": ["actions_get", "actions_list", "actions_run_trigger", "get_job_logs"] }, "code_security": { "description": "Code scanning alerts", @@ -38,6 +14,12 @@ "write_permissions": ["security-events"], "tools": ["get_code_scanning_alert", "list_code_scanning_alerts"] }, + "context": { + "description": "GitHub context and environment (current user, teams)", + "read_permissions": [], + "write_permissions": [], + "tools": ["get_me", "get_team_members", "get_teams"] + }, "dependabot": { "description": "Dependabot alerts", "read_permissions": ["security-events"], @@ -51,28 +33,34 @@ "tools": ["get_discussion", "get_discussion_comments", "list_discussion_categories", "list_discussions"] }, "experiments": { - "description": "Experimental features", + "description": "Experimental features (dynamic toolset management)", "read_permissions": [], "write_permissions": [], - "tools": [] + "tools": ["enable_toolset", "get_toolset_tools", "list_available_toolsets"] }, "gists": { "description": "Gist operations", "read_permissions": [], "write_permissions": [], - "tools": ["get_gist", "list_gists"] + "tools": ["create_gist", "get_gist", "list_gists", "update_gist"] + }, + "issues": { + "description": "Issue management", + "read_permissions": ["issues"], + "write_permissions": ["issues"], + "tools": ["add_issue_comment", "issue_read", "issue_write", "list_issue_types", "list_issues", "search_issues", "sub_issue_write"] }, "labels": { "description": "Label management", "read_permissions": ["issues"], "write_permissions": ["issues"], - "tools": ["get_label", "list_label"] + "tools": ["get_label", "label_write", "list_label"] }, "notifications": { "description": "Notification management", "read_permissions": [], "write_permissions": [], - "tools": ["get_notification_details", "list_notifications"] + "tools": ["dismiss_notification", "get_notification_details", "list_notifications", "manage_notification_subscription", "manage_repository_notification_subscription", "mark_all_notifications_read"] }, "orgs": { "description": "Organization operations", @@ -84,7 +72,52 @@ "description": "GitHub Projects (requires PAT - not supported by GITHUB_TOKEN)", "read_permissions": [], "write_permissions": [], - "tools": ["get_project", "get_project_field", "get_project_item", "list_project_fields", "list_project_items", "list_projects"] + "tools": ["projects_get", "projects_list", "projects_write"] + }, + "pull_requests": { + "description": "Pull request operations", + "read_permissions": ["pull-requests"], + "write_permissions": ["pull-requests"], + "tools": [ + "add_comment_to_pending_review", + "add_reply_to_pull_request_comment", + "create_pull_request", + "list_pull_requests", + "merge_pull_request", + "pull_request_read", + "pull_request_review_write", + "search_pull_requests", + "update_pull_request", + "update_pull_request_branch" + ] + }, + "repos": { + "description": "Repository operations", + "read_permissions": ["contents"], + "write_permissions": ["contents"], + "tools": [ + "create_branch", + "create_or_update_file", + "create_repository", + "delete_file", + "fork_repository", + "get_commit", + "get_file_contents", + "get_latest_release", + "get_release_by_tag", + "get_tag", + "list_branches", + "list_commits", + "list_releases", + "list_tags", + "push_files" + ] + }, + "search": { + "description": "Advanced search across GitHub", + "read_permissions": [], + "write_permissions": [], + "tools": ["search_code", "search_orgs", "search_repositories", "search_users"] }, "secret_protection": { "description": "Secret scanning", @@ -102,19 +135,13 @@ "description": "Repository stars", "read_permissions": [], "write_permissions": [], - "tools": ["list_starred_repositories"] + "tools": ["list_starred_repositories", "star_repository", "unstar_repository"] }, "users": { "description": "User information", "read_permissions": [], "write_permissions": [], "tools": [] - }, - "search": { - "description": "Advanced search", - "read_permissions": [], - "write_permissions": [], - "tools": ["search_code", "search_issues", "search_orgs", "search_pull_requests", "search_repositories", "search_users"] } } } diff --git a/pkg/workflow/github_tool_to_toolset.go b/pkg/workflow/github_tool_to_toolset.go index 85fbeed1712..04a6fcfc871 100644 --- a/pkg/workflow/github_tool_to_toolset.go +++ b/pkg/workflow/github_tool_to_toolset.go @@ -18,7 +18,7 @@ var githubToolToToolsetJSON []byte // GitHubToolToToolsetMap maps individual GitHub MCP tools to their respective toolsets // This mapping is loaded from an embedded JSON file based on the documentation -// in .github/instructions/github-mcp-server.instructions.md +// in .github/aw/github-mcp-server.md var GitHubToolToToolsetMap map[string]string func init() { diff --git a/pkg/workflow/github_toolsets.go b/pkg/workflow/github_toolsets.go index e129e43d96b..fad70f13e3f 100644 --- a/pkg/workflow/github_toolsets.go +++ b/pkg/workflow/github_toolsets.go @@ -10,7 +10,7 @@ var toolsetsLog = logger.New("workflow:github_toolsets") // DefaultGitHubToolsets defines the toolsets that are enabled by default // when toolsets are not explicitly specified in the GitHub MCP configuration. -// These match the documented default toolsets in github-mcp-server.instructions.md +// These match the documented default toolsets in github-mcp-server.md var DefaultGitHubToolsets = []string{"context", "repos", "issues", "pull_requests"} // ActionFriendlyGitHubToolsets defines the default toolsets that work with GitHub Actions tokens. diff --git a/pkg/workflow/permissions_validation.go b/pkg/workflow/permissions_validation.go index de78284df1e..ddb059d8ac0 100644 --- a/pkg/workflow/permissions_validation.go +++ b/pkg/workflow/permissions_validation.go @@ -193,20 +193,13 @@ func collectRequiredPermissions(toolsets []string, readOnly bool) map[Permission continue } - // Add read permissions + // Add read permissions only (write tools are not considered for permission requirements) for _, scope := range perms.ReadPermissions { // Always require at least read access if existing, found := required[scope]; !found || existing == PermissionNone { required[scope] = PermissionRead } } - - // Add write permissions only if not in read-only mode - if !readOnly { - for _, scope := range perms.WritePermissions { - required[scope] = PermissionWrite - } - } } return required diff --git a/pkg/workflow/permissions_validator_test.go b/pkg/workflow/permissions_validator_test.go index b0609086128..b3e5581ec8e 100644 --- a/pkg/workflow/permissions_validator_test.go +++ b/pkg/workflow/permissions_validator_test.go @@ -25,7 +25,7 @@ func TestCollectRequiredPermissions(t *testing.T) { toolsets: []string{"repos"}, readOnly: false, expected: map[PermissionScope]PermissionLevel{ - PermissionContents: PermissionWrite, + PermissionContents: PermissionRead, }, }, { @@ -41,7 +41,7 @@ func TestCollectRequiredPermissions(t *testing.T) { toolsets: []string{"issues"}, readOnly: false, expected: map[PermissionScope]PermissionLevel{ - PermissionIssues: PermissionWrite, + PermissionIssues: PermissionRead, }, }, { @@ -49,9 +49,9 @@ func TestCollectRequiredPermissions(t *testing.T) { toolsets: []string{"repos", "issues", "pull_requests"}, readOnly: false, expected: map[PermissionScope]PermissionLevel{ - PermissionContents: PermissionWrite, - PermissionIssues: PermissionWrite, - PermissionPullRequests: PermissionWrite, + PermissionContents: PermissionRead, + PermissionIssues: PermissionRead, + PermissionPullRequests: PermissionRead, }, }, { @@ -59,13 +59,13 @@ func TestCollectRequiredPermissions(t *testing.T) { toolsets: DefaultGitHubToolsets, readOnly: false, expected: map[PermissionScope]PermissionLevel{ - PermissionContents: PermissionWrite, - PermissionIssues: PermissionWrite, - PermissionPullRequests: PermissionWrite, + PermissionContents: PermissionRead, + PermissionIssues: PermissionRead, + PermissionPullRequests: PermissionRead, }, }, { - name: "Actions toolset (read-only)", + name: "Actions toolset", toolsets: []string{"actions"}, readOnly: false, expected: map[PermissionScope]PermissionLevel{ @@ -77,7 +77,7 @@ func TestCollectRequiredPermissions(t *testing.T) { toolsets: []string{"code_security"}, readOnly: false, expected: map[PermissionScope]PermissionLevel{ - PermissionSecurityEvents: PermissionWrite, + PermissionSecurityEvents: PermissionRead, }, }, { @@ -85,7 +85,7 @@ func TestCollectRequiredPermissions(t *testing.T) { toolsets: []string{"discussions"}, readOnly: false, expected: map[PermissionScope]PermissionLevel{ - PermissionDiscussions: PermissionWrite, + PermissionDiscussions: PermissionRead, }, }, { @@ -150,9 +150,9 @@ func TestValidatePermissions_MissingPermissions(t *testing.T) { { name: "Default toolsets with all required permissions", permissions: NewPermissionsFromMap(map[PermissionScope]PermissionLevel{ - PermissionContents: PermissionWrite, - PermissionIssues: PermissionWrite, - PermissionPullRequests: PermissionWrite, + PermissionContents: PermissionRead, + PermissionIssues: PermissionRead, + PermissionPullRequests: PermissionRead, }), githubToolConfig: &GitHubToolConfig{ Toolset: GitHubToolsets{"default"}, @@ -162,17 +162,15 @@ func TestValidatePermissions_MissingPermissions(t *testing.T) { expectHasIssues: false, }, { - name: "Default toolsets with only read permissions (missing write)", + name: "Default toolsets with no permissions (missing read)", permissions: NewPermissionsFromMap(map[PermissionScope]PermissionLevel{ - PermissionContents: PermissionRead, - PermissionIssues: PermissionRead, - PermissionPullRequests: PermissionRead, + PermissionContents: PermissionRead, }), githubToolConfig: &GitHubToolConfig{ Toolset: GitHubToolsets{"default"}, - ReadOnly: false, // Need write permissions + ReadOnly: false, // Only read permissions required }, - expectMissingCount: 3, // All need write + expectMissingCount: 2, // Missing issues: read, pull-requests: read expectHasIssues: true, }, { @@ -192,13 +190,13 @@ func TestValidatePermissions_MissingPermissions(t *testing.T) { { name: "Specific toolsets with partial permissions", permissions: NewPermissionsFromMap(map[PermissionScope]PermissionLevel{ - PermissionContents: PermissionWrite, + PermissionContents: PermissionRead, }), githubToolConfig: &GitHubToolConfig{ Toolset: GitHubToolsets{"repos", "issues"}, ReadOnly: false, }, - expectMissingCount: 1, // Missing issues: write + expectMissingCount: 1, // Missing issues: read expectHasIssues: true, }, { @@ -350,12 +348,7 @@ func TestValidatePermissions_ComplexScenarios(t *testing.T) { Toolset: GitHubToolsets{"default"}, ReadOnly: false, }, - expectMsg: []string{ - "Missing required permissions for GitHub toolsets:", - "contents: write", - "issues: write", - "pull-requests: write", - }, + expectMsg: []string{}, // read-all satisfies the read-only permission requirements }, { name: "All: read with discussions toolset", @@ -364,10 +357,7 @@ func TestValidatePermissions_ComplexScenarios(t *testing.T) { Toolset: GitHubToolsets{"discussions"}, ReadOnly: false, }, - expectMsg: []string{ - "Missing required permissions for GitHub toolsets:", - "discussions: write", - }, + expectMsg: []string{}, // all:read satisfies discussions read requirement }, } diff --git a/pkg/workflow/permissions_warning_test.go b/pkg/workflow/permissions_warning_test.go index 48843ce8aca..d1897b72e46 100644 --- a/pkg/workflow/permissions_warning_test.go +++ b/pkg/workflow/permissions_warning_test.go @@ -219,10 +219,8 @@ tools: "Option 2: Reduce the required toolsets in your workflow:", "issues", "pull_requests", - "repos", - "contents: write", - "issues: write", - "pull-requests: write", + "issues: read", + "pull-requests: read", } for _, phrase := range expectedPhrases {