mcptool

package
v0.3.3 Latest Latest
Warning

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

Go to latest
Published: Jun 23, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package mcptool provides the shared, spec-compliant MCP typed tool-error contract for the mivia-server MCP surface.

Per the MCP 2025-06-18 Tools specification, recoverable tool-execution failures (validated bad arguments, not-found, claim conflicts, illegal lifecycle transitions) must be returned inside a normal CallToolResult with isError: true so the model can see and recover from them. JSON-RPC error codes are reserved for protocol-level failures (parse errors, unknown methods, internal crashes).

ToolError is the canonical, package-neutral envelope. It satisfies the TypedError interface, which the top-level MCP router recognizes via errors.As and renders as an isError:true tool result instead of a JSON-RPC protocol error. TypedError lets other packages (integrations, workplan, automation, workflow, ...) participate by projecting their own error types into this shared envelope without an import cycle through the router.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsProjectIDValid

func IsProjectIDValid(id string) bool

IsProjectIDValid reports whether id passes the shape check performed by ValidateProjectID without allocating a typed error.

func MustJSON

func MustJSON(value any) string

MustJSON marshals value or panics. Intended only for in-memory values whose JSON shape is known (tool results, typed errors). Provided as a test helper and for callers that build envelopes from already-safe values.

func ToolErrorResult

func ToolErrorResult(value any) map[string]any

ToolErrorResult builds the canonical MCP tool error result envelope: {content: [{type:text, text: <json>}], structuredContent: value, isError: true}.

value should be a *ToolError (or a projection that implements TypedError). The top-level router renders TypedError values through this helper.

func ToolResult

func ToolResult(value any) map[string]any

ToolResult builds the canonical MCP tool success result envelope: {content: [{type:text, text: <json>}], structuredContent: value, isError: false}.

This is the single source of truth for the envelope; per-package copies that previously duplicated this shape should call this helper.

func ValidateProjectID

func ValidateProjectID(id string) error

ValidateProjectID rejects id values that are filesystem paths, UNC paths, drive prefixes, home-directory shortcuts, or empty after trimming. It returns a typed bad_project_id *ToolError that guides the agent to projects.list.

It is a pure shape check; it does not resolve the id against configured projects (callers that need resolution should additionally consult the project registry). A non-nil error always satisfies the TypedError interface.

Types

type Detail

type Detail map[string]any

Detail carries optional, safe, structured context about a typed error. Keys are part of the agent-facing contract only when documented for a reason; all values must be safe scalars or slices (never raw prompts, source, stderr, credentials, provider payloads, roots, or PII). Empty Detail is omitted from JSON.

type Reason

type Reason string

Reason is the stable, machine-readable typed-error discriminator an agent branches on. Values are part of the agent-facing contract and must remain stable; add new reasons additively.

const (
	// ReasonBadProjectID: the id/project_id is not a Mivia project slug or
	// alias (e.g. a filesystem path, UNC path, or drive prefix was supplied).
	// Agent action: call projects.list and retry.
	ReasonBadProjectID Reason = "bad_project_id"
	// ReasonNotFound: a project-scoped resource (project, file, symbol,
	// automation run, work task, ...) does not exist locally. Detail carries
	// resource_kind and id. Agent action: re-list the relevant resource.
	ReasonNotFound Reason = "not_found"
	// ReasonNotIndexed: a project-scoped integration resource (Jira issue,
	// Confluence page) is not present in the local rich-content index. This is
	// distinct from generic not_found: the project exists, but the item has not
	// been ingested locally. Detail carries provider and key. Agent action:
	// inspect integrations status, optionally poll, then retry.
	ReasonNotIndexed Reason = "not_indexed"
	// ReasonBadArgument: a tool argument failed tool-level validation in a way
	// the caller can correct (malformed key, missing required ref).
	ReasonBadArgument Reason = "bad_argument"
	// ReasonIllegalTransition: a lifecycle status transition is not legal from
	// the current state. Detail carries from, to, and allowed next statuses.
	ReasonIllegalTransition Reason = "illegal_transition"
	// ReasonAlreadyClaimed: a claimable resource is held by another run.
	// Detail carries ref and claimed_by.
	ReasonAlreadyClaimed Reason = "already_claimed"
	// ReasonClaimMismatch: a caller referenced a claim it does not own.
	ReasonClaimMismatch Reason = "claim_mismatch"
	// ReasonClaimExpired: the caller's claim lease lapsed and was reclaimed.
	// Agent action: re-claim.
	ReasonClaimExpired Reason = "claim_expired"
	// ReasonUnsupported: the operation is not supported for this project or
	// configuration (e.g. digest mode on a content-graph project).
	ReasonUnsupported Reason = "unsupported"
)

type ToolError

type ToolError struct {
	Code        string   `json:"code"`
	Reason      Reason   `json:"reason"`
	Message     string   `json:"message,omitempty"`
	Detail      Detail   `json:"detail,omitempty"`
	Remediation []string `json:"remediation,omitempty"`
	// contains filtered or unexported fields
}

ToolError is the canonical MCP typed tool-error envelope rendered to agents.

func AlreadyClaimed

func AlreadyClaimed(ref, claimedBy string) *ToolError

AlreadyClaimed builds a typed already_claimed error.

func AsTypedError

func AsTypedError(err error) *ToolError

AsTypedError extracts a *ToolError from err if it (or any wrapped error) implements TypedError. Returns nil otherwise.

func BadArgument

func BadArgument(message string, detail Detail) *ToolError

BadArgument builds a typed bad_argument error with optional detail.

func BadProjectID

func BadProjectID(id string) *ToolError

BadProjectID builds a typed bad_project_id error guiding the agent to projects.list. The offending id is intentionally not echoed (it may be a filesystem path); only the shape rejection is conveyed.

func ClaimExpired

func ClaimExpired(ref string) *ToolError

ClaimExpired builds a typed claim_expired error.

func ClaimMismatch

func ClaimMismatch() *ToolError

ClaimMismatch builds a typed claim_mismatch error.

func IllegalTransition

func IllegalTransition(from, to string, allowed []string) *ToolError

IllegalTransition builds a typed illegal_transition error naming the allowed next statuses so the agent can pick a legal move.

func NewToolError

func NewToolError(reason Reason, code, message string, detail Detail, remediation []string) *ToolError

NewToolError builds a canonical typed error without a fallback sentinel.

func NewToolErrorWrap

func NewToolErrorWrap(reason Reason, code, message string, detail Detail, remediation []string, wrap error) *ToolError

NewToolErrorWrap builds a canonical typed error whose Unwrap preserves the given sentinel, so errors.Is against it still matches in code paths that have not yet migrated to typed results.

func NotFound

func NotFound(resourceKind, id string) *ToolError

NotFound builds a typed not_found error for a project-scoped resource. resourceKind names what to re-list (project, file, symbol, automation_run, work_task, ...).

func (*ToolError) Error

func (e *ToolError) Error() string

Error implements error. It reports code:reason so logs stay compact.

func (*ToolError) MCPToolError

func (e *ToolError) MCPToolError() *ToolError

MCPToolError projects the error into the canonical shared envelope. It satisfies the TypedError interface and is the single render path used by the router.

func (*ToolError) Sanitized

func (e *ToolError) Sanitized() *ToolError

Sanitized returns a copy of e with any Message or Detail string value that contains an unsafe marker replaced with an empty/omitted value. It is the redaction boundary applied at render time so that typed errors — which bypass the router's JSON-RPC message filter — cannot leak derived error text. Reason, Code, and Remediation are constructed by the package constructors from controlled strings only and are passed through unchanged.

func (*ToolError) Unwrap

func (e *ToolError) Unwrap() error

Unwrap preserves errors.Is fallback classification.

type TypedError

type TypedError interface {
	error
	MCPToolError() *ToolError
}

TypedError is the duck-typed contract the top-level MCP router recognizes. Any error implementing it is rendered as an isError:true tool result rather than a JSON-RPC protocol error. This keeps the router decoupled from the concrete ToolError type and lets other packages participate without import cycles.

Jump to

Keyboard shortcuts

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