Skip to content

Commit 1855a38

Browse files
Merge branch 'github:main' into main
2 parents 6f3fde0 + 9205304 commit 1855a38

76 files changed

Lines changed: 6411 additions & 429 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/close-inactive-issues.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
issues: write
1515
pull-requests: write
1616
steps:
17-
- uses: actions/stale@v10
17+
- uses: actions/stale@v11
1818
with:
1919
days-before-issue-stale: ${{ env.PR_DAYS_BEFORE_STALE }}
2020
days-before-issue-close: ${{ env.PR_DAYS_BEFORE_CLOSE }}

.github/workflows/code-scanning.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ jobs:
4444
uses: actions/checkout@v7
4545

4646
- name: Initialize CodeQL
47-
uses: github/codeql-action/init@v4.37.4
47+
uses: github/codeql-action/init@v4.37.9
4848
with:
4949
languages: ${{ matrix.language }}
5050
build-mode: ${{ matrix.build-mode }}
@@ -61,13 +61,13 @@ jobs:
6161
threat-models: [ ]
6262
- name: Setup proxy for registries
6363
id: proxy
64-
uses: github/codeql-action/start-proxy@v4.37.4
64+
uses: github/codeql-action/start-proxy@v4.37.9
6565
with:
6666
registries_credentials: ${{ secrets.GITHUB_REGISTRIES_PROXY }}
6767
language: ${{ matrix.language }}
6868

6969
- name: Configure
70-
uses: github/codeql-action/resolve-environment@v4.37.4
70+
uses: github/codeql-action/resolve-environment@v4.37.9
7171
id: resolve-environment
7272
with:
7373
language: ${{ matrix.language }}
@@ -91,10 +91,10 @@ jobs:
9191
uses: ./.github/actions/build-ui
9292

9393
- name: Autobuild
94-
uses: github/codeql-action/autobuild@v4.37.4
94+
uses: github/codeql-action/autobuild@v4.37.9
9595

9696
- name: Perform CodeQL Analysis
97-
uses: github/codeql-action/analyze@v4.37.4
97+
uses: github/codeql-action/analyze@v4.37.9
9898
env:
9999
CODEQL_PROXY_HOST: ${{ steps.proxy.outputs.proxy_host }}
100100
CODEQL_PROXY_PORT: ${{ steps.proxy.outputs.proxy_port }}

README.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,7 @@ The following sets of tools are available:
586586
| <picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/comment-discussion-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/comment-discussion-light.png"><img src="pkg/octicons/icons/comment-discussion-light.png" width="20" height="20" alt="comment-discussion"></picture> | `discussions` | GitHub Discussions related tools |
587587
| <picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/logo-gist-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/logo-gist-light.png"><img src="pkg/octicons/icons/logo-gist-light.png" width="20" height="20" alt="logo-gist"></picture> | `gists` | GitHub Gist related tools |
588588
| <picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/git-branch-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/git-branch-light.png"><img src="pkg/octicons/icons/git-branch-light.png" width="20" height="20" alt="git-branch"></picture> | `git` | GitHub Git API related tools for low-level Git operations |
589+
| <picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/law-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/law-light.png"><img src="pkg/octicons/icons/law-light.png" width="20" height="20" alt="law"></picture> | `governance` | Repository governance tools for managing rulesets and custom properties at the repository, organization, and enterprise levels |
589590
| <picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/issue-opened-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/issue-opened-light.png"><img src="pkg/octicons/icons/issue-opened-light.png" width="20" height="20" alt="issue-opened"></picture> | `issues` | GitHub Issues related tools |
590591
| <picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/tag-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/tag-light.png"><img src="pkg/octicons/icons/tag-light.png" width="20" height="20" alt="tag"></picture> | `labels` | GitHub Labels related tools |
591592
| <picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/bell-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/bell-light.png"><img src="pkg/octicons/icons/bell-light.png" width="20" height="20" alt="bell"></picture> | `notifications` | GitHub Notifications related tools |
@@ -872,6 +873,81 @@ The following sets of tools are available:
872873

873874
<details>
874875

876+
<summary><picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/law-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/law-light.png"><img src="pkg/octicons/icons/law-light.png" width="20" height="20" alt="law"></picture> Governance</summary>
877+
878+
- **create_repository_ruleset** - Create repository ruleset
879+
- **OAuth Challenge Scopes**: `repo`, `admin:org`, `admin:enterprise`
880+
- `bypass_actors`: The actors that can bypass the rules in this ruleset (object[], optional)
881+
- `conditions`: Conditions for when this ruleset applies, e.g. {"ref_name": {"include": ["refs/heads/main"], "exclude": []}} (object, optional)
882+
- `enforcement`: The enforcement level of the ruleset. 'evaluate' allows admins to test rules before enforcing them (string, required)
883+
- `enterprise`: Enterprise slug. Required when level is 'enterprise'. (string, optional)
884+
- `level`: The level at which the ruleset is configured:
885+
- 'repository': A ruleset on a single repository (requires 'owner' and 'repo').
886+
- 'organization': A ruleset covering repositories in an organization (requires 'org').
887+
- 'enterprise': A ruleset covering repositories across an enterprise (requires 'enterprise'). (string, required)
888+
- `name`: The name of the ruleset (string, required)
889+
- `org`: Organization name. Required when level is 'organization'. (string, optional)
890+
- `owner`: Repository owner. Required when level is 'repository'. (string, optional)
891+
- `repo`: Repository name. Required when level is 'repository'. (string, optional)
892+
- `rules`: An array of rules within the ruleset. Each rule is an object with a 'type' (e.g. 'creation', 'deletion', 'non_fast_forward', 'required_signatures', 'pull_request', 'required_status_checks') and, for rules that need configuration, a 'parameters' object (object[], required)
893+
- `target`: The target of the ruleset. Defaults to 'branch'. 'repository' is only valid for 'organization' and 'enterprise' level rulesets. (string, optional)
894+
895+
- **custom_properties_read** - Read custom properties
896+
- **OAuth Challenge Scopes**: `repo`, `read:org`, `read:enterprise`
897+
- `enterprise`: Enterprise slug. Required when level is 'enterprise'. (string, optional)
898+
- `level`: The level at which custom properties are managed:
899+
- 'repository': The custom property VALUES assigned to a repository (requires 'owner' and 'repo').
900+
- 'organization': The custom property DEFINITIONS (schema) for an organization (requires 'org').
901+
- 'enterprise': The custom property DEFINITIONS (schema) for an enterprise (requires 'enterprise'). (string, required)
902+
- `org`: Organization name. Required when level is 'organization'. (string, optional)
903+
- `owner`: Repository owner. Required when level is 'repository'. (string, optional)
904+
- `repo`: Repository name. Required when level is 'repository'. (string, optional)
905+
906+
- **custom_properties_write** - Set custom properties
907+
- **OAuth Challenge Scopes**: `repo`, `admin:org`, `admin:enterprise`
908+
- `enterprise`: Enterprise slug. Required when level is 'enterprise'. (string, optional)
909+
- `level`: The level at which custom properties are managed:
910+
- 'repository': The custom property VALUES assigned to a repository (requires 'owner' and 'repo').
911+
- 'organization': The custom property DEFINITIONS (schema) for an organization (requires 'org').
912+
- 'enterprise': The custom property DEFINITIONS (schema) for an enterprise (requires 'enterprise'). (string, required)
913+
- `org`: Organization name. Required when level is 'organization'. (string, optional)
914+
- `owner`: Repository owner. Required when level is 'repository'. (string, optional)
915+
- `properties`: The custom properties to create or update. At the repository level each item assigns a value ('property_name' and 'value'); at the organization and enterprise levels each item defines the schema ('property_name' and 'value_type', plus optional definition fields). (object[], required)
916+
- `repo`: Repository name. Required when level is 'repository'. (string, optional)
917+
918+
- **repository_ruleset_read** - Read repository rulesets
919+
- **OAuth Challenge Scopes**: `repo`, `read:org`, `read:enterprise`
920+
- `actor_name`: The handle for the GitHub user account to filter rule suites on. Used by the 'list_rule_suites' method. (string, optional)
921+
- `branch`: Branch name. Required for the 'get_rules_for_branch' method. (string, optional)
922+
- `enterprise`: Enterprise slug. Required when level is 'enterprise'. (string, optional)
923+
- `evaluate_status`: Filter rule suites by ruleset evaluation mode. Used by the 'list_rule_suites' method. (string, optional)
924+
- `includes_parents`: Include rulesets configured at higher levels that also apply. Defaults to true. Used by the 'get' and 'list' methods at the repository level. (boolean, optional)
925+
- `level`: The level at which the ruleset is configured:
926+
- 'repository': A ruleset on a single repository (requires 'owner' and 'repo').
927+
- 'organization': A ruleset covering repositories in an organization (requires 'org').
928+
- 'enterprise': A ruleset covering repositories across an enterprise (requires 'enterprise'). (string, required)
929+
- `method`: Operation to perform:
930+
- 'get': Get a specific ruleset by ID (requires 'ruleset_id'). Supported at every level.
931+
- 'list': List all rulesets. Supported at every level.
932+
- 'get_rules_for_branch': Get all rules that apply to a branch (requires 'branch'). Repository level only.
933+
- 'list_rule_suites': List rule suites, the evaluations of rules against pushes. Repository and organization levels only.
934+
- 'get_rule_suite': Get a specific rule suite by ID (requires 'rule_suite_id'). Repository and organization levels only. (string, required)
935+
- `org`: Organization name. Required when level is 'organization'. (string, optional)
936+
- `owner`: Repository owner. Required when level is 'repository'. (string, optional)
937+
- `page`: Page number for pagination (min 1) (number, optional)
938+
- `perPage`: Results per page for pagination (min 1, max 100) (number, optional)
939+
- `ref`: The name of the ref (branch, tag, etc.) to filter rule suites by. Used by the 'list_rule_suites' method. (string, optional)
940+
- `repo`: Repository name. Required when level is 'repository'. (string, optional)
941+
- `repository_name`: Repository name to filter rule suites by. Used by the 'list_rule_suites' method at the organization level. (string, optional)
942+
- `rule_suite_id`: Rule suite ID. Required for the 'get_rule_suite' method. (number, optional)
943+
- `rule_suite_result`: The rule suite result to filter by. Used by the 'list_rule_suites' method. (string, optional)
944+
- `ruleset_id`: Ruleset ID. Required for the 'get' method. (number, optional)
945+
- `time_period`: The time period to filter rule suites by. Used by the 'list_rule_suites' method. (string, optional)
946+
947+
</details>
948+
949+
<details>
950+
875951
<summary><picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/issue-opened-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/issue-opened-light.png"><img src="pkg/octicons/icons/issue-opened-light.png" width="20" height="20" alt="issue-opened"></picture> Issues</summary>
876952

877953
- **add_issue_comment** - Add comment to issue or pull request

agent-plugin/mcp.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
3+
"mcpServers": {
4+
"github": {
5+
"type": "streamable-http",
6+
"url": "https://api.githubcopilot.com/mcp/"
7+
}
8+
}
9+
}

agent-plugin/plugin.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
3+
"name": "github",
4+
"description": "Work with GitHub repositories, issues, pull requests, reviews, and code search through MCP.",
5+
"author": {
6+
"name": "GitHub",
7+
"url": "https://github.com/"
8+
},
9+
"homepage": "https://github.com/github/github-mcp-server",
10+
"repository": "https://github.com/github/github-mcp-server",
11+
"license": "MIT",
12+
"keywords": ["code-search", "github", "issues", "mcp", "pull-requests"]
13+
}

cmd/github-mcp-server/generate_docs.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,8 @@ func generateReadmeDocs(readmePath string) error {
6161

6262
// The README documents the default user experience: tools that are
6363
// enabled with no special flags set. Installing a checker that reports
64-
// every flag as disabled excludes tools gated by FeatureFlagEnable and
65-
// keeps the legacy variants of tools gated by FeatureFlagDisable, so
66-
// flag-gated duplicates don't appear twice.
64+
// every flag as disabled keeps the default variants selected by functional
65+
// feature rules, so flag-gated duplicates don't appear twice.
6766
// Build() can only fail if WithTools specifies invalid tools - not used here
6867
r, _ := github.NewInventory(t).
6968
WithToolsets([]string{"all"}).

docs/feature-flags.md

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,54 @@ Only flags listed in
3535
[`AllowedFeatureFlags`](../pkg/github/feature_flags.go) can be enabled by
3636
end users. Insiders-only flags are not user-toggleable.
3737

38+
## Declaring tool availability
39+
40+
Tools, resources, and prompts use `inventory.NewFeatureRule` when feature flags
41+
change whether they are available. Each rule declares the flags it references
42+
and evaluates them with a fail-closed `FeatureResolver`, so normal Go boolean
43+
expressions can represent AND, OR, NOT, and mixed conditions:
44+
45+
```go
46+
tool.FeatureRule = inventory.NewFeatureRule(
47+
[]inventory.FeatureFlag{x, y},
48+
func(featureAsBool inventory.FeatureResolver) bool {
49+
return !(featureAsBool(x) && featureAsBool(y))
50+
},
51+
)
52+
```
53+
54+
Library consumers migrating existing inventory declarations should replace
55+
`FeatureFlagEnable`, `FeatureFlagEnableAll`, and `FeatureFlagDisable` on
56+
`ServerTool`, `ServerResourceTemplate`, and `ServerPrompt` with `FeatureRule`.
57+
`FeatureFlagChecker` and `ToolDependencies.IsFeatureEnabled` continue to accept
58+
string flag names.
59+
60+
Rules are evaluated lazily after request narrowing and static availability
61+
filters. Normal Go short-circuiting avoids checks that cannot affect the result,
62+
while one request-owned memo ensures each flag actually reached is resolved at
63+
most once across tools, resources, prompts, and `deps.IsFeatureEnabled`.
64+
Unavailable named tool calls skip rule evaluation but remain registered so the
65+
handler can return the specific client-availability error.
66+
67+
Feature predicates are pure and may depend only on their resolver. Construction
68+
validates every combination of up to 16 declared flags, so an undeclared lookup
69+
fails immediately even when ordinary evaluation would short-circuit that
70+
branch.
71+
72+
The inventory's string-based checker owns request feature state. Once installed,
73+
that state is authoritative; a checker stored on tool dependencies is used only
74+
as a fallback when handlers are invoked directly without request state.
75+
Feature checkers must not call `ResolveFeature`; nested resolution fails the
76+
owning check closed.
77+
3878
---
3979

4080
## Tools affected by each flag
4181

42-
The list below is regenerated from the Go source. For each user-controllable
43-
feature flag, it lists every tool whose **inventory or input schema** differs
44-
from the default — either because the flag introduces a new tool, or because
45-
it selects a flag-aware variant of an existing tool. Flags that only affect
46-
runtime behavior (such as output formatting) won't appear here.
82+
The list below is regenerated by comparing the default tool surface with each
83+
user-controllable flag enabled individually. Complex multi-flag rules may
84+
require separate documentation. Flags that only affect runtime behavior (such
85+
as output formatting) won't appear here.
4786

4887
<!-- START AUTOMATED FEATURE FLAG TOOLS -->
4988

docs/insiders-features.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,11 @@ Insiders is a **meta feature flag** — the same shape as `default` or `all` for
207207
3. **Insiders expansion.** If insiders mode is on (`--insiders`, `/insiders` route, or `X-MCP-Insiders: true`), every flag in [`InsidersFeatureFlags`](../pkg/github/feature_flags.go) is unioned in. The insiders expansion is **not** re-validated against the allowlist — insiders is a server-controlled switch that can reach internal-only flags.
208208
4. **Server-side fallback (remote server only).** Any flag not yet decided falls back to the remote server's feature manager, which can roll a feature out independently of user input or insiders membership.
209209

210+
For tool availability, functional rules declare the flags they may read and are
211+
evaluated lazily after request narrowing. Short-circuiting skips unnecessary
212+
checks, and request-owned state memoizes each flag that is reached. The same
213+
state backs `deps.IsFeatureEnabled`.
214+
210215
`AllowedFeatureFlags` and `InsidersFeatureFlags` are deliberately independent sets:
211216

212217
- A flag in **`AllowedFeatureFlags` only** is a regular opt-in: users can turn it on, but insiders does not auto-enable it. Granular issues/PRs flags work this way.
@@ -219,5 +224,6 @@ Insiders is a **meta feature flag** — the same shape as `default` or `all` for
219224
2. Add it to `AllowedFeatureFlags` if end users should be able to opt in via
220225
`--features`, `X-MCP-Features`, or the `features` URL query parameter.
221226
3. Add it to `InsidersFeatureFlags` if insiders mode should turn it on automatically.
222-
4. Gate the behavior on the concrete flag (`deps.IsFeatureEnabled(ctx, FeatureFlagX)`), never on `cfg.InsidersMode`. There is a `TestGitHubPackageDoesNotReadInsidersMode` guard test that fails if `pkg/github` reads `InsidersMode` directly.
223-
5. The MCP-diff CI workflow picks up new entries in `AllowedFeatureFlags` automatically — see `.github/workflows/mcp-diff.yml`.
227+
4. For tool availability, attach an `inventory.NewFeatureRule` that declares every flag used by its predicate. For behavior inside a handler, use `deps.IsFeatureEnabled(ctx, FeatureFlagX)`.
228+
5. Gate on concrete flags, never on `cfg.InsidersMode`. There is a `TestGitHubPackageDoesNotReadInsidersMode` guard test that fails if `pkg/github` reads `InsidersMode` directly.
229+
6. The MCP-diff CI workflow picks up new entries in `AllowedFeatureFlags` automatically — see `.github/workflows/mcp-diff.yml`.

0 commit comments

Comments
 (0)