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 ¶
- func IsProjectIDValid(id string) bool
- func MustJSON(value any) string
- func ToolErrorResult(value any) map[string]any
- func ToolResult(value any) map[string]any
- func ValidateProjectID(id string) error
- type Detail
- type Reason
- type ToolError
- func AlreadyClaimed(ref, claimedBy string) *ToolError
- func AsTypedError(err error) *ToolError
- func BadArgument(message string, detail Detail) *ToolError
- func BadProjectID(id string) *ToolError
- func ClaimExpired(ref string) *ToolError
- func ClaimMismatch() *ToolError
- func IllegalTransition(from, to string, allowed []string) *ToolError
- func NewToolError(reason Reason, code, message string, detail Detail, remediation []string) *ToolError
- func NewToolErrorWrap(reason Reason, code, message string, detail Detail, remediation []string, ...) *ToolError
- func NotFound(resourceKind, id string) *ToolError
- type TypedError
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsProjectIDValid ¶
IsProjectIDValid reports whether id passes the shape check performed by ValidateProjectID without allocating a typed error.
func MustJSON ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
AlreadyClaimed builds a typed already_claimed error.
func AsTypedError ¶
AsTypedError extracts a *ToolError from err if it (or any wrapped error) implements TypedError. Returns nil otherwise.
func BadArgument ¶
BadArgument builds a typed bad_argument error with optional detail.
func BadProjectID ¶
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 ¶
ClaimExpired builds a typed claim_expired error.
func ClaimMismatch ¶
func ClaimMismatch() *ToolError
ClaimMismatch builds a typed claim_mismatch error.
func IllegalTransition ¶
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 ¶
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) MCPToolError ¶
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 ¶
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.
type TypedError ¶
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.