Documentation
¶
Overview ¶
Package mcpriskscan evaluates mediated MCP operations before execution.
Index ¶
- Constants
- Variables
- type ApprovalGate
- type Decision
- type Disposition
- type Evaluator
- func NewEvaluator(observers ...Observer) *Evaluator
- func NewNoop(tracerProvider trace.TracerProvider, meterProvider metric.MeterProvider, ...) *Evaluator
- func NewPolicyEvaluator(logger *slog.Logger, tracerProvider trace.TracerProvider, ...) *Evaluator
- func PrependObserver(observer Observer, next *Evaluator) *Evaluator
- type Event
- type FailMode
- type MCPFindingEvidenceWriter
- type Observer
- type ObserverFunc
- type Payload
- func BorrowPayload(data []byte) Payload
- func JSONRPCErrorPayload(rpcErr *jsonrpc.Error) Payload
- func ParseResourceResultPayload(data []byte) (Payload, error)
- func ParseToolResultPayload(data []byte) (Payload, error)
- func TextResponsePayload(data []byte) Payload
- func ToolResultPayload(contentBlocks []json.RawMessage, structuredContent json.RawMessage) (Payload, error)
- type PayloadAvailability
- type PayloadStorageCheck
- type PolicyConfig
- type PolicyDetector
- type PolicyEvaluatorOption
- type PolicyLookup
- type Subject
Constants ¶
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" )
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 ¶
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 (Decision) HeldForApproval ¶
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 ¶
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 ¶
PrependObserver composes test or instrumentation observation without exposing a second scan boundary that could bypass the subject claim.
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 ¶
ExecutionID correlates request and response subjects for one execution.
func (Event) IdentityStamped ¶
IdentityStamped reports whether mcpidentity supplied validated provenance.
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.
type MCPFindingEvidenceWriter ¶
type MCPFindingEvidenceWriter interface {
Store(context.Context, risk.MCPFindingEvidenceBatch) error
}
MCPFindingEvidenceWriter stores raw matches for published findings.
type Observer ¶
Observer performs one bounded synchronous inspection. It cannot return a decision, reject a request, or take ownership of borrowed payload bytes.
type ObserverFunc ¶
ObserverFunc adapts a function to 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 ¶
BorrowPayload never copies or truncates bytes, and never changes the request.
func JSONRPCErrorPayload ¶
JSONRPCErrorPayload extracts error message and structured data without the envelope.
func ParseResourceResultPayload ¶
ParseResourceResultPayload extracts text resources and skips binary blobs.
func ParseToolResultPayload ¶
ParseToolResultPayload extracts textual and structured tool result content.
func TextResponsePayload ¶
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.
type PayloadAvailability ¶
type PayloadAvailability string
PayloadAvailability explains why inspection bytes are absent.
const ( 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 ¶
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 ¶
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 ¶
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 ¶
EvaluationOwner reports whether this is the authoritative concrete seam.