Help us shape the future of Go! Take the 2026 Go Developer Survey

mcpriskscan

package
v0.0.0-...-0370dea Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2026 License: AGPL-3.0 Imports: 25 Imported by: 0

Documentation

Overview

Package mcpriskscan evaluates mediated MCP operations before execution.

Index

Constants

View Source
const (
	SurfaceHostedMCP   = "hosted_mcp"
	SurfacePlatformMCP = "platform_mcp"
	SurfaceInstances   = "instances"
	SurfaceRemoteMCP   = "remote_mcp"

	MethodToolsCall     = "tools/call"
	MethodResourcesRead = "resources/read"
	MethodPromptsGet    = "prompts/get"

	PhaseRequest  = "request"
	PhaseResponse = "response"
)
View Source
const MaxPayloadBytes = 50 * 1024

MaxPayloadBytes is the synchronous inspection budget, not a request limit. Larger requests still execute, but their payload is unavailable to risk evaluation at this seam.

Variables

View Source
var DefaultPolicyConfig = PolicyConfig{
	Deadline:        5 * time.Second,
	FailMode:        FailOpen,
	FlagConcurrency: 8,
}

DefaultPolicyConfig is the process-level MCP enforcement configuration.

Functions

This section is empty.

Types

type ApprovalGate

type ApprovalGate interface {
	// HoldCall lets the call through when an approval covers it. Otherwise it
	// records or refreshes the call's approval request and returns its token
	// and the instructions the agent needs.
	HoldCall(ctx context.Context, call approval.HoldInput) (approval.HoldOutcome, error)
}

ApprovalGate holds MCP tool calls that a require_approval policy covers.

type Decision

type Decision struct {
	Disposition   Disposition
	PolicyID      string
	PolicyName    string
	RuleID        string
	Description   string
	UserMessage   string
	Indeterminate bool

	// ApprovalToken is set when a require_approval policy holds the call. The
	// deny is then an instruction to the agent, not a refusal: seams that can
	// return a tool result return UserMessage as an isError result so the agent
	// requests approval and retries.
	ApprovalToken string
}

Decision is the complete request-path policy result. Indeterminate records that fail mode resolved an incomplete evaluation to the final disposition.

func Allow

func Allow() Decision

Allow returns a clean allow decision.

func (Decision) Denied

func (d Decision) Denied() bool

Denied reports whether the caller must stop before execution.

func (Decision) HeldForApproval

func (d Decision) HeldForApproval() bool

HeldForApproval reports whether the call is denied pending approval.

type Disposition

type Disposition string

Disposition is the request-path result of an MCP risk scan.

const (
	DispositionAllow Disposition = "allow"
	DispositionDeny  Disposition = "deny"
)

type Evaluator

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

Evaluator is the final scan boundary held by mediation seams. It enforces the Subject's single-owner, once-per-phase claim, owns the policy decision, and fans the claimed subject out to observation-only consumers.

func NewEvaluator

func NewEvaluator(observers ...Observer) *Evaluator

NewEvaluator wraps observers with ownership and duplicate protection.

func NewNoop

func NewNoop(tracerProvider trace.TracerProvider, meterProvider metric.MeterProvider, logger *slog.Logger) *Evaluator

NewNoop returns an Evaluator that records reachability and the scan cost baseline, without evaluating policies, recording findings, or gating calls.

func NewPolicyEvaluator

func NewPolicyEvaluator(
	logger *slog.Logger,
	tracerProvider trace.TracerProvider,
	meterProvider metric.MeterProvider,
	lookup PolicyLookup,
	detector PolicyDetector,
	publisher gcp.Publisher[*riskv1.Finding],
	config PolicyConfig,
	options ...PolicyEvaluatorOption,
) *Evaluator

NewPolicyEvaluator creates an evaluator that enforces block policies inline and evaluates every other policy in the bounded flag lane.

func PrependObserver

func PrependObserver(observer Observer, next *Evaluator) *Evaluator

PrependObserver composes test or instrumentation observation without exposing a second scan boundary that could bypass the subject claim.

func (*Evaluator) Drain

func (e *Evaluator) Drain(ctx context.Context) error

Drain waits for detached flag evaluations after request admission has stopped.

func (*Evaluator) Scan

func (e *Evaluator) Scan(ctx context.Context, subject Subject) Decision

Scan synchronously evaluates an authoritative subject at most once.

type Event

type Event struct {
	Surface        string
	Method         string
	OrganizationID string
	ProjectID      string
	ServerID       string
	MetaServerID   string
	ToolsetID      string
	ToolName       string
	ResourceURI    string
	PromptName     string
	ChatID         string
	// ToolAnnotations contains trusted annotations from a code-owned tool descriptor.
	ToolAnnotations *gentypes.ToolAnnotations
	// contains filtered or unexported fields
}

Event is identifiers-only metadata that may be retained independently of the synchronous payload. MetaServerID is route attribution; it never replaces the concrete ServerID or changes Surface.

func (Event) ExecutionID

func (e Event) ExecutionID() string

ExecutionID correlates request and response subjects for one execution.

func (Event) IdentityStamped

func (e Event) IdentityStamped() bool

IdentityStamped reports whether mcpidentity supplied validated provenance.

func (Event) Phase

func (e Event) Phase() string

Phase returns the inspection phase assigned by the subject constructor.

func (Event) Principal

func (e Event) Principal() mcpidentity.Identity

Principal returns provenance captured exclusively from mcpidentity.

type FailMode

type FailMode string

FailMode determines the request-path result of an indeterminate block scan.

const (
	// FailOpen allows requests when block policy evaluation is indeterminate.
	FailOpen FailMode = "open"

	// FailClosed denies requests when block policy evaluation is indeterminate.
	FailClosed FailMode = "closed"
)

type MCPFindingEvidenceWriter

type MCPFindingEvidenceWriter interface {
	Store(context.Context, risk.MCPFindingEvidenceBatch) error
}

MCPFindingEvidenceWriter stores raw matches for published findings.

type Observer

type Observer interface {
	Observe(ctx context.Context, subject Subject)
}

Observer performs one bounded synchronous inspection. It cannot return a decision, reject a request, or take ownership of borrowed payload bytes.

type ObserverFunc

type ObserverFunc func(context.Context, Subject)

ObserverFunc adapts a function to Observer.

func (ObserverFunc) Observe

func (f ObserverFunc) Observe(ctx context.Context, subject Subject)

Observe implements Observer.

type Payload

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

Payload holds complete inspection bytes only. Its zero value is unavailable. Bytes are borrowed from the caller and valid only during Evaluator.Scan; an observer must not mutate or retain them, including from a telemetry defer or goroutine. A stream or reader is deliberately not representable.

func BorrowPayload

func BorrowPayload(data []byte) Payload

BorrowPayload never copies or truncates bytes, and never changes the request.

func JSONRPCErrorPayload

func JSONRPCErrorPayload(rpcErr *jsonrpc.Error) Payload

JSONRPCErrorPayload extracts error message and structured data without the envelope.

func ParseResourceResultPayload

func ParseResourceResultPayload(data []byte) (Payload, error)

ParseResourceResultPayload extracts text resources and skips binary blobs.

func ParseToolResultPayload

func ParseToolResultPayload(data []byte) (Payload, error)

ParseToolResultPayload extracts textual and structured tool result content.

func TextResponsePayload

func TextResponsePayload(data []byte) Payload

TextResponsePayload creates a response payload from one textual result.

func ToolResultPayload

func ToolResultPayload(contentBlocks []json.RawMessage, structuredContent json.RawMessage) (Payload, error)

ToolResultPayload extracts textual content blocks and structured content.

func (Payload) Availability

func (p Payload) Availability() PayloadAvailability

Availability distinguishes absent content from content too large to inspect.

func (Payload) Bytes

func (p Payload) Bytes() []byte

Bytes returns the borrowed complete payload, or nil when unavailable.

type PayloadAvailability

type PayloadAvailability string

PayloadAvailability explains why inspection bytes are absent.

const (
	// PayloadUnavailable means the seam has no meaningful materialized payload.
	PayloadUnavailable PayloadAvailability = "unavailable"
	// PayloadAvailable means the complete payload fits within the inspection budget.
	PayloadAvailable PayloadAvailability = "available"
	// PayloadOversized means the complete payload exceeds the inspection budget.
	PayloadOversized PayloadAvailability = "oversized"
)

type PayloadStorageCheck

type PayloadStorageCheck = func(ctx context.Context, organizationID string) (bool, error)

PayloadStorageCheck reports whether an organization allows storing scanned tool payloads.

type PolicyConfig

type PolicyConfig struct {
	// Deadline bounds lookup, block scanning, and each detached flag lane.
	Deadline time.Duration

	// FailMode resolves incomplete block policy evaluation.
	FailMode FailMode

	// FlagConcurrency bounds detached flag evaluation goroutines.
	FlagConcurrency int
}

PolicyConfig controls bounded MCP policy evaluation.

type PolicyDetector

type PolicyDetector interface {
	ScanMCPPolicy(ctx context.Context, policy policycore.Policy, request risk.MCPScanRequest) ([]scanners.Finding, error)
}

PolicyDetector runs one policy through the shared synchronous detector set.

type PolicyEvaluatorOption

type PolicyEvaluatorOption func(*policyEvaluator)

PolicyEvaluatorOption configures optional evaluator dependencies.

func WithApprovalGate

func WithApprovalGate(gate ApprovalGate) PolicyEvaluatorOption

WithApprovalGate enables require_approval enforcement. Without a gate, a require_approval policy denies the call.

func WithMCPFindingEvidenceWriter

func WithMCPFindingEvidenceWriter(writer MCPFindingEvidenceWriter, payloadStorage PayloadStorageCheck) PolicyEvaluatorOption

WithMCPFindingEvidenceWriter enables encrypted evidence persistence. Scanned payloads are stored only for organizations payloadStorage admits.

type PolicyLookup

type PolicyLookup interface {
	ListEnabledForMCP(ctx context.Context, organizationID string, projectID uuid.UUID, target policycore.MCPTarget) ([]policycore.Policy, error)
}

PolicyLookup resolves enabled policies for one concrete MCP subject.

type Subject

type Subject struct {
	Event   Event
	Payload Payload `json:"-"`
	// contains filtered or unexported fields
}

Subject is the one value a mediation seam hands to risk evaluation. It keeps retainable identifiers separate from bounded, synchronous-only payload bytes. The private ownership and claim state make one concrete seam authoritative and make repeated scans of the same phase a no-op.

func NewRequest

func NewRequest(ctx context.Context, event Event, payload Payload) Subject

NewRequest captures trusted principal provenance and creates the request-phase subject owned by a supported concrete mediation seam. Unknown surface/method pairs are observation-only and Evaluator.Scan ignores them; there is no meta surface owner because a meta route delegates to its concrete hosted or remote member seam.

func NewResponse

func NewResponse(request Subject, payload Payload) Subject

NewResponse derives a response-phase subject from its request without accepting a response stream. Repeated derivations share one response claim, so duplicate same-id terminal events cannot evaluate twice. A future response adapter must pass one bounded, materialized terminal message. For SSE, progress, EOF, cancellation, malformed events, and missing terminal messages are not whole-stream enforcement points.

func (Subject) EvaluationOwner

func (s Subject) EvaluationOwner() bool

EvaluationOwner reports whether this is the authoritative concrete seam.

Jump to

Keyboard shortcuts

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