| layout | default |
|---|---|
| title | Chapter 3: Authentication and Token Strategy |
| nav_order | 3 |
| parent | GitHub MCP Server Tutorial |
Welcome to Chapter 3: Authentication and Token Strategy. In this part of GitHub MCP Server Tutorial: Production GitHub Operations Through MCP, you will build an intuitive mental model first, then move into concrete implementation details and practical production tradeoffs.
This chapter covers secure authentication choices and scope minimization.
- choose between OAuth and PAT approaches by context
- minimize scopes while preserving required functionality
- understand scope filtering behavior in different auth flows
- reduce token handling risk in local and shared environments
| Method | Typical Use | Security Consideration |
|---|---|---|
| OAuth (remote) | interactive hosts with app support | strong user flow, host-dependent behavior |
| fine-grained PAT | local/portable compatibility | scope discipline required |
| classic PAT | legacy compatibility only | broader risk surface |
- prefer fine-grained PATs
- scope to required repos and operations only
- avoid hardcoding in committed config
- rotate credentials on schedule or incident
You now have an authentication strategy that balances compatibility and risk.
Next: Chapter 4: Toolsets, Tools, and Dynamic Discovery
The NewToolFromHandler function in pkg/github/dependencies.go handles a key part of this chapter's functionality:
}
// NewToolFromHandler creates a ServerTool that retrieves ToolDependencies from context at call time.
// Use this when you have a handler that conforms to mcp.ToolHandler directly.
//
// The handler function receives deps extracted from context via MustDepsFromContext.
// Ensure ContextWithDeps is called to inject deps before any tool handlers are invoked.
//
// requiredScopes specifies the minimum OAuth scopes needed for this tool.
// AcceptedScopes are automatically derived using the scope hierarchy.
func NewToolFromHandler(
toolset inventory.ToolsetMetadata,
tool mcp.Tool,
requiredScopes []scopes.Scope,
handler func(ctx context.Context, deps ToolDependencies, req *mcp.CallToolRequest) (*mcp.CallToolResult, error),
) inventory.ServerTool {
st := inventory.NewServerToolWithRawContextHandler(tool, toolset, func(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
deps := MustDepsFromContext(ctx)
return handler(ctx, deps, req)
})
st.RequiredScopes = scopes.ToStringSlice(requiredScopes...)
st.AcceptedScopes = scopes.ExpandScopes(requiredScopes...)
return st
}
type RequestDeps struct {
// Static dependencies
apiHosts utils.APIHostResolver
version string
lockdownMode bool
RepoAccessOpts []lockdown.RepoAccessOption
T translations.TranslationHelperFuncThis function is important because it defines how GitHub MCP Server Tutorial: Production GitHub Operations Through MCP implements the patterns covered in this chapter.
The NewRequestDeps function in pkg/github/dependencies.go handles a key part of this chapter's functionality:
}
// NewRequestDeps creates a RequestDeps with the provided clients and configuration.
func NewRequestDeps(
apiHosts utils.APIHostResolver,
version string,
lockdownMode bool,
repoAccessOpts []lockdown.RepoAccessOption,
t translations.TranslationHelperFunc,
contentWindowSize int,
featureChecker inventory.FeatureFlagChecker,
obsv observability.Exporters,
) *RequestDeps {
return &RequestDeps{
apiHosts: apiHosts,
version: version,
lockdownMode: lockdownMode,
RepoAccessOpts: repoAccessOpts,
T: t,
ContentWindowSize: contentWindowSize,
featureChecker: featureChecker,
obsv: obsv,
}
}
// GetClient implements ToolDependencies.
func (d *RequestDeps) GetClient(ctx context.Context) (*gogithub.Client, error) {
// extract the token from the context
tokenInfo, ok := ghcontext.GetTokenInfo(ctx)
if !ok {
return nil, fmt.Errorf("no token info in context")
}This function is important because it defines how GitHub MCP Server Tutorial: Production GitHub Operations Through MCP implements the patterns covered in this chapter.
The GetClient function in pkg/github/dependencies.go handles a key part of this chapter's functionality:
// The toolsets package uses `any` for deps and tool handlers type-assert to this interface.
type ToolDependencies interface {
// GetClient returns a GitHub REST API client
GetClient(ctx context.Context) (*gogithub.Client, error)
// GetGQLClient returns a GitHub GraphQL client
GetGQLClient(ctx context.Context) (*githubv4.Client, error)
// GetRawClient returns a raw content client for GitHub
GetRawClient(ctx context.Context) (*raw.Client, error)
// GetRepoAccessCache returns the lockdown mode repo access cache
GetRepoAccessCache(ctx context.Context) (*lockdown.RepoAccessCache, error)
// GetT returns the translation helper function
GetT() translations.TranslationHelperFunc
// GetFlags returns feature flags
GetFlags(ctx context.Context) FeatureFlags
// GetContentWindowSize returns the content window size for log truncation
GetContentWindowSize() int
// IsFeatureEnabled checks if a feature flag is enabled.
IsFeatureEnabled(ctx context.Context, flagName string) bool
// Logger returns the structured logger, optionally enriched with
// request-scoped data from ctx. Integrators provide their own slog.Handler
// to control where logs are sent.
Logger(ctx context.Context) *slog.Logger
// Metrics returns the metrics clientThis function is important because it defines how GitHub MCP Server Tutorial: Production GitHub Operations Through MCP implements the patterns covered in this chapter.
The GetGQLClient function in pkg/github/dependencies.go handles a key part of this chapter's functionality:
GetClient(ctx context.Context) (*gogithub.Client, error)
// GetGQLClient returns a GitHub GraphQL client
GetGQLClient(ctx context.Context) (*githubv4.Client, error)
// GetRawClient returns a raw content client for GitHub
GetRawClient(ctx context.Context) (*raw.Client, error)
// GetRepoAccessCache returns the lockdown mode repo access cache
GetRepoAccessCache(ctx context.Context) (*lockdown.RepoAccessCache, error)
// GetT returns the translation helper function
GetT() translations.TranslationHelperFunc
// GetFlags returns feature flags
GetFlags(ctx context.Context) FeatureFlags
// GetContentWindowSize returns the content window size for log truncation
GetContentWindowSize() int
// IsFeatureEnabled checks if a feature flag is enabled.
IsFeatureEnabled(ctx context.Context, flagName string) bool
// Logger returns the structured logger, optionally enriched with
// request-scoped data from ctx. Integrators provide their own slog.Handler
// to control where logs are sent.
Logger(ctx context.Context) *slog.Logger
// Metrics returns the metrics client
Metrics(ctx context.Context) metrics.Metrics
}This function is important because it defines how GitHub MCP Server Tutorial: Production GitHub Operations Through MCP implements the patterns covered in this chapter.
flowchart TD
A[NewToolFromHandler]
B[NewRequestDeps]
C[GetClient]
D[GetGQLClient]
E[GetRawClient]
A --> B
B --> C
C --> D
D --> E