Documentation
¶
Overview ¶
Package http provides HTTP/Streamable HTTP transport for Sentinel Gate.
This package implements inbound HTTP transport following the MCP Streamable HTTP specification (2025-03-26). It enables remote clients to connect to Sentinel Gate via HTTP/HTTPS instead of stdio.
Usage ¶
Create and start an HTTP transport:
transport := http.NewHTTPTransport(proxyService,
http.WithAddr(":8080"),
http.WithTLS("cert.pem", "key.pem"),
http.WithAllowedOrigins([]string{"https://example.com"}),
http.WithLogger(logger),
)
err := transport.Start(ctx)
Endpoints ¶
The transport exposes a single endpoint at the root path:
POST / - Send JSON-RPC request, receive JSON-RPC response GET / - Open SSE stream for server-initiated messages DELETE / - Terminate session and close SSE connections OPTIONS / - CORS preflight handling
Request Headers ¶
Authorization: Bearer <api-key> - API key for authentication Mcp-Session-Id: <session-id> - Session identifier for stateful requests Content-Type: application/json - Required for POST requests
Response Headers ¶
MCP-Protocol-Version: 2025-06-18 - MCP protocol version Mcp-Session-Id: <session-id> - Session identifier echoed back Content-Type: application/json - JSON-RPC response format
Security Features ¶
The transport implements several security measures:
- TLS 1.2 minimum: When HTTPS enabled via WithTLS, TLS 1.2 is enforced
- DNS rebinding protection: Origin header validation via WithAllowedOrigins
- Rate limiting: Applied via split interceptor chain (IPRateLimitInterceptor pre-auth, UserRateLimitInterceptor post-auth)
- API key authentication: Extracted from Authorization header for AuthInterceptor
- Real IP extraction: From X-Forwarded-For/X-Real-IP for rate limiting
Middleware Chain ¶
Requests pass through middleware in this order:
- RealIPMiddleware - Extracts client IP from proxy headers
- DNSRebindingProtection - Validates Origin header
- APIKeyMiddleware - Extracts API key from Authorization header
- Handler - Routes to POST/GET/DELETE handlers
The handler then passes requests through the ProxyService's interceptor chain: Validation -> IPRateLimit -> Auth -> UserRateLimit -> Audit -> Policy -> Passthrough
Server-Sent Events (SSE) ¶
GET requests open an SSE stream for server-initiated messages. The stream:
- Requires Mcp-Session-Id header
- Sends "data: <json>\n\n" formatted events
- Supports multiple connections per session
- Cleanly disconnects on context cancellation or session termination
LangChain / Framework Compatibility ¶
This transport is compatible with:
- LangChain MCP client (via Streamable HTTP transport)
- Direct HTTP clients using JSON-RPC
- Browser-based clients with CORS support
Session management via Mcp-Session-Id enables stateful interactions across multiple HTTP requests.
Package http provides the HTTP transport adapter for the proxy.
Package http provides the HTTP transport adapter for the proxy.
Package http provides the HTTP transport adapter for the proxy.
Package http provides the HTTP transport adapter for the proxy.
Package http provides the HTTP transport adapter for the proxy.
Index ¶
- Constants
- Variables
- func APIKeyMiddleware(next http.Handler) http.Handler
- func DNSRebindingProtection(allowedOrigins []string) func(http.Handler) http.Handler
- func LoggerFromContext(ctx context.Context) *slog.Logger
- func MetricsMiddleware(metrics *Metrics) func(http.Handler) http.Handler
- func RealIPMiddleware(next http.Handler) http.Handler
- func RequestIDMiddleware(logger *slog.Logger) func(http.Handler) http.Handler
- type HTTPTransport
- type HealthChecker
- type HealthResponse
- type Metrics
- type Option
- func WithAddr(addr string) Option
- func WithAllowedOrigins(origins []string) Option
- func WithExtraHandler(h http.Handler) Option
- func WithHTTPGatewayHandler(h http.Handler) Option
- func WithHealthChecker(hc *HealthChecker) Option
- func WithLogger(logger *slog.Logger) Option
- func WithTLS(certFile, keyFile string) Option
Constants ¶
const MCPProtocolVersion = "2025-06-18"
MCPProtocolVersion is the MCP protocol version this handler supports.
const MCPProtocolVersionHeader = "MCP-Protocol-Version"
MCPProtocolVersionHeader is the header for protocol version.
const MCPSessionIDHeader = "Mcp-Session-Id"
MCPSessionIDHeader is the header for session identification.
Variables ¶
var LoggerKey = ctxkey.LoggerKey{}
LoggerKey is the context key for the enriched logger. Uses shared key type from ctxkey package to allow cross-package access without import cycles.
var RequestIDKey = requestIDContextKey{}
RequestIDKey is the context key for the request ID.
Functions ¶
func APIKeyMiddleware ¶
APIKeyMiddleware extracts API key from Authorization header. The API key is stored in context using proxy.APIKeyContextKey for downstream handlers. It also sets proxy.ConnectionIDKey based on the API key so that different clients get isolated session cache entries in the AuthInterceptor. Without this, all HTTP requests share connID="default" and the first authenticated client's session is reused for all subsequent requests regardless of their API key. If no Authorization header or invalid format, the request continues without an API key. AuthInterceptor will validate the API key later in the interceptor chain.
func DNSRebindingProtection ¶
DNSRebindingProtection validates Origin header against an allowlist. This prevents DNS rebinding attacks by ensuring requests come from allowed origins. If allowedOrigins is empty, all requests with an Origin header are blocked (local-only mode). Requests without an Origin header are allowed (same-origin or non-browser).
func LoggerFromContext ¶
LoggerFromContext retrieves the enriched logger from context. Returns slog.Default() if no logger is in context.
func MetricsMiddleware ¶
MetricsMiddleware wraps an HTTP handler to record Prometheus metrics. It records: - request_duration_seconds histogram (by method) - requests_total counter (by method and status)
func RealIPMiddleware ¶
RealIPMiddleware extracts the client's real IP address for rate limiting. It checks X-Forwarded-For and X-Real-IP headers (for reverse proxy support), falling back to r.RemoteAddr if no proxy headers are present. Only the first IP in X-Forwarded-For is trusted to avoid spoofing. The IP is stored in context using proxy.IPAddressKey.
func RequestIDMiddleware ¶
RequestIDMiddleware extracts or generates a request ID and enriches the logger. The request ID is stored in context using RequestIDKey. An enriched logger with request_id field is stored using LoggerKey.
Types ¶
type HTTPTransport ¶
type HTTPTransport struct {
// contains filtered or unexported fields
}
HTTPTransport is the inbound adapter that connects the proxy to HTTP clients. It implements the inbound.ProxyService interface, allowing MCP clients to connect via HTTP Streamable Transport instead of stdio.
func NewHTTPTransport ¶
func NewHTTPTransport(proxyService *service.ProxyService, opts ...Option) *HTTPTransport
NewHTTPTransport creates an HTTP transport adapter wrapping the given proxy service.
func (*HTTPTransport) Close ¶
func (t *HTTPTransport) Close() error
Close gracefully shuts down the transport.
type HealthChecker ¶
type HealthChecker struct {
// contains filtered or unexported fields
}
HealthChecker verifies component health.
func NewHealthChecker ¶
func NewHealthChecker( sessionStore *memory.MemorySessionStore, rateLimiter *memory.MemoryRateLimiter, auditService *service.AuditService, version string, ) *HealthChecker
NewHealthChecker creates a HealthChecker with optional components. Pass nil for components that aren't available.
func (*HealthChecker) Check ¶
func (h *HealthChecker) Check() HealthResponse
Check performs health checks on all components.
func (*HealthChecker) Handler ¶
func (h *HealthChecker) Handler() http.Handler
Handler returns an HTTP handler for the health endpoint.
type HealthResponse ¶
type HealthResponse struct {
Status string `json:"status"` // "healthy" or "unhealthy"
Checks map[string]string `json:"checks"` // Component check results
Version string `json:"version,omitempty"` // Optional version info
}
HealthResponse is the JSON response from the /health endpoint.
type Metrics ¶
type Metrics struct {
RequestsTotal *prometheus.CounterVec
RequestDuration *prometheus.HistogramVec
ActiveSessions prometheus.Gauge
PolicyEvaluations *prometheus.CounterVec
AuditDropsTotal prometheus.Counter
RateLimitKeys prometheus.Gauge
}
Metrics holds all Prometheus metrics for Sentinelgate. Pass to components that need to record metrics.
func NewMetrics ¶
func NewMetrics(reg prometheus.Registerer) *Metrics
NewMetrics creates and registers all metrics with the given registry.
type Option ¶
type Option func(*HTTPTransport)
Option is a functional option for configuring HTTPTransport.
func WithAddr ¶
WithAddr sets the listen address for the HTTP server. Default is "127.0.0.1:8080" (localhost only).
func WithAllowedOrigins ¶
WithAllowedOrigins sets the allowed origins for DNS rebinding protection. If empty, all requests with an Origin header are blocked (local-only mode). Example: []string{"https://example.com", "http://localhost:3000"}
func WithExtraHandler ¶
WithExtraHandler adds an extra HTTP handler that will be consulted for routes not handled by the MCP transport (e.g., admin UI).
func WithHTTPGatewayHandler ¶
WithHTTPGatewayHandler sets the HTTP Gateway handler for single-port routing. When set, non-MCP paths (except /admin/, /health, /metrics) route to this handler. When nil, MCP remains the catch-all handler (backward compatible).
func WithHealthChecker ¶
func WithHealthChecker(hc *HealthChecker) Option
WithHealthChecker sets the health checker for the /health endpoint.
func WithLogger ¶
WithLogger sets the logger for the HTTP transport.