interceptors

package
v0.0.0-...-5bd7ab4 Latest Latest
Warning

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

Go to latest
Published: Apr 30, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

Documentation

Overview

Package interceptors defines the core types for the MCP interceptor framework: interceptor descriptors (Validator, Mutator), wire protocol types (InvokeParams, InvokeResult), result types (ValidationResult, MutationResult), and supporting enums.

This package is transport-agnostic — it has no dependency on the MCP SDK's server or client types. The chain orchestrator lives in the interceptors/chain sub-package, MCP server integration in interceptors/extension, and middleware in interceptors/integrations/gomiddleware.

Usage with MCP

Create an [extension.Extension], register interceptors, install on an mcp.Server, then use [extension.Extension.LocalChain] to get a chain for middleware:

ext := extension.New()
ext.AddInterceptor(myValidator)
ext.AddInterceptor(myMutator)
ext.Install(mcpServer)

chain, err := ext.LocalChain(ctx, mcpServer)
mcpServer.AddReceivingMiddleware(
    gomiddleware.Middleware(chain),
)

Validators

A Validator inspects the payload and decides whether the request or response should proceed. All validators for a given event run in parallel. If any validator in enforced mode (ModeEnforce) returns an error-severity message, the chain aborts before any mutators run. Only error-severity messages cause an abort; warn and info findings are recorded in the chain execution result but do not block the chain.

Interceptor handlers receive json.RawMessage payloads when invoked via interceptor/invoke:

v := &interceptors.Validator{
    Metadata: interceptors.Metadata{
        Name: "block-dangerous-tool",
        Hook: interceptors.Hook{
            Events: []string{"tools/call"},
            Phase:  interceptors.PhaseRequest,
        },
        Mode: interceptors.ModeEnforce,
    },
    Handler: func(ctx context.Context, inv *interceptors.Invocation) (*interceptors.ValidationResult, error) {
        raw := inv.Payload.(json.RawMessage)
        var params struct{ Name string `json:"name"` }
        json.Unmarshal(raw, &params)
        // inspect params ...
        return &interceptors.ValidationResult{Valid: true}, nil
    },
}

Mutators

A Mutator transforms the payload. Mutators run sequentially in priority order (see Priority). Each mutator receives the payload as json.RawMessage, unmarshals it, modifies it, and sets the updated JSON back on inv.Payload. If any mutator fails (and is not configured with FailOpen), the chain aborts. FailOpen mutators record an InvokeResult (with the error captured) for observability but do not block.

m := &interceptors.Mutator{
    Metadata: interceptors.Metadata{
        Name: "redact-pii",
        Hook: interceptors.Hook{
            Events: []string{"tools/call"},
            Phase:  interceptors.PhaseResponse,
        },
        Mode: interceptors.ModeEnforce,
    },
    Handler: func(ctx context.Context, inv *interceptors.Invocation) (*interceptors.MutationResult, error) {
        raw := inv.Payload.(json.RawMessage)
        var result map[string]any
        json.Unmarshal(raw, &result)
        // modify result ...
        data, _ := json.Marshal(result)
        return &interceptors.MutationResult{Modified: true, Payload: data}, nil
    },
}

Execution Order

The chain execution order depends on direction:

Request phase (untrusted → trusted):

Validate (parallel) → Mutate (sequential)

Response phase (trusted → untrusted):

Mutate (sequential) → Validate (parallel)

Validators act as a security gate on the trust boundary side, while mutators prepare or sanitize data on the other side.

Modes and FailOpen

Each interceptor has a Mode that controls what happens with successful results, and a FailOpen flag that controls what happens when the handler returns a Go error. These are orthogonal:

  • ModeEnforce: fully enforced — validation failures block, mutations are applied.
  • ModeAudit: the handler runs and results are recorded, but validation findings do not block and mutated payloads are not propagated to subsequent interceptors.

FailOpen (default false) controls crash resilience:

  • FailOpen=false: a handler error aborts the chain. An InvokeResult and a [chain.AbortInfo] are both recorded.
  • FailOpen=true: a handler error is logged and an InvokeResult is recorded, but the chain continues.

Note that ModeAudit does NOT imply FailOpen. Audit mode only suppresses enforcement of successful results (validation findings and mutations). If the handler itself returns an error and FailOpen is false, the chain still aborts. For truly safe observation-only interceptors, set both ModeAudit and FailOpen:

Metadata: interceptors.Metadata{
    Mode:     interceptors.ModeAudit,
    FailOpen: true,
}

Behavior matrix for validators:

Mode=Enforce,  FailOpen=false → error aborts, Valid=false+SeverityError aborts
Mode=Enforce,  FailOpen=true  → error continues, Valid=false+SeverityError aborts
Mode=Audit, FailOpen=false → error aborts, findings recorded only
Mode=Audit, FailOpen=true  → error continues, findings recorded only

Behavior matrix for mutators:

Mode=Enforce,  FailOpen=false → error aborts, mutations applied
Mode=Enforce,  FailOpen=true  → error continues, mutations applied
Mode=Audit, FailOpen=false → error aborts, mutations not propagated
Mode=Audit, FailOpen=true  → error continues, mutations not propagated

Index

Constants

View Source
const (
	MethodList   = "interceptors/list"
	MethodInvoke = "interceptor/invoke"
)

JSON-RPC method names for the interceptor protocol.

View Source
const (
	// Server Features
	EventToolsList          = "tools/list"
	EventToolsCall          = "tools/call"
	EventPromptsList        = "prompts/list"
	EventPromptsGet         = "prompts/get"
	EventResourcesList      = "resources/list"
	EventResourcesRead      = "resources/read"
	EventResourcesSubscribe = "resources/subscribe"
)

Event name constants for standard MCP methods.

Variables

This section is empty.

Functions

This section is empty.

Types

type Compat

type Compat struct {
	MinProtocol string `json:"minProtocol"`
	MaxProtocol string `json:"maxProtocol,omitempty"`
}

Compat represents protocol version compatibility.

type Hook

type Hook struct {
	Events []InterceptionEvent `json:"events"`
	Phase  InterceptionPhase   `json:"phase"`
}

Hook defines which lifecycle events and phase trigger an interceptor.

type InterceptionEvent

type InterceptionEvent = string

InterceptionEvent identifies a lifecycle event that can be intercepted.

type InterceptionPhase

type InterceptionPhase string

InterceptionPhase determines when an interceptor runs.

const (
	PhaseRequest  InterceptionPhase = "request"
	PhaseResponse InterceptionPhase = "response"
	PhaseBoth     InterceptionPhase = "both"
)

type Interceptor

type Interceptor interface {
	GetMetadata() *Metadata
	GetType() InterceptorType
}

Interceptor is the common interface for all interceptors. It is implemented by both Validator and Mutator.

type InterceptorInfo

type InterceptorInfo struct {
	Name         string          `json:"name"`
	Version      string          `json:"version,omitempty"`
	Description  string          `json:"description,omitempty"`
	Type         InterceptorType `json:"type"`
	Hook         Hook            `json:"hook"`
	PriorityHint Priority        `json:"priorityHint,omitempty"`
	Compat       *Compat         `json:"compat,omitempty"`
	ConfigSchema json.RawMessage `json:"configSchema,omitempty"`
	Mode         Mode            `json:"mode"`
	FailOpen     bool            `json:"failOpen,omitempty"`
}

InterceptorInfo describes a registered interceptor in wire format.

func InfoFromInterceptor

func InfoFromInterceptor(i Interceptor) InterceptorInfo

InfoFromInterceptor builds an InterceptorInfo from an Interceptor.

type InterceptorType

type InterceptorType string

InterceptorType identifies the category of an interceptor.

const (
	TypeValidation InterceptorType = "validation"
	TypeMutation   InterceptorType = "mutation"
)

type Invocation

type Invocation struct {
	Event   string             // e.g. "tools/call"
	Phase   InterceptionPhase  // "request" or "response"
	Payload any                // The payload (json.RawMessage when invoked via interceptor/invoke)
	Config  map[string]any     // Per-invocation config
	Context *InvocationContext // Optional caller context (identity, trace, etc.)
}

Invocation is the context passed to every interceptor handler.

type InvocationContext

type InvocationContext struct {
	Principal *Principal `json:"principal,omitempty"`
	TraceID   string     `json:"traceId,omitempty"`
	SpanID    string     `json:"spanId,omitempty"`
	Timestamp string     `json:"timestamp,omitempty"`
	SessionID string     `json:"sessionId,omitempty"`
}

InvocationContext holds optional context passed to interceptors.

type InvokeParams

type InvokeParams struct {
	mcp.ParamsBase
	Name      string             `json:"name"`
	Event     string             `json:"event"`
	Phase     InterceptionPhase  `json:"phase"`
	Payload   json.RawMessage    `json:"payload"`
	TimeoutMs int64              `json:"timeoutMs,omitempty"`
	Config    map[string]any     `json:"config,omitempty"`
	Context   *InvocationContext `json:"context,omitempty"`
}

InvokeParams are the parameters for the interceptor/invoke method. The caller specifies which interceptor to invoke by name.

type InvokeResult

type InvokeResult struct {
	mcp.ResultBase
	Interceptor string            `json:"interceptor"`
	Type        InterceptorType   `json:"type"`
	Phase       InterceptionPhase `json:"phase"`
	DurationMs  int64             `json:"durationMs"`

	// Validation result (type == "validation")
	Validation *ValidationResult `json:"validation,omitempty"`

	// Mutation result (type == "mutation")
	Mutation *MutationResult `json:"mutation,omitempty"`
	Payload  json.RawMessage `json:"payload,omitempty"` // Mutated payload (only for mutators)
}

InvokeResult is the result of the interceptor/invoke method. Fields are type-specific: validators populate Validation, mutators populate Mutation + Payload.

type ListParams

type ListParams struct {
	mcp.ParamsBase
	Event string `json:"event,omitempty"` // Filter by event name; empty = all
}

ListParams are the optional parameters for the interceptors/list method.

type ListResult

type ListResult struct {
	mcp.ResultBase
	Interceptors []InterceptorInfo `json:"interceptors"`
}

ListResult is the result of the interceptors/list method.

type Metadata

type Metadata struct {
	Name         string          `json:"name"`
	Version      string          `json:"version,omitempty"`
	Description  string          `json:"description,omitempty"`
	Type         InterceptorType `json:"type"`
	Hook         Hook            `json:"hook"`
	PriorityHint Priority        `json:"priorityHint,omitempty"`
	Compat       *Compat         `json:"compat,omitempty"`
	ConfigSchema json.RawMessage `json:"configSchema,omitempty"`
	Mode         Mode            `json:"mode"`
	FailOpen     bool            `json:"failOpen,omitempty"`
}

Metadata holds all common interceptor metadata.

type Mode

type Mode string

Mode controls enforcement behavior.

const (
	ModeEnforce Mode = "enforce" // Enforced: validation failures block, mutations apply
	ModeAudit   Mode = "audit"   // Audit: log results but don't block or apply mutations
)

type MutationResult

type MutationResult struct {
	Modified bool            `json:"modified"`
	Info     map[string]any  `json:"info,omitempty"`
	Payload  json.RawMessage `json:"payload,omitempty"`
}

MutationResult is returned by mutation interceptors.

type Mutator

type Mutator struct {
	Metadata
	Handler MutatorHandler
}

Mutator is a mutation interceptor.

func (*Mutator) GetMetadata

func (m *Mutator) GetMetadata() *Metadata

func (*Mutator) GetType

func (m *Mutator) GetType() InterceptorType

type MutatorHandler

type MutatorHandler func(ctx context.Context, inv *Invocation) (*MutationResult, error)

MutatorHandler is the function signature for raw mutation handlers.

type Principal

type Principal struct {
	Type   string         `json:"type"`
	ID     string         `json:"id,omitempty"`
	Claims map[string]any `json:"claims,omitempty"`
}

Principal identifies the caller.

type Priority

type Priority struct {
	Request  int
	Response int
}

Priority represents an interceptor's ordering hint. Can be a single value (applies to both phases) or per-phase.

JSON representation is polymorphic: a single number when both phases are equal, or {"request": N, "response": N} when they differ.

func NewPriority

func NewPriority(v int) Priority

NewPriority creates a Priority with the same value for both phases.

func (Priority) MarshalJSON

func (p Priority) MarshalJSON() ([]byte, error)

MarshalJSON implements polymorphic serialization: emits a single number when both phases are equal, or an object otherwise.

func (Priority) Resolve

func (p Priority) Resolve(phase InterceptionPhase) int

Resolve returns the priority for the given phase.

func (*Priority) UnmarshalJSON

func (p *Priority) UnmarshalJSON(data []byte) error

UnmarshalJSON handles both number and {request, response} forms.

type Severity

type Severity string

Severity represents validation message severity.

const (
	SeverityInfo  Severity = "info"
	SeverityWarn  Severity = "warn"
	SeverityError Severity = "error" // Only error blocks execution
)

type ValidationMessage

type ValidationMessage struct {
	Path     string   `json:"path,omitempty"`
	Message  string   `json:"message"`
	Severity Severity `json:"severity"`
}

ValidationMessage is a single validation finding.

type ValidationResult

type ValidationResult struct {
	Valid       bool                   `json:"valid"`
	Severity    Severity               `json:"severity,omitempty"`
	Messages    []ValidationMessage    `json:"messages,omitempty"`
	Suggestions []ValidationSuggestion `json:"suggestions,omitempty"`
}

ValidationResult is returned by validation interceptors.

type ValidationSuggestion

type ValidationSuggestion struct {
	Path  string `json:"path"`
	Value any    `json:"value"`
}

ValidationSuggestion is an optional suggested correction.

type Validator

type Validator struct {
	Metadata
	Handler ValidatorHandler
}

Validator is a validation interceptor.

func (*Validator) GetMetadata

func (v *Validator) GetMetadata() *Metadata

func (*Validator) GetType

func (v *Validator) GetType() InterceptorType

type ValidatorHandler

type ValidatorHandler func(ctx context.Context, inv *Invocation) (*ValidationResult, error)

ValidatorHandler is the function signature for validation handlers.

Handlers MUST treat the Invocation and its Payload as read-only. Multiple validators for the same event run concurrently and share the same Invocation pointer, so any mutation of the Payload (or other Invocation fields) is a data race.

Directories

Path Synopsis
Package chain provides the SEP-compliant interceptor chain orchestrator.
Package chain provides the SEP-compliant interceptor chain orchestrator.
Package extension registers interceptors as first-class MCP primitives.
Package extension registers interceptors as first-class MCP primitives.
integrations
gomiddleware
Package gomiddleware provides an optional MCP middleware that automatically executes interceptors for every matching request/response.
Package gomiddleware provides an optional MCP middleware that automatically executes interceptors for every matching request/response.

Jump to

Keyboard shortcuts

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