serverpool

package
v1.4.1 Latest Latest
Warning

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

Go to latest
Published: Apr 30, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package serverpool manages a pool of MCP servers keyed by GitLab token and URL.

Each unique GitLab Personal Access Token and GitLab URL pair gets its own *mcp.Server, GitLab client, and server-scoped configuration snapshot with independently registered tools, resources, prompts, detected token scopes, and detected CE/EE edition. This provides zero cross-contamination between HTTP clients by construction: each client operates on its own server entry.

The pool has a configurable maximum size (WithMaxSize) and uses LRU eviction when the limit is reached. Token plus URL hashes (SHA-256) are used as pool keys so that raw tokens are never stored in memory.

Usage

Create a pool with New, retrieve or create servers with ServerPool.GetOrCreate, and extract tokens from HTTP requests with ExtractToken:

pool := serverpool.New(cfg, factory, serverpool.WithMaxSize(100))
defer pool.Close()

handler := mcp.NewStreamableHTTPHandler(func(r *http.Request) *mcp.Server {
    token := serverpool.ExtractToken(r)
    gitlabURL, err := serverpool.ExtractGitLabURL(r, cfg.GitLabURL)
    if err != nil {
        return nil
    }
    srv, err := pool.GetOrCreate(token, gitlabURL)
    if err != nil {
        return nil
    }
    return srv
}, opts)

pool.go implements a bounded LRU pool of per-token MCP servers for HTTP mode.

ratelimit.go implements per-IP rate limiting for the HTTP MCP server, protecting against abuse of the server pool endpoint.

token.go provides token and GitLab URL extraction for HTTP mode authentication.

Index

Constants

View Source
const DefaultRevalidateInterval = 15 * time.Minute

DefaultRevalidateInterval is the default period between token re-validation checks via a lightweight GitLab API call.

View Source
const RequestOptionGitLabURL = "GITLAB-URL"

RequestOptionGitLabURL identifies the per-request GitLab URL header option.

Variables

This section is empty.

Functions

func ExtractGitLabURL added in v1.1.0

func ExtractGitLabURL(r *http.Request, defaultURL string) (string, error)

ExtractGitLabURL resolves the GitLab instance URL for an HTTP request. It is a compatibility wrapper around ResolveRequestOptions.

func ExtractToken

func ExtractToken(r *http.Request) string

ExtractToken retrieves the GitLab Personal Access Token from the HTTP request. It checks the following sources in order:

  1. PRIVATE-TOKEN header (GitLab standard)
  2. Authorization header with Bearer scheme

Returns the token string, or empty string if no token is found.

Types

type AuthRateLimiter

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

AuthRateLimiter tracks authentication failures per client IP and blocks clients that exceed the maximum failure count within the configured window.

func NewAuthRateLimiter

func NewAuthRateLimiter(maxFails int, window time.Duration) *AuthRateLimiter

NewAuthRateLimiter creates a rate limiter that blocks a client IP after maxFails authentication failures within the given time window.

func (*AuthRateLimiter) Cleanup

func (l *AuthRateLimiter) Cleanup()

Cleanup removes expired entries. Call periodically to prevent memory growth.

func (*AuthRateLimiter) IsBlocked

func (l *AuthRateLimiter) IsBlocked(ip string) bool

IsBlocked returns true if the IP has exceeded the failure limit within the window.

func (*AuthRateLimiter) RecordFailure

func (l *AuthRateLimiter) RecordFailure(ip string)

RecordFailure records an authentication failure for the given IP.

type InvalidGitLabURLError added in v1.1.0

type InvalidGitLabURLError struct {
	// URL is the offending URL value. It is retained for programmatic
	// inspection by callers but is deliberately omitted from [Error] output.
	URL    string
	Reason string
}

InvalidGitLabURLError is returned when the GITLAB-URL header contains an invalid URL. The raw URL value is intentionally not included in the error message to avoid leaking embedded credentials or sensitive query parameters into server logs.

func (*InvalidGitLabURLError) Error added in v1.1.0

func (e *InvalidGitLabURLError) Error() string

Error implements the [error] interface. The returned message contains only the validation [InvalidGitLabURLError.Reason], never the raw URL, to avoid leaking credentials in logs.

type Metrics

type Metrics struct {
	Hits                   atomic.Int64
	Misses                 atomic.Int64
	Evictions              atomic.Int64
	RevalidationsFailed    atomic.Int64
	RevalidationsSucceeded atomic.Int64
}

Metrics holds operational counters for the ServerPool. All counters are monotonically increasing and use lock-free atomic increments.

type Option

type Option func(*ServerPool)

Option configures pool behavior.

func WithMaxSize

func WithMaxSize(n int) Option

WithMaxSize sets the maximum number of unique token entries in the pool. Values ≤ 0 are ignored; the default is 100.

func WithRevalidateInterval

func WithRevalidateInterval(d time.Duration) Option

WithRevalidateInterval sets the interval between periodic token re-validation checks. Values ≤ 0 disable revalidation.

type RequestOptions added in v1.4.1

type RequestOptions struct {
	GitLabURL      string
	IgnoredOptions []string
}

RequestOptions contains the effective per-request options after applying server-wide MCP configuration precedence.

func ResolveRequestOptions added in v1.4.1

func ResolveRequestOptions(r *http.Request, defaultURL string) (RequestOptions, error)

ResolveRequestOptions applies server-wide MCP configuration precedence to the request-provided options. When defaultURL is set, it is authoritative and any GITLAB-URL header is ignored. When defaultURL is empty, callers must provide GITLAB-URL per request. Effective URLs are normalized so equivalent values hash to the same server-pool session key.

func (RequestOptions) HasIgnoredOptions added in v1.4.1

func (o RequestOptions) HasIgnoredOptions() bool

HasIgnoredOptions reports whether any request-provided options were ignored because server-wide MCP configuration is authoritative.

func (RequestOptions) IgnoredOptionsCopy added in v1.4.1

func (o RequestOptions) IgnoredOptionsCopy() []string

IgnoredOptionsCopy returns a defensive copy of the ignored option names.

type ServerFactory

type ServerFactory func(client *gitlabclient.Client, cfg *config.ServerConfig) *mcp.Server

ServerFactory creates a fully configured *mcp.Server with all tools, resources, and prompts registered for the given GitLab client and per-entry configuration. This is provided by the caller to decouple pool management from registration logic.

type ServerPool

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

ServerPool maintains a bounded set of *mcp.Server instances keyed by token plus GitLab URL hash (SHA-256). When the pool reaches maxSize, the least recently used entry is evicted. Entries are periodically re-validated against the GitLab API; entries with revoked tokens are evicted automatically.

func New

func New(cfg *config.Config, factory ServerFactory, opts ...Option) *ServerPool

New creates a ServerPool. The cfg provides shared server-wide settings (GitLabURL, SkipTLSVerify, etc.). The factory function creates a fully registered *mcp.Server for each new GitLab client.

func (*ServerPool) Close

func (p *ServerPool) Close()

Close removes all entries from the pool. Active MCP sessions for evicted servers are not forcefully terminated — they will expire naturally via [StreamableHTTPOptions.SessionTimeout].

func (*ServerPool) GetOrCreate

func (p *ServerPool) GetOrCreate(token, gitlabURL string) (*mcp.Server, error)

GetOrCreate returns the *mcp.Server for the given token and GitLab URL, creating one if it doesn't exist. The pool key is derived from both the token and gitlabURL, so the same token against different GitLab instances gets separate server entries. It is safe for concurrent use. Returns an error if the GitLab client cannot be created.

func (*ServerPool) Size

func (p *ServerPool) Size() int

Size returns the current number of entries in the pool.

func (*ServerPool) StartRevalidation

func (p *ServerPool) StartRevalidation(ctx context.Context)

StartRevalidation launches a background goroutine that periodically checks all pool entries for token validity using a lightweight GitLab API call. Entries that fail validation are evicted. Cancel the context to stop.

func (*ServerPool) Stats

func (p *ServerPool) Stats() Snapshot

Stats returns a point-in-time Snapshot of pool metrics and state.

type Snapshot

type Snapshot struct {
	Hits                   int64     `json:"hits"`
	Misses                 int64     `json:"misses"`
	Evictions              int64     `json:"evictions"`
	RevalidationsFailed    int64     `json:"revalidations_failed"`
	RevalidationsSucceeded int64     `json:"revalidations_succeeded"`
	CurrentSize            int       `json:"current_size"`
	MaxSize                int       `json:"max_size"`
	CreatedAt              time.Time `json:"created_at"`
}

Snapshot is a point-in-time copy of pool Metrics plus current state. Safe for JSON serialization and cross-goroutine use.

Jump to

Keyboard shortcuts

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