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 ¶
- type Gateway
- func (g *Gateway) RefreshUpstreams(ctx context.Context, store *UpstreamStore) error
- func (g *Gateway) Routes() chi.Router
- func (g *Gateway) StartRevocationRefresh(ctx context.Context) error
- func (g *Gateway) StartUpstreamRefresh(ctx context.Context, store *UpstreamStore, interval time.Duration) error
- type GatewayOption
- type Upstream
- type UpstreamHandler
- type UpstreamStore
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 (*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) StartRevocationRefresh ¶
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 ¶
Delete removes an upstream by slug; returns whether a row was removed.