Skip to content

[Enhancement] Return structured Kubernetes status for tool execution errors #1452

Description

@jordigilh

Problem

Kubernetes API errors returned by core resource tools are currently reduced to server-specific text in an MCP CallToolResult with isError: true. For example, the resources_create_or_update and resources_get handlers wrap the underlying Kubernetes error with fmt.Errorf and return it through api.NewToolCallResult.

That loses the machine-readable fields from metav1.Status / apierrors.StatusError, including:

  • HTTP status code
  • Kubernetes reason (NotFound, Forbidden, Invalid, Conflict, etc.)
  • resource and name details
  • field causes and other structured details

Downstream clients must parse prose such as field is immutable or not found. This is brittle across server versions, Kubernetes libraries, alternate MCP servers, and gateway formatting.

Proposal

When a Kubernetes operation fails, include a structured Kubernetes Status object in the MCP tool result structuredContent, while retaining the existing text content and isError: true response for backward compatibility.

Example:

{
  "apiVersion": "v1",
  "kind": "Status",
  "status": "Failure",
  "reason": "Invalid",
  "code": 422,
  "message": "...",
  "details": {
    "group": "batch",
    "kind": "Job",
    "name": "example"
  }
}

The structured payload should preserve the original Kubernetes status information where available, including details.causes for validation failures. It should apply consistently to the core resource operations (resources_get, resources_list, resources_create_or_update, resources_delete, and resources_scale).

Compatibility and semantics

  • Keep the current human-readable TextContent response for existing clients.
  • Keep isError: true for tool execution failures.
  • Do not reinterpret resources_create_or_update errors as AlreadyExists: that tool is documented as server-side apply and should retain the actual Kubernetes reason/code. A separate create-only tool would be a distinct enhancement if Kubernetes Create semantics are needed.
  • Add tests covering at least NotFound, Forbidden, Invalid, and conflict/status payloads.
  • Document the structured error contract so clients do not need to parse server-specific prose.

Downstream motivation

Kubernaut currently needs to translate remote MCP errors into controller-runtime-compatible errors. The downstream hardening is tracked in PR #2435, but a structured upstream response would remove the need for any text-based fallback.

References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions