mcpgw

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jun 23, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Overview

Package mcpgw is the MCP auth-gateway: a reverse proxy that enforces per-tool delegation in front of MCP servers. It verifies the inbound delegated token, authorizes the specific tool against the token's scope and constraints, mints a fresh minimally-scoped downstream token bound to the upstream (never forwarding the inbound token — confused-deputy protection), proxies the call, and audits it with the full sub/act provenance chain.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Gateway

type Gateway struct {
	// contains filtered or unexported fields
}

Gateway fronts one or more MCP upstreams.

func NewGateway

func NewGateway(issuer string, keys *keystore.Keystore, rev *revocation.Store, pool *pgxpool.Pool, pub *live.Publisher, upstreams []*Upstream, opts ...GatewayOption) (*Gateway, error)

func (*Gateway) RefreshUpstreams

func (g *Gateway) RefreshUpstreams(ctx context.Context, store *UpstreamStore) error

RefreshUpstreams rebuilds the live upstream set from the static config base plus the DB registry. Static upstreams win on a slug or inbound-audience collision; a DB upstream that would duplicate an inbound audience is skipped (isolation is never weakened). The swap is atomic.

func (*Gateway) Routes

func (g *Gateway) Routes() chi.Router

Routes returns the gateway router, to mount under /mcp.

func (*Gateway) StartRevocationRefresh

func (g *Gateway) StartRevocationRefresh(ctx context.Context) error

StartRevocationRefresh loads the revoked set once (synchronously, so the gateway fails closed if it can't reach the DB at startup) and then refreshes it on the configured interval until ctx is cancelled. A no-op unless feed mode is enabled.

func (*Gateway) StartUpstreamRefresh

func (g *Gateway) StartUpstreamRefresh(ctx context.Context, store *UpstreamStore, interval time.Duration) error

StartUpstreamRefresh loads the DB registry once (synchronously) and then merges it on the given interval until ctx is cancelled. A no-op if store is nil.

type GatewayOption

type GatewayOption func(*Gateway)

GatewayOption tunes a Gateway at construction.

func WithDownstreamTTL

func WithDownstreamTTL(d time.Duration) GatewayOption

WithDownstreamTTL caps the lifetime of the per-call downstream token the gateway mints (still clamped to the inbound token's expiry). Zero keeps the 60s default.

func WithRevocationRefresh

func WithRevocationRefresh(d time.Duration) GatewayOption

WithRevocationRefresh switches revocation checks from a per-call store lookup (Tier A, instant) to an in-memory set of revoked-but-unexpired token ids refreshed on the given interval (Tier B). It avoids a database round-trip per call for high-QPS gateways, at the cost of a revoke taking effect within the interval. Call StartRevocationRefresh to begin refreshing.

type Upstream

type Upstream struct {
	Slug string `json:"slug"` // path segment: /mcp/{slug}
	// InboundAudience is the audience an inbound delegated token MUST carry to be
	// accepted for this slug. It is per-upstream so a token bound to one upstream
	// cannot be replayed against another even when their tool scopes overlap.
	InboundAudience string            `json:"inbound_audience"`
	URL             string            `json:"url"`         // upstream MCP server endpoint
	ResourceID      string            `json:"resource_id"` // the upstream's resource indicator (downstream token aud)
	ToolScopes      map[string]string `json:"tool_scopes"` // tool name -> required scope
}

Upstream describes a registered MCP server the gateway fronts.

type UpstreamHandler

type UpstreamHandler struct {
	// contains filtered or unexported fields
}

UpstreamHandler is the superadmin CRUD API over the DB-backed upstream registry, mounted under /api/v1/gateway/upstreams. The gateway process refreshes from the same table, so changes here propagate without a redeploy.

func NewUpstreamHandler

func NewUpstreamHandler(store *UpstreamStore) *UpstreamHandler

func (*UpstreamHandler) Routes

func (h *UpstreamHandler) Routes() chi.Router

type UpstreamStore

type UpstreamStore struct {
	// contains filtered or unexported fields
}

UpstreamStore is the DB-backed registry of MCP gateway upstreams. It lets an operator add/remove upstreams without redeploying the gateway; the gateway merges these with its static config and refreshes on a timer.

func NewUpstreamStore

func NewUpstreamStore(pool *pgxpool.Pool) *UpstreamStore

func (*UpstreamStore) Delete

func (s *UpstreamStore) Delete(ctx context.Context, slug string) (bool, error)

Delete removes an upstream by slug; returns whether a row was removed.

func (*UpstreamStore) List

func (s *UpstreamStore) List(ctx context.Context) ([]*Upstream, error)

List returns all registered upstreams.

func (*UpstreamStore) Upsert

func (s *UpstreamStore) Upsert(ctx context.Context, u *Upstream) error

Upsert creates or replaces an upstream by slug.

Jump to

Keyboard shortcuts

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