tool

package
v0.1.10 Latest Latest
Warning

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

Go to latest
Published: Jul 12, 2026 License: MIT Imports: 28 Imported by: 0

Documentation

Overview

Package tool defines the DML tool components and their registry. Each tool implements the Tool interface; Enabled(flags) decides whether it is registered with the MCP server (invariant I8). CostGated marks tools whose execution must pass the cost gate (invariant I4). Tools construct relalg.IR, which codegen renders; they never build SQL by hand, keeping queries inject-proof.

Index

Constants

View Source
const (
	CodeUnauthorized        = "UNAUTHORIZED"
	CodeEntityNotFound      = "ENTITY_NOT_FOUND"
	CodeInvalidInput        = "INVALID_INPUT"
	CodeDMLToolsDisabled    = "DML_TOOLS_DISABLED"
	CodeUnsafeWrite         = "UNSAFE_WRITE"
	CodeNotImplemented      = "NOT_IMPLEMENTED"
	CodeDatabaseError       = "DATABASE_ERROR"
	CodeCostExceeded        = "COST_EXCEEDED"
	CodeBudgetExceeded      = "BUDGET_EXCEEDED"
	CodeTransactionNotFound = "TRANSACTION_NOT_FOUND"
	CodeTransactionScope    = "TRANSACTION_SCOPE"
	CodeTransactionCapacity = "TRANSACTION_CAPACITY"
)

Stable machine codes for business-level rejections. Retryable means a revised request could succeed under the caller's current privileges; hints may only tighten or equivalently rewrite the request, never widen it.

Variables

View Source
var (
	// ErrEntityNotFound is returned when the requested entity is unknown.
	ErrEntityNotFound = errors.New("tool: entity not found")
	// ErrUnauthorized is returned when the role lacks the action.
	ErrUnauthorized = errors.New("tool: unauthorized")
	// ErrInvalidInput is returned for malformed tool input.
	ErrInvalidInput = errors.New("tool: invalid input")
	// ErrDMLToolsDisabled is returned when an entity is not exposed to the
	// generic entity tools.
	ErrDMLToolsDisabled = errors.New("tool: entity DML tools disabled")
	// ErrUnsafeWrite is returned when an update/delete lacks a PK-scoped filter.
	ErrUnsafeWrite = errors.New("tool: unsafe write without primary-key filter")
	// ErrNotImplemented is returned by stub tools.
	ErrNotImplemented = errors.New("tool: not implemented")
	// ErrDuplicateTool is returned by NewRegistry for duplicate tool names.
	ErrDuplicateTool = errors.New("tool: duplicate name")
	// ErrDatabase identifies errors returned by the database driver.
	ErrDatabase = errors.New("tool: database error")
)

Sentinel errors. Business errors (Unauthorized/NotFound/UnsafeWrite/Cost) are mapped by x/mcpserver to IsError results; protocol errors to JSON-RPC.

View Source
var (
	ErrTransactionNotFound = errors.New("tool: transaction not found")
	ErrTransactionScope    = errors.New("tool: transaction scope mismatch")
	ErrTransactionCapacity = errors.New("tool: transaction capacity reached")
)

Functions

func DecisionIDFromContext added in v0.1.5

func DecisionIDFromContext(ctx context.Context) string

DecisionIDFromContext returns the decision ID attached by RunTool, or "".

func NewDecisionID added in v0.1.5

func NewDecisionID() string

NewDecisionID returns a 128-bit random identifier correlating one tool call's MCP response, audit event, and trace span.

func ProcedureToolName

func ProcedureToolName(entityName string) string

ProcedureToolName returns a stable MCP-safe name. The prefix separates procedure tools from built-ins; the hash prevents normalization collisions.

func WithDecisionID added in v0.1.5

func WithDecisionID(ctx context.Context, id string) context.Context

WithDecisionID attaches a decision ID to ctx for hooks and telemetry.

func WrapDBError

func WrapDBError(err error) error

WrapDBError classifies a database driver error while preserving its cause.

Types

type AggregateTool

type AggregateTool struct{}

AggregateTool runs an aggregate query (cost-gated).

func (AggregateTool) CostGated

func (AggregateTool) CostGated()

func (AggregateTool) Enabled

func (AggregateTool) Enabled(f config.ToolFlags) bool

func (AggregateTool) Info

func (AggregateTool) Info() Info

func (AggregateTool) Run

type BeginTransactionTool

type BeginTransactionTool struct{}

func (BeginTransactionTool) Enabled

func (BeginTransactionTool) Info

func (BeginTransactionTool) Info() Info

func (BeginTransactionTool) Run

type CommitTransactionTool

type CommitTransactionTool struct{}

func (CommitTransactionTool) Enabled

func (CommitTransactionTool) Info

func (CommitTransactionTool) Info() Info

func (CommitTransactionTool) Run

type Context

type Context struct {
	Role                       string
	Subject                    map[string]any // caller attributes for row-level ${subject.x} policies
	Session                    string         // MCP session ID when the transport provides one
	DecisionID                 string         // per-call ID correlating response, audit, and trace
	DB                         store.DB
	Dialect                    dialect.Dialect
	Registry                   *entity.Registry
	Authorizer                 rbac.Authorizer
	Masker                     mask.Masker
	Gate                       cost.Gate
	Cache                      cache.Cache[[]map[string]any]
	Engine                     *engine.Engine
	Auditor                    audit.Auditor
	Hooks                      *hook.Hooks
	Timeout                    time.Duration
	MaxRows                    int64
	MaxProcedureRows           int64
	MaxReturnedBytes           int64
	MaxINListSize              int
	MaxFilterConditions        int
	MaxGroupByFields           int
	MaxAggregates              int
	MaxExpand                  int
	CacheMaxEntryRows          int
	CacheMaxEntryBytes         int64
	TransactionBeginTimeout    time.Duration
	TransactionCommitTimeout   time.Duration
	TransactionRollbackTimeout time.Duration
	Feedback                   cost.FeedbackStore
	Analyze                    cost.AnalyzePolicy
	DataSource                 string
	Sources                    map[string]DataSource
	Budget                     budget.Manager
	BudgetLimits               budget.Limits
	Transactions               *TransactionManager
	TxBeginners                map[string]store.TxBeginner
	Transaction                string
}

Context carries per-request dependencies (injected, no mutable global state).

type CostGated

type CostGated interface {
	Tool
	CostGated()
}

CostGated marks a tool whose execution must pass the cost gate.

type CreateTool

type CreateTool struct{}

CreateTool inserts one record.

func (CreateTool) Enabled

func (CreateTool) Enabled(f config.ToolFlags) bool

func (CreateTool) Info

func (CreateTool) Info() Info

func (CreateTool) Run

func (CreateTool) Run(ctx context.Context, input json.RawMessage, tc Context) (Result, error)

type DataSource

type DataSource struct {
	DB      store.DB
	Dialect dialect.Dialect
	Gate    cost.Gate
	Analyze cost.AnalyzePolicy
}

DataSource is the per-entity execution route.

type DeleteTool

type DeleteTool struct{}

DeleteTool deletes records (cost-gated, off by default).

func (DeleteTool) CostGated

func (DeleteTool) CostGated()

func (DeleteTool) Enabled

func (DeleteTool) Enabled(f config.ToolFlags) bool

func (DeleteTool) Info

func (DeleteTool) Info() Info

func (DeleteTool) Run

func (DeleteTool) Run(ctx context.Context, input json.RawMessage, tc Context) (Result, error)

type Denial added in v0.1.5

type Denial struct {
	Code        string         `json:"code"`
	Reason      string         `json:"reason"`
	Retryable   bool           `json:"retryable"`
	Constraints map[string]any `json:"constraints,omitempty"`
	Hints       []string       `json:"hints,omitempty"`
	DecisionID  string         `json:"decisionId"`
}

Denial is the stable, machine-readable rejection contract returned to MCP clients for business-level errors. Field names and code values are part of the public tool contract: adding a new optional field or a new code is a compatible change; renaming or removing either is breaking.

func DenialFor added in v0.1.5

func DenialFor(err error, decisionID string) (Denial, bool)

DenialFor maps a business-level error to the rejection contract. ok is false for internal errors, which must not be reflected to clients.

type DescribeTool

type DescribeTool struct{}

DescribeTool lists entities or one entity's fields.

func (DescribeTool) Enabled

func (DescribeTool) Enabled(f config.ToolFlags) bool

Enabled implements Tool.

func (DescribeTool) Info

func (DescribeTool) Info() Info

Info implements Tool.

func (DescribeTool) Run

func (DescribeTool) Run(ctx context.Context, input json.RawMessage, tc Context) (Result, error)

Run implements Tool.

type ExecuteTool

type ExecuteTool struct{}

ExecuteTool calls a stored procedure.

func (ExecuteTool) CostGated

func (ExecuteTool) CostGated()

func (ExecuteTool) Enabled

func (ExecuteTool) Enabled(f config.ToolFlags) bool

func (ExecuteTool) Info

func (ExecuteTool) Info() Info

func (ExecuteTool) Run

func (ExecuteTool) Run(ctx context.Context, input json.RawMessage, tc Context) (Result, error)

type Info

type Info struct {
	Name        string
	Description string
	InputSchema json.RawMessage
	ReadOnly    bool
}

Info is a tool's static metadata, mapped to an MCP tool definition.

type ProcedureTool

type ProcedureTool struct {
	Entity entity.Entity
}

ProcedureTool exposes one configured procedure as an independent MCP tool. It accepts the procedure parameters directly and delegates execution to the same implementation as execute_entity.

func (ProcedureTool) CostGated

func (ProcedureTool) CostGated()

func (ProcedureTool) Enabled

Enabled implements Tool. Procedure tools are registered independently of the generic tool flags.

func (ProcedureTool) Info

func (t ProcedureTool) Info() Info

Info implements Tool.

func (ProcedureTool) Run

func (t ProcedureTool) Run(ctx context.Context, input json.RawMessage, tc Context) (Result, error)

Run implements Tool.

type ReadTool

type ReadTool struct{}

ReadTool reads records (cost-gated).

func (ReadTool) CostGated

func (ReadTool) CostGated()

func (ReadTool) Enabled

func (ReadTool) Enabled(f config.ToolFlags) bool

func (ReadTool) Info

func (ReadTool) Info() Info

func (ReadTool) Run

func (ReadTool) Run(ctx context.Context, input json.RawMessage, tc Context) (Result, error)

type Registry

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

Registry holds an immutable set of tools.

func NewRegistry

func NewRegistry(tools []Tool) (*Registry, error)

NewRegistry builds a Registry, rejecting duplicate tool names.

func (*Registry) Enabled

func (r *Registry) Enabled(flags config.ToolFlags) []Tool

Enabled returns the tools whose Enabled(flags) is true.

func (*Registry) Get

func (r *Registry) Get(name string) (Tool, bool)

Get returns a tool by name.

func (*Registry) Tools

func (r *Registry) Tools() []Tool

Tools returns all registered tools.

type Result

type Result struct {
	Content              []map[string]any
	IsError              bool
	StructuredResult     any
	ReturnedRows         int64
	ReturnedBytes        int64
	EstimatedScannedRows int64
}

Result is a tool's outcome. Content holds structured rows/text; IsError marks a business-level error the agent can act on.

func RunTool

func RunTool(ctx context.Context, t Tool, input json.RawMessage, tc Context) (Result, error)

RunTool executes a tool with the cross-cutting wiring that must apply to every call regardless of transport: lifecycle hooks, bounded concurrency + backpressure + circuit breaking + (for read-only tools) singleflight via the engine, and best-effort audit. Transports (x/mcpserver) call this instead of Tool.Run directly, keeping the wiring in the core where it is unit-testable. A nil Engine/Auditor/Hooks each degrade to a no-op.

type RollbackTransactionTool

type RollbackTransactionTool struct{}

func (RollbackTransactionTool) Enabled

func (RollbackTransactionTool) Info

func (RollbackTransactionTool) Run

type Tool

type Tool interface {
	Info() Info
	Enabled(flags config.ToolFlags) bool
	Run(ctx context.Context, input json.RawMessage, tc Context) (Result, error)
}

Tool is a single DML capability.

func DefaultTools

func DefaultTools() []Tool

DefaultTools returns the entity and explicit transaction tool instances.

type TransactionManager

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

TransactionManager owns bounded, expiring explicit transaction handles. Tokens are unguessable and additionally bound to role, subject, and source.

func NewTransactionManager

func NewTransactionManager(ttl time.Duration, maxOpen int) *TransactionManager

func (*TransactionManager) Begin

func (m *TransactionManager) Begin(
	ctx context.Context,
	beginner store.TxBeginner,
	session, role string,
	subject map[string]any,
	datasource string,
	opts *store.TxOptions,
) (string, error)

func (*TransactionManager) Close

func (m *TransactionManager) Close()

func (*TransactionManager) Commit

func (m *TransactionManager) Commit(token, session, role string, subject map[string]any) error

func (*TransactionManager) CommitWithEntities

func (m *TransactionManager) CommitWithEntities(token, session, role string, subject map[string]any) ([]string, error)

CommitWithEntities commits and returns entities written by the transaction. The list is returned only after a successful commit so callers can invalidate global read caches without rollback pollution.

func (*TransactionManager) Configuration

func (m *TransactionManager) Configuration() (time.Duration, int)

Configuration returns the immutable limits used by this manager.

func (*TransactionManager) DB

func (m *TransactionManager) DB(
	token, session, role string,
	subject map[string]any,
	datasource string,
) (store.DB, error)

func (*TransactionManager) MarkDirty

func (m *TransactionManager) MarkDirty(
	token, session, role string,
	subject map[string]any,
	datasource, entity string,
) error

MarkDirty records an entity changed inside a transaction.

func (*TransactionManager) Rollback

func (m *TransactionManager) Rollback(token, session, role string, subject map[string]any) error

func (*TransactionManager) RollbackSession

func (m *TransactionManager) RollbackSession(session string)

RollbackSession rolls back all handles owned by a disconnected non-empty transport session. Token-only transports use TTL and App.Close instead.

func (*TransactionManager) Validate

func (m *TransactionManager) Validate(token, session, role string, subject map[string]any) error

Validate verifies a token's transport and authorization identity without exposing its transaction or datasource.

type UpdateTool

type UpdateTool struct{}

UpdateTool updates records (cost-gated).

func (UpdateTool) CostGated

func (UpdateTool) CostGated()

func (UpdateTool) Enabled

func (UpdateTool) Enabled(f config.ToolFlags) bool

func (UpdateTool) Info

func (UpdateTool) Info() Info

func (UpdateTool) Run

func (UpdateTool) Run(ctx context.Context, input json.RawMessage, tc Context) (Result, error)

Jump to

Keyboard shortcuts

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