mcp-authkit-go

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 23, 2026 License: MIT

README

mcp-authkit-go

CI Go Reference

Go port of mcp-authkit — a pluggable authentication library for MCP servers built on the official modelcontextprotocol/go-sdk.

It handles two independent authentication legs:

  • Leg 1 — session auth — every MCP session is gated behind a standard OIDC provider (Keycloak, Okta, Entra ID, Auth0, …) using JWT bearer tokens. middleware.New validates tokens and middleware.RegisterWellKnownRoutes publishes the RFC 8414 / MCP-spec well-known endpoints so the MCP client drives the PKCE flow automatically.
  • Leg 2 — tool-level credentials — individual tools can additionally require a third-party OAuth token (oauthprovider.Provider) or a PAT / API key (credentialsprovider.Provider), collected on demand via MCP URL-mode elicitation.

This port targets the pre-2026-07-28 push-style elicitation model (session.Elicit blocking in-process) — the same model the Python original and the official github-mcp-server use today. See ARCHITECTURE.md for the full design and known deviations from the Python original.


Installation

go get github.com/masterela/mcp-authkit-go

Quick start

Step 1 — Add the JWT middleware (Leg 1)
validator, err := jwtvalidator.New(ctx)
if err != nil {
    log.Fatal(err)
}

mux := http.NewServeMux()
middleware.RegisterWellKnownRoutes(mux, middleware.WellKnownOptions{
    ServerBaseURL: serverBaseURL,
    IssuerURL:     issuerURL,
    ClientID:      clientID,
})

authMiddleware := middleware.New(middleware.Options{
    Validator:     validator,
    IssuerURL:     issuerURL,
    ServerBaseURL: serverBaseURL,
    OpenPaths:     []string{"/.well-known", "/health", "/register"},
})
mux.Handle("/mcp/", authMiddleware(mcpHandler))
Step 2 — Gate a tool behind a third-party OAuth token (Leg 2a)
provider, err := oauthprovider.FromStandardOAuth2(oauthprovider.StandardOAuth2Options{
    Name:             "github",
    AuthorizationURL: "https://github.com/login/oauth/authorize",
    TokenURL:         "https://github.com/login/oauth/access_token",
    ClientID:         os.Getenv("GITHUB_CLIENT_ID"),
    ClientSecret:     os.Getenv("GITHUB_CLIENT_SECRET"),
    Scope:            "read:user repo",
    RedirectURI:      serverBaseURL + "/github/callback",
})
mux.HandleFunc("GET "+provider.CallbackPath(), provider.HandleCallback)

listPRs := provider.RequireToken(false)(func(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    token, _ := oauthprovider.TokenFromContext(ctx)
    // use token against the GitHub API
    return &mcp.CallToolResult{}, nil
})
Step 3 — Gate a tool behind a PAT / API key form (Leg 2b)
creds, err := credentialsprovider.New(credentialsprovider.Options{
    Name: "confluence",
    Variables: map[string]credentialsprovider.Variable{
        "pat": credentialsprovider.NewVariable("Personal Access Token", credentialsprovider.FieldPassword),
    },
    ServerBaseURL: serverBaseURL,
})
mux.HandleFunc("GET "+creds.OpenPaths()[0], creds.HandleEntry)
mux.HandleFunc("POST "+creds.OpenPaths()[1], creds.HandleSubmit)

listPages := creds.RequireCredentials(false)(func(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    values, _ := credentialsprovider.CredentialsFromContext(ctx)
    pat := values["pat"]
    // use pat against the Confluence API
    return &mcp.CallToolResult{}, nil
})

Storage backends

Mode Notes
memory (default) In-process. Tokens lost on restart. Good for development.
file AES-256-GCM-encrypted JSON files. Single-instance deployments.
redis go-redis/v9. Multi-replica deployments.

Select via the TOKEN_STORAGE_MODE env var (memory / file / redis). See ARCHITECTURE.md for why this port uses AES-256-GCM rather than the Python original's Fernet.


Documentation

Full API reference: pkg.go.dev/github.com/masterela/mcp-authkit-go

Architecture, the two-leg auth model, and known deviations from the Python original: ARCHITECTURE.md


Contributing

go build ./...
golangci-lint run ./...
go test ./... -race -cover

Directories

Path Synopsis
Package credentialsprovider implements MCP tool-level PAT/API-key collection ("Leg 2b"): structurally parallel to oauthprovider, but the "external redirect" is instead a form hosted by the MCP server ITSELF, never a third party's domain.
Package credentialsprovider implements MCP tool-level PAT/API-key collection ("Leg 2b"): structurally parallel to oauthprovider, but the "external redirect" is instead a form hosted by the MCP server ITSELF, never a third party's domain.
Package jwtvalidator implements stateless OIDC/JWKS-based JWT verification for MCP server session auth ("Leg 1").
Package jwtvalidator implements stateless OIDC/JWKS-based JWT verification for MCP server session auth ("Leg 1").
Package middleware implements MCP server session auth ("Leg 1"): an http.Handler-wrapping middleware that validates a Bearer JWT on every request (except explicitly open paths) via a jwtvalidator.Validator, and the OIDC/MCP well-known endpoints an MCP client needs to discover how to authenticate.
Package middleware implements MCP server session auth ("Leg 1"): an http.Handler-wrapping middleware that validates a Bearer JWT on every request (except explicitly open paths) via a jwtvalidator.Validator, and the OIDC/MCP well-known endpoints an MCP client needs to discover how to authenticate.
Package oauthprovider implements MCP tool-level third-party OAuth gating ("Leg 2a"): a redirect-based OAuth 2.0 flow that a specific tool call can require before proceeding, using MCP's URL-mode elicitation to present the authorization URL to the human.
Package oauthprovider implements MCP tool-level third-party OAuth gating ("Leg 2a"): a redirect-based OAuth 2.0 flow that a specific tool call can require before proceeding, using MCP's URL-mode elicitation to present the authorization URL to the human.
Package store defines the pluggable persistence abstraction used by the oauthprovider and credentialsprovider packages ("Leg 2"): a TokenStore for long-lived, encrypted-at-rest tokens/credentials keyed by OIDC subject, and a PendingStore for short-lived, encrypted, TTL-bound in-flight-flow state with a signal/wait pair used to synchronize a blocked tool call with an out-of-band HTTP callback.
Package store defines the pluggable persistence abstraction used by the oauthprovider and credentialsprovider packages ("Leg 2"): a TokenStore for long-lived, encrypted-at-rest tokens/credentials keyed by OIDC subject, and a PendingStore for short-lived, encrypted, TTL-bound in-flight-flow state with a signal/wait pair used to synchronize a blocked tool call with an out-of-band HTTP callback.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL