diagnostics

package
v0.25.0 Latest Latest
Warning

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

Go to latest
Published: Apr 24, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package diagnostics implements the stable error-code catalog used by mcpproxy to surface human-readable, fixable failure states to the user.

Every terminal (non-automatically-recoverable) error in the upstream, OAuth, Docker, config, and network paths is classified into a stable code of the form MCPX_<DOMAIN>_<SPECIFIC>. Once shipped, a code is never renamed; deprecation is the only allowed transition. See spec 044.

Index

Constants

View Source
const (
	OutcomeSuccess = "success"
	OutcomeFailed  = "failed"
	OutcomeBlocked = "blocked"
)

Outcome constants used in FixResult.Outcome.

View Source
const (
	ModeDryRun  = "dry_run"
	ModeExecute = "execute"
)

Mode constants used in FixRequest.Mode.

Variables

View Source
var ErrUnknownFixer = errors.New("diagnostics: unknown fixer key")

ErrUnknownFixer is returned when InvokeFixer cannot find a registered fixer.

Functions

func FixerKeys

func FixerKeys() []string

FixerKeys returns a sorted slice of all registered fixer keys (for tests and `doctor list-codes`).

func Has

func Has(c Code) bool

Has reports whether a code is registered in the catalog.

func Register

func Register(key string, f FixerFunc)

Register installs a fixer keyed by its FixStep.FixerKey. Subsequent calls with the same key overwrite the previous registration (useful for tests).

func WrapConfigDeprecatedField

func WrapConfigDeprecatedField(err error) error

WrapConfigDeprecatedField marks a use of a deprecated config field.

func WrapConfigMissingSecret

func WrapConfigMissingSecret(err error) error

WrapConfigMissingSecret marks a missing / unresolved secret reference.

func WrapConfigParseError

func WrapConfigParseError(err error) error

WrapConfigParseError marks a configuration-parse failure.

func WrapDockerDaemonDown

func WrapDockerDaemonDown(err error) error

WrapDockerDaemonDown marks a Docker daemon unreachable error.

func WrapDockerImagePullFailed

func WrapDockerImagePullFailed(err error) error

WrapDockerImagePullFailed marks a Docker image-pull failure.

func WrapDockerNoPermission

func WrapDockerNoPermission(err error) error

WrapDockerNoPermission marks a Docker permission-denied error.

func WrapError

func WrapError(code Code, err error) error

WrapError attaches a stable Code to an existing error so the classifier can recognise it without falling back to free-text matching. Producers in the OAUTH / DOCKER / CONFIG / QUARANTINE domains should wrap their terminal (non-automatically-recoverable) errors with WrapError at the point the failure is first observed. Spec 044.

The returned error preserves the original via errors.Unwrap(), so callers that still inspect typed error chains (errors.Is / errors.As) continue to work unchanged.

func WrapOAuthDiscoveryFailed

func WrapOAuthDiscoveryFailed(err error) error

WrapOAuthDiscoveryFailed marks an OAuth authorization-server discovery failure.

func WrapOAuthRefresh403

func WrapOAuthRefresh403(err error) error

WrapOAuthRefresh403 marks an error as an OAuth refresh 403 / invalid_grant.

func WrapOAuthRefreshExpired

func WrapOAuthRefreshExpired(err error) error

WrapOAuthRefreshExpired marks an error as the refresh-token-expired code.

func WrapQuarantinePendingApproval

func WrapQuarantinePendingApproval(err error) error

WrapQuarantinePendingApproval marks a tool-quarantine rejection.

func WrapQuarantineToolChanged

func WrapQuarantineToolChanged(err error) error

WrapQuarantineToolChanged marks a tool-description-changed rejection.

Types

type CatalogEntry

type CatalogEntry struct {
	Code        Code      `json:"code"`
	Severity    Severity  `json:"severity"`
	UserMessage string    `json:"user_message"`
	FixSteps    []FixStep `json:"fix_steps"`
	DocsURL     string    `json:"docs_url"`
	Deprecated  bool      `json:"deprecated,omitempty"`
	ReplacedBy  Code      `json:"replaced_by,omitempty"`
}

CatalogEntry is the authoritative description of one error code.

func All

func All() []CatalogEntry

All returns a stable-sorted copy of every registered catalog entry. The ordering is by code lexicographically so output is deterministic.

func Get

func Get(c Code) (CatalogEntry, bool)

Get looks up a catalog entry by code. Returns (zero, false) for unknown codes.

type ClassifierHints

type ClassifierHints struct {
	Transport string // "stdio", "http", "sse", "docker", etc.
	ServerID  string
}

ClassifierHints lets callers nudge the classifier when context is known (e.g., "this error came from the stdio spawn path").

type Code

type Code string

Code is a stable error-code identifier. Immutable across releases once shipped.

const (
	STDIOSpawnENOENT      Code = "MCPX_STDIO_SPAWN_ENOENT"
	STDIOSpawnEACCES      Code = "MCPX_STDIO_SPAWN_EACCES"
	STDIOExitNonzero      Code = "MCPX_STDIO_EXIT_NONZERO"
	STDIOHandshakeTimeout Code = "MCPX_STDIO_HANDSHAKE_TIMEOUT"
	STDIOHandshakeInvalid Code = "MCPX_STDIO_HANDSHAKE_INVALID"
)

STDIO domain — stdio-transport MCP server failures.

const (
	OAuthRefreshExpired   Code = "MCPX_OAUTH_REFRESH_EXPIRED"
	OAuthRefresh403       Code = "MCPX_OAUTH_REFRESH_403"
	OAuthDiscoveryFailed  Code = "MCPX_OAUTH_DISCOVERY_FAILED"
	OAuthCallbackTimeout  Code = "MCPX_OAUTH_CALLBACK_TIMEOUT"
	OAuthCallbackMismatch Code = "MCPX_OAUTH_CALLBACK_MISMATCH"
)

OAUTH domain — OAuth 2.1 / PKCE flow failures.

const (
	HTTPDNSFailed  Code = "MCPX_HTTP_DNS_FAILED"
	HTTPTLSFailed  Code = "MCPX_HTTP_TLS_FAILED"
	HTTPUnauth     Code = "MCPX_HTTP_401"
	HTTPForbidden  Code = "MCPX_HTTP_403"
	HTTPNotFound   Code = "MCPX_HTTP_404"
	HTTPServerErr  Code = "MCPX_HTTP_5XX"
	HTTPConnRefuse Code = "MCPX_HTTP_CONN_REFUSED"
)

HTTP domain — HTTP/SSE transport failures.

const (
	DockerDaemonDown      Code = "MCPX_DOCKER_DAEMON_DOWN"
	DockerImagePullFailed Code = "MCPX_DOCKER_IMAGE_PULL_FAILED"
	DockerNoPermission    Code = "MCPX_DOCKER_NO_PERMISSION"
	DockerSnapAppArmor    Code = "MCPX_DOCKER_SNAP_APPARMOR"
)

DOCKER domain — Docker isolation subsystem failures.

const (
	ConfigDeprecatedField Code = "MCPX_CONFIG_DEPRECATED_FIELD"
	ConfigParseError      Code = "MCPX_CONFIG_PARSE_ERROR"
	ConfigMissingSecret   Code = "MCPX_CONFIG_MISSING_SECRET"
)

CONFIG domain — configuration parsing and validation failures.

const (
	QuarantinePendingApproval Code = "MCPX_QUARANTINE_PENDING_APPROVAL"
	QuarantineToolChanged     Code = "MCPX_QUARANTINE_TOOL_CHANGED"
)

QUARANTINE domain — security quarantine failures.

const (
	NetworkProxyMisconfig Code = "MCPX_NETWORK_PROXY_MISCONFIG"
	NetworkOffline        Code = "MCPX_NETWORK_OFFLINE"
)

NETWORK domain — network environment failures.

const (
	UnknownUnclassified Code = "MCPX_UNKNOWN_UNCLASSIFIED"
)

UNKNOWN — fallback when no specific classification applies.

func Classify

func Classify(err error, hints ClassifierHints) Code

Classify maps a raw error to a stable Code. It prefers typed-error inspection via errors.Is / errors.As over string matching; falls back to string matching only when the underlying library does not expose structured error types.

The hints parameter lets callers nudge the classifier with context ("this error came from the stdio spawn path", etc.).

If no specific classification applies, Classify returns UnknownUnclassified.

func DiagnoseHTTPStatus

func DiagnoseHTTPStatus(status int) Code

DiagnoseHTTPStatus maps an HTTP status code to a Code. Returns empty if the status is not a known failure.

type DiagnosticError

type DiagnosticError struct {
	Code       Code      `json:"code"`
	Severity   Severity  `json:"severity"`
	Cause      string    `json:"cause,omitempty"`
	CauseType  string    `json:"cause_type,omitempty"`
	ServerID   string    `json:"server_id"`
	DetectedAt time.Time `json:"detected_at"`
}

DiagnosticError is the runtime record attached to a server's stateview snapshot while the server has an active failure.

type FixRequest

type FixRequest struct {
	ServerID string
	Mode     string // "dry_run" or "execute"
}

FixRequest is the input to a registered fixer.

type FixResult

type FixResult struct {
	Outcome    string // "success" | "failed" | "blocked"
	Preview    string // populated for dry_run
	FailureMsg string
}

FixResult is the output of a registered fixer.

func InvokeFixer

func InvokeFixer(ctx context.Context, key string, req FixRequest) (FixResult, error)

InvokeFixer runs the registered fixer with the given key. Returns ErrUnknownFixer if no fixer is registered. Respects req.Mode — the fixer is responsible for not mutating state when req.Mode == ModeDryRun.

type FixStep

type FixStep struct {
	Type        FixStepType `json:"type"`
	Label       string      `json:"label"`
	Command     string      `json:"command,omitempty"`
	URL         string      `json:"url,omitempty"`
	FixerKey    string      `json:"fixer_key,omitempty"`
	Destructive bool        `json:"destructive,omitempty"`
}

FixStep is one actionable remediation suggestion attached to a CatalogEntry.

type FixStepType

type FixStepType string

FixStepType tells the UI how to render a fix step.

const (
	FixStepLink    FixStepType = "link"    // external URL; clickable
	FixStepCommand FixStepType = "command" // shell command; copyable
	FixStepButton  FixStepType = "button"  // triggers a registered fixer via /api/v1/diagnostics/fix
)

type FixerFunc

type FixerFunc func(ctx context.Context, req FixRequest) (FixResult, error)

FixerFunc is the signature every registered fixer implements.

type Severity

type Severity string

Severity drives UI badge colour and CLI formatting.

const (
	SeverityInfo  Severity = "info"
	SeverityWarn  Severity = "warn"
	SeverityError Severity = "error"
)

Jump to

Keyboard shortcuts

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