MCPcopy Create free account
hub / github.com/PerpetualSoftware/pad / classifyHTTPStatusKind

Function classifyHTTPStatusKind

internal/mcp/errors.go:753–867  ·  view source on GitHub ↗

classifyHTTPStatusKind turns an HTTP error response into a structured envelope, using the dispatcher's known resource context to emit the right error code and an actionable hint (TASK-1078 / TASK-1079). Parameters: - ctx, cmdKey, lookup — same as classifyHTTPStatus. - route — the URL path the disp

(
	ctx context.Context,
	cmdKey, route string,
	status int,
	body []byte,
	lookup WorkspaceLister,
	kind ResourceKind,
	refOrSlug string,
)

Source from the content-addressed store, hash-verified

751// not found in workspace foo" knows exactly what to fix. May be
752// empty.
753func classifyHTTPStatusKind(
754 ctx context.Context,
755 cmdKey, route string,
756 status int,
757 body []byte,
758 lookup WorkspaceLister,
759 kind ResourceKind,
760 refOrSlug string,
761) *mcp.CallToolResult {
762 bodyText := strings.TrimSpace(string(body))
763 bodyMessage := extractUpstreamMessage(bodyText)
764 if bodyText == "" {
765 bodyText = http.StatusText(status)
766 }
767
768 switch status {
769 case http.StatusUnauthorized:
770 return NewErrorResult(ErrorPayload{
771 Code: ErrAuthRequired,
772 Message: "Authentication required.",
773 Hint: authHintFor(bodyMessage, route),
774 })
775 case http.StatusForbidden:
776 // TASK-788: when the handler emitted a plan_limit_exceeded structured body,
777 // surface it with the dedicated code + details so MCP-driven agents can
778 // present an upgrade-to-Pro signal instead of a generic permission error.
779 // Whitelisted through allowedStructuredErrorCodes (same pattern as
780 // open_children on 409) so unknown 403 codes still collapse to
781 // ErrPermissionDenied.
782 upstream403 := extractUpstreamErrorEnvelope(bodyText)
783 if _, allowed := allowedStructuredErrorCodes[upstream403.Code]; allowed {
784 return NewErrorResult(ErrorPayload{
785 Code: ErrorCode(upstream403.Code),
786 Message: upstream403.Message,
787 Hint: planLimitHintFor(upstream403.Message, route),
788 Details: upstream403.Details,
789 })
790 }
791 return NewErrorResult(ErrorPayload{
792 Code: ErrPermissionDenied,
793 Message: "Permission denied for this operation.",
794 Hint: permissionHintFor(bodyMessage, route),
795 })
796 case http.StatusNotFound:
797 return classify404(ctx, cmdKey, route, bodyText, bodyMessage, lookup, kind, refOrSlug)
798 case http.StatusConflict:
799 // IDEA-1494 R2/R4 P2: preserve the upstream `code` + `details`
800 // when the handler emitted a structured rejection — but ONLY
801 // for codes that appear in the shared allow-list
802 // (allowedStructuredErrorCodes, defined below). The stdio
803 // classifier already gates on the same set; routing both
804 // transports through the same whitelist keeps the
805 // ErrorCode enum's closed contract honest (round-4 P2:
806 // HTTP was forwarding any non-"conflict" code, diverging
807 // from stdio).
808 //
809 // New structured codes get added to allowedStructuredErrorCodes
810 // in one place; both transports adopt them in lockstep.

Calls 13

extractUpstreamMessageFunction · 0.85
NewErrorResultFunction · 0.85
authHintForFunction · 0.85
ErrorCodeTypeAlias · 0.85
planLimitHintForFunction · 0.85
permissionHintForFunction · 0.85
classify404Function · 0.85
conflictHintForFunction · 0.85
validationHintForFunction · 0.85
rateLimitHintForFunction · 0.85
upstreamHintForFunction · 0.85