github / github/github-mcp-server

Support declaring a token's granted permissions/scopes up front for tool pre-filtering (stdio config + HTTP header)

未關閉
#2,706 1 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視
enhancement request ai review
主要語言
Go
星號
33k
分支
5k
平均合併
2 天 1 小時
30 天內合併 PR
52

描述

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

貢獻指南

開啟貢獻指南

評估

這個 Issue 還沒有評估資料。

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。