MCPcopy
hub / github.com/github/github-mcp-server / WithScopeChallenge

Function WithScopeChallenge

pkg/http/middleware/scope_challenge.go:19–145  ·  view source on GitHub ↗

WithScopeChallenge creates a new middleware that determines if an OAuth request contains sufficient scopes to complete the request and returns a scope challenge if not.

(oauthCfg *oauth.Config, scopeFetcher scopes.FetcherInterface)

Source from the content-addressed store, hash-verified

17// WithScopeChallenge creates a new middleware that determines if an OAuth request contains sufficient scopes to
18// complete the request and returns a scope challenge if not.
19func WithScopeChallenge(oauthCfg *oauth.Config, scopeFetcher scopes.FetcherInterface) func(http.Handler) http.Handler {
20 return func(next http.Handler) http.Handler {
21 fn := func(w http.ResponseWriter, r *http.Request) {
22 ctx := r.Context()
23
24 // Skip health check endpoints
25 if r.URL.Path == "/_ping" {
26 next.ServeHTTP(w, r)
27 return
28 }
29
30 // Get user from context
31 tokenInfo, ok := ghcontext.GetTokenInfo(ctx)
32 if !ok {
33 next.ServeHTTP(w, r)
34 return
35 }
36
37 // Only check OAuth tokens - scope challenge allows OAuth apps to request additional scopes
38 if tokenInfo.TokenType != utils.TokenTypeOAuthAccessToken {
39 next.ServeHTTP(w, r)
40 return
41 }
42
43 // Try to use pre-parsed MCP method info first (performance optimization)
44 // This avoids re-parsing the JSON body if WithMCPParse middleware ran earlier
45 var toolName string
46 if methodInfo, ok := ghcontext.MCPMethod(ctx); ok && methodInfo != nil {
47 // Only check tools/call requests
48 if methodInfo.Method != "tools/call" {
49 next.ServeHTTP(w, r)
50 return
51 }
52 toolName = methodInfo.ItemName
53 } else {
54 // Fallback: parse the request body directly
55 body, err := io.ReadAll(r.Body)
56 if err != nil {
57 next.ServeHTTP(w, r)
58 return
59 }
60 r.Body = io.NopCloser(bytes.NewReader(body))
61
62 var mcpRequest struct {
63 JSONRPC string `json:"jsonrpc"`
64 Method string `json:"method"`
65 Params struct {
66 Name string `json:"name,omitempty"`
67 Arguments map[string]any `json:"arguments,omitempty"`
68 } `json:"params"`
69 }
70
71 err = json.Unmarshal(body, &mcpRequest)
72 if err != nil {
73 next.ServeHTTP(w, r)
74 return
75 }
76

Callers 1

RegisterMiddlewareMethod · 0.92

Calls 9

GetToolScopeInfoFunction · 0.92
ResolveResourcePathFunction · 0.92
BuildResourceMetadataURLFunction · 0.92
ServeHTTPMethod · 0.80
HasAcceptedScopeMethod · 0.80
HeaderMethod · 0.80
FetchTokenScopesMethod · 0.65
ErrorMethod · 0.45

Tested by

no test coverage detected