github / github/github-mcp-server
Support declaring a token's granted permissions/scopes up front for tool pre-filtering (stdio config + HTTP header)
- Ngôn ngữ chính
- Go
- Star
- 33k
- Fork
- 5k
- Merge trung bình
- 2 ngày 1 giờ
- Pull request đã merge (30 ngày)
- 52
Mô tả
## Problem
We filter tools by what a token can do in only a few narrow cases today:
- Classic PATs (`ghp_`) — we read the `X-OAuth-Scopes` response header and hide tools requiring scopes the token lacks.
- OAuth login (stdio) — we filter by the *requested* OAuth scopes (default set hides nothing; a narrower `--oauth-scopes` filters).
For everything else we **fail open** and show every tool:
- Fine-grained PATs and GitHub App installation tokens do **not** advertise their granted permissions in a way we can read up front.
- The FGP requirement subsystem from #2676 ships **dormant** in OSS precisely because there is no grant source — `CreateToolPermissionFilter(granted)` fails open on a nil `granted`.
The result: a token that physically cannot perform an action still surfaces the tool, so the model discovers the limitation only by calling it and getting a `403`. We already know the catalog of what each tool needs (#2676/#2679); what's missing is a way to tell the server what the token actually has.
## Proposal
Let the operator declare the token's granted permissions/scopes up front, independent of OAuth, so we can pre-filter tools against the FGP catalog (#2676) and the classic scope catalog (`pkg/scopes`):
- **stdio**: a config flag / env var, e.g. `--granted-permissions` / `GITHUB_GRANTED_PERMISSIONS` (fine-grained) and/or `--granted-scopes` / `GITHUB_GRANTED_SCOPES` (classic). Applies regardless of whether the token came from a PAT, a GitHub App installation token, or OAuth.
- **HTTP mode**: a request header (e.g. `X-MCP-Granted-Permissions`) carrying the same declaration per request, so a remote host that already knows the caller's grant can drive filtering without us re-deriving it.
When a grant declaration is present, feed it as the `granted` source to `CreateToolPermissionFilter` (FGP) and to the existing scope filter, so tools the token cannot use are hidden. When absent, keep today's fail-open behavior.
## Caveats (call out in the design)
This is deliberately flagged as a sharp-edged feature:
- **Manual and messy interface.** Enumerating fine-grained permissions + levels (read/write/admin) by hand is verbose and error-prone. The format needs thought — a flat `perm:level` list is ugly; anything richer is heavy for a CLI flag / header.
- **No validation against the real token.** A declared grant can drift from what the token actually has. Over-declaring hides nothing it shouldn't but re-introduces the 403-on-call surprise; under-declaring hides usable tools. We are trusting the operator's declaration.
- **Two vocabularies.** Classic scopes vs fine-grained permissions are different models; we'd need to be explicit about which a given token uses (and possibly support both).
- It is a **pre-filter for ergonomics/safety, not an authorization boundary** — GitHub still enforces the real permissions server-side.
## Context / related
- #2676 — declarative FGP requirement subsystem (catalog + `CreateToolPermissionFilter`, ships dormant; this issue is the grant-source piece that's out of scope there).
- #2679 — expand per-tool FGP annotations.
- Existing classic-scope filtering for `ghp_` PATs and OAuth requested scopes (stdio).
- OAuth stdio stack (in progress) — OAuth can only filter by *requested* scopes, and even then we don't know the granted set from the app alone; this issue is the general, OAuth-independent mechanism.
## Out of scope
- Auto-deriving grants from the token (not generally possible for fine-grained PATs / installation tokens).
- Any change to runtime per-call authorization — GitHub remains the enforcement point.
Hướng dẫn đóng góp
Đánh giá
Issue này chưa được đánh giá.