Documentation
¶
Overview ¶
Package serverpool manages a pool of MCP servers keyed by GitLab token hash.
Each unique GitLab Personal Access Token gets its own *mcp.Server with independently registered tools, resources, and prompts. This provides zero cross-contamination between HTTP clients by construction — each client operates on its own server instance.
The pool has a configurable maximum size (WithMaxSize) and uses LRU eviction when the limit is reached. Token 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)
srv, err := pool.GetOrCreate(token)
if err != nil {
return nil
}
return srv
}, opts)
Index ¶
Constants ¶
const DefaultRevalidateInterval = 15 * time.Minute
DefaultRevalidateInterval is the default period between token re-validation checks via a lightweight GitLab API call.
Variables ¶
This section is empty.
Functions ¶
func ExtractToken ¶
ExtractToken retrieves the GitLab Personal Access Token from the HTTP request. It checks the following sources in order:
- PRIVATE-TOKEN header (GitLab standard)
- 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 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 ¶
WithMaxSize sets the maximum number of unique token entries in the pool. Values ≤ 0 are ignored; the default is 100.
func WithRevalidateInterval ¶
WithRevalidateInterval sets the interval between periodic token re-validation checks. Values ≤ 0 disable revalidation.
type ServerFactory ¶
type ServerFactory func(client *gitlabclient.Client) *mcp.Server
ServerFactory creates a fully configured *mcp.Server with all tools, resources, and prompts registered for the given GitLab client. 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 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 string) (*mcp.Server, error)
GetOrCreate returns the *mcp.Server for the given token, creating one if it doesn't exist. It is safe for concurrent use. Returns an error if the GitLab client cannot be created (e.g., invalid URL).
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.